From 2f47bdff3ae9b3b7fb462fea0579cd3e87551e75 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 7 Oct 2026 15:47:58 +0800 Subject: [PATCH 001/156] [INTERP] Fixed FIST/FISTP/FISTTP range check (#4534) --- src/emu/x64rundb.c | 16 ++++++++++------ src/emu/x64rundf.c | 22 +++++++++++++--------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/emu/x64rundb.c b/src/emu/x64rundb.c index 5c12a9bd5..256129fc4 100644 --- a/src/emu/x64rundb.c +++ b/src/emu/x64rundb.c @@ -32,6 +32,7 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr) { uint8_t nextop; int32_t tmp32s; + double tmpd; reg64_t *oped; #ifdef TEST_INTERPRETER x64emu_t*emu = test->emu; @@ -148,30 +149,33 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 1: /* FISTTP Ed, ST0 */ GETE4(0); - if(isgreater(ST0.d, (double)0x7fffffff) || isless(ST0.d, -(double)0x80000000U) || !isfinite(ST0.d)) { + tmpd = trunc(ST0.d); + if(tmpd > (double)0x7fffffff || tmpd < -(double)0x80000000U || !isfinite(tmpd)) { fpu_raise_invalid(emu); ED->sdword[0] = 0x80000000; } else - ED->sdword[0] = ST0.d; + ED->sdword[0] = tmpd; fpu_do_pop(emu); break; case 2: /* FIST Ed, ST0 */ GETE4(0); - if(isgreater(ST0.d, (double)0x7fffffff) || isless(ST0.d, -(double)0x80000000U) || !isfinite(ST0.d)) { + tmpd = fpu_round(emu, ST0.d); + if(tmpd > (double)0x7fffffff || tmpd < -(double)0x80000000U || !isfinite(tmpd)) { fpu_raise_invalid(emu); ED->sdword[0] = 0x80000000; } else { - volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR + volatile int32_t tmp = (int32_t)tmpd; // tmp to avoid BUS ERROR ED->sdword[0] = tmp; } break; case 3: /* FISTP Ed, ST0 */ GETE4(0); - if(isgreater(ST0.d, (double)0x7fffffff) || isless(ST0.d, -(double)0x80000000U) || !isfinite(ST0.d)) { + tmpd = fpu_round(emu, ST0.d); + if(tmpd > (double)0x7fffffff || tmpd < -(double)0x80000000U || !isfinite(tmpd)) { fpu_raise_invalid(emu); ED->sdword[0] = 0x80000000; } else { - volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR + volatile int32_t tmp = (int32_t)tmpd; // tmp to avoid BUS ERROR ED->sdword[0] = tmp; } fpu_do_pop(emu); diff --git a/src/emu/x64rundf.c b/src/emu/x64rundf.c index 5170aff36..092dd6af9 100644 --- a/src/emu/x64rundf.c +++ b/src/emu/x64rundf.c @@ -30,6 +30,7 @@ uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr) { uint8_t nextop; int16_t tmp16s; + double tmpd; int64_t tmp64s; reg64_t *oped; #ifdef TEST_INTERPRETER @@ -107,29 +108,31 @@ uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 1: /* FISTTP Ew, ST0 */ GETEW(0); - tmp16s = ST0.d; - if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x8000) || !isfinite(ST0.d)) { + tmpd = trunc(ST0.d); + if(tmpd > (double)(int32_t)0x7fff || tmpd < -(double)(int32_t)0x8000 || !isfinite(tmpd)) { fpu_raise_invalid(emu); EW->sword[0] = 0x8000; } else - EW->sword[0] = tmp16s; + EW->sword[0] = tmpd; fpu_do_pop(emu); break; case 2: /* FIST Ew, ST0 */ GETEW(0); - if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x8000) || !isfinite(ST0.d)) { + tmpd = fpu_round(emu, ST0.d); + if(tmpd > (double)(int32_t)0x7fff || tmpd < -(double)(int32_t)0x8000 || !isfinite(tmpd)) { fpu_raise_invalid(emu); EW->sword[0] = 0x8000; } else - EW->sword[0] = fpu_round(emu, ST0.d); + EW->sword[0] = tmpd; break; case 3: /* FISTP Ew, ST0 */ GETEW(0); - if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x8000) || !isfinite(ST0.d)) { + tmpd = fpu_round(emu, ST0.d); + if(tmpd > (double)(int32_t)0x7fff || tmpd < -(double)(int32_t)0x8000 || !isfinite(tmpd)) { fpu_raise_invalid(emu); EW->sword[0] = 0x8000; } else - EW->sword[0] = fpu_round(emu, ST0.d); + EW->sword[0] = tmpd; fpu_do_pop(emu); break; case 4: /* FBLD ST0, tbytes */ @@ -155,11 +158,12 @@ uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr) if(STll(0).sref==ST(0).sq) ED->sq[0] = STll(0).sq; else { - if(isgreater(ST0.d, (double)0x7fffffffffffffffLL) || isless(ST0.d, -(double)0x8000000000000000LL) || !isfinite(ST0.d)) { + tmpd = fpu_round(emu, ST0.d); + if(tmpd >= (double)0x8000000000000000LL || tmpd < -(double)0x8000000000000000LL || !isfinite(tmpd)) { fpu_raise_invalid(emu); ED->sq[0] = 0x8000000000000000LL; } else - ED->sq[0] = fpu_round(emu, ST0.d); + ED->sq[0] = tmpd; } fpu_do_pop(emu); break; From c269865bb20d62e0904d02a60a40e4bf78f9d9e2 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 8 Oct 2026 14:49:11 +0800 Subject: [PATCH 002/156] [LA64_DYNAREC] Refined vector registers restore (#4536) * [LA64_DYNAREC] Refined vector registers restore * [LA64_DYNAREC] Fixed x87 stack count not synced when leaving a block --- src/dynarec/la64/dynarec_la64_arch.c | 123 +++++++++++++++++++++++++-- 1 file changed, 118 insertions(+), 5 deletions(-) diff --git a/src/dynarec/la64/dynarec_la64_arch.c b/src/dynarec/la64/dynarec_la64_arch.c index 29cb72c9a..040acbf59 100644 --- a/src/dynarec/la64/dynarec_la64_arch.c +++ b/src/dynarec/la64/dynarec_la64_arch.c @@ -19,21 +19,37 @@ typedef struct arch_arch_s { uint16_t unaligned : 1; uint16_t host_call : 1; // instruction performs a native call - uint16_t seq : 10; // how many instruction on the same values + uint16_t vec : 1; // vector registers of the block are cached + uint16_t seq : 9; // how many instruction on the same values uint16_t up32; // GPRs with pending 32-bit zero-up at this instruction uint16_t ymm_zero; // YMM upper halves with a deferred architectural zero int16_t rsp; // pending rsp offset at this instruction uint32_t call_window; // spill offset within the instruction + uint16_t xmm; // XMMs with their value cached in a vector register + uint16_t ymm; // YMM upper halves cached in a vector register + uint8_t x87; // x87 stack registers cached in a vector register + uint8_t mmx; // MMX registers cached in a vector register + uint32_t x87_pos; // vector register of each stack register, 3 bits each + uint16_t x87_type; // type of each cached x87 value, 2 bits each + int8_t x87delta; // pending x87 stack count at this instruction } arch_arch_t; typedef struct arch_build_s { uint8_t unaligned; uint8_t host_call; + uint16_t vec; uint16_t up32; uint16_t ymm_zero; int16_t rsp; uint32_t call_window; + uint16_t xmm; + uint16_t ymm; + uint8_t x87; + uint8_t mmx; + uint32_t x87_pos; + uint16_t x87_type; + int8_t x87delta; } arch_build_t; static int arch_build(dynarec_la64_t* dyn, int ninst, arch_build_t* arch) @@ -47,7 +63,35 @@ static int arch_build(dynarec_la64_t* dyn, int ninst, arch_build_t* arch) arch->up32 = dyn->insts[ninst].up32_pending; arch->ymm_zero = dyn->insts[ninst].vector_liveness.ymm_pending; arch->rsp = dyn->insts[ninst].rsp_entry; - return arch->unaligned || arch->host_call || arch->up32 || arch->ymm_zero || arch->rsp; + arch->x87delta = dyn->insts[ninst].lsx.x87stack; + for (int i = 0; i < 16; ++i) { + if (dyn->insts[ninst].lsx.ssecache[i].v != -1) arch->xmm |= (uint16_t)(1 << i); + if (dyn->insts[ninst].lsx.avxcache[i].v != -1) arch->ymm |= (uint16_t)(1 << i); + } + for (int i = 16; i < 24; ++i) { + int n = dyn->insts[ninst].lsx.lsxcache[i].n; + if (dyn->insts[ninst].lsx.lsxcache[i].v) { + switch (dyn->insts[ninst].lsx.lsxcache[i].t) { + case LSX_CACHE_ST_D: + case LSX_CACHE_ST_F: + case LSX_CACHE_ST_I64: + if (n < 0 || n > 7) break; + arch->x87 |= (uint8_t)(1 << n); + arch->x87_pos |= (uint32_t)(i - 16) << (n * 3); + arch->x87_type |= (uint16_t)(dyn->insts[ninst].lsx.lsxcache[i].t - + LSX_CACHE_ST_D) + << (n * 2); + break; + case LSX_CACHE_MM: + if (i == 16 + n) arch->mmx |= (uint8_t)(1 << n); + break; + default: break; + } + } + } + arch->vec = (arch->xmm || arch->ymm || arch->x87 || arch->mmx); + return arch->unaligned || arch->host_call || arch->vec || arch->up32 || arch->ymm_zero || + arch->rsp || arch->x87delta; } size_t get_size_arch(dynarec_la64_t* dyn) @@ -61,7 +105,7 @@ size_t get_size_arch(dynarec_la64_t* dyn) if(!dyn->size) return 0; for(int i=0; isize; ++i) { last = arch_build(dyn, i, &build); - if((!memcmp(&build, &previous, sizeof(arch_build_t))) && (seq<((1<<10)-1)) && i) { + if((!memcmp(&build, &previous, sizeof(arch_build_t))) && (seq<((1<<9)-1)) && i) { // same sequence, increment ++seq; } else { @@ -85,6 +129,14 @@ static void build_next(arch_arch_t* arch, arch_build_t* build) arch->up32 = build->up32; arch->ymm_zero = build->ymm_zero; arch->rsp = build->rsp; + arch->vec = build->vec; + arch->xmm = build->xmm; + arch->ymm = build->ymm; + arch->x87 = build->x87; + arch->mmx = build->mmx; + arch->x87_pos = build->x87_pos; + arch->x87_type = build->x87_type; + arch->x87delta = build->x87delta; } void* populate_arch(dynarec_la64_t* dyn, void* p, size_t sz) @@ -97,7 +149,7 @@ void* populate_arch(dynarec_la64_t* dyn, void* p, size_t sz) int seq = 0; for(int i=0; isize; ++i) { arch_build(dyn, i, &build); - if((!memcmp(&build, &previous, sizeof(arch_build_t))) && (seq<((1<<10)-1)) && i) { + if((!memcmp(&build, &previous, sizeof(arch_build_t))) && (seq<((1<<9)-1)) && i) { // same sequence, increment seq++; arch->seq = seq; @@ -164,7 +216,6 @@ int arch_host_call(dynablock_t* db, void* native_pc, uintptr_t x64pc) void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) { - (void)p; if(!db) return; if(!db->arch_size || !db->arch) return; int ninst = getX64AddressInst(db, x64pc); @@ -183,4 +234,66 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) emu->ymm[r].u128 = 0; } if (arch->rsp && !arch->host_call) emu->regs[_SP].q[0] += arch->rsp; + if (arch->x87delta) { + emu->fpu_stack += arch->x87delta; + emu->top = (emu->top - arch->x87delta) & 7; + } + if (arch->vec && !arch->host_call) { + struct sctx_info* info = (struct sctx_info*)p->uc_mcontext.__extcontext; + uint64_t* vec = NULL; + int stride = 0; + while (info->magic && !vec) { + if (info->magic == LSX_CTX_MAGIC || info->magic == LASX_CTX_MAGIC || + info->magic == FPU_CTX_MAGIC) { + stride = (info->magic == LASX_CTX_MAGIC) + ? 4 + : ((info->magic == LSX_CTX_MAGIC) ? 2 : 1); + vec = (uint64_t*)((uintptr_t)info + sizeof(struct sctx_info)); + } else { + info = (struct sctx_info*)((uintptr_t)info + info->size); + } + } + if (vec) { + uint16_t xmm = arch->xmm; + uint16_t ymm = arch->ymm; + for (int i = 0; i < 16; ++i) { + if (!((xmm >> i) & 1) && !((ymm >> i) & 1)) continue; + if (stride == 1) { + emu->xmm[i].q[0] = vec[i]; + } else { + memcpy(&emu->xmm[i].u128, &vec[i * stride], 16); + if ((ymm >> i) & 1) { + if ((arch->ymm_zero >> i) & 1) + emu->ymm[i].u128 = 0; + else if (stride == 4) + memcpy(&emu->ymm[i].u128, &vec[i * stride + 2], 16); + } + } + } + uint8_t x87 = arch->x87; + while (x87) { + int i = __builtin_ctz(x87); + x87 &= x87 - 1; + int slot = 16 + ((arch->x87_pos >> (i * 3)) & 7); + uint64_t raw = vec[slot * stride]; + switch ((arch->x87_type >> (i * 2)) & 3) { + case LSX_CACHE_ST_D - LSX_CACHE_ST_D: + emu->x87[(emu->top + i) & 7].d = *(double*)&raw; + break; + case LSX_CACHE_ST_F - LSX_CACHE_ST_D: + emu->x87[(emu->top + i) & 7].d = *(float*)&raw; + break; + default: + emu->x87[(emu->top + i) & 7].d = *(int64_t*)&raw; + break; + } + } + uint8_t mmx = arch->mmx; + while (mmx) { + int i = __builtin_ctz(mmx); + mmx &= mmx - 1; + emu->mmx[i].q = vec[(16 + i) * stride] & 0xffffffffffffffffULL; + } + } + } } From 430a408f0ae964da7be1d136f4f55ddcd195bdb4 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 8 Oct 2026 15:01:22 +0800 Subject: [PATCH 003/156] [ARM64_DYNAREC] Fixed x87 top restore on interrupted block (#4539) --- src/dynarec/arm64/dynarec_arm64_arch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dynarec/arm64/dynarec_arm64_arch.c b/src/dynarec/arm64/dynarec_arm64_arch.c index 1622d02d4..4ff3a494a 100644 --- a/src/dynarec/arm64/dynarec_arm64_arch.c +++ b/src/dynarec/arm64/dynarec_arm64_arch.c @@ -377,7 +377,7 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) } if(x87) { dynarec_log_prefix(0, LOG_INFO, " x87[%x, pos=%x, type=%x (fpsimd=%p)] ", x87->x87, x87->x87_pos, x87->x87_type, fpsimd); - emu->top -= x87->delta; + if (x87->delta) emu->top = (emu->top - x87->delta) & 7; for(int i=0; i<8; ++i) { if(x87->x87&(1<x87_pos>>(i*4))&0x0f); From a43469d7a5b79b96654f4d6cf37406ad7ea69aba Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 8 Oct 2026 15:05:21 +0800 Subject: [PATCH 004/156] [RV64_DYNAREC] Refined registers restore on interrupted block (#4540) --- src/dynarec/dynarec_arch.h | 2 +- src/dynarec/rv64/dynarec_rv64_arch.c | 195 +++++++++++++++++++++++++-- 2 files changed, 188 insertions(+), 9 deletions(-) diff --git a/src/dynarec/dynarec_arch.h b/src/dynarec/dynarec_arch.h index 30037b8f0..d5468cdc9 100644 --- a/src/dynarec/dynarec_arch.h +++ b/src/dynarec/dynarec_arch.h @@ -118,7 +118,7 @@ extern void la64_next_invalid(); #define ARCH_SIZE(A) get_size_arch(A) #define ARCH_FILL(A, B, C) populate_arch(A, B, C) -#define ARCH_ADJUST(A, B, C, D) {} +#define ARCH_ADJUST(A, B, C, D) adjust_arch(A, B, C, D) #define STOP_NATIVE_FLAGS(A, B) {} #define ARCH_UNALIGNED(A, B) arch_unaligned(A, B) #define ARCH_HOST_CALL(A, B, C) 0 diff --git a/src/dynarec/rv64/dynarec_rv64_arch.c b/src/dynarec/rv64/dynarec_rv64_arch.c index 9e6c64cb0..1a254b2a5 100644 --- a/src/dynarec/rv64/dynarec_rv64_arch.c +++ b/src/dynarec/rv64/dynarec_rv64_arch.c @@ -32,25 +32,28 @@ typedef struct arch_flags_s #define X87_ST_D 0 #define X87_ST_F 1 #define X87_ST_I64 2 -#define XMM0 0 -#define X870 XMM0 + 16 -#define EMM0 XMM0 + 16 + typedef struct arch_x87_s { - int8_t delta; //up to +/-7 + int8_t delta; // pending x87 stack count at that instruction uint8_t x87; // 1bit is STx present - uint16_t x87_type; // 2bits per STx type - uint32_t x87_pos; //4bits per STx position (well, 3 would be enough) + uint8_t reg[8]; // FP register of each present STx + uint8_t type[8]; // type of each present STx } arch_x87_t; typedef struct arch_mmx_s { uint8_t mmx; //1bit for each mmx reg present + uint8_t vector; // 1bit for each mmx reg cached in a vector register + uint8_t reg[8]; // register of each present mmx reg } arch_mmx_t; typedef struct arch_sse_s { - uint16_t sse; //1bit for each sse reg present + uint16_t sse; // 1bit for each sse reg present + uint16_t vector; // 1bit for each sse reg cached in a vector register + uint8_t reg[16]; // register of each present sse reg + uint8_t single[16]; // 1 if the sse value is single precision } arch_sse_t; typedef struct arch_ymm_s @@ -86,6 +89,59 @@ static int arch_build(dynarec_rv64_t* dyn, int ninst, arch_build_t* arch) // todo // opcode can handle unaligned arch->unaligned = dyn->insts[ninst].unaligned; + extcache_t* e = &dyn->insts[ninst].e; + for (int i = 0; i < 32; ++i) { + if (!e->extcache[i].t) + continue; + int reg = EXTREG(i); + switch (e->extcache[i].t) { + case EXT_CACHE_ST_D: + case EXT_CACHE_ST_F: + case EXT_CACHE_ST_I64: { + int st = e->extcache[i].n & 7; + arch->x87_.x87 |= (uint8_t)(1 << st); + arch->x87_.reg[st] = (uint8_t)reg; + arch->x87_.type[st] = (uint8_t)(e->extcache[i].t - EXT_CACHE_ST_D); + break; + } + case EXT_CACHE_MM: { + int mm = e->extcache[i].n & 7; + arch->mmx_.mmx |= (uint8_t)(1 << mm); + arch->mmx_.reg[mm] = (uint8_t)reg; + break; + } + case EXT_CACHE_MMV: { + int mm = e->extcache[i].n & 7; + arch->mmx_.mmx |= (uint8_t)(1 << mm); + arch->mmx_.vector |= (uint8_t)(1 << mm); + arch->mmx_.reg[mm] = (uint8_t)reg; + break; + } + case EXT_CACHE_SS: + case EXT_CACHE_SD: + case EXT_CACHE_XMMR: + case EXT_CACHE_XMMW: { + int xmm = e->extcache[i].n & 15; + arch->sse_.sse |= (uint16_t)(1 << xmm); + if (e->extcache[i].t == EXT_CACHE_XMMR || e->extcache[i].t == EXT_CACHE_XMMW) + arch->sse_.vector |= (uint16_t)(1 << xmm); + arch->sse_.reg[xmm] = (uint8_t)reg; + arch->sse_.single[xmm] = (e->extcache[i].t == EXT_CACHE_SS) ? 1 : 0; + break; + } + default: + break; + } + } + // pending x87 stack count + if (e->x87stack) + arch->x87_.delta = e->x87stack; + if (arch->x87_.x87 || arch->x87_.delta) + arch->x87 = 1; + if (arch->mmx_.mmx) + arch->mmx = 1; + if (arch->sse_.sse) + arch->sse = 1; return arch->flags + arch->x87 + arch->mmx + arch->sse + arch->ymm + arch->unaligned; } @@ -144,6 +200,74 @@ static int sizeof_arch(arch_arch_t* arch) return sz; } + +static void read_vector_reg(const void* vframe, size_t vlenb, int reg, void* buf) +{ + if (vframe) { + memcpy(buf, (const uint8_t*)vframe + (reg & 31) * vlenb, 16); + return; + } + + // HACK: if vframe is absent, the live register is read instead. + switch (reg & 31) { +#define VREG_CASE(N) \ + case N: \ + __asm__ volatile(".option push\n\t.option arch, +v\n\taddi t1, zero, 16\n\tvsetvli t0, t1, 0\n\tvse8.v v" #N ", (%0)\n\t.option pop\n\t" ::"r"(buf) \ + : "memory", "t0", "t1"); \ + break; + VREG_CASE(0) + VREG_CASE(1) + VREG_CASE(2) + VREG_CASE(3) + VREG_CASE(4) + VREG_CASE(5) + VREG_CASE(6) + VREG_CASE(7) + VREG_CASE(8) + VREG_CASE(9) + VREG_CASE(10) + VREG_CASE(11) + VREG_CASE(12) + VREG_CASE(13) + VREG_CASE(14) + VREG_CASE(15) + VREG_CASE(16) + VREG_CASE(17) + VREG_CASE(18) + VREG_CASE(19) + VREG_CASE(20) + VREG_CASE(21) + VREG_CASE(22) + VREG_CASE(23) + VREG_CASE(24) + VREG_CASE(25) + VREG_CASE(26) + VREG_CASE(27) + VREG_CASE(28) + VREG_CASE(29) + VREG_CASE(30) + VREG_CASE(31) +#undef VREG_CASE + } +} + +static const void* get_vframe(const ucontext_t* p, size_t* vlenb) +{ + // struct __riscv_extra_ext_header { uint32_t padding[129]; uint32_t reserved; struct { uint32_t magic, size; } hdr; } + const uint8_t* fp = (const uint8_t*)&p->uc_mcontext.__fpregs; + if (*(const uint32_t*)(fp + 520) != 0x53465457) // RISCV_V_MAGIC + return NULL; + struct riscv_v_ext_state_s { + unsigned long vstart, vl, vtype, vcsr, vlenb; + void* datap; + }; + const struct riscv_v_ext_state_s* vs = (const struct riscv_v_ext_state_s*)(fp + 528); + if (!vs->datap || vs->vlenb < 16 || vs->vlenb > 4096) + return NULL; + *vlenb = vs->vlenb; + return vs->datap; +} + void* populate_arch(dynarec_rv64_t* dyn, void* p, size_t sz) { arch_build_t build = {0}; @@ -205,7 +329,62 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) } SUPER() #undef GO - // todo + if (sse || mmx) { + size_t vlenb = 0; + const void* vframe = get_vframe(p, &vlenb); + if (sse) { + dynarec_log(LOG_INFO, " sse[%x, vector=%x, %s] ", sse->sse, sse->vector, vframe ? "frame" : "live"); + for (int i = 0; i < 16; ++i) { + if (!((sse->sse >> i) & 1)) + continue; + if ((sse->vector >> i) & 1) { + uint8_t vbuf[16]; + read_vector_reg(vframe, vlenb, sse->reg[i], vbuf); + memcpy(&emu->xmm[i], vbuf, 16); + } else if (sse->single[i]) { + uint64_t raw = p->uc_mcontext.__fpregs.__d.__f[sse->reg[i] & 31]; + *(uint32_t*)&emu->xmm[i] = (uint32_t)raw; + } else { + emu->xmm[i].q[0] = p->uc_mcontext.__fpregs.__d.__f[sse->reg[i] & 31]; + } + } + } + if (mmx) { + dynarec_log(LOG_INFO, " mmx[%x, vector=%x] ", mmx->mmx, mmx->vector); + for (int i = 0; i < 8; ++i) { + if (!((mmx->mmx >> i) & 1)) + continue; + if ((mmx->vector >> i) & 1) { + uint8_t vbuf[16]; + read_vector_reg(vframe, vlenb, mmx->reg[i], vbuf); + emu->mmx[i].q = *(uint64_t*)vbuf; + } else { + emu->mmx[i].q = p->uc_mcontext.__fpregs.__d.__f[mmx->reg[i] & 31]; + } + } + } + } + if (x87) { + dynarec_log(LOG_INFO, " x87[%x, delta=%d] ", x87->x87, x87->delta); + if (x87->delta) + emu->top = (emu->top - x87->delta) & 7; + for (int i = 0; i < 8; ++i) { + if (!((x87->x87 >> i) & 1)) + continue; + uint64_t raw = p->uc_mcontext.__fpregs.__d.__f[x87->reg[i] & 31]; + switch (x87->type[i]) { + case X87_ST_F: + emu->x87[(emu->top + i) & 7].d = *(float*)&raw; + break; + case X87_ST_I64: + emu->x87[(emu->top + i) & 7].d = (double)*(int64_t*)&raw; + break; + default: + emu->x87[(emu->top + i) & 7].d = *(double*)&raw; + break; + } + } + } dynarec_log(LOG_INFO, "\n"); } From cf250c5661c508376a60697afaeb43b95a6f75ca Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Thu, 8 Oct 2026 15:15:11 +0800 Subject: [PATCH 005/156] [RV64_DYNAREC] Raise illegal inst error for MOVHPS 0F 17 and MOVLPS 0F 13 (#4537) Also change loogarch movhps 0f 17 opcode. --- src/dynarec/la64/dynarec_la64_0f.c | 8 +++--- src/dynarec/rv64/dynarec_rv64_0f.c | 32 ++++++++++++++--------- src/dynarec/rv64/dynarec_rv64_0f_vector.c | 32 +++++++++-------------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c index 617306182..93223c7e3 100644 --- a/src/dynarec/la64/dynarec_la64_0f.c +++ b/src/dynarec/la64/dynarec_la64_0f.c @@ -300,12 +300,12 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0x17: nextop = F8; - INST_NAME("MOVHPS Ex,Gx"); - GETGX(v0, 0); if (MODREG) { - v1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 1); - VEXTRINS_D(v1, v0, 0x01); + INST_NAME("Illegal 0F 17"); + UDF(); } else { + INST_NAME("MOVHPS Ex,Gx"); + GETGX(v0, 0); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); VSTELM_D(v0, ed, 0, 1); SMWRITE2(); diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index 09d7f00f6..bc4c6eacb 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -267,14 +267,18 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; case 0x13: - INST_NAME("MOVLPS Ex,Gx"); nextop = F8; - GETGX(); - GETEX(x2, 0, 1); - LD(x3, gback, gdoffset + 0); - SD(x3, wback, fixedaddress + 0); - if (!MODREG) + if (MODREG) { + INST_NAME("Illegal 0F 13"); + UDF(); + } else { + INST_NAME("MOVLPS Ex,Gx"); + GETGX(); + GETEX(x2, 0, 1); + LD(x3, gback, gdoffset + 0); + SD(x3, wback, fixedaddress + 0); SMWRITE2(); + } break; case 0x14: INST_NAME("UNPCKLPS Gx,Ex"); @@ -315,14 +319,18 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SD(x4, gback, gdoffset + 8); break; case 0x17: - INST_NAME("MOVHPS Ex,Gx"); nextop = F8; - GETGX(); - GETEX(x2, 0, 1); - LD(x4, gback, gdoffset + 8); - SD(x4, wback, fixedaddress + 0); - if (!MODREG) + if (MODREG) { + INST_NAME("Illegal 0F 17"); + UDF(); + } else { + INST_NAME("MOVHPS Ex,Gx"); + GETGX(); + GETEX(x2, 0, 1); + LD(x4, gback, gdoffset + 8); + SD(x4, wback, fixedaddress + 0); SMWRITE2(); + } break; case 0x18: nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_0f_vector.c index 0e61732d0..175e66a2d 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_0f_vector.c @@ -121,15 +121,15 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, } break; case 0x13: - INST_NAME("MOVLPS Ex, Gx"); nextop = F8; - GETG; - SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); - v0 = sse_get_reg_vector(dyn, ninst, x1, gd, 0, VECTOR_SEW64); if (MODREG) { - DEFAULT; - return addr; + INST_NAME("Illegal 0F 13"); + UDF(); } else { + INST_NAME("MOVLPS Ex, Gx"); + GETG; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); + v0 = sse_get_reg_vector(dyn, ninst, x1, gd, 0, VECTOR_SEW64); VMV_X_S(x4, v0); addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0); SD(x4, ed, fixedaddress); @@ -210,23 +210,15 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, } break; case 0x17: - INST_NAME("MOVHPS Ex, Gx"); nextop = F8; - SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); - GETGX_vector(v0, 0, VECTOR_SEW64); - // EX->q[0] = GX->q[1]; if (MODREG) { - v1 = sse_get_reg_vector(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 1, VECTOR_SEW64); - q0 = fpu_get_scratch(dyn); - VSLIDE1DOWN_VX(q0, v0, xZR, VECTOR_UNMASKED); - if (cpuext.xtheadvector) { - VECTOR_LOAD_VMASK(0b01, x4, 1); - VMERGE_VVM(v1, v1, q0); // implies VMASK - } else { - VMV_X_S(x4, q0); - VMV_S_X(v1, x4); - } + INST_NAME("Illegal 0F 17"); + UDF(); } else { + INST_NAME("MOVHPS Ex, Gx"); + SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); + GETGX_vector(v0, 0, VECTOR_SEW64); + // EX->q[0] = GX->q[1]; addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); q0 = fpu_get_scratch(dyn); VSLIDE1DOWN_VX(q0, v0, xZR, VECTOR_UNMASKED); From 89453f420d94b2d685685eb1ce95bbc6b56b1308 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 8 Oct 2026 15:19:01 +0800 Subject: [PATCH 006/156] [ARM64_DYNAREC] Fixed native flags forwarded from REP CMPS/SCAS with count 0 (#4541) The flags are not generated when the count is 0 (they are left untouched), so native flags cannot be forwarded from those instructions. --- src/dynarec/arm64/dynarec_arm64_00.c | 4 ++++ src/dynarec/arm64/dynarec_arm64_66.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 1b0dd6234..cfb3b1801 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -2162,6 +2162,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin CBNZx_MARK2(xRCX); MARK3; // end emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5); + STOP_NATIVE_FLAGS(dyn, ninst); break; default: INST_NAME("CMPSB"); @@ -2214,6 +2215,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin CBNZx_MARK2(xRCX); MARK3; // end emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5); + STOP_NATIVE_FLAGS(dyn, ninst); break; default: INST_NAME("CMPSD"); @@ -2412,6 +2414,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin CBNZx_MARK2(xRCX); MARK3; // end emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5); + STOP_NATIVE_FLAGS(dyn, ninst); break; default: INST_NAME("SCASB"); @@ -2458,6 +2461,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin CBNZx_MARK2(xRCX); MARK3; // end emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5); + STOP_NATIVE_FLAGS(dyn, ninst); break; default: INST_NAME("SCASD"); diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c index 276a43706..c723bb623 100644 --- a/src/dynarec/arm64/dynarec_arm64_66.c +++ b/src/dynarec/arm64/dynarec_arm64_66.c @@ -950,6 +950,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin CBNZx_MARK2(xRCX); MARK3; // end emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5); + STOP_NATIVE_FLAGS(dyn, ninst); break; default: INST_NAME("CMPSW"); @@ -1070,6 +1071,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin CBNZx_MARK2(xRCX); MARK3; // end emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5); + STOP_NATIVE_FLAGS(dyn, ninst); break; default: INST_NAME("SCASW"); From 2a30952898be0bd6b8f6f285874f34e82988761e Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Thu, 8 Oct 2026 09:29:57 +0200 Subject: [PATCH 007/156] [ARM64_DYNAREC] Added a few FLAGM optimisations --- src/dynarec/arm64/dynarec_arm64_660f.c | 10 ++-- src/dynarec/arm64/dynarec_arm64_emit_math.c | 60 ++++++++++++++------- 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_660f.c b/src/dynarec/arm64/dynarec_arm64_660f.c index ba7ce5350..64ccd13dd 100644 --- a/src/dynarec/arm64/dynarec_arm64_660f.c +++ b/src/dynarec/arm64/dynarec_arm64_660f.c @@ -951,9 +951,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n } } } else { - MRS_nzcv(x3); - BFIx(x3, xFlags, 29, 1); // set C - MSR_nzcv(x3); // load CC into ARM CF + if(cpuext.flagm) + RMIF(xFlags, 63, 0b0010); + else { + MRS_nzcv(x3); + BFIx(x3, xFlags, 29, 1); // set C + MSR_nzcv(x3); // load CC into ARM CF + } } IFX(X_CF) { ADCSxw_REG(gd, gd, ed); diff --git a/src/dynarec/arm64/dynarec_arm64_emit_math.c b/src/dynarec/arm64/dynarec_arm64_emit_math.c index 10272f382..a2590d63b 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_math.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_math.c @@ -1001,9 +1001,13 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 } } } else { - MRS_nzcv(s3); - BFIx(s3, xFlags, 29, 1); // set C - MSR_nzcv(s3); // load CC into ARM CF + if(cpuext.flagm) + RMIF(xFlags, 63, 0b0010); + else { + MRS_nzcv(s3); + BFIx(s3, xFlags, 29, 1); // set C + MSR_nzcv(s3); // load CC into ARM CF + } } IFX(X_AF) { ORRxw_REG(s3, s1, s2); // s3 = op1 | op2 @@ -1144,9 +1148,13 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) } } } else { - MRS_nzcv(s3); - BFIx(s3, xFlags, 29, 1); // set C - MSR_nzcv(s3); // load CC into ARM CF + if(cpuext.flagm) + RMIF(xFlags, 63, 0b0010); + else { + MRS_nzcv(s3); + BFIx(s3, xFlags, 29, 1); // set C + MSR_nzcv(s3); // load CC into ARM CF + } } IFX(X_AF | X_OF) { ORRw_REG(s3, s1, s2); // s3 = op1 | op2 @@ -1208,9 +1216,13 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) } } } else { - MRS_nzcv(s3); - BFIx(s3, xFlags, 29, 1); // set C - MSR_nzcv(s3); // load CC into ARM CF + if(cpuext.flagm) + RMIF(xFlags, 63, 0b0010); + else { + MRS_nzcv(s3); + BFIx(s3, xFlags, 29, 1); // set C + MSR_nzcv(s3); // load CC into ARM CF + } } IFX(X_AF | X_OF) { ORRw_REG(s3, s1, s2); // s3 = op1 | op2 @@ -1332,9 +1344,13 @@ void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 } } else { EORw_mask(s4, xFlags, 0, 0); // invert CC because it's reverted for SUB on ARM - MRS_nzcv(s3); - BFIx(s3, s4, 29, 1); // set C - MSR_nzcv(s3); // load CC into ARM CF + if(cpuext.flagm) + RMIF(s4, 63, 0b0010); + else { + MRS_nzcv(s3); + BFIx(s3, s4, 29, 1); // set C + MSR_nzcv(s3); // load CC into ARM CF + } } IFX(X_AF) { ORNxw_REG(s3, s2, s1); // s3 = ~op1 | op2 @@ -1481,9 +1497,13 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) } } else { EORw_mask(s4, xFlags, 0, 0); // invert CC because it's reverted for SUB on ARM - MRS_nzcv(s3); - BFIx(s3, s4, 29, 1); // set C - MSR_nzcv(s3); // load CC into ARM CF + if(cpuext.flagm) + RMIF(s4, 63, 0b0010); + else { + MRS_nzcv(s3); + BFIx(s3, s4, 29, 1); // set C + MSR_nzcv(s3); // load CC into ARM CF + } } IFX(X_AF|X_OF|X_CF) { ORNw_REG(s3, s2, s1); // s3 = ~op1 | op2 @@ -1546,9 +1566,13 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) } } else { EORw_mask(s4, xFlags, 0, 0); // invert CC because it's reverted for SUB on ARM - MRS_nzcv(s3); - BFIx(s3, s4, 29, 1); // set C, bit 29 - MSR_nzcv(s3); // load CC into ARM CF + if(cpuext.flagm) + RMIF(s4, 63, 0b0010); + else { + MRS_nzcv(s3); + BFIx(s3, s4, 29, 1); // set C, bit 29 + MSR_nzcv(s3); // load CC into ARM CF + } } IFX(X_AF|X_OF|X_CF) { ORNw_REG(s3, s2, s1); // s3 = ~op1 | op2 From b00d767d1a22f1c8b6fce5fba4351953596879c9 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 8 Oct 2026 16:39:40 +0800 Subject: [PATCH 008/156] [ARM64_DYNAREC] Fixed ymm_pos encoding in arch restore (#4542) --- src/dynarec/arm64/dynarec_arm64_arch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_arch.c b/src/dynarec/arm64/dynarec_arm64_arch.c index 4ff3a494a..35cdc07c6 100644 --- a/src/dynarec/arm64/dynarec_arm64_arch.c +++ b/src/dynarec/arm64/dynarec_arm64_arch.c @@ -121,11 +121,11 @@ static int arch_build(dynarec_arm_t* dyn, int ninst, arch_build_t* arch, int noa arch->ymm = 1; arch->ymm_.ymm |= 1<insts[ninst].n.neoncache[i].n; idx = i; - if(idx>=EMM0 && idx<=EMM0+8) + if(idx>=EMM0 && idxymm_.ymm_pos |= idx<<(dyn->insts[ninst].n.neoncache[i].n*4); + arch->ymm_.ymm_pos |= (uint64_t)idx<<(dyn->insts[ninst].n.neoncache[i].n*4); break; case NEON_CACHE_ST_D: arch->x87 = 1; From 76f318d4530690591ece05fa8b23742c9aec6a26 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 8 Oct 2026 16:51:49 +0800 Subject: [PATCH 009/156] [DYNAREC] Fixed x87 cache transform not syncing pending stack count (#4538) * [DYNAREC] Fixed x87 cache transform not syncing pending stack count * [DYNAREC] Fixed x87 cache transform applying pending stack count twice --- src/dynarec/arm64/dynarec_arm64_helper.c | 6 +++--- src/dynarec/la64/dynarec_la64_helper.c | 6 +++--- src/dynarec/rv64/dynarec_rv64_helper.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index 92f455fc7..d0038c09f 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -2265,9 +2265,9 @@ static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int } } } - if(stack_cnt != cache_i2.stack) { - MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d -\n", stack_cnt, cache_i2.stack); - int a = stack_cnt - cache_i2.stack; + if(stack_cnt != cache_i2.stack || dyn->n.x87stack != cache_i2.x87stack) { + MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d / pending %d -> %d -\n", stack_cnt, cache_i2.stack, dyn->n.x87stack, cache_i2.x87stack); + int a = dyn->n.x87stack - cache_i2.x87stack; // Add x87stack to emu fpu_stack LDRw_U12(s3, xEmu, offsetof(x64emu_t, fpu_stack)); if(a>0) { diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c index 3f3335115..73c2af5ff 100644 --- a/src/dynarec/la64/dynarec_la64_helper.c +++ b/src/dynarec/la64/dynarec_la64_helper.c @@ -2431,9 +2431,9 @@ static void fpuCacheTransform(dynarec_la64_t* dyn, int ninst, int s1, int s2, in } } } - if (stack_cnt != cache_i2.stack) { - MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d -\n", stack_cnt, cache_i2.stack); - int a = stack_cnt - cache_i2.stack; + if (stack_cnt != cache_i2.stack || dyn->lsx.x87stack != cache_i2.x87stack) { + MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d / pending %d -> %d -\n", stack_cnt, cache_i2.stack, dyn->lsx.x87stack, cache_i2.x87stack); + int a = dyn->lsx.x87stack - cache_i2.x87stack; // Add x87stack to emu fpu_stack LD_W(s3, xEmu, offsetof(x64emu_t, fpu_stack)); ADDI_D(s3, s3, a); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 392b9b17b..e1e7cd2ba 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -2579,9 +2579,9 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in } } } - if (stack_cnt != cache_i2.stack) { - MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d -\n", stack_cnt, cache_i2.stack); - int a = stack_cnt - cache_i2.stack; + if (stack_cnt != cache_i2.stack || dyn->e.x87stack != cache_i2.x87stack) { + MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d / pending %d -> %d -\n", stack_cnt, cache_i2.stack, dyn->e.x87stack, cache_i2.x87stack); + int a = dyn->e.x87stack - cache_i2.x87stack; // Add x87stack to emu fpu_stack LW(s3, xEmu, offsetof(x64emu_t, fpu_stack)); ADDI(s3, s3, a); From 78ae59d67bae41b44f08f928e1b19179521ae737 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Thu, 8 Oct 2026 11:24:28 +0200 Subject: [PATCH 010/156] [INTERP] Better handling of invalid CS on CALL/RET FAR opcodes --- src/emu/x64run.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/emu/x64run.c b/src/emu/x64run.c index 17502ed7f..6079b3e50 100644 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -947,8 +947,6 @@ int Run(x64emu_t *emu, int step) if(is32bits) { uint32_t new_addr = (rex.is32bits && rex.is66)?(F16):(F32); uint16_t new_cs = F16; - Push32(emu, emu->segs[_CS]); - Push32(emu, addr); #ifndef TEST_INTERPRETER if((new_cs&3)!=3) { // R_RIP doesn't advance @@ -957,6 +955,8 @@ int Run(x64emu_t *emu, int step) EmitSignal(emu, X64_SIGSEGV, (void*)R_RIP, 0xbad0); // GP if trying to change priv level goto fini; } + Push32(emu, emu->segs[_CS]); + Push32(emu, addr); emu->segs[_CS] = new_cs; addr = new_addr; if(is32bits!=(emu->segs[_CS]==0x23)) { @@ -1665,32 +1665,44 @@ int Run(x64emu_t *emu, int step) tmp16u = F16; if(rex.is32bits || !rex.w) { addr = Pop32(emu); - emu->segs[_CS] = Pop32(emu); // no check, no use.... + tmp16u = Pop32(emu); // no check, no use.... } else { addr = Pop64(emu); - emu->segs[_CS] = Pop64(emu); // no check, no use.... + tmp16u = Pop64(emu); // no check, no use.... } R_RSP += tmp16u; - is32bits = (R_CS==0x23); // checking if CS changed + is32bits = (tmp16u==0x23); // checking if CS changed #ifndef TEST_INTERPRETER if(is32bits) running32bits = 1; #endif + if((tmp16u&3)!=3) { + R_RSP-=(rex.w?4:8)*2; + EmitSignal(emu, X64_SIGSEGV, (void*)R_RIP, 0xbad0); // GP if trying to change priv level + goto fini; + } else + emu->segs[_CS] = tmp16u; STEP2; break; case 0xCB: /* FAR RET */ if(rex.is32bits || !rex.w) { addr = Pop32(emu); - emu->segs[_CS] = Pop32(emu); // no check.... + tmp16u = Pop32(emu); // no check.... } else { addr = Pop64(emu); - emu->segs[_CS] = Pop64(emu); // no check.... + tmp16u = Pop64(emu); // no check.... } - is32bits = (R_CS==0x23); // checking if CS changed + is32bits = (tmp16u==0x23); // checking if CS changed #ifndef TEST_INTERPRETER if(is32bits) running32bits = 1; #endif + if((tmp16u&3)!=3) { + R_RSP-=(rex.w?4:8)*2; + EmitSignal(emu, X64_SIGSEGV, (void*)R_RIP, 0xbad0); // GP if trying to change priv level + goto fini; + } else + emu->segs[_CS] = tmp16u; STEP2; break; case 0xCC: /* INT 3 */ @@ -2408,6 +2420,18 @@ int Run(x64emu_t *emu, int step) EmitSignal(emu, X64_SIGILL, (void*)R_RIP, 0); goto fini; } else { + tmp8u = 0; + if(rex.is32bits || !rex.w) { + if((ED->word[2]&3)!=3) + tmp8u = 1; + } else { + if(((ED+1)->word[0]&3)!=3) + tmp8u = 2; + } + if(tmp8u) { + EmitSignal(emu, X64_SIGSEGV, (void*)R_RIP, 0xbad0); // GP if trying to change priv level + goto fini; + } if(rex.is32bits || !rex.w) { Push32(emu, R_CS); Push32(emu, addr); From f3bec61f27a6a7c0bacc49f84d2d394729403b22 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Thu, 8 Oct 2026 11:25:12 +0200 Subject: [PATCH 011/156] [ARM64_DYNAREC] Better handling of invalid CS on CALL/RET FAR opcodes (for #4535) --- src/dynarec/arm64/dynarec_arm64_00.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index cfb3b1801..8fc276575 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -2959,6 +2959,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin READFLAGS(X_PEND); BARRIER(BARRIER_FLOAT); if(rex.w) {POP2(xRIP, x3);} else {POP2_32(xRIP, x3);} + TBZ_MARK(x3, 0); + TBZ_MARK(x3, 1); //GP if CS is incorect STRH_U12(x3, xEmu, offsetof(x64emu_t, segs[_CS])); if(u16<0x1000) ADDz_U12(xRSP, xRSP, u16); @@ -2967,6 +2969,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin ADDz_REG(xRSP, xRSP, x1); } ret_to_next(dyn, ip, ninst, rex); + MARK; + ADDx_U12(xRSP, xRSP, (rex.w?8:4)*2); + MOV64x(xRIP, ip); // move back RIP to the opcode + CALL_S(const_native_priv, -1); + jump_to_epilog(dyn, 0, xRIP, ninst); *need_epilog = 0; *ok = 0; break; @@ -2975,8 +2982,15 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin READFLAGS(X_PEND); BARRIER(BARRIER_FLOAT); if(rex.w) {POP2(xRIP, x3);} else {POP2_32(xRIP, x3);} + TBZ_MARK(x3, 0); + TBZ_MARK(x3, 1); //GP if CS is incorect STRH_U12(x3, xEmu, offsetof(x64emu_t, segs[_CS])); ret_to_next(dyn, ip, ninst, rex); + MARK; + ADDx_U12(xRSP, xRSP, (rex.w?8:4)*2); + MOV64x(xRIP, ip); // move back RIP to the opcode + CALL_S(const_native_priv, -1); + jump_to_epilog(dyn, 0, xRIP, ninst); *need_epilog = 0; *ok = 0; break; @@ -4657,6 +4671,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin LDxw(x1, wback, 0); ed = x1; LDH(x3, wback, rex.w?8:4); + TBZ(x3, 0, 4+4); + TBNZ_MARK2(x3, 1); + // Bad CS => GP + CALL_S(const_native_priv, -1); + jump_to_epilog(dyn, 0, xRIP, ninst); + MARK2; LDH(x5, xEmu, offsetof(x64emu_t, segs[_CS])); if (BOX64DRENV(dynarec_callret) && BOX64DRENV(dynarec_bigblock) > 1) { BARRIER(BARRIER_FULL); From bffb9ee4d1072a0a038c69b8c439c7fdfbf5e955 Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Thu, 8 Oct 2026 18:36:51 +0800 Subject: [PATCH 012/156] [WRAPPER] Add missing parameters for openssl PKCS12_create (#4544) For openssl 1.0.2, ``` PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, int mac_iter, int keytype); ``` For openssl 3.0, ``` PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, int mac_iter, int keytype); ``` --- src/emu/x64printer.c | 2 ++ src/wrapped/generated/functions_list.txt | 1 + src/wrapped/generated/wrapper.c | 2 ++ src/wrapped/generated/wrapper.h | 1 + src/wrapped/wrappedcrypto3_private.h | 2 +- src/wrapped/wrappedcrypto_private.h | 2 +- 6 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/emu/x64printer.c b/src/emu/x64printer.c index 7654cb67d..131a6d746 100644 --- a/src/emu/x64printer.c +++ b/src/emu/x64printer.c @@ -7214,6 +7214,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu64 ", %" PRIu64 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uintptr_t)R_R8, (uintptr_t)R_R9, *(uint32_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32)); } else if (w == pFpppiiiiiii) { snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(int32_t*)(R_RSP + 32)); + } else if (w == pFpppppiiiii) { + snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(int32_t*)(R_RSP + 32)); } else if (w == pFpppppppppp) { snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32)); } else if (w == vFEppLpLpLLpp) { diff --git a/src/wrapped/generated/functions_list.txt b/src/wrapped/generated/functions_list.txt index c8525f16c..29ddbcf0c 100644 --- a/src/wrapped/generated/functions_list.txt +++ b/src/wrapped/generated/functions_list.txt @@ -3925,6 +3925,7 @@ #() pFppuiipuuii #() pFppuuLLuppp #() pFpppiiiiiii +#() pFpppppiiiii #() pFpppppppppp #() pFbuuuWWWCCi #() iWEpuipupppp diff --git a/src/wrapped/generated/wrapper.c b/src/wrapped/generated/wrapper.c index bf7313827..a98662071 100644 --- a/src/wrapped/generated/wrapper.c +++ b/src/wrapped/generated/wrapper.c @@ -3953,6 +3953,7 @@ typedef void* (*pFppippLLLip_t)(void*, void*, int32_t, void*, void*, uintptr_t, typedef void* (*pFppuiipuuii_t)(void*, void*, uint32_t, int32_t, int32_t, void*, uint32_t, uint32_t, int32_t, int32_t); typedef void* (*pFppuuLLuppp_t)(void*, void*, uint32_t, uint32_t, uintptr_t, uintptr_t, uint32_t, void*, void*, void*); typedef void* (*pFpppiiiiiii_t)(void*, void*, void*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t); +typedef void* (*pFpppppiiiii_t)(void*, void*, void*, void*, void*, int32_t, int32_t, int32_t, int32_t, int32_t); typedef void* (*pFpppppppppp_t)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*); typedef void* (*pFbuuuWWWCCi_t)(void*, uint32_t, uint32_t, uint32_t, uint16_t, uint16_t, uint16_t, uint8_t, uint8_t, int32_t); typedef int32_t (*iWEpuipupppp_t)(x64emu_t*, void*, uint32_t, int32_t, void*, uint32_t, void*, void*, void*, void*); @@ -8241,6 +8242,7 @@ void pFppippLLLip(x64emu_t *emu, uintptr_t fcn) { pFppippLLLip_t fn = (pFppippLL void pFppuiipuuii(x64emu_t *emu, uintptr_t fcn) { pFppuiipuuii_t fn = (pFppuiipuuii_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (void*)R_R9, *(uint32_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(int32_t*)(R_RSP + 32)); } void pFppuuLLuppp(x64emu_t *emu, uintptr_t fcn) { pFppuuLLuppp_t fn = (pFppuuLLuppp_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uintptr_t)R_R8, (uintptr_t)R_R9, *(uint32_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32)); } void pFpppiiiiiii(x64emu_t *emu, uintptr_t fcn) { pFpppiiiiiii_t fn = (pFpppiiiiiii_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(int32_t*)(R_RSP + 32)); } +void pFpppppiiiii(x64emu_t *emu, uintptr_t fcn) { pFpppppiiiii_t fn = (pFpppppiiiii_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(int32_t*)(R_RSP + 32)); } void pFpppppppppp(x64emu_t *emu, uintptr_t fcn) { pFpppppppppp_t fn = (pFpppppppppp_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32)); } void pFbuuuWWWCCi(x64emu_t *emu, uintptr_t fcn) { pFbuuuWWWCCi_t fn = (pFbuuuWWWCCi_t)fcn; void *aligned_xcb = align_xcb_connection((void*)R_RDI); R_RAX=(uintptr_t)fn(aligned_xcb, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint16_t)R_R8, (uint16_t)R_R9, *(uint16_t*)(R_RSP + 8), *(uint8_t*)(R_RSP + 16), *(uint8_t*)(R_RSP + 24), *(int32_t*)(R_RSP + 32)); unalign_xcb_connection(aligned_xcb, (void*)R_RDI); } void iWEpuipupppp(x64emu_t *emu, uintptr_t fcn) { iWEpuipupppp_t fn = (iWEpuipupppp_t)fcn; R_RAX=(int)fn(emu, (void*)R_RCX, (uint32_t)R_RDX, (int32_t)R_R8, (void*)R_R9, *(uint32_t*)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56), *(void**)(R_RSP + 64), *(void**)(R_RSP + 72)); } diff --git a/src/wrapped/generated/wrapper.h b/src/wrapped/generated/wrapper.h index 0d6c831d3..180a881a5 100644 --- a/src/wrapped/generated/wrapper.h +++ b/src/wrapped/generated/wrapper.h @@ -3963,6 +3963,7 @@ void pFppippLLLip(x64emu_t *emu, uintptr_t fnc); void pFppuiipuuii(x64emu_t *emu, uintptr_t fnc); void pFppuuLLuppp(x64emu_t *emu, uintptr_t fnc); void pFpppiiiiiii(x64emu_t *emu, uintptr_t fnc); +void pFpppppiiiii(x64emu_t *emu, uintptr_t fnc); void pFpppppppppp(x64emu_t *emu, uintptr_t fnc); void pFbuuuWWWCCi(x64emu_t *emu, uintptr_t fnc); void iWEpuipupppp(x64emu_t *emu, uintptr_t fnc); diff --git a/src/wrapped/wrappedcrypto3_private.h b/src/wrapped/wrappedcrypto3_private.h index 89af41aee..e8b2fe1f8 100644 --- a/src/wrapped/wrappedcrypto3_private.h +++ b/src/wrapped/wrappedcrypto3_private.h @@ -2999,7 +2999,7 @@ GOM(PEM_X509_INFO_read_bio, pFEpppp) //GO(PKCS12_BAGS_new, //GO(PKCS12_certbag2x509, //GO(PKCS12_certbag2x509crl, -GO(PKCS12_create, pFppppp) +GO(PKCS12_create, pFpppppiiiii) //GO(PKCS12_decrypt_skey, GO(PKCS12_free, vFp) //GO(PKCS12_gen_mac, diff --git a/src/wrapped/wrappedcrypto_private.h b/src/wrapped/wrappedcrypto_private.h index fb37bb355..9f5d8cbf9 100644 --- a/src/wrapped/wrappedcrypto_private.h +++ b/src/wrapped/wrappedcrypto_private.h @@ -2861,7 +2861,7 @@ GO(PEM_write_bio_X509_REQ, iFpp) //GO(PKCS12_BAGS_new, //GO(PKCS12_certbag2x509, //GO(PKCS12_certbag2x509crl, -GO(PKCS12_create, pFppppp) +GO(PKCS12_create, pFpppppiiiii) //GO(PKCS12_decrypt_skey, GO(PKCS12_free, vFp) //GO(PKCS12_gen_mac, From 6ece2e87f2c4ef9bf2f759e255d36cf4730a06e3 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 8 Oct 2026 23:15:52 +0800 Subject: [PATCH 013/156] [ARM64_DYNAREC] Fixed o64 PCMPESTRI fastpath (#4545) --- src/dynarec/arm64/dynarec_arm64_660f.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_660f.c b/src/dynarec/arm64/dynarec_arm64_660f.c index 64ccd13dd..2d09c4bf6 100644 --- a/src/dynarec/arm64/dynarec_arm64_660f.c +++ b/src/dynarec/arm64/dynarec_arm64_660f.c @@ -1421,10 +1421,17 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n Bcond(cPL, 4+4); NEGxw_REG(x3, x3); MOV32w(x4, (u8&1)?8:16); - CMPSw_REG(x3, x4); - CSELw(x3, x3, x4, cLO); // x3 is lmem - CMPSw_REG(x2, x4); - CSELw(x6, x2, x4, cLO); // x6 is lreg + if(rex.w) { + CMPSx_REG(x3, x4); + CSELx(x3, x3, x4, cLO); // x3 is lmem + CMPSx_REG(x2, x4); + CSELx(x6, x2, x4, cLO); // x6 is lreg + } else { + CMPSw_REG(x3, x4); + CSELw(x3, x3, x4, cLO); // x3 is lmem + CMPSw_REG(x2, x4); + CSELw(x6, x2, x4, cLO); // x6 is lreg + } CMPSw_REG(x6, x3); CSELw(x5, x3, x6, cLT); // x5 is max(lmem, lreg) CSELw(x2, x6, x3, cLT); // x2 is min(lmem, lreg) From 935b6d090fbb8b28d019586bf1e18833c9e21b05 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Fri, 9 Oct 2026 15:25:48 +0800 Subject: [PATCH 014/156] [DYNAREC] Fixed dynablock not getting out when writing in its own page (#4543) A write faulting on a protected page, with the target not inside the running block, only unprotected the page and let the block continue. The page then stays writable for the rest of that block, so a later write of the same block can silently modify code it is going to execute, and the stale translation gets executed. So also get out of the block when the target is in the same page as the block, and mark the write instruction as internal smc so the rebuilt block is cut there. That mark is also used to not get out a second time, so the write can complete instead of looping. --- src/dynarec/dynarec_native_pass.c | 3 +-- src/libtools/signals.c | 21 +++++++-------------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index 3a6db2fd7..7e08b081d 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -113,7 +113,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int dyn->forward_ninst = 0; dyn->ymm_zero = 0; dyn->is_file_mapped = IsAddrElfOrFileMapped(addr); - int dynarec_dirty = BOX64ENV(dynarec_dirty); #if STEP == 0 memset(&dyn->insts[ninst], 0, sizeof(instruction_native_t)); #endif @@ -364,7 +363,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int #define PROT_READ 1 #endif #if STEP == 0 - if(dynarec_dirty && ok && is_addr_autosmc(ip)) { + if(ok && is_addr_autosmc(ip)) { // this is the last opcode, because it will write in current block if not stopped ok = 0; need_epilog = 1; diff --git a/src/libtools/signals.c b/src/libtools/signals.c index ababbda5f..0575a8bdb 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -1007,27 +1007,20 @@ else dynarec_log(LOG_INFO, "SIGILL at %p/%p for Dynablock (%p, x64addr=%p) with // access error, unprotect the block (and mark them dirty) CheckHotPage((uintptr_t)addr, prot); unprotectDB((uintptr_t)addr, 1, 1); // unprotect 1 byte... But then, the whole page will be unprotected + int autosmc = 0; + if(db) { + autosmc = (addr >= db->x64_addr && addr < (db->x64_addr + db->x64_size)) + || (!BOX64ENV(dynarec_dirty) && ALIGN_DOWN((uintptr_t)addr) == ALIGN_DOWN((uintptr_t)db->x64_addr) && !is_addr_autosmc(x64pc)); + } int db_need_test = (db && !BOX64ENV(dynarec_dirty))?getNeedTest((uintptr_t)db->x64_addr):0; - if(db && ((addr>=db->x64_addr && addr<(db->x64_addr+db->x64_size)) || db_need_test)) { + if(db && (autosmc || db_need_test)) { emu = getEmuSignal(emu, p, db); // dynablock got auto-dirty! need to get out of it!!! - uintptr_t x64pc = getX64Address(db, (uintptr_t)pc); copyUCTXreg2Emu(emu, p, db, x64pc); adjustregs(emu, pc); if(db && db->arch_size) ARCH_ADJUST(db, emu, p, x64pc); - int autosmc = (addr>=db->x64_addr && addr<(db->x64_addr+db->x64_size)); - if(autosmc && BOX64ENV(dynarec_dirty)) { - // check if current block should be cut there - int inst = getX64AddressInst(db, (uintptr_t)pc); - // is it the last instruction - uintptr_t next = getX64InstAddress(db, inst+1); - if(next!=(uintptr_t)-1LL) { - // there is a next, so lets mark the address and dirty the block - mark_db_autosmc(db, x64pc); - } - - } + if (autosmc) mark_db_autosmc(db, x64pc); dynarec_log(LOG_INFO, "Dynablock (%p, x64addr=%p, need_test=%d/%d/%d) %s, getting out at %p (%p)!\n", db, db->x64_addr, db_need_test, db->dirty, db->always_test, autosmc?"Auto-SMC":"unprotected", (void*)R_RIP, (void*)addr); //relockMutex(Locks); unlock_signal(); From 55caa39c606029b326a100a12c046088dd18344f Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Fri, 9 Oct 2026 15:26:27 +0800 Subject: [PATCH 015/156] [TEST] Set emu on the thread (#4547) --- src/test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test.c b/src/test.c index 45d0b9e5a..f308225f5 100644 --- a/src/test.c +++ b/src/test.c @@ -613,6 +613,7 @@ static int runSingleTest(const char* filepath, const char* include_path) x64emu_t* emu = NewX64Emu(my_context, my_context->ep, (uintptr_t)my_context->stack, my_context->stacksz, 0); + thread_set_emu(emu); bool have_mmregs = false; for (int i = 0; i < 8; ++i) { From 779d69f2ec3472faad6f1ffc60d74ab784bdab98 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Fri, 9 Oct 2026 17:11:25 +0800 Subject: [PATCH 016/156] [RV64_DYNAREC] Fixed SEW cache after 256-bit AVX instructions (#4548) --- src/dynarec/rv64/dynarec_rv64_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index e1e7cd2ba..22eff68d7 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -2825,7 +2825,7 @@ void fpu_propagate_stack(dynarec_rv64_t* dyn, int ninst) void avx_set_vector_width(dynarec_rv64_t* dyn, int ninst, int s1, int sew, int width) { - dyn->vector_sew = sew; + dyn->vector_sew = (width == 16) ? sew : VECTOR_SEWNA; dyn->vector_eew = vector_vsetvli(dyn, ninst, s1, sew, VECTOR_LMUL1, (float)width / 16.0f); } From 937d39e71c3001db4a01f29bfd6de598706a86ec Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Fri, 9 Oct 2026 21:19:50 +0800 Subject: [PATCH 017/156] [ARM64_DYNAREC] Fixed x87 !fastnan handling with both operands are NaN (#4546) --- src/dynarec/arm64/dynarec_arm64_d8.c | 48 ++++++++++++------------ src/dynarec/arm64/dynarec_arm64_da.c | 12 +++--- src/dynarec/arm64/dynarec_arm64_dc.c | 36 +++++++++--------- src/dynarec/arm64/dynarec_arm64_de.c | 36 +++++++++--------- src/dynarec/arm64/dynarec_arm64_helper.h | 38 +++++++++++++++---- 5 files changed, 96 insertions(+), 74 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_d8.c b/src/dynarec/arm64/dynarec_arm64_d8.c index e2395358d..da414c771 100644 --- a/src/dynarec/arm64/dynarec_arm64_d8.c +++ b/src/dynarec/arm64/dynarec_arm64_d8.c @@ -63,7 +63,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -73,7 +73,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -101,7 +101,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -111,7 +111,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -176,7 +176,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -186,7 +186,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -214,7 +214,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -224,7 +224,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -252,7 +252,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -262,7 +262,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -290,7 +290,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -300,7 +300,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -328,7 +328,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDS(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -339,7 +339,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDD(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -362,7 +362,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULS(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -373,7 +373,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULD(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -425,7 +425,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -436,7 +436,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -459,7 +459,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, s0, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -470,7 +470,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, s0, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -493,7 +493,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -504,7 +504,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -527,7 +527,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, s0, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -538,7 +538,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, s0, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); diff --git a/src/dynarec/arm64/dynarec_arm64_da.c b/src/dynarec/arm64/dynarec_arm64_da.c index 8531c3f7b..9cd975af3 100644 --- a/src/dynarec/arm64/dynarec_arm64_da.c +++ b/src/dynarec/arm64/dynarec_arm64_da.c @@ -157,7 +157,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -180,7 +180,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -226,7 +226,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -249,7 +249,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -290,7 +290,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -313,7 +313,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) diff --git a/src/dynarec/arm64/dynarec_arm64_dc.c b/src/dynarec/arm64/dynarec_arm64_dc.c index 07ff6a416..72f260358 100644 --- a/src/dynarec/arm64/dynarec_arm64_dc.c +++ b/src/dynarec/arm64/dynarec_arm64_dc.c @@ -59,7 +59,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -69,7 +69,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -97,7 +97,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -107,7 +107,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -172,7 +172,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -182,7 +182,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -210,7 +210,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -220,7 +220,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -248,7 +248,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -258,7 +258,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -286,7 +286,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -296,7 +296,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -323,7 +323,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -344,7 +344,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -384,7 +384,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -405,7 +405,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -426,7 +426,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -447,7 +447,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) diff --git a/src/dynarec/arm64/dynarec_arm64_de.c b/src/dynarec/arm64/dynarec_arm64_de.c index 6ee877134..f68dc2c35 100644 --- a/src/dynarec/arm64/dynarec_arm64_de.c +++ b/src/dynarec/arm64/dynarec_arm64_de.c @@ -59,7 +59,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -69,7 +69,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -98,7 +98,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -108,7 +108,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -169,7 +169,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -179,7 +179,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -208,7 +208,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -218,7 +218,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -247,7 +247,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -257,7 +257,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -286,7 +286,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -296,7 +296,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -327,7 +327,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -351,7 +351,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -400,7 +400,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -424,7 +424,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -448,7 +448,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -472,7 +472,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index b44334bdf..f53500a12 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -861,11 +861,22 @@ #endif #ifndef X87_ARITH_NAN_END_D -#define X87_ARITH_NAN_END_D(vres, tmp, tmp2) \ +#define X87_ARITH_NAN_END_D(vres, vb, tmp, tmp2) \ FCMEQD(tmp2, vres, vres); \ - VBIC(tmp, tmp, tmp2); \ - VSHLQ_64(tmp, tmp, 63); \ - VORR(vres, vres, tmp) + VBIC(tmp2, tmp, tmp2); \ + VSHLQ_64(tmp2, tmp2, 63); \ + VORR(vres, vres, tmp2); \ + VSSHRQ_64(tmp2, vres, 63); \ + FCMEQD(tmp, vres, vres); \ + VMVNQ(tmp, tmp); \ + VANDQ(tmp, tmp, tmp2); \ + VSSHRQ_64(tmp2, vb, 63); \ + VMVNQ(tmp2, tmp2); \ + VANDQ(tmp, tmp, tmp2); \ + FCMEQD(tmp2, vb, vb); \ + VMVNQ(tmp2, tmp2); \ + VANDQ(tmp, tmp, tmp2); \ + VBIT(vres, vb, tmp) #endif #ifndef X87_ARITH_NAN_START_S @@ -875,11 +886,22 @@ #endif #ifndef X87_ARITH_NAN_END_S -#define X87_ARITH_NAN_END_S(vres, tmp, tmp2) \ +#define X87_ARITH_NAN_END_S(vres, vb, tmp, tmp2) \ FCMEQS(tmp2, vres, vres); \ - VBIC(tmp, tmp, tmp2); \ - VSHL_32(tmp, tmp, 31); \ - VORR(vres, vres, tmp) + VBIC(tmp2, tmp, tmp2); \ + VSHL_32(tmp2, tmp2, 31); \ + VORR(vres, vres, tmp2); \ + VSSHR_32(tmp2, vres, 31); \ + FCMEQS(tmp, vres, vres); \ + VMVNQ(tmp, tmp); \ + VANDQ(tmp, tmp, tmp2); \ + VSSHR_32(tmp2, vb, 31); \ + VMVNQ(tmp2, tmp2); \ + VANDQ(tmp, tmp, tmp2); \ + FCMEQS(tmp2, vb, vb); \ + VMVNQ(tmp2, tmp2); \ + VANDQ(tmp, tmp, tmp2); \ + VBIT(vres, vb, tmp) #endif #define STORE_REG(A) STRx_U12(x##A, xEmu, offsetof(x64emu_t, regs[_##A])) From a489cfe7d03f6d57aa38580c157711fbfc69ed7a Mon Sep 17 00:00:00 2001 From: mikolajserediuk Date: Fri, 9 Oct 2026 16:49:38 +0200 Subject: [PATCH 018/156] [WOWBOX64] Fix exceptions in JIT code above 4GB and pass the fault state to the guest (#4550) BTCpuResetToConsistentState truncated the host PC to 32 bits before the JIT lookup, so faults in JIT code above 4GB were not handled and Wine spun in RtlVirtualUnwind. Also sync the WOW64 context with the guest registers at the fault, since Wow64PassExceptionToGuest builds the guest context from it. Fixes #4549 --- wine/wow64/wowbox64.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/wine/wow64/wowbox64.c b/wine/wow64/wowbox64.c index 7ee9fe474..b1c36728b 100644 --- a/wine/wow64/wowbox64.c +++ b/wine/wow64/wowbox64.c @@ -16,6 +16,7 @@ #include "env.h" #include "emu/x64emu_private.h" #include "emu/x87emu_private.h" +#include "emu/x64run_private.h" #include "x64trace.h" #include "box64context.h" #include "box64cpu.h" @@ -307,13 +308,6 @@ NTSTATUS WINAPI BTCpuProcessInit(void) return STATUS_SUCCESS; } -static uint8_t box64_is_addr_in_jit(void* addr) -{ - if (!addr) - return FALSE; - return !!FindDynablockFromNativeAddress(addr); -} - NTSTATUS WINAPI BTCpuResetToConsistentState(EXCEPTION_POINTERS* ptrs) { printf_log(LOG_DEBUG, "BTCpuResetToConsistentState(%p)\n", ptrs); @@ -335,9 +329,34 @@ NTSTATUS WINAPI BTCpuResetToConsistentState(EXCEPTION_POINTERS* ptrs) } } - if (!box64_is_addr_in_jit(ULongToPtr(ctx->Pc))) + dynablock_t* db = FindDynablockFromNativeAddress((void*)ctx->Pc); + if (!db) return STATUS_SUCCESS; + { + WOW64_CPURESERVED* cpu = NtCurrentTeb()->TlsSlots[WOW64_TLS_CPURESERVED]; + WOW64_CONTEXT* wctx = (WOW64_CONTEXT*)(cpu + 1); + uintptr_t x64pc = getX64Address(db, ctx->Pc); + + for (int i = 0; i < 8; i++) // x10-x17 hold RAX-RDI + emu->regs[i].q[0] = (uint32_t)ctx->X[10 + i]; + emu->eflags.x64 = (uint32_t)ctx->X[26]; + CHECK_FLAGS(emu); + R_RIP = x64pc ? x64pc : (uint32_t)ctx->X[27]; + + wctx->Eax = R_EAX; + wctx->Ecx = R_ECX; + wctx->Edx = R_EDX; + wctx->Ebx = R_EBX; + wctx->Esp = R_ESP; + wctx->Ebp = R_EBP; + wctx->Esi = R_ESI; + wctx->Edi = R_EDI; + wctx->Eip = R_RIP; + wctx->EFlags = emu->eflags.x64; + box_to_fpu(wctx, emu); + } + /* Replace the host context with one captured before JIT entry so host code can unwind */ memcpy(ctx, NtCurrentTeb()->TlsSlots[WOW64_TLS_ENTRY_CONTEXT], sizeof(*ctx)); return STATUS_SUCCESS; From 72cbb140c870787da82f513a08ce82ddf9d1d6bb Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Sat, 10 Oct 2026 15:15:53 +0800 Subject: [PATCH 019/156] [RV64_DYNAREC] Use ADDSL to replace SLLI+ADD pattern (#4551) * [RV64_DYNAREC] Use ADDSL to replace shxadd pattern * [RV64_DYNAREC] Use ADDSL to replace SLLI+ADD pattern --- src/dynarec/rv64/dynarec_rv64_66f0.c | 9 +-- src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c | 24 +++---- src/dynarec/rv64/dynarec_rv64_d9.c | 7 +-- src/dynarec/rv64/dynarec_rv64_helper.c | 70 +++------------------ 4 files changed, 22 insertions(+), 88 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_66f0.c b/src/dynarec/rv64/dynarec_rv64_66f0.c index 0a913fa60..90fd7662d 100644 --- a/src/dynarec/rv64/dynarec_rv64_66f0.c +++ b/src/dynarec/rv64/dynarec_rv64_66f0.c @@ -113,9 +113,8 @@ uintptr_t dynarec64_66F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int u8 &= 0x0f; ADDI(x3, wback, u8 >> 3); ANDI(x4, x3, 3); - SLLI(x4, x4, 3); ADDI(x5, xZR, u8 & 7); - ADD(x5, x4, x5); + ADDSL(x5, x5, x4, 3, x4); ANDI(x3, x3, ~3); ADDI(x6, xZR, 1); SLL(x6, x6, x5); @@ -143,9 +142,8 @@ uintptr_t dynarec64_66F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int u8 &= 0x0f; ADDI(x3, wback, u8 >> 3); ANDI(x4, x3, 3); - SLLI(x4, x4, 3); ADDI(x5, xZR, u8 & 7); - ADD(x5, x4, x5); + ADDSL(x5, x5, x4, 3, x4); ANDI(x3, x3, ~3); ADDI(x6, xZR, 1); SLL(x6, x6, x5); @@ -174,9 +172,8 @@ uintptr_t dynarec64_66F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int u8 &= 0x0f; ADDI(x3, wback, u8 >> 3); ANDI(x4, x3, 3); - SLLI(x4, x4, 3); ADDI(x5, xZR, u8 & 7); - ADD(x5, x4, x5); + ADDSL(x5, x5, x4, 3, x4); ANDI(x3, x3, ~3); ADDI(x6, xZR, 1); SLL(x6, x6, x5); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c index 1adec115e..766daed6c 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c @@ -585,8 +585,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i for (int i = 0; i < 4; ++i) { LWU(x4, xEmu, offsetof(x64emu_t, scratch) + 16 + 4 * i); ANDI(x4, x4, 3); - SLLI(x4, x4, 2); - ADD(x4, x4, xEmu); + ADDSL(x4, xEmu, x4, 2, x4); LWU(x5, x4, offsetof(x64emu_t, scratch) + 0); SW(x5, gback, gdoffset + 4 * i); } @@ -604,8 +603,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i for (int i = 0; i < 4; ++i) { LWU(x4, xEmu, offsetof(x64emu_t, scratch) + 16 + 4 * i); ANDI(x4, x4, 3); - SLLI(x4, x4, 2); - ADD(x4, x4, xEmu); + ADDSL(x4, xEmu, x4, 2, x4); LWU(x5, x4, offsetof(x64emu_t, scratch) + 0); SW(x5, gback, gyoffset + 4 * i); } @@ -631,8 +629,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i LD(x4, xEmu, offsetof(x64emu_t, scratch) + 16 + 8 * i); SRLI(x4, x4, 1); ANDI(x4, x4, 1); - SLLI(x4, x4, 3); - ADD(x4, x4, xEmu); + ADDSL(x4, xEmu, x4, 3, x4); LD(x5, x4, offsetof(x64emu_t, scratch) + 0); SD(x5, gback, gdoffset + 8 * i); } @@ -651,8 +648,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i LD(x4, xEmu, offsetof(x64emu_t, scratch) + 16 + 8 * i); SRLI(x4, x4, 1); ANDI(x4, x4, 1); - SLLI(x4, x4, 3); - ADD(x4, x4, xEmu); + ADDSL(x4, xEmu, x4, 3, x4); LD(x5, x4, offsetof(x64emu_t, scratch) + 0); SD(x5, gback, gyoffset + 8 * i); } @@ -727,16 +723,14 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i for (int i = 0; i < 4; ++i) { LWU(x3, vback, vxoffset + 4 * i); ANDI(x3, x3, 7); - SLLI(x3, x3, 2); - ADD(x4, wback, x3); + ADDSL(x4, wback, x3, 2, x3); LWU(x5, x4, fixedaddress); SW(x5, gback, gdoffset + 4 * i); } for (int i = 0; i < 4; ++i) { LWU(x3, vback, vyoffset + 4 * i); ANDI(x3, x3, 7); - SLLI(x3, x3, 2); - ADD(x4, wback, x3); + ADDSL(x4, wback, x3, 2, x3); LWU(x5, x4, fixedaddress); SW(x5, gback, gyoffset + 4 * i); } @@ -1474,16 +1468,14 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i for (int i = 0; i < 4; ++i) { LWU(x3, vback, vxoffset + 4 * i); ANDI(x3, x3, 7); - SLLI(x3, x3, 2); - ADD(x4, wback, x3); + ADDSL(x4, wback, x3, 2, x3); LWU(x5, x4, fixedaddress); SW(x5, gback, gdoffset + 4 * i); } for (int i = 0; i < 4; ++i) { LWU(x3, vback, vyoffset + 4 * i); ANDI(x3, x3, 7); - SLLI(x3, x3, 2); - ADD(x4, wback, x3); + ADDSL(x4, wback, x3, 2, x3); LWU(x5, x4, fixedaddress); SW(x5, gback, gyoffset + 4 * i); } diff --git a/src/dynarec/rv64/dynarec_rv64_d9.c b/src/dynarec/rv64/dynarec_rv64_d9.c index 239219177..da6052bdb 100644 --- a/src/dynarec/rv64/dynarec_rv64_d9.c +++ b/src/dynarec/rv64/dynarec_rv64_d9.c @@ -142,12 +142,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni ANDI(x5, x5, 7); // (emu->top + i)&7 } // load x2 with ST0 anyway, for sign extraction - if (cpuext.zba) - SH3ADD(x1, x5, xEmu); - else { - SLLI(x5, x5, 3); - ADD(x1, xEmu, x5); - } + ADDSL(x1, xEmu, x5, 3, x5); LD(x2, x1, offsetof(x64emu_t, x87)); // load tag if (i2 >= 0) { diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 22eff68d7..6c4a65fa3 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -942,12 +942,7 @@ void x87_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1, int s2, in #endif ADDI(s3, s2, dyn->e.x87cache[i]); // unadjusted count, as it's relative to real top ANDI(s3, s3, 7); // (emu->top + st)&7 - if (cpuext.zba) - SH3ADD(s1, s3, xEmu); - else { - SLLI(s1, s3, 3); - ADD(s1, xEmu, s1); - } + ADDSL(s1, xEmu, s3, 3, s1); switch (extcache_get_current_st(dyn, ninst, st)) { case EXT_CACHE_ST_D: FSD(dyn->e.x87reg[i], s1, offsetof(x64emu_t, x87)); // save the value @@ -1054,12 +1049,7 @@ static void x87_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int if (dyn->e.x87cache[i] != -1) { ADDI(s3, s2, dyn->e.x87cache[i]); ANDI(s3, s3, 7); // (emu->top + i)&7 - if (cpuext.zba) - SH3ADD(s1, s3, xEmu); - else { - SLLI(s1, s3, 3); - ADD(s1, xEmu, s1); - } + ADDSL(s1, xEmu, s3, 3, s1); if (extcache_get_current_st_f(dyn, dyn->e.x87cache[i]) >= 0) { FCVTDS(SCRATCH0, dyn->e.x87reg[i]); FSD(SCRATCH0, s1, offsetof(x64emu_t, x87)); @@ -1136,12 +1126,7 @@ int x87_get_cache(dynarec_rv64_t* dyn, int ninst, int populate, int s1, int s2, ADDI(s2, s2, a); ANDI(s2, s2, 7); } - if (cpuext.zba) - SH3ADD(s1, s2, xEmu); - else { - SLLI(s2, s2, 3); - ADD(s1, xEmu, s2); - } + ADDSL(s1, xEmu, s2, 3, s2); FLD(dyn->e.x87reg[ret], s1, offsetof(x64emu_t, x87)); } MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st); @@ -1188,12 +1173,7 @@ void x87_refresh(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int st) ADDI(s2, s2, a); ANDI(s2, s2, 7); // (emu->top + i)&7 } - if (cpuext.zba) - SH3ADD(s1, s2, xEmu); - else { - SLLI(s2, s2, 3); - ADD(s1, xEmu, s2); - } + ADDSL(s1, xEmu, s2, 3, s2); if (dyn->e.extcache[EXTIDX(reg)].t == EXT_CACHE_ST_F) { FCVTDS(SCRATCH0, reg); FSD(SCRATCH0, s1, offsetof(x64emu_t, x87)); @@ -1231,12 +1211,7 @@ void x87_forget(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int st) ADDI(s2, s2, a); ANDI(s2, s2, 7); // (emu->top + i)&7 } - if (cpuext.zba) - SH3ADD(s1, s2, xEmu); - else { - SLLI(s2, s2, 3); - ADD(s1, xEmu, s2); - } + ADDSL(s1, xEmu, s2, 3, s2); if (dyn->e.extcache[EXTIDX(reg)].t == EXT_CACHE_ST_F) { FCVTDS(SCRATCH0, reg); FSD(SCRATCH0, s1, offsetof(x64emu_t, x87)); @@ -1275,12 +1250,7 @@ void x87_reget_st(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int st) ADDI(s2, s2, a); AND(s2, s2, 7); } - if (cpuext.zba) - SH3ADD(s1, s2, xEmu); - else { - SLLI(s2, s2, 3); - ADD(s1, xEmu, s2); - } + ADDSL(s1, xEmu, s2, 3, s2); FLD(dyn->e.x87reg[i], s1, offsetof(x64emu_t, x87)); MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st); // ok @@ -1300,12 +1270,7 @@ void x87_reget_st(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int st) int a = st - dyn->e.x87stack; ADDI(s2, s2, a); ANDI(s2, s2, 7); // (emu->top + i)&7 - if (cpuext.zba) - SH3ADD(s1, s2, xEmu); - else { - SLLI(s2, s2, 3); - ADD(s1, xEmu, s2); - } + ADDSL(s1, xEmu, s2, 3, s2); FLD(dyn->e.x87reg[ret], s1, offsetof(x64emu_t, x87)); MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st); } @@ -1335,12 +1300,7 @@ void x87_free(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int st) } ANDI(s2, s2, 7); // (emu->top + i)&7 } - if (cpuext.zba) - SH3ADD(s1, s2, xEmu); - else { - SLLI(s2, s2, 3); - ADD(s1, xEmu, s2); - } + ADDSL(s1, xEmu, s2, 3, s2); if (dyn->e.extcache[EXTIDX(reg)].t == EXT_CACHE_ST_F) { FCVTDS(SCRATCH0, reg); FSD(SCRATCH0, s1, offsetof(x64emu_t, x87)); @@ -2356,12 +2316,7 @@ static void loadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, int } *s3_top += a; *s2_val = 0; - if (cpuext.zba) - SH3ADD(s2, s3, xEmu); - else { - SLLI(s2, s3, 3); - ADD(s2, xEmu, s2); - } + ADDSL(s2, xEmu, s3, 3, s2); FLD(reg, s2, offsetof(x64emu_t, x87)); if (t == EXT_CACHE_ST_F) { FCVTSD(reg, reg); @@ -2433,12 +2388,7 @@ static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, i ANDI(s3, s3, 7); } *s3_top += a; - if (cpuext.zba) - SH3ADD(s2, s3, xEmu); - else { - SLLI(s2, s3, 3); - ADD(s2, xEmu, s2); - } + ADDSL(s2, xEmu, s3, 3, s2); *s2_val = 0; if (t == EXT_CACHE_ST_F) { FCVTDS(reg, reg); From 84972663c51a303fea6f7666bea78a20b4ecb662 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sat, 10 Oct 2026 15:51:55 +0800 Subject: [PATCH 020/156] [RV64_DYNAREC] Fixed x87 FST/FSTP float NaN handling (#4553) --- src/dynarec/rv64/dynarec_rv64_d9.c | 14 ++------------ src/dynarec/rv64/dynarec_rv64_helper.h | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_d9.c b/src/dynarec/rv64/dynarec_rv64_d9.c index da6052bdb..b4f497455 100644 --- a/src/dynarec/rv64/dynarec_rv64_d9.c +++ b/src/dynarec/rv64/dynarec_rv64_d9.c @@ -516,12 +516,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni if (!BOX64ENV(dynarec_fastnan)) { FEQS(x5, s0, s0); BNEZ_MARK(x5); - FMVXD(x5, v1); - SRLI(x5, x5, 63); - BNEZ_MARK2(x5); - B_MARK_nocond; - MARK2; - FNEGS(s0, s0); + X87_DOUBLE_TO_FLOAT(s0, v1, x5, x6); MARK; } } @@ -543,12 +538,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni if (!BOX64ENV(dynarec_fastnan)) { FEQS(x5, v1, v1); BNEZ_MARK(x5); - FMVXD(x5, s1); - SRLI(x5, x5, 63); - BNEZ_MARK2(x5); - B_MARK_nocond; - MARK2; - FNEGS(v1, v1); + X87_DOUBLE_TO_FLOAT(v1, s1, x5, x6); MARK; } } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 23d93c1de..253301864 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1016,6 +1016,20 @@ MARKSEG #endif +#ifndef X87_DOUBLE_TO_FLOAT +#define X87_DOUBLE_TO_FLOAT(d, sd, xs, xt) \ + FMVXD(xs, sd); \ + SRLI(xt, xs, 63); \ + SLLI(xt, xt, 31); \ + SRLI(xs, xs, 29); \ + SLLI(xs, xs, 41); \ + SRLI(xs, xs, 41); \ + OR(xs, xs, xt); \ + LUI(xt, 0x7fc00); \ + OR(xs, xs, xt); \ + FMVWX(d, xs) +#endif + #define STORE_REG(A) SD(x##A, xEmu, offsetof(x64emu_t, regs[_##A])) #define LOAD_REG(A) LD(x##A, xEmu, offsetof(x64emu_t, regs[_##A])) From f9bc4a4170797197e6d9314a2f97f78744e61e1f Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sat, 10 Oct 2026 16:12:53 +0800 Subject: [PATCH 021/156] [RV64_DYNAREC] Ported up32 and rsp merge optimization (#4554) --- src/dynarec/dynarec_native.c | 2 +- src/dynarec/dynarec_native_pass.c | 4 +- src/dynarec/rv64/dynarec_rv64_00_0.c | 36 ++-- src/dynarec/rv64/dynarec_rv64_00_1.c | 110 ++++++++--- src/dynarec/rv64/dynarec_rv64_00_2.c | 76 ++++++-- src/dynarec/rv64/dynarec_rv64_00_3.c | 110 +++++++---- src/dynarec/rv64/dynarec_rv64_0f.c | 83 +++++---- src/dynarec/rv64/dynarec_rv64_0f_vector.c | 6 +- src/dynarec/rv64/dynarec_rv64_66.c | 14 ++ src/dynarec/rv64/dynarec_rv64_660f.c | 7 +- src/dynarec/rv64/dynarec_rv64_660f38.c | 8 + src/dynarec/rv64/dynarec_rv64_660f_vector.c | 7 +- src/dynarec/rv64/dynarec_rv64_arch.c | 21 ++- src/dynarec/rv64/dynarec_rv64_avx_0f.c | 2 +- src/dynarec/rv64/dynarec_rv64_avx_0f38.c | 12 +- src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c | 2 +- src/dynarec/rv64/dynarec_rv64_avx_66_0f.c | 5 +- src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c | 2 +- src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c | 4 + .../rv64/dynarec_rv64_avx_66_0f_vector.c | 6 +- src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c | 4 +- src/dynarec/rv64/dynarec_rv64_avx_f2_0f38.c | 6 +- .../rv64/dynarec_rv64_avx_f2_0f_vector.c | 2 +- src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c | 2 +- src/dynarec/rv64/dynarec_rv64_avx_f3_0f38.c | 4 +- .../rv64/dynarec_rv64_avx_f3_0f_vector.c | 2 +- src/dynarec/rv64/dynarec_rv64_emit_logic.c | 36 ++-- src/dynarec/rv64/dynarec_rv64_emit_math.c | 51 +++-- src/dynarec/rv64/dynarec_rv64_emit_shift.c | 65 ++++--- src/dynarec/rv64/dynarec_rv64_emit_tests.c | 4 +- src/dynarec/rv64/dynarec_rv64_f0.c | 9 +- src/dynarec/rv64/dynarec_rv64_f20f.c | 14 +- src/dynarec/rv64/dynarec_rv64_f20f_vector.c | 4 +- src/dynarec/rv64/dynarec_rv64_f30f.c | 24 +-- src/dynarec/rv64/dynarec_rv64_f30f_vector.c | 4 +- src/dynarec/rv64/dynarec_rv64_functions.c | 176 ++++++++++++++++++ src/dynarec/rv64/dynarec_rv64_functions.h | 3 + src/dynarec/rv64/dynarec_rv64_helper.c | 13 +- src/dynarec/rv64/dynarec_rv64_helper.h | 141 +++++++++++++- src/dynarec/rv64/dynarec_rv64_pass0.h | 1 + src/dynarec/rv64/dynarec_rv64_private.h | 15 ++ src/dynarec/rv64/rv64_emitter.h | 143 ++++++++++---- src/dynarec/rv64/rv64_mapping.h | 2 + 43 files changed, 944 insertions(+), 298 deletions(-) diff --git a/src/dynarec/dynarec_native.c b/src/dynarec/dynarec_native.c index f78489cb1..3c80f848e 100644 --- a/src/dynarec/dynarec_native.c +++ b/src/dynarec/dynarec_native.c @@ -1155,7 +1155,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, int pos = helper.size-1; while (pos>=0) pos = updateNeed(&helper, pos, 0); - #if defined(LA64) + #if defined(LA64) || defined(RV64) updateUpperLiveness(&helper); updateRspMerge(&helper, is32bits); #endif diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index 7e08b081d..2c159beec 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -250,7 +250,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int MESSAGE(LOG_DUMP, "TEST STEP ----\n"); extcache_native_t save; fpu_save_and_unwind(dyn, ninst, &save); - #ifdef LA64 + #if defined(LA64) || defined(RV64) UP32_READALL(); #endif fpu_reflectcache(dyn, ninst, x1, x2, x3); @@ -267,7 +267,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int #if defined (SPILL_NF_REGISTERS) if (BOX64ENV(dynarec_nativeflags)) SPILL_NF_REGISTERS; #endif - #ifdef LA64 + #if defined(LA64) || defined(RV64) UP32_READALL(); #endif fpu_reflectcache(dyn, ninst, x1, x2, x3); diff --git a/src/dynarec/rv64/dynarec_rv64_00_0.c b/src/dynarec/rv64/dynarec_rv64_00_0.c index 2aabe08f2..116e83ae0 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_0.c +++ b/src/dynarec/rv64/dynarec_rv64_00_0.c @@ -65,7 +65,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; GETGD; - GETED(0); + GETEDsd(0); emit_add32(dyn, ninst, rex, ed, gd, x3, x4, x5); WBACK; break; @@ -83,7 +83,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("ADD Gd, Ed"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); emit_add32(dyn, ninst, rex, gd, ed, x3, x4, x5); break; @@ -99,6 +99,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x05: INST_NAME("ADD EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + MARKREGsd(xRAX); i64 = F32S; emit_add32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5, x6); break; @@ -155,7 +156,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; GETGD; - GETED(0); + GETEDsd(0); emit_or32(dyn, ninst, rex, ed, gd, x3, x4); WBACK; break; @@ -173,7 +174,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("OR Gd, Ed"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); emit_or32(dyn, ninst, rex, gd, ed, x3, x4); break; @@ -189,6 +190,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x0D: INST_NAME("OR EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + MARKREGsd(xRAX); i64 = F32S; emit_or32c(dyn, ninst, rex, xRAX, i64, x3, x4); break; @@ -255,7 +257,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; GETGD; - GETED(0); + GETEDsd(0); emit_adc32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6); WBACK; break; @@ -280,7 +282,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int READFLAGS(X_CF); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); emit_adc32(dyn, ninst, rex, gd, ed, x3, x4, x5, x6); break; @@ -298,6 +300,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("ADC EAX, Id"); READFLAGS(X_CF); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + MARKREGsd(xRAX); i64 = F32S; MOV64xw(x1, i64); emit_adc32(dyn, ninst, rex, xRAX, x1, x3, x4, x5, x6); @@ -364,7 +367,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; GETGD; - GETED(0); + GETEDsd(0); emit_sbb32(dyn, ninst, rex, ed, gd, x3, x4, x5); WBACK; break; @@ -389,7 +392,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int READFLAGS(X_CF); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); emit_sbb32(dyn, ninst, rex, gd, ed, x3, x4, x5); break; @@ -407,6 +410,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("SBB EAX, Id"); READFLAGS(X_CF); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + MARKREGsd(xRAX); i64 = F32S; MOV64xw(x2, i64); emit_sbb32(dyn, ninst, rex, xRAX, x2, x3, x4, x5); @@ -465,7 +469,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; GETGD; - GETED(0); + GETEDsd(0); emit_and32(dyn, ninst, rex, ed, gd, x3, x4); WBACK; break; @@ -482,7 +486,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("AND Gd, Ed"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); emit_and32(dyn, ninst, rex, gd, ed, x3, x4); break; @@ -498,6 +502,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x25: INST_NAME("AND EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + MARKREGsd(xRAX); i64 = F32S; emit_and32c(dyn, ninst, rex, xRAX, i64, x3, x4); break; @@ -516,7 +521,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; GETGD; - GETED(0); + GETEDsd(0); emit_sub32(dyn, ninst, rex, ed, gd, x3, x4, x5); WBACK; break; @@ -534,7 +539,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("SUB Gd, Ed"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); emit_sub32(dyn, ninst, rex, gd, ed, x3, x4, x5); break; @@ -550,6 +555,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x2D: INST_NAME("SUB EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + MARKREGsd(xRAX); i64 = F32S; emit_sub32c(dyn, ninst, rex, xRAX, i64, x2, x3, x4, x5); break; @@ -571,7 +577,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; GETGD; - GETED(0); + GETEDsd(0); emit_xor32(dyn, ninst, rex, ed, gd, x3, x4); if (ed != gd) { WBACK; @@ -591,7 +597,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("XOR Gd, Ed"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); emit_xor32(dyn, ninst, rex, gd, ed, x3, x4); break; @@ -607,6 +613,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x35: INST_NAME("XOR EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + MARKREGsd(xRAX); i64 = F32S; emit_xor32c(dyn, ninst, rex, xRAX, i64, x3, x4); break; @@ -661,6 +668,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("CMP EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); i64 = F32S; + MARKREGs(xRAX); if (i64) { MOV64x(x2, i64); emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5, x6); diff --git a/src/dynarec/rv64/dynarec_rv64_00_1.c b/src/dynarec/rv64/dynarec_rv64_00_1.c index ec23eeba1..06fe32736 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_1.c +++ b/src/dynarec/rv64/dynarec_rv64_00_1.c @@ -63,6 +63,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("INC Reg (32bits)"); SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING, NAT_FLAGS_FUSION); gd = TO_NAT(opcode & 7); + MARKREGsd(gd); emit_inc32(dyn, ninst, rex, gd, x1, x2, x3, x4); break; case 0x48: @@ -76,6 +77,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("DEC Reg (32bits)"); SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING, NAT_FLAGS_FUSION); gd = TO_NAT(opcode & 7); + MARKREGsd(gd); emit_dec32(dyn, ninst, rex, gd, x1, x2, x3, x4); break; case 0x50: @@ -89,7 +91,9 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("PUSH reg"); SCRATCH_USAGE(0); gd = TO_NAT((opcode & 0x07) + (rex.b << 3)); - PUSH1z(gd); + MARKREGsz(gd); + if (!rex.is32bits) UP32_READ(xRSP); + PUSH1mz(gd); break; case 0x58: case 0x59: @@ -102,21 +106,39 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("POP reg"); SCRATCH_USAGE(0); gd = TO_NAT((opcode & 0x07) + (rex.b << 3)); - POP1z(gd); + if (!rex.is32bits) UP32_READ(xRSP); + MARKREGdz(gd); + POP1mz(gd); break; case 0x60: if (rex.is32bits) { INST_NAME("PUSHAD"); + dyn->insts[ninst].rsp_class = RSP_CLASS_PUSH; + dyn->insts[ninst].rsp_span = 32; ZEXTW2(x1, xRSP); - PUSH1_32(xRAX); - PUSH1_32(xRCX); - PUSH1_32(xRDX); - PUSH1_32(xRBX); - PUSH1_32(x1); - PUSH1_32(xRBP); - PUSH1_32(xRSI); - PUSH1_32(xRDI); + if (dyn->insts[ninst].rsp_merge && !(cpuext.xtheadmemidx && dyn->insts[ninst].rsp_flush && !dyn->insts[ninst].rsp_entry)) { + int entry = dyn->insts[ninst].rsp_entry; + SW(xRAX, xRSP, entry - 4); + SW(xRCX, xRSP, entry - 8); + SW(xRDX, xRSP, entry - 12); + SW(xRBX, xRSP, entry - 16); + SW(x1, xRSP, entry - 20); + SW(xRBP, xRSP, entry - 24); + SW(xRSI, xRSP, entry - 28); + SW(xRDI, xRSP, entry - 32); + if (dyn->insts[ninst].rsp_flush) + ADDI(xRSP, xRSP, dyn->insts[ninst].rsp_flush); + } else { + PUSH1_32(xRAX); + PUSH1_32(xRCX); + PUSH1_32(xRDX); + PUSH1_32(xRBX); + PUSH1_32(x1); + PUSH1_32(xRBP); + PUSH1_32(xRSI); + PUSH1_32(xRDI); + } SMWRITE(); } else { INST_NAME("Illegal 60"); @@ -135,15 +157,45 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x61: if (rex.is32bits) { INST_NAME("POPAD"); + dyn->insts[ninst].rsp_class = RSP_CLASS_POP; + dyn->insts[ninst].rsp_span = 32; SMREAD(); - POP1_32(xRDI); - POP1_32(xRSI); - POP1_32(xRBP); - POP1_32(x1); - POP1_32(xRBX); - POP1_32(xRDX); - POP1_32(xRCX); - POP1_32(xRAX); + if (dyn->insts[ninst].rsp_merge && !(cpuext.xtheadmemidx && dyn->insts[ninst].rsp_flush && !dyn->insts[ninst].rsp_entry)) { + int entry = dyn->insts[ninst].rsp_entry; + LWU(xRDI, xRSP, entry + 0); + LWU(xRSI, xRSP, entry + 4); + LWU(xRBP, xRSP, entry + 8); + LWU(x1, xRSP, entry + 12); + LWU(xRBX, xRSP, entry + 16); + LWU(xRDX, xRSP, entry + 20); + LWU(xRCX, xRSP, entry + 24); + LWU(xRAX, xRSP, entry + 28); + if (dyn->insts[ninst].rsp_flush) + ADDI(xRSP, xRSP, dyn->insts[ninst].rsp_flush); + } else { + POP1_32(xRDI); + POP1_32(xRSI); + POP1_32(xRBP); + POP1_32(x1); + POP1_32(xRBX); + POP1_32(xRDX); + POP1_32(xRCX); + POP1_32(xRAX); + } + UP32_WRITE32(xRDI); + UP32_ZERO(xRDI); + UP32_WRITE32(xRSI); + UP32_ZERO(xRSI); + UP32_WRITE32(xRBP); + UP32_ZERO(xRBP); + UP32_WRITE32(xRBX); + UP32_ZERO(xRBX); + UP32_WRITE32(xRDX); + UP32_ZERO(xRDX); + UP32_WRITE32(xRCX); + UP32_ZERO(xRCX); + UP32_WRITE32(xRAX); + UP32_ZERO(xRAX); } else { INST_NAME("Illegal 61"); if (BOX64DRENV(dynarec_safeflags) > 1) { @@ -199,7 +251,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } else { INST_NAME("MOVSXD Gd, Ed"); nextop = F8; - GETGD; + GETGDd; SCRATCH_USAGE(0); if (rex.w) { if (MODREG) { // reg <= reg @@ -222,18 +274,19 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x68: INST_NAME("PUSH Id"); + if (!rex.is32bits) UP32_READ(xRSP); i64 = F32S; if (PK(0) == 0xC3) { MESSAGE(LOG_DUMP, "PUSH then RET, using indirect\n"); TABLE64(x3, addr - 4); LW(x1, x3, 0); - PUSH1z(x1); + PUSH1mz(x1); } else { if (!i64) { - PUSH1z(xZR); + PUSH1mz(xZR); } else { MOV64z(x3, i64); - PUSH1z(x3); + PUSH1mz(x3); } } break; @@ -241,7 +294,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("IMUL Gd, Ed, Id"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); nextop = F8; - GETGD; + GETGDd; GETED(4); i64 = F32S; MOV64x(x4, i64); @@ -284,7 +337,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ZEXTW2(gd, x5); } else { MULxw(gd, ed, x4); - ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); } } IFX (X_SF) { @@ -296,19 +349,20 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x6A: INST_NAME("PUSH Ib"); + if (!rex.is32bits) UP32_READ(xRSP); i64 = F8S; if (!i64) { - PUSH1z(xZR); + PUSH1mz(xZR); } else { MOV64z(x3, i64); - PUSH1z(x3); + PUSH1mz(x3); } break; case 0x6B: INST_NAME("IMUL Gd, Ed, Ib"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); nextop = F8; - GETGD; + GETGDd; GETED(1); i64 = F8S; MOV64x(x4, i64); @@ -351,7 +405,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ZEXTW2(gd, x5); } else { MULW(gd, ed, x4); - ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); } } IFX (X_SF) { diff --git a/src/dynarec/rv64/dynarec_rv64_00_2.c b/src/dynarec/rv64/dynarec_rv64_00_2.c index 464d858f8..e11d57a1d 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_2.c +++ b/src/dynarec/rv64/dynarec_rv64_00_2.c @@ -137,7 +137,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("ADD Ed, Ib"); } SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED((opcode == 0x81) ? 4 : 1); + GETEDsd((opcode == 0x81) ? 4 : 1); if (opcode == 0x81) i64 = F32S; else @@ -152,7 +152,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("OR Ed, Ib"); } SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED((opcode == 0x81) ? 4 : 1); + GETEDsd((opcode == 0x81) ? 4 : 1); if (opcode == 0x81) i64 = F32S; else @@ -168,7 +168,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } READFLAGS(X_CF); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED((opcode == 0x81) ? 4 : 1); + GETEDsd((opcode == 0x81) ? 4 : 1); if (opcode == 0x81) i64 = F32S; else @@ -185,7 +185,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } READFLAGS(X_CF); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED((opcode == 0x81) ? 4 : 1); + GETEDsd((opcode == 0x81) ? 4 : 1); if (opcode == 0x81) i64 = F32S; else @@ -201,7 +201,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("AND Ed, Ib"); } SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED((opcode == 0x81) ? 4 : 1); + GETEDsd((opcode == 0x81) ? 4 : 1); if (opcode == 0x81) i64 = F32S; else @@ -216,7 +216,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("SUB Ed, Ib"); } SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED((opcode == 0x81) ? 4 : 1); + GETEDsd((opcode == 0x81) ? 4 : 1); if (opcode == 0x81) i64 = F32S; else @@ -231,7 +231,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("XOR Ed, Ib"); } SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED((opcode == 0x81) ? 4 : 1); + GETEDsd((opcode == 0x81) ? 4 : 1); if (opcode == 0x81) i64 = F32S; else @@ -327,7 +327,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("(LOCK) XCHG Ed, Gd"); nextop = F8; if (MODREG) { - GETGD; + GETGDsd; GETED(0); MVxw(x3, gd); MVxw(gd, ed); @@ -400,7 +400,9 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETGD; if (MODREG) { // reg <= reg SCRATCH_USAGE(0); - MVxw(TO_NAT((nextop & 7) + (rex.b << 3)), gd); + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGd(ed); + MVxw(ed, gd); } else { // mem <= reg IF_UNALIGNED(ip) { addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, (1 << (2 + rex.w)) - 1, 0); @@ -467,7 +469,8 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x8B: INST_NAME("MOV Gd, Ed"); nextop = F8; - GETGD; + GETGDd; + if (!rex.w) UP32_ZERO(gd); SCRATCH_USAGE(0); if (MODREG) { MVxw(gd, TO_NAT((nextop & 7) + (rex.b << 3))); @@ -496,7 +499,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x8D: INST_NAME("LEA Gd, Ed"); nextop = F8; - GETGD; + GETGDd; if (MODREG) { // reg <= reg? that's an invalid operation DEFAULT; } else { // mem <= reg @@ -536,8 +539,11 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x8F: INST_NAME("POP Ed"); nextop = F8; + MARKREGsdz(xRSP); if (MODREG) { - POP1z(TO_NAT((nextop & 7) + (rex.b << 3))); + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGdz(ed); + POP1z(ed); } else { POP1z(x2); // so this can handle POP [ESP] and maybe some variant too addr = geted(dyn, addr, ninst, nextop, &ed, x3, x1, &fixedaddress, rex, NULL, 1, 0); @@ -564,6 +570,8 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("NOP"); } else { INST_NAME("XCHG EAX, Reg"); + MARKREGsd(gd); + MARKREGsd(xRAX); MVxw(x2, xRAX); MVxw(xRAX, gd); MVxw(gd, x2); @@ -572,20 +580,24 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x98: INST_NAME("CWDE"); if (rex.w) { + MARKREGd(xRAX); SEXT_W(xRAX, xRAX); } else { + MARKREGd(xRAX); SEXTH(xRAX, xRAX); - ZEROUP(xRAX); + if (NEED_ZEROUP(xRAX)) ZEROUP_RESULT(xRAX); } break; case 0x99: INST_NAME("CDQ"); + MARKREGd(xRDX); + MARKREGs(xRAX); if (rex.w) { SRAI(xRDX, xRAX, 63); } else { SLLI(xRDX, xRAX, 32); SRAI(xRDX, xRDX, 63); - ZEROUP(xRDX); + if (NEED_ZEROUP(xRDX)) ZEROUP_RESULT(xRDX); } break; case 0x9B: @@ -594,12 +606,14 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x9C: INST_NAME("PUSHF"); READFLAGS(X_ALL); + if (!rex.is32bits) UP32_READ(xRSP); FLAGS_ADJUST_TO11(x3, xFlags, x2); PUSH1z(x3); break; case 0x9D: INST_NAME("POPF"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); + if (!rex.is32bits) UP32_READ(xRSP); POP1z(xFlags); FLAGS_ADJUST_FROM11(xFlags, xFlags, x2); MOV32w(x1, 0x3E7FF7); @@ -657,6 +671,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xA1: INST_NAME("MOV EAX, Od"); + MARKREGd(xRAX); if (rex.is32bits && rex.is67) u64 = F16S; else if (rex.is32bits || rex.is67) @@ -691,6 +706,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xA3: INST_NAME("MOV Od, EAX"); + MARKREGs(xRAX); if (rex.is32bits && rex.is67) u64 = F16S; else if (rex.is32bits || rex.is67) @@ -707,8 +723,11 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITELOCK(lock); break; case 0xA4: + UP32_READ(xRSI); + UP32_READ(xRDI); if (rex.rep) { INST_NAME("REP MOVSB"); + UP32_READ(xRCX); CBZ_NEXT(xRCX); if (rex.is67 && !rex.is32bits) { ZEROUP(xRSI); @@ -766,8 +785,11 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITE(); break; case 0xA5: + UP32_READ(xRSI); + UP32_READ(xRDI); if (rex.rep) { INST_NAME("REP MOVSD"); + UP32_READ(xRCX); CBZ_NEXT(xRCX); if (rex.is67 && !rex.is32bits) { ZEROUP(xRSI); @@ -807,9 +829,12 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITE(); break; case 0xA6: + UP32_READ(xRSI); + UP32_READ(xRDI); switch (rex.rep) { case 1: case 2: + UP32_READ(xRCX); if (rex.rep == 1) { INST_NAME("REPNZ CMPSB"); } else { @@ -872,9 +897,12 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0xA7: + UP32_READ(xRSI); + UP32_READ(xRDI); switch (rex.rep) { case 1: case 2: + UP32_READ(xRCX); if (rex.rep == 1) { INST_NAME("REPNZ CMPSD"); } else { @@ -947,12 +975,16 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("TEST EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); i64 = F32S; + MARKREGs(xRAX); MOV64xw(x2, i64); emit_test32(dyn, ninst, rex, xRAX, x2, x3, x4, x5); break; case 0xAA: + UP32_READ(xRDI); + UP32_READ(xRAX); if (rex.rep) { INST_NAME("REP STOSB"); + UP32_READ(xRCX); CBZ_NEXT(xRCX); if (rex.is67 && !rex.is32bits) { ZEROUP(xRDI); @@ -1001,8 +1033,11 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITE(); break; case 0xAB: + UP32_READ(xRDI); + UP32_READ(xRAX); if (rex.rep) { INST_NAME("REP STOSD"); + UP32_READ(xRCX); CBZ_NEXT(xRCX); if (rex.is67 && !rex.is32bits) { ZEROUP(xRDI); @@ -1033,6 +1068,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITE(); break; case 0xAC: + UP32_READ(xRSI); if (rex.rep) { DEFAULT; } else { @@ -1048,6 +1084,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0xAD: + UP32_READ(xRSI); if (rex.rep) { DEFAULT; } else { @@ -1061,9 +1098,12 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0xAE: + UP32_READ(xRDI); + UP32_READ(xRAX); switch (rex.rep) { case 1: case 2: + UP32_READ(xRCX); if (rex.rep == 1) { INST_NAME("REPNZ SCASB"); } else { @@ -1120,9 +1160,12 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0xAF: + UP32_READ(xRDI); + UP32_READ(xRAX); switch (rex.rep) { case 1: case 2: + UP32_READ(xRCX); if (rex.rep == 1) { INST_NAME("REPNZ SCASD"); } else { @@ -1225,12 +1268,17 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("MOV Reg, Id"); gd = TO_NAT((opcode & 7) + (rex.b << 3)); SCRATCH_USAGE(0); + MARKREGd(gd); if (rex.w) { u64 = F64; MOV64x(gd, u64); } else { u32 = F32; MOV32w(gd, u32); + if ((int32_t)u32 >= 0) + UP32_ZERO(gd); + else if (NEED_ZEROUP(gd)) + ZEROUP_RESULT(gd); } break; default: diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 8c8f76de8..2d387731d 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -181,14 +181,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int // flags are not affected if count is 0, we make it a nop if possible. if (u8) { SETFLAGS((!BOX64ENV(cputype) && (u8 > 1) && MODREG) ? X_CF : (X_OF | X_CF), SF_SUBSET, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); F8; emit_rol32c(dyn, ninst, rex, ed, u8, x3, x4); WBACK; } else { if (MODREG && !rex.w) { GETED(1); - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } else { FAKEED; } @@ -201,14 +201,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int // flags are not affected if count is 0, we make it a nop if possible. if (u8) { SETFLAGS((!BOX64ENV(cputype) && (u8 > 1) && MODREG) ? X_CF : (X_OF | X_CF), SF_SUBSET, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); F8; emit_ror32c(dyn, ninst, rex, ed, u8, x3, x4); WBACK; } else { if (MODREG && !rex.w) { GETED(1); - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } else { FAKEED; } @@ -221,7 +221,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (u8) { READFLAGS(X_CF); SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); u8 = (F8) & (rex.w ? 0x3f : 0x1f); emit_rcl32c(dyn, ninst, rex, ed, u8, x3, x4, x5); WBACK; @@ -238,7 +238,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (u8) { READFLAGS(X_CF); SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); u8 = (F8) & (rex.w ? 0x3f : 0x1f); emit_rcr32c(dyn, ninst, rex, ed, u8, x3, x4, x5); WBACK; @@ -256,14 +256,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int // flags are not affected if count is 0, we make it a nop if possible. if (u8) { SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); F8; emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4, x5); WBACK; } else { if (MODREG && !rex.w) { GETED(1); - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } else { FAKEED; } @@ -276,14 +276,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int // flags are not affected if count is 0, we make it a nop if possible. if (u8) { SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); F8; emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4); WBACK; } else { if (MODREG && !rex.w) { GETED(1); - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } else { FAKEED; } @@ -296,14 +296,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int // flags are not affected if count is 0, we make it a nop if possible. if (u8) { SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); F8; emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4); WBACK; } else { if (MODREG && !rex.w) { GETED(1); - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } else { FAKEED; } @@ -322,6 +322,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } BARRIER(BARRIER_FLOAT); u16 = F16; + if (!rex.is32bits) UP32_READ(xRSP); POP1z(xRIP); if (u16 < 0x7ff) ADDIz(xRSP, xRSP, u16); @@ -340,6 +341,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int READFLAGS(X_PEND); // so instead, force the deferred flags, so it's not too slow, and flags are not lost } BARRIER(BARRIER_FLOAT); + if (!rex.is32bits) UP32_READ(xRSP); POP1z(xRIP); ret_to_next(dyn, ip, ninst, rex); *need_epilog = 0; @@ -474,6 +476,10 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xC8: INST_NAME("ENTER Iw, Ib"); + if (!rex.is32bits) { + UP32_READ(xRSP); + UP32_READ(xRBP); + } u16 = F16; u8 = (F8) & 0x1f; if (u8) { @@ -498,6 +504,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xC9: INST_NAME("LEAVE"); + MARKREGsz(xRBP); MVz(xRSP, xRBP); POP1z(xRBP); break; @@ -506,6 +513,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int u16 = F16; READFLAGS(X_PEND); BARRIER(BARRIER_FLOAT); + if (!rex.is32bits) UP32_READ(xRSP); if (rex.w) { POP1(xRIP); POP1(x3); @@ -528,6 +536,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("FAR RET"); READFLAGS(X_PEND); BARRIER(BARRIER_FLOAT); + if (!rex.is32bits) UP32_READ(xRSP); if (rex.w) { POP1(xRIP); POP1(x3); @@ -839,7 +848,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0: INST_NAME("ROL Ed, 1"); SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); - GETED(0); + GETEDsd(0); emit_rol32c(dyn, ninst, rex, ed, 1, x3, x4); WBACK; if (!wback && !rex.w) ZEROUP(ed); @@ -847,7 +856,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 1: INST_NAME("ROR Ed, 1"); SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); - GETED(0); + GETEDsd(0); emit_ror32c(dyn, ninst, rex, ed, 1, x3, x4); WBACK; if (!wback && !rex.w) ZEROUP(ed); @@ -856,7 +865,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("RCL Ed, 1"); READFLAGS(X_CF); SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); - GETED(0); + GETEDsd(0); emit_rcl32c(dyn, ninst, rex, ed, 1, x3, x4, x5); WBACK; if (!wback && !rex.w) ZEROUP(ed); @@ -865,7 +874,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("RCR Ed, 1"); READFLAGS(X_CF); SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); - GETED(0); + GETEDsd(0); emit_rcr32c(dyn, ninst, rex, ed, 1, x3, x4, x5); WBACK; if (!wback && !rex.w) ZEROUP(ed); @@ -874,21 +883,21 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 6: INST_NAME("SHL Ed, 1"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined - GETED(0); + GETEDsd(0); emit_shl32c(dyn, ninst, rex, ed, 1, x3, x4, x5); WBACK; break; case 5: INST_NAME("SHR Ed, 1"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined - GETED(0); + GETEDsd(0); emit_shr32c(dyn, ninst, rex, ed, 1, x3, x4); WBACK; break; case 7: INST_NAME("SAR Ed, 1"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined - GETED(0); + GETEDsd(0); emit_sar32c(dyn, ninst, rex, ed, 1, x3, x4); WBACK; break; @@ -906,8 +915,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int READFLAGS(X_OF | X_CF); } SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); // removed PENDING on purpose - GETED(0); - if (!wback && !rex.w) ZEROUP(ed); + GETEDsd(0); + if (!wback && !rex.w) if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); ANDI(x6, xRCX, rex.w ? 0x3f : 0x1f); BEQ_NEXT(x6, xZR); emit_rol32(dyn, ninst, rex, ed, x6, x3, x4); @@ -919,8 +928,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int READFLAGS(X_OF | X_CF); } SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); // removed PENDING on purpose - GETED(0); - if (!wback && !rex.w) ZEROUP(ed); + GETEDsd(0); + if (!wback && !rex.w) if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); ANDI(x6, xRCX, rex.w ? 0x3f : 0x1f); BEQ_NEXT(x6, xZR); emit_ror32(dyn, ninst, rex, ed, x6, x3, x4); @@ -934,8 +943,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int READFLAGS(X_CF); } SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); - GETED(0); - if (!wback && !rex.w) ZEROUP(ed); + GETEDsd(0); + if (!wback && !rex.w) if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); ANDI(x6, xRCX, rex.w ? 0x3f : 0x1f); BEQ_NEXT(x6, xZR); emit_rcl32(dyn, ninst, rex, ed, x6, x3, x4, x5); @@ -949,8 +958,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int READFLAGS(X_CF); } SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); - GETED(0); - if (!wback && !rex.w) ZEROUP(ed); + GETEDsd(0); + if (!wback && !rex.w) if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); ANDI(x6, xRCX, rex.w ? 0x3f : 0x1f); BEQ_NEXT(x6, xZR); emit_rcr32(dyn, ninst, rex, ed, x6, x3, x4, x5); @@ -965,7 +974,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } else SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); // some flags are left undefined if (!dyn->insts[ninst].x64.gen_flags) { - GETED(0); + GETEDsd(0); if (rex.w) SLL(ed, ed, xRCX); else @@ -994,7 +1003,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } else SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); // some flags are left undefined if (!dyn->insts[ninst].x64.gen_flags) { - GETED(0); + GETEDsd(0); if (rex.w) SRL(ed, ed, xRCX); else @@ -1022,8 +1031,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); ANDI(x3, xRCX, rex.w ? 0x3f : 0x1f); - GETED(0); - if (!rex.w && MODREG) { ZEROUP(ed); } + GETEDsd(0); + if (!rex.w && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } CBZ_NEXT(x3); emit_sar32(dyn, ninst, rex, ed, x3, x4, x5, x6); WBACK; @@ -1105,6 +1114,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xD7: INST_NAME("XLAT"); + UP32_READ(xRBX); ANDI(x1, xRAX, 0xff); if (rex.seg) { grab_segdata(dyn, addr, ninst, x2, rex.seg); @@ -1181,6 +1191,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int CBNZ_NEXT(x1); GO(0, x3); } else { + UP32_READ(xRCX); ADDIy(xRCX, xRCX, -1); ANDI(x1, xFlags, 1 << F_ZF); CBNZ_NEXT(x1); @@ -1199,6 +1210,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int CBZ_NEXT(x1); GO(0, x3); } else { + UP32_READ(xRCX); ADDIy(xRCX, xRCX, -1); ANDI(x1, xFlags, 1 << F_ZF); CBZ_NEXT(x1); @@ -1214,6 +1226,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INSH(xRCX, x3, x5, x6, 1, 0); GO(0, x3); } else { + UP32_READ(xRCX); ADDIy(xRCX, xRCX, -1); GO(0, xRCX); } @@ -1225,9 +1238,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ZEXTH(x3, xRCX); GO(1, x3); } else if (rex.is32bits || rex.is67) { + UP32_READ(xRCX); ADDIy(x3, xRCX, 0); GO(1, x3); } else { + UP32_READ(xRCX); GO(1, xRCX); } break; @@ -1612,16 +1627,16 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 2: INST_NAME("NOT Ed"); - GETED(0); + GETEDsd(0); XORI(ed, ed, -1); if (!rex.w && MODREG) - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); WBACK; break; case 3: INST_NAME("NEG Ed"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED(0); + GETEDsd(0); emit_neg32(dyn, ninst, rex, ed, x3, x4, x5, x6); WBACK; break; @@ -1632,6 +1647,9 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SET_DFNONE(); GETED(0); if (rex.w) { + MARKREGd(xRAX); + MARKREGd(xRDX); + MARKREGs(xRAX); if (ed == xRDX) gd = x3; else @@ -1640,6 +1658,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int MUL(xRAX, xRAX, ed); if (gd != xRDX) { MV(xRDX, gd); } } else { + MARKREGd(xRAX); + MARKREGd(xRDX); ZEXTW2(x3, xRAX); if (MODREG) { ZEXTW2(x4, ed); @@ -1674,6 +1694,9 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SET_DFNONE(); GETSED(0); if (rex.w) { + MARKREGd(xRAX); + MARKREGd(xRDX); + MARKREGs(xRAX); if (ed == xRDX) gd = x3; else @@ -1682,6 +1705,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int MUL(xRAX, xRAX, ed); if (gd != xRDX) { MV(xRDX, gd); } } else { + MARKREGd(xRAX); + MARKREGd(xRDX); ADDIW(x3, xRAX, 0); // sign extend 32bits-> 64bits MUL(xRDX, x3, ed); // 64 <- 32x32 ZEXTW2(xRAX, xRDX); @@ -1711,6 +1736,10 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("DIV Ed"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); SET_DFNONE(); + MARKREGd(xRAX); + MARKREGd(xRDX); + MARKREGs(xRAX); + MARKREGs(xRDX); if (!rex.w) { GETED(0); if (ninst && (nextop == 0xF0) @@ -1744,7 +1773,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int DIVU(x2, x3, ed); REMU(xRDX, x3, ed); ZEXTW2(xRAX, x2); - ZEROUP(xRDX); + if (NEED_ZEROUP(xRDX)) ZEROUP_RESULT(xRDX); } } else { if (ninst @@ -1798,6 +1827,10 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); SET_DFNONE(); } + MARKREGd(xRAX); + MARKREGd(xRDX); + MARKREGs(xRAX); + MARKREGs(xRDX); if (!rex.w) { GETSED(0); if (BOX64ENV(dynarec_div0)) { @@ -1816,7 +1849,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int DIV(x2, x3, ed); REM(xRDX, x3, ed); ZEXTW2(xRAX, x2); - ZEROUP(xRDX); + if (NEED_ZEROUP(xRDX)) ZEROUP_RESULT(xRDX); } else { if (ninst && dyn->insts && dyn->insts[ninst - 1].x64.addr @@ -1918,14 +1951,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0: // INC Ed INST_NAME("INC Ed"); SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING, NAT_FLAGS_FUSION); - GETED(0); + GETEDsd(0); emit_inc32(dyn, ninst, rex, ed, x3, x4, x5, x6); WBACK; break; case 1: // DEC Ed INST_NAME("DEC Ed"); SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING, NAT_FLAGS_FUSION); - GETED(0); + GETEDsd(0); emit_dec32(dyn, ninst, rex, ed, x3, x4, x5, x6); WBACK; break; @@ -2084,6 +2117,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 6: // Push Ed INST_NAME("PUSH Ed"); + if (!rex.is32bits) UP32_READ(xRSP); GETEDz(0); PUSH1z(ed); break; diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index bc4c6eacb..16cc94958 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -509,6 +509,8 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SLLI(x3, x3, box64_rdtsc_shift); } SRLI(xRDX, x3, 32); + MARKREGd(xRAX); + MARKREGd(xRDX); ZEXTW2(xRAX, x3); // wipe upper part break; case 0x38: @@ -996,7 +998,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xF0: INST_NAME("MOVBE Gd, Ed"); nextop = F8; - GETGD; + GETGDd; SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); LDxw(gd, ed, fixedaddress); @@ -1081,15 +1083,16 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETFLAGS; \ } \ nextop = F8; \ - GETGD; \ + GETGDsd; \ if (MODREG) { \ ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ + MARKREGs(ed); \ if (dyn->insts[ninst].nat_flags_fusion) { \ NATIVEMV(NATYES, gd, ed); \ } else { \ MV##YES(gd, ed, tmp1); \ } \ - if (!rex.w) ZEROUP(gd); \ + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); \ } else { \ addr = geted(dyn, addr, ninst, nextop, &ed, tmp2, tmp3, &fixedaddress, rex, NULL, 1, 0); \ if (dyn->insts[ninst].nat_flags_fusion) { \ @@ -1098,7 +1101,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni B##NO(tmp1, 8); \ } \ LDxw(gd, ed, fixedaddress); \ - if (!rex.w) ZEROUP(gd); \ + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); \ } GOCOND(0x40, "CMOV", "Gd, Ed"); @@ -1106,7 +1109,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0x50: INST_NAME("MOVMSKPS Gd, Ex"); nextop = F8; - GETGD; + GETGDd; GETEX(x1, 0, 12); XOR(gd, gd, gd); for (int i = 0; i < 4; ++i) { @@ -1706,6 +1709,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETGM(); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGs(ed); if (!rex.w) { ZEXTW2(x4, ed); ed = x4; @@ -1935,11 +1939,12 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni v0 = mmx_get_reg(dyn, ninst, x1, x2, x3, gd); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGd(ed); if (rex.w) FMVXD(ed, v0); else { FMVXW(ed, v0); - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } } else { addr = geted(dyn, addr, ninst, nextop, &wback, x3, x2, &fixedaddress, rex, NULL, 1, 0); @@ -2054,6 +2059,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETGD; if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGs(ed); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0); @@ -2077,14 +2083,14 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("SHLD Ed, Gd, Ib"); if (geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 63 : 31)) { SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); GETGD; u8 = F8 & (rex.w ? 63 : 31); emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4, x5); WBACK; } else { FAKEED; - if (!rex.w && !rex.is32bits && MODREG) { ZEROUP(ed); } + if (!rex.w && !rex.is32bits && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } F8; } break; @@ -2097,8 +2103,8 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } else SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); // some flags are left undefined GETGD; - GETED(0); - if (!rex.w && !rex.is32bits && MODREG) { ZEROUP(ed); } + GETEDsd(0); + if (!rex.w && !rex.is32bits && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } ANDI(x3, xRCX, rex.w ? 0x3f : 0x1f); BEQ_NEXT(x3, xZR); emit_shld32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6); @@ -2112,6 +2118,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETGD; if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGsd(ed); wback = 0; } else { SMREAD(); @@ -2142,7 +2149,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SDxw(ed, wback, fixedaddress); SMWRITE(); } else if (!rex.w) { - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } break; case 0xAC: @@ -2150,14 +2157,14 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("SHRD Ed, Gd, Ib"); if (geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 63 : 31)) { SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); GETGD; u8 = F8 & (rex.w ? 63 : 31); emit_shrd32c(dyn, ninst, rex, ed, gd, u8, x3, x4, x5); WBACK; } else { FAKEED; - if (!rex.w && !rex.is32bits && MODREG) { ZEROUP(ed); } + if (!rex.w && !rex.is32bits && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } F8; } break; @@ -2170,8 +2177,8 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } else SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); GETGD; - GETED(0); - if (!rex.w && !rex.is32bits && MODREG) { ZEROUP(ed); } + GETEDsd(0); + if (!rex.w && !rex.is32bits && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } ANDI(x3, xRCX, rex.w ? 0x3f : 0x1f); BEQ_NEXT(x3, xZR); emit_shrd32(dyn, ninst, rex, ed, gd, x3, x5, x4, x6); @@ -2315,7 +2322,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("IMUL Gd, Ed"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); CLEAR_FLAGS(); if (rex.w) { @@ -2357,7 +2364,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni ZEXTW2(gd, x5); } else { MULxw(gd, gd, ed); - ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); } } IFX (X_SF) { @@ -2422,6 +2429,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETGD; if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGsd(ed); wback = 0; } else { SMREAD(); @@ -2453,13 +2461,13 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SDxw(ed, wback, fixedaddress); SMWRITE(); } else if (!rex.w) { - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } break; case 0xB6: INST_NAME("MOVZX Gd, Eb"); nextop = F8; - GETGD; + GETGDd; SCRATCH_USAGE(0); if (MODREG) { if (rex.rex) { @@ -2485,7 +2493,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xB7: INST_NAME("MOVZX Gd, Ew"); nextop = F8; - GETGD; + GETGDd; if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); ZEXTH(gd, ed); @@ -2513,7 +2521,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("BTS Ed, Ib"); SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); SET_DFNONE(); - GETED(1); + GETEDsd(1); u8 = F8; u8 &= (rex.w ? 0x3f : 0x1f); if (cpuext.zbs) { @@ -2542,13 +2550,13 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SMWRITE(); } MARK; - if (!rex.w && !wback) ZEROUP(ed); + if (!rex.w && !wback) if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); break; case 6: INST_NAME("BTR Ed, Ib"); SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); SET_DFNONE(); - GETED(1); + GETEDsd(1); u8 = F8; u8 &= (rex.w ? 0x3f : 0x1f); if (cpuext.zbs) { @@ -2577,14 +2585,14 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SDxw(ed, wback, fixedaddress); SMWRITE(); } else if (!rex.w) { - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } break; case 7: INST_NAME("BTC Ed, Ib"); SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); SET_DFNONE(); - GETED(1); + GETEDsd(1); u8 = F8; u8 &= rex.w ? 0x3f : 0x1f; BEXTI(x3, ed, u8); // F_CF is 1 @@ -2602,7 +2610,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SDxw(ed, wback, fixedaddress); SMWRITE(); } else if (!rex.w) { - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } break; default: @@ -2617,6 +2625,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETGD; if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGsd(ed); wback = 0; } else { SMREAD(); @@ -2647,7 +2656,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SDxw(ed, wback, fixedaddress); SMWRITE(); } else if (!rex.w) { - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } break; case 0xBC: @@ -2719,7 +2728,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xBE: INST_NAME("MOVSX Gd, Eb"); nextop = F8; - GETGD; + GETGDd; if (MODREG) { if (rex.rex) { wback = TO_NAT((nextop & 7) + (rex.b << 3)); @@ -2737,12 +2746,12 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni LB(gd, ed, fixedaddress); } if (!rex.w) - ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); break; case 0xBF: INST_NAME("MOVSX Gd, Ew"); nextop = F8; - GETGD; + GETGDd; if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); SEXTH(gd, ed); @@ -2752,7 +2761,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni LH(gd, ed, fixedaddress); } if (!rex.w) - ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); break; case 0xC0: INST_NAME("XADD Eb, Gb"); @@ -2773,7 +2782,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("XADD Ed, Gd"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); if (ed != gd) MV(x7, ed); @@ -2843,7 +2852,9 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni nextop = F8; GETGD; if (MODREG) { - MVxw(TO_NAT((nextop & 7) + (rex.b << 3)), gd); + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGd(ed); + MVxw(ed, gd); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); SDxw(gd, ed, fixedaddress); @@ -2868,7 +2879,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xC5: INST_NAME("PEXTRW Gd,Em,Ib"); nextop = F8; - GETGD; + GETGDd; GETEM(x2, 1, 6); u8 = (F8) & 3; LHU(gd, wback, fixedaddress + u8 * 2); @@ -2969,6 +2980,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xCF: INST_NAME("BSWAP Reg"); gd = TO_NAT((opcode & 7) + (rex.b << 3)); + MARKREGsd(gd); REV8xw(gd, gd, x1, x2, x3, x4); break; case 0xD1: @@ -3040,7 +3052,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xD7: INST_NAME("PMOVMSKB Gd, Em"); nextop = F8; - GETGD; + GETGDd; GETEM(x2, 0, 1); LD(x1, wback, fixedaddress + 0); for (int i = 0; i < 8; i++) { @@ -3554,6 +3566,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0xF7: INST_NAME("MASKMOVQ Gm, Em"); + UP32_READ(xRDI); nextop = F8; GETGM(); GETEM(x5, 0, 7); diff --git a/src/dynarec/rv64/dynarec_rv64_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_0f_vector.c index 175e66a2d..372a9996c 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_0f_vector.c @@ -477,7 +477,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, INST_NAME("MOVMSKPS Gd, Ex"); nextop = F8; SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); - GETGD; + GETGDd; GETEX_vector(q0, 0, 0, VECTOR_SEW32); if (cpuext.xtheadvector) { v0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL8); @@ -1099,7 +1099,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0xC5: INST_NAME("PEXTRW Gd, Em, Ib"); nextop = F8; - GETGD; + GETGDd; if (MODREG) { SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); GETEM_vector(q0, 1); @@ -1207,7 +1207,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0xD7: INST_NAME("PMOVMSKB Gd, Em"); nextop = F8; - GETGD; + GETGDd; SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); GETEM_vector(q0, 0); SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index d56e19006..37251b07b 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -905,8 +905,11 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xA4: return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); case 0xA5: + UP32_READ(xRSI); + UP32_READ(xRDI); if (rex.rep) { INST_NAME("REP MOVSW"); + UP32_READ(xRCX); CBZ_NEXT(xRCX); if (rex.is67 && !rex.is32bits) { ZEROUP(xRSI); @@ -952,13 +955,17 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SMWRITE(); break; case 0xA7: + UP32_READ(xRSI); + UP32_READ(xRDI); switch (rex.rep) { case 1: case 2: if (rex.rep == 1) { INST_NAME("REPNZ CMPSW"); + UP32_READ(xRCX); } else { INST_NAME("REPZ CMPSW"); + UP32_READ(xRCX); } if (BOX64DRENV(dynarec_safeflags) > 1) { READFLAGS(X_ALL); @@ -1025,8 +1032,10 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_test16(dyn, ninst, x1, x2, x3, x4, x5); break; case 0xAB: + UP32_READ(xRDI); if (rex.rep) { INST_NAME("REP STOSW"); + UP32_READ(xRCX); CBZ_NEXT(xRCX); if (rex.is67 && !rex.is32bits) { ZEROUP(xRDI); @@ -1056,6 +1065,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; case 0xAD: + UP32_READ(xRSI); if (rex.rep) { DEFAULT; } else { @@ -1070,13 +1080,17 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; case 0xAF: + UP32_READ(xRDI); + if (rex.w) MARKREGs(xRAX); switch (rex.rep) { case 1: case 2: if (rex.rep == 1) { INST_NAME("REPNZ SCASW"); + UP32_READ(xRCX); } else { INST_NAME("REPZ SCASW"); + UP32_READ(xRCX); } if (BOX64DRENV(dynarec_safeflags) > 1) { READFLAGS(X_ALL); diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index 8a7c8742e..6dc7cb954 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -1281,6 +1281,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (rex.w) { if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGd(ed); LD(ed, gback, gdoffset + 0); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); @@ -1291,6 +1292,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } else { if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGd(ed); LWU(ed, gback, gdoffset + 0); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); @@ -1942,7 +1944,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xC5: INST_NAME("PEXTRW Gd,Ex,Ib"); nextop = F8; - GETGD; + GETGDd; GETEX(x1, 0, 14); u8 = (F8) & 7; LHU(gd, wback, fixedaddress + u8 * 2); @@ -2105,7 +2107,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("PMOVMSKB Gd, Ex"); nextop = F8; GETEX(x2, 0, 8); - GETGD; + GETGDd; LD(x1, wback, fixedaddress + 8); // high part LD(x2, wback, fixedaddress + 0); // low part, also destroyed wback(x2) MOV64x(x5, 0x8080808080808080); @@ -2660,6 +2662,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xF7: INST_NAME("MASKMOVDQU Gx, Ex"); + UP32_READ(xRDI); nextop = F8; GETEX(x1, 0, 15); GETGX(); diff --git a/src/dynarec/rv64/dynarec_rv64_660f38.c b/src/dynarec/rv64/dynarec_rv64_660f38.c index 43caafdf9..5e5edbcb3 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f38.c +++ b/src/dynarec/rv64/dynarec_rv64_660f38.c @@ -1370,6 +1370,7 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, GETGX(); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + UP32_WRITE32(ed); wback = 0; } else { addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 1); @@ -1388,6 +1389,7 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, GETGX(); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + UP32_WRITE32(ed); wback = 0; } else { addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 1); @@ -1410,6 +1412,7 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, GETGX(); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + UP32_WRITE32(ed); wback = 0; } else { addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 1); @@ -1431,6 +1434,7 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, GETGX(); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + UP32_WRITE32(ed); wback = 0; } else { addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 1); @@ -1640,6 +1644,8 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, break; case 0x61: INST_NAME("PCMPESTRI Gx, Ex, Ib"); + MARKREGs(xRAX); + MARKREGs(xRDX); nextop = F8; GETG; SETFLAGS(X_ALL, SF_SET_DF, NAT_FLAGS_NOFUSION); @@ -1726,6 +1732,8 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, break; case 0x63: INST_NAME("PCMPISTRI Gx, Ex, Ib"); + MARKREGs(xRAX); + MARKREGs(xRDX); SETFLAGS(X_ALL, SF_SET_DF, NAT_FLAGS_NOFUSION); nextop = F8; GETG; diff --git a/src/dynarec/rv64/dynarec_rv64_660f_vector.c b/src/dynarec/rv64/dynarec_rv64_660f_vector.c index 85480959c..a925c548e 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_660f_vector.c @@ -1062,7 +1062,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i INST_NAME("PMOVMSKD Gd, Ex"); nextop = F8; SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); - GETGD; + GETGDd; GETEX_vector(q0, 0, 0, VECTOR_SEW64); if (cpuext.xtheadvector) { v0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); @@ -1806,7 +1806,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i INST_NAME("PEXTRW Gd, Ex, Ib"); nextop = F8; SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); - GETGD; + GETGDd; if (MODREG) { GETEX_vector(q0, 0, 1, VECTOR_SEW16); u8 = (F8) & 7; @@ -1923,7 +1923,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i INST_NAME("PMOVMSKB Gd, Ex"); nextop = F8; SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); - GETGD; + GETGDd; GETEX_vector(q0, 0, 0, VECTOR_SEW8); if (cpuext.xtheadvector) { v0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL8); @@ -2343,6 +2343,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i break; case 0xF7: INST_NAME("MASKMOVDQU Gx, Ex"); + UP32_READ(xRDI); nextop = F8; SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); GETGX_vector(q0, 0, VECTOR_SEW8); diff --git a/src/dynarec/rv64/dynarec_rv64_arch.c b/src/dynarec/rv64/dynarec_rv64_arch.c index 1a254b2a5..4b926664c 100644 --- a/src/dynarec/rv64/dynarec_rv64_arch.c +++ b/src/dynarec/rv64/dynarec_rv64_arch.c @@ -70,6 +70,8 @@ typedef struct arch_arch_s #undef GO uint16_t unaligned:1; uint16_t seq:10; // how many instruction on the same values + int16_t rsp; // pending rsp offset at the end of this instruction + uint16_t up32; // GPRs with pending 32-bit zero-up at the end of this instruction } arch_arch_t; typedef struct arch_build_s @@ -78,7 +80,9 @@ typedef struct arch_build_s SUPER() #undef GO uint8_t unaligned; - #define GO(A) arch_##A##_t A##_; + int16_t rsp; + uint16_t up32; +#define GO(A) arch_##A##_t A##_; SUPER() #undef GO } arch_build_t; @@ -86,9 +90,10 @@ typedef struct arch_build_s static int arch_build(dynarec_rv64_t* dyn, int ninst, arch_build_t* arch) { memset(arch, 0, sizeof(arch_build_t)); - // todo // opcode can handle unaligned arch->unaligned = dyn->insts[ninst].unaligned; + arch->rsp = dyn->insts[ninst].rsp_entry; + arch->up32 = dyn->insts[ninst].up32_pending; extcache_t* e = &dyn->insts[ninst].e; for (int i = 0; i < 32; ++i) { if (!e->extcache[i].t) @@ -180,6 +185,8 @@ static void build_next(arch_arch_t* arch, arch_build_t* build) SUPER() #undef GO arch->unaligned = build->unaligned; + arch->rsp = build->rsp; + arch->up32 = build->up32; arch->seq = 0; void* p = ((void*)arch)+sizeof(arch_arch_t); #define GO(A) \ @@ -329,6 +336,16 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) } SUPER() #undef GO + uint16_t up32 = arch->up32; + while (up32) { + int r = __builtin_ctz(up32); + up32 &= up32 - 1; + emu->regs[r].q[0] &= 0xffffffffULL; + } + if (arch->rsp) { + dynarec_log(LOG_INFO, " rsp[%d] ", arch->rsp); + emu->regs[_SP].q[0] += arch->rsp; + } if (sse || mmx) { size_t vlenb = 0; const void* vframe = get_vframe(p, &vlenb); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_0f.c index c847d178c..f40b53e30 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f.c @@ -309,7 +309,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in case 0x50: INST_NAME("VMOVMSKPS Gd, Ex"); nextop = F8; - GETGD; + GETGDd; GETEX(x2, 0, vex.l ? 24 : 8); XOR(gd, gd, gd); for (int i = 0; i < 4; ++i) { diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_0f38.c index 882a157a0..6fcc85a53 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f38.c @@ -61,7 +61,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, INST_NAME("ANDN Gd, Vd, Ed"); nextop = F8; SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); - GETGD; + GETGDd; GETED(0); GETVD; ANDN(gd, ed, vd, x5); @@ -88,7 +88,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, INST_NAME("BLSR Vd, Ed"); SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); GETED(0); - GETVD; + GETVDsd; if (!rex.w) { ZEXTW2(x4, ed); ed = x4; @@ -116,7 +116,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, INST_NAME("BLSMSK Vd, Ed"); SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); GETED(0); - GETVD; + GETVDsd; if (!rex.w) { ZEXTW2(x4, ed); ed = x4; @@ -141,7 +141,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, INST_NAME("BLSI Vd, Ed"); SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); GETED(0); - GETVD; + GETVDsd; if (!rex.w) { ZEXTW2(x4, ed); ed = x4; @@ -174,7 +174,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, INST_NAME("BZHI Gd, Ed, Vd"); nextop = F8; SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); - GETGD; + GETGDd; GETED(0); GETVD; CLEAR_FLAGS(); @@ -208,7 +208,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, INST_NAME("BEXTR Gd, Ed, Vd"); nextop = F8; SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); - GETGD; + GETGDd; GETED(0); GETVD; ANDI(x4, vd, 0xff); // start diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index a1e7c630d..232abe931 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -214,7 +214,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t INST_NAME("VMOVMSKPS Gd, Ex"); nextop = F8; GETEY_vector(q0, 0, VECTOR_SEW32); - GETGD; + GETGDd; VMSLT_VX(VMASK, q0, xZR, VECTOR_UNMASKED); VMV_X_S(gd, VMASK); ANDI(gd, gd, vex.l ? 0xff : 0x0f); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c index cd8d1e6a3..14dab7efc 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c @@ -273,7 +273,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0x50: INST_NAME("VMOVMSKPD Gd, Ex"); nextop = F8; - GETGD; + GETGDd; GETEX(x1, 0, vex.l ? 24 : 8); XOR(gd, gd, gd); for (int i = 0; i < 2; ++i) { @@ -2268,7 +2268,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0xC5: INST_NAME("VPEXTRW Gd, Ex, Ib"); nextop = F8; - GETGD; + GETGDd; GETEX(x2, 1, 14); u8 = (F8) & 7; LHU(gd, wback, fixedaddress + 2 * u8); @@ -3682,6 +3682,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, break; case 0xF7: INST_NAME("VMASKMOVDQU Gx, Ex"); + UP32_READ(xRDI); nextop = F8; GETEX(x1, 0, 15); GETGX(); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c index 766daed6c..ca38759b1 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c @@ -2516,7 +2516,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xF7: INST_NAME("SHLX Gd, Ed, Vd"); nextop = F8; - GETGD; + GETGDd; GETED(0); GETVD; ANDI(x5, vd, rex.w ? 0x3f : 0x1f); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c index 2eb590fdb..0bbbcf117 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c @@ -1259,6 +1259,8 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i break; case 0x61: INST_NAME("VPCMPESTRI Gx, Ex, Ib"); + MARKREGs(xRAX); + MARKREGs(xRDX); nextop = F8; if (vex.l) { DEFAULT; @@ -1345,6 +1347,8 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i break; case 0x63: INST_NAME("VPCMPISTRI Gx, Ex, Ib"); + MARKREGs(xRAX); + MARKREGs(xRDX); nextop = F8; if (vex.l) { DEFAULT; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index 929ed966d..92278d489 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -199,7 +199,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt INST_NAME("VMOVMSKPD Gd, Ex"); nextop = F8; GETEY_vector(q0, 0, VECTOR_SEW64); - GETGD; + GETGDd; VMSLT_VX(VMASK, q0, xZR, VECTOR_UNMASKED); VMV_X_S(gd, VMASK); ANDI(gd, gd, vex.l ? 0x0f : 0x03); @@ -1306,7 +1306,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt nextop = F8; if (!MODREG) return 0; INST_NAME("VPEXTRW Gd, Ex, Ib"); - GETGD; + GETGDd; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW16); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW16); @@ -1319,7 +1319,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD7: INST_NAME("VPMOVMSKB Gd, Ex"); nextop = F8; - GETGD; + GETGDd; SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW8); q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, (nextop & 7) + (rex.b << 3), 16 << vex.l, VECTOR_SEW8); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c index 605aaf2cd..c107e90cb 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c @@ -155,7 +155,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0x2C: INST_NAME("VCVTTSD2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; d0 = fpu_get_scratch(dyn); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); @@ -184,7 +184,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0x2D: INST_NAME("VCVTSD2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; d0 = fpu_get_scratch(dyn); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f38.c index 9cf35d265..aad73d8fe 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f38.c @@ -60,7 +60,7 @@ uintptr_t dynarec64_AVX_F2_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xF5: INST_NAME("PDEP Gd, Vd, Ed"); nextop = F8; - GETGD; + GETGDd; GETVD; GETED(0); if (gd == ed || gd == vd) { @@ -94,7 +94,7 @@ uintptr_t dynarec64_AVX_F2_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xF6: INST_NAME("MULX Gd, Vd, Ed (,RDX)"); nextop = F8; - GETGD; + GETGDd; GETED(0); GETVD; if (rex.w) { @@ -118,7 +118,7 @@ uintptr_t dynarec64_AVX_F2_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xF7: INST_NAME("SHRX Gd, Ed, Vd"); nextop = F8; - GETGD; + GETGDd; GETED(0); GETVD; ANDI(x5, vd, rex.w ? 0x3f : 0x1f); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c index 6582ff1f4..8a2addb52 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c @@ -76,7 +76,7 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x2C: INST_NAME("VCVTTSD2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; d0 = fpu_get_scratch(dyn); if (MODREG) { q0 = fpu_get_scratch(dyn); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c index e8f453606..e634722a3 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c @@ -223,7 +223,7 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0x2C: INST_NAME("VCVTTSS2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; d0 = fpu_get_scratch(dyn); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f38.c index 9c9b2b17c..a3a2366fd 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f38.c @@ -60,7 +60,7 @@ uintptr_t dynarec64_AVX_F3_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xF5: INST_NAME("PEXT Gd, Vd, Ed"); nextop = F8; - GETGD; + GETGDd; GETVD; GETED(0); if (gd == ed || gd == vd) { @@ -95,7 +95,7 @@ uintptr_t dynarec64_AVX_F3_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xF7: INST_NAME("SARX Gd, Ed, Vd"); nextop = F8; - GETGD; + GETGDd; GETED(0); GETVD; ANDI(x5, vd, rex.w ? 0x3f : 0x1f); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c index f4866e29b..91d4044fa 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c @@ -123,7 +123,7 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x2C: INST_NAME("VCVTTSS2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; d0 = fpu_get_scratch(dyn); if (MODREG) { q0 = fpu_get_scratch(dyn); diff --git a/src/dynarec/rv64/dynarec_rv64_emit_logic.c b/src/dynarec/rv64/dynarec_rv64_emit_logic.c index b0e6b20d2..f1e2a4a53 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_logic.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_logic.c @@ -95,9 +95,9 @@ void emit_xor32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s if (!rex.w && s1 != s2) { IFX (X_ZF) - ZEROUP(s1); - else if (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion) - ZEROUP(s1); + ZEROUP_RESULT(s1); + else if (NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) + ZEROUP_RESULT(s1); } IFX (X_PEND) { @@ -137,9 +137,9 @@ void emit_xor32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i } if (!rex.w) { IFX (X_ZF) - ZEROUP(s1); - else if (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion) - ZEROUP(s1); + ZEROUP_RESULT(s1); + else if (NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -233,9 +233,9 @@ void emit_or32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 } if (!rex.w) { IFX (X_ZF) - ZEROUP(s1); - else if (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion) - ZEROUP(s1); + ZEROUP_RESULT(s1); + else if (NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -273,9 +273,9 @@ void emit_or32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in } if (!rex.w) { IFX (X_ZF) - ZEROUP(s1); - else if (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion) - ZEROUP(s1); + ZEROUP_RESULT(s1); + else if (NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -388,9 +388,9 @@ void emit_and32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s AND(s1, s1, s2); // res = s1 & s2 if (!rex.w) { IFX (X_ZF | X_SF) - ZEROUP(s1); - else if (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion) - ZEROUP(s1); + ZEROUP_RESULT(s1); + else if (NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -426,9 +426,9 @@ void emit_and32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i } if (!rex.w) { IFX (X_ZF | X_SF) - ZEROUP(s1); - else if (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion) - ZEROUP(s1); + ZEROUP_RESULT(s1); + else if (NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c index a36886abb..751451d00 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_math.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c @@ -72,8 +72,9 @@ void emit_add32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s5); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } IFX (X_PF) { emit_pf(dyn, ninst, s1, s3, s4); @@ -95,8 +96,9 @@ void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i MOV64x(s2, c); ADD(s1, s1, s2); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } return; } @@ -160,8 +162,9 @@ void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s5); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } IFX (X_PF) { emit_pf(dyn, ninst, s1, s3, s4); @@ -447,8 +450,9 @@ void emit_sub32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } CALC_SUB_FLAGS(s5, s2, s1, s3, s4, rex.w ? 64 : 32); IFX (X_ZF) { @@ -472,8 +476,9 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i MOV64xw(s2, c); SUBxw(s1, s1, s2); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } return; } @@ -514,8 +519,9 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } CALC_SUB_FLAGS(s5, s2, s1, s3, s4, rex.w ? 64 : 32); IFX (X_ZF) { @@ -671,8 +677,9 @@ void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s4, s5); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } IFX (X_PF) { emit_pf(dyn, ninst, s1, s3, s2); @@ -724,8 +731,9 @@ void emit_dec32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s4, s5); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } IFX (X_PF) { emit_pf(dyn, ninst, s1, s3, s2); @@ -1018,8 +1026,9 @@ void emit_sbb32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } IFX (X_PEND) { @@ -1079,8 +1088,9 @@ void emit_neg32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s4, s5); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } IFX (X_PF) { emit_pf(dyn, ninst, s1, s3, s2); @@ -1328,8 +1338,9 @@ void emit_adc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s5, s6); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } IFX (X_PF) { emit_pf(dyn, ninst, s1, s3, s4); diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c index 390e61a45..ea3a1fb2f 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c @@ -671,8 +671,9 @@ void emit_shl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -689,7 +690,7 @@ void emit_shl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s void emit_shl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4, int s5) { if (!c) { - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); return; } @@ -725,8 +726,9 @@ void emit_shl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -777,8 +779,9 @@ void emit_shr32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -835,8 +838,9 @@ void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } + UP32_WRITE32(s1); if (!rex.w && c == 0) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -854,7 +858,7 @@ void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { if (!c) { - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); return; } @@ -893,8 +897,9 @@ void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -935,8 +940,9 @@ void emit_sar32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_ZF) { SET_FLAGS_EQZ(s1, F_ZF, s3); @@ -952,8 +958,9 @@ void emit_rol32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s { int64_t j64; + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_CF | X_OF) { @@ -974,7 +981,7 @@ void emit_rol32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s ROL(s1, s1, s2); } else { ROLW(s1, s1, s2); - ZEROUP(s1); + ZEROUP_RESULT(s1); } } else { SLLxw(s3, s1, s2); @@ -999,8 +1006,9 @@ void emit_ror32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s { int64_t j64; + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_CF) ANDI(xFlags, xFlags, ~(1UL << F_CF)); @@ -1019,7 +1027,7 @@ void emit_ror32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s ROR(s1, s1, s2); } else { RORW(s1, s1, s2); - ZEROUP(s1); + ZEROUP_RESULT(s1); } } else { SRLxw(s3, s1, s2); @@ -1480,7 +1488,7 @@ void emit_rcl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, if (!c) return; SET_DFNONE(); - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); IFX (X_OF) { ANDI(xFlags, xFlags, ~(1UL << F_OF2)); @@ -1509,7 +1517,7 @@ void emit_rcl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, SRLIxw(s5, s1, (rex.w ? 65 : 33) - c); OR(s1, s4, s5); } - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR, s3, xZR); } @@ -1520,7 +1528,7 @@ void emit_rcr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, if (!c) return; SET_DFNONE(); - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); IFX (X_OF) { ANDI(xFlags, xFlags, ~(1UL << F_OF2)); @@ -1549,7 +1557,7 @@ void emit_rcr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, SLLIxw(s5, s1, (rex.w ? 65 : 33) - c); OR(s1, s4, s5); } - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR, s3, xZR); } @@ -1558,7 +1566,7 @@ void emit_rcl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s { int64_t j64; SET_DFNONE(); - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); IFX (X_OF) { ANDI(xFlags, xFlags, ~(1UL << F_OF2)); @@ -1597,7 +1605,7 @@ void emit_rcl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s SRL(s5, s1, s5); OR(s4, s4, s5); MV(s1, s4); - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR, s3, xZR); } @@ -1606,7 +1614,7 @@ void emit_rcr32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s { int64_t j64; SET_DFNONE(); - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); IFX (X_OF) { ANDI(xFlags, xFlags, ~(1UL << F_OF2)); @@ -1644,7 +1652,7 @@ void emit_rcr32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s SLL(s5, s1, s5); OR(s4, s4, s5); MV(s1, s4); - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR, s3, xZR); } @@ -1687,7 +1695,7 @@ void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, { c &= rex.w ? 0x3f : 0x1f; if (!c) { - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); return; } @@ -1714,7 +1722,7 @@ void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, OR(s1, s3, s1); } - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); IFX (X_CF) { ANDI(s4, s1, 1 << F_CF); @@ -1786,7 +1794,7 @@ void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, OR(s1, s3, s1); } - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); IFX (X_CF) { SRLIxw(s3, s1, rex.w ? 63 : 31); @@ -1828,8 +1836,9 @@ void emit_shrd32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin SLLIxw(s1, s2, (rex.w ? 64 : 32) - c); OR(s1, s1, s3); + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_SF) { SRLIxw(s3, s1, rex.w ? 63 : 31); @@ -1946,7 +1955,7 @@ void emit_shld32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin SRLIxw(s1, s2, (rex.w ? 64 : 32) - c); OR(s1, s1, s3); - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -2002,8 +2011,9 @@ void emit_shrd32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_ZF) { SET_FLAGS_EQZ(s1, F_ZF, s5); @@ -2056,8 +2066,9 @@ void emit_shld32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_ZF) { SET_FLAGS_EQZ(s1, F_ZF, s5); diff --git a/src/dynarec/rv64/dynarec_rv64_emit_tests.c b/src/dynarec/rv64/dynarec_rv64_emit_tests.c index d5280a016..bc82e7594 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_tests.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_tests.c @@ -270,7 +270,7 @@ void emit_cmp32_0(dynarec_rv64_t* dyn, int ninst, rex_t rex, uint8_t nextop, int } int res = s1; IFX (X_ZF | X_PF) { - if (!rex.w && MODREG) { + if (!rex.w && MODREG && !isUpper32Zero(dyn, ninst, s1)) { ZEXTW2(s5, s1); res = s5; } @@ -419,7 +419,7 @@ void emit_test32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int } IFX (X_SF | X_ZF) { - if (!rex.w) ZEROUP(s3); + if (!rex.w && !isUpper32Zero(dyn, ninst, s1) && !isUpper32Zero(dyn, ninst, s2)) ZEROUP(s3); } IFX (X_SF) { diff --git a/src/dynarec/rv64/dynarec_rv64_f0.c b/src/dynarec/rv64/dynarec_rv64_f0.c index 1d27850c0..72c3ce996 100644 --- a/src/dynarec/rv64/dynarec_rv64_f0.c +++ b/src/dynarec/rv64/dynarec_rv64_f0.c @@ -267,6 +267,7 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("LOCK CMPXCHG Ed, Gd"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); GETGD; + MARKREGs(xRAX); addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); UFLAG_IF { MVxw(x6, xRAX); } ANDI(x1, wback, (1 << (rex.w + 2)) - 1); @@ -474,6 +475,8 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("LOCK CMPXCHG8B Gq, Eq"); SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION); SET_DFNONE(); + MARKREGd(xRAX); + MARKREGd(xRDX); nextop = F8; addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, LOCK_LOCK, 0, 0); ANDI(xFlags, xFlags, ~(1 << F_ZF)); @@ -515,6 +518,10 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 1: INST_NAME("LOCK CMPXCHG16B Gq, Eq"); + MARKREGsd(xRAX); + MARKREGsd(xRDX); + MARKREGs(xRBX); + MARKREGs(xRCX); static int warned = 0; PASS3(if (!warned) dynarec_log(LOG_INFO, "Warning, LOCK CMPXCHG16B is not well supported on RISC-V and issues are expected.\n")); PASS3(warned = 1); @@ -1264,7 +1271,7 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni *ok = 0; } else { INST_NAME("LOCK XCHG Ed, Gd"); - GETGD; + GETGDsd; addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); ANDI(x1, wback, (1 << (rex.w + 2)) - 1); BNEZ_MARK3(x1); diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c index 7d402778a..6dda8c52a 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f.c @@ -102,13 +102,13 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x2C: INST_NAME("CVTTSD2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; GETEXSD(v0, 0); if (!BOX64ENV(dynarec_fastround)) { FSFLAGSI(0); // reset all bits } FCVTLDxw(gd, v0, RD_RTZ); - if (!rex.w) ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); if (!BOX64ENV(dynarec_fastround)) { FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); @@ -123,14 +123,14 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x2D: INST_NAME("CVTSD2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; GETEXSD(v0, 0); if (!BOX64ENV(dynarec_fastround)) { FSFLAGSI(0); // // reset all bits } u8 = sse_setround(dyn, ninst, x2, x3); FCVTLDxw(gd, v0, RD_DYN); - if (!rex.w) ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); x87_restoreround(dyn, ninst, u8); if (!BOX64ENV(dynarec_fastround)) { FRFLAGS(x5); // get back FPSR to check the IOC bit @@ -149,11 +149,12 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xF0: // CRC32 Gd, Eb INST_NAME("CRC32 Gd, Eb"); + UP32_WRITE32(gd); nextop = F8; GETEB(x1, 0); GETGD; MV(x5, ed); - ZEROUP(gd); + if (NEED_ZEROUP32(gd)) ZEROUP_RESULT(gd); XOR(gd, gd, x5); MOV32w(x2, 0x82f63b78); for (int i = 0; i < 8; i++) { @@ -165,11 +166,12 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xF1: // CRC32 Gd, Ed INST_NAME("CRC32 Gd, Ed"); + UP32_WRITE32(gd); nextop = F8; GETGD; GETED(0); MV(x5, ed); - ZEROUP(gd); + if (NEED_ZEROUP32(gd)) ZEROUP_RESULT(gd); MOV32w(x2, 0x82f63b78); for (int j = 0; j < 4 * (rex.w + 1); ++j) { SRLI(x3, x5, 8 * j); diff --git a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c index 8ab7ef44e..fc0d5bfed 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c @@ -137,7 +137,7 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0x2C: INST_NAME("CVTTSD2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); if (MODREG) { v0 = sse_get_reg_vector(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0, dyn->vector_eew); @@ -170,7 +170,7 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0x2D: INST_NAME("CVTSD2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); if (MODREG) { v0 = sse_get_reg_vector(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0, dyn->vector_eew); diff --git a/src/dynarec/rv64/dynarec_rv64_f30f.c b/src/dynarec/rv64/dynarec_rv64_f30f.c index 0d24c933c..a10fd880c 100644 --- a/src/dynarec/rv64/dynarec_rv64_f30f.c +++ b/src/dynarec/rv64/dynarec_rv64_f30f.c @@ -134,14 +134,14 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x2C: INST_NAME("CVTTSS2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; GETEXSS(d0, 0); if (!BOX64ENV(dynarec_fastround)) { FSFLAGSI(0); // // reset all bits } FCVTSxw(gd, d0, RD_RTZ); - if (!rex.w) - ZEROUP(gd); + if (NEED_ZEROUP(gd)) + ZEROUP_RESULT(gd); if (!BOX64ENV(dynarec_fastround)) { FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); @@ -156,7 +156,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x2D: INST_NAME("CVTSS2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; GETEXSS(d0, 0); if (!BOX64ENV(dynarec_fastround)) { FSFLAGSI(0); // // reset all bits @@ -164,8 +164,8 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int u8 = sse_setround(dyn, ninst, x5, x6); FCVTSxw(gd, d0, RD_DYN); x87_restoreround(dyn, ninst, u8); - if (!rex.w) - ZEROUP(gd); + if (NEED_ZEROUP(gd)) + ZEROUP_RESULT(gd); if (!BOX64ENV(dynarec_fastround)) { FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); @@ -573,6 +573,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("RDFSBASE"); } ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGd(ed); int seg = _FS + ((nextop >> 3) & 7); grab_segdata(dyn, addr, ninst, x4, seg); MVxw(ed, x4); @@ -591,6 +592,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("WRFSBASE"); } ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGs(ed); int seg = _FS + ((nextop >> 3) & 7) - 2; if (!rex.w) { ZEXTW2(x4, ed); @@ -620,7 +622,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SET_DFNONE(); nextop = F8; GETED(0); - GETGD; + GETGDsd; if (!rex.w && MODREG) { ZEXTW2(x4, ed); ed = x4; @@ -727,7 +729,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SET_DFNONE(); nextop = F8; GETED(0); - GETGD; + GETGDsd; CLEAR_FLAGS(); if (!rex.w && MODREG) { ZEXTW2(x4, ed); @@ -752,7 +754,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SET_DFNONE(); nextop = F8; GETED(0); - GETGD; + GETGDsd; CLEAR_FLAGS(); if (!rex.w && MODREG) { ZEXTW2(x4, ed); @@ -853,7 +855,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int nextop = F8; READFLAGS(X_OF); SETFLAGS(X_OF, SF_SUBSET, NAT_FLAGS_NOFUSION); - GETGD; + GETGDsd; GETED(0); BEXTI(x3, xFlags, F_OF2); IFX (X_OF) { @@ -878,7 +880,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } else { ADDxw(x5, gd, ed); ADDxw(gd, x5, x3); - if (!rex.w) ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); } break; default: diff --git a/src/dynarec/rv64/dynarec_rv64_f30f_vector.c b/src/dynarec/rv64/dynarec_rv64_f30f_vector.c index a95ce2cd7..f4f2e2485 100644 --- a/src/dynarec/rv64/dynarec_rv64_f30f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f30f_vector.c @@ -163,7 +163,7 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0x2C: INST_NAME("CVTTSS2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; SET_ELEMENT_WIDTH(x3, VECTOR_SEW32, 1); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); @@ -189,7 +189,7 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0x2D: INST_NAME("CVTSS2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; SET_ELEMENT_WIDTH(x3, VECTOR_SEW32, 1); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index 399b5c6cd..9b8f0f739 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -872,6 +872,7 @@ void updateNativeFlags(dynarec_rv64_t* dyn) } dyn->insts[i].x64.use_flags = 0; dyn->insts[j].nat_next_inst = i; + dyn->insts[i].up32_read |= dyn->insts[j].up32_write32; found = 1; break; } else if (j && dyn->insts[j].pred_sz == 1 && dyn->insts[j].pred[0] == j - 1 @@ -913,3 +914,178 @@ void fpu_unwind_restore(dynarec_rv64_t* dyn, int ninst, extcache_t* cache) { memcpy(&dyn->insts[ninst].e, cache, sizeof(extcache_t)); } + +static int hasLinearPredecessor(const dynarec_rv64_t* dyn, int ninst) +{ + return ninst > 0 && dyn->insts[ninst].pred_sz == 1 && dyn->insts[ninst].pred[0] == ninst - 1; +} + +int isUpper32Zero(dynarec_rv64_t* dyn, int ninst, int reg) +{ + if (!IS_GPR(reg)) + return 0; + + const uint16_t bit = (uint16_t)(1 << TO_X64(reg)); + int current = ninst; + for (int depth = 0; depth < 4 && hasLinearPredecessor(dyn, current); ++depth) { + const instruction_rv64_t* prev = &dyn->insts[current - 1]; + if (prev->x64.has_callret || prev->x64.barrier) + return 0; + if (prev->up32_write64 & bit) return prev->up32_zero & bit; + --current; + } + return 0; +} + +void updateUpperLiveness(dynarec_rv64_t* dyn) +{ + int n = dyn->size; + if (n <= 0) + return; + + size_t live_size = (size_t)n * sizeof(uint16_t); + size_t pending_size = (size_t)n * sizeof(uint16_t); + size_t work_size = (size_t)n * sizeof(int); + size_t list_size = (size_t)n * sizeof(uint8_t); + void* buffer = calloc(1, 2 * live_size + pending_size + work_size + list_size); + if (!buffer) + return; + uint16_t* live_in = (uint16_t*)buffer; + uint16_t* live_out = (uint16_t*)((char*)live_in + live_size); + uint16_t* pending_in = (uint16_t*)((char*)live_out + live_size); + int* work = (int*)((char*)pending_in + pending_size); + uint8_t* on_list = (uint8_t*)((char*)work + work_size); + + int sp = 0; + for (int i = n - 1; i >= 0; --i) { + if (dyn->insts[i].x64.alive) { + work[sp++] = i; + on_list[i] = 1; + } + } + // backward analysis + while (sp > 0) { + int i = work[--sp]; + on_list[i] = 0; + const instruction_rv64_t* inst = &dyn->insts[i]; + if (!inst->x64.alive) + continue; + uint16_t combined_out = 0; + if (inst->x64.has_next && i + 1 < n && dyn->insts[i + 1].x64.alive) + combined_out |= live_in[i + 1]; + if (inst->x64.jmp) { + if (inst->x64.jmp_insts >= 0 && inst->x64.jmp_insts < n) + combined_out |= live_in[inst->x64.jmp_insts]; + else + combined_out = UINT16_MAX; + } + int has_internal_jump = inst->x64.jmp && inst->x64.jmp_insts >= 0 && inst->x64.jmp_insts < n; + if ((inst->x64.has_next && i == n - 1) || (!inst->x64.has_next && !has_internal_jump)) + combined_out = UINT16_MAX; + live_out[i] = combined_out; + + uint16_t live_in_val = inst->up32_read | (combined_out & (uint16_t)~inst->up32_write64); + if (live_in_val != live_in[i]) { + live_in[i] = live_in_val; + for (int p = 0; p < inst->pred_sz; ++p) { + int j = inst->pred[p]; + if (!on_list[j]) { + work[sp++] = j; + on_list[j] = 1; + } + } + } + } + + for (int i = 0; i < n; ++i) { + instruction_rv64_t* inst = &dyn->insts[i]; + inst->up32_skip = inst->up32_write32 & (uint16_t)~live_out[i]; + } + + memset(on_list, 0, list_size); + sp = 0; + for (int i = 0; i < n; ++i) { + if (dyn->insts[i].x64.alive) { + work[sp++] = i; + on_list[i] = 1; + } + } + // forward analysis + while (sp > 0) { + int i = work[--sp]; + on_list[i] = 0; + instruction_rv64_t* inst = &dyn->insts[i]; + if (!inst->x64.alive) + continue; + + uint16_t merged_pending = 0; + for (int p = 0; p < inst->pred_sz; ++p) { + int j = inst->pred[p]; + const instruction_rv64_t* pred = &dyn->insts[j]; + merged_pending |= (pending_in[j] & (uint16_t)~pred->up32_write64) | pred->up32_skip; + } + if (merged_pending != pending_in[i]) { + pending_in[i] = merged_pending; + if (inst->x64.has_next && i + 1 < n && dyn->insts[i + 1].x64.alive && !on_list[i + 1]) { + work[sp++] = i + 1; + on_list[i + 1] = 1; + } + if (inst->x64.jmp && inst->x64.jmp_insts >= 0 && inst->x64.jmp_insts < n) { + int j = inst->x64.jmp_insts; + if (dyn->insts[j].x64.alive && !on_list[j]) { + work[sp++] = j; + on_list[j] = 1; + } + } + } + } + for (int i = 0; i < n; ++i) { + dyn->insts[i].up32_pending = pending_in[i]; + } + + free(buffer); +} + +void updateRspMerge(dynarec_rv64_t* dyn, int is32bits) +{ + const int delta = is32bits ? 4 : 8; + int pending = 0; + int last_pushpop = -1; + for (int i = 0; i < dyn->size; ++i) { + instruction_rv64_t* inst = &dyn->insts[i]; + inst->rsp_entry = 0; + inst->rsp_flush = 0; + inst->rsp_merge = 0; + int class = (inst->x64.alive && !BOX64ENV(dynarec_test)) ? inst->rsp_class : RSP_CLASS_BARRIER; + if (pending && (class == RSP_CLASS_BARRIER || (i == 0) || (inst->pred_sz != 1) || (inst->pred[0] != i - 1))) { + dyn->insts[last_pushpop].rsp_flush = pending; + pending = 0; + last_pushpop = -1; + } + switch (class) { + case RSP_CLASS_PUSH: + if (pending - (inst->rsp_span ? inst->rsp_span : delta) < -2048) { + dyn->insts[last_pushpop].rsp_flush = pending; + pending = 0; + } + inst->rsp_entry = pending; + inst->rsp_merge = 1; + pending -= (inst->rsp_span ? inst->rsp_span : delta); + last_pushpop = i; + break; + case RSP_CLASS_POP: + if (pending + (inst->rsp_span ? inst->rsp_span : delta) > 2047) { + dyn->insts[last_pushpop].rsp_flush = pending; + pending = 0; + } + inst->rsp_entry = pending; + inst->rsp_merge = 1; + pending += (inst->rsp_span ? inst->rsp_span : delta); + last_pushpop = i; + break; + default: + break; + } + } + if (pending) dyn->insts[last_pushpop].rsp_flush = pending; +} diff --git a/src/dynarec/rv64/dynarec_rv64_functions.h b/src/dynarec/rv64/dynarec_rv64_functions.h index 5f949ac7b..507404d0f 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.h +++ b/src/dynarec/rv64/dynarec_rv64_functions.h @@ -70,6 +70,9 @@ void fpu_reset_ninst(dynarec_native_t* dyn, int ninst); int fpu_is_st_freed(dynarec_native_t* dyn, int ninst, int st); void updateNativeFlags(dynarec_rv64_t* dyn); +void updateUpperLiveness(dynarec_rv64_t* dyn); +int isUpper32Zero(dynarec_rv64_t* dyn, int ninst, int reg); +void updateRspMerge(dynarec_rv64_t* dyn, int is32bits); void get_free_scratch(dynarec_rv64_t* dyn, int ninst, uint8_t* tmp1, uint8_t* tmp2, uint8_t* tmp3, uint8_t s1, uint8_t s2, uint8_t s3, uint8_t s4, uint8_t s5); #endif //__DYNAREC_RV64_FUNCTIONS_H__ diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 6c4a65fa3..0f4ae160f 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -56,6 +56,8 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t sib = F8; int sib_reg = ((sib >> 3) & 7) + (rex.x << 3); int sib_reg2 = (sib & 0x7) + (rex.b << 3); + if ((sib & 0x7) != 5) UP32_READ(TO_NAT(sib_reg2)); + if (sib_reg != 4) UP32_READ(TO_NAT(sib_reg)); if ((sib & 0x7) == 5) { int64_t tmp = F32S; if (sib_reg != 4) { @@ -173,6 +175,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, if (!IS_GPR(ret)) SCRATCH_USAGE(1); } } else { + UP32_READ(TO_NAT((nextop & 7) + (rex.b << 3))); ret = TO_NAT((nextop & 7) + (rex.b << 3)); } } else { @@ -182,6 +185,8 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, if ((nextop & 7) == 4) { sib = F8; sib_reg = ((sib >> 3) & 7) + (rex.x << 3); + UP32_READ(TO_NAT((sib & 0x07) + (rex.b << 3))); + if (sib_reg != 4) UP32_READ(TO_NAT(sib_reg)); } int sib_reg2 = (sib & 0x07) + (rex.b << 3); if (nextop & 0x80) @@ -210,8 +215,10 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, } else { ret = TO_NAT(sib_reg2); } - } else + } else { + UP32_READ(TO_NAT((nextop & 0x07) + (rex.b << 3))); ret = TO_NAT((nextop & 0x07) + (rex.b << 3)); + } } else { if (i64 >= -2048 && i64 <= 2047) { if ((nextop & 7) == 4) { @@ -236,6 +243,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, if (!IS_GPR(ret)) SCRATCH_USAGE(1); } } else { + UP32_READ(TO_NAT((nextop & 0x07) + (rex.b << 3))); ADDIy(ret, TO_NAT((nextop & 0x07) + (rex.b << 3)), i64); if (!IS_GPR(ret)) SCRATCH_USAGE(1); } @@ -251,6 +259,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, ADDy(ret, tmp, scratch); } } else { + UP32_READ(TO_NAT((nextop & 0x07) + (rex.b << 3))); PASS3(int tmp = TO_NAT((nextop & 0x07) + (rex.b << 3))); ADDy(ret, tmp, scratch); } @@ -605,6 +614,7 @@ void call_c(dynarec_rv64_t* dyn, int ninst, rv64_consts_t fnc, int reg, int ret, { MAYUSE(fnc); CHECK_DFNONE(1); + UP32_READALL(); if (savereg == 0) savereg = x87pc; if (saveflags) { @@ -672,6 +682,7 @@ void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w) { MAYUSE(fnc); CHECK_DFNONE(1); + UP32_READALL(); fpu_pushcache(dyn, ninst, x3, 1); // save RSP in case there are x86 callbacks... SD(xRSP, xEmu, offsetof(x64emu_t, regs[_SP])); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 253301864..a6e304ffd 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -37,13 +37,130 @@ // LOCK_* define #define LOCK_LOCK (int*)1 +#if STEP == 0 +#define UP32_READ(r) \ + do { \ + if (IS_GPR(r)) dyn->insts[ninst].up32_read |= (uint16_t)(1 << (TO_X64(r))); \ + } while (0) +#define UP32_WRITE64(r) \ + do { \ + if (IS_GPR(r)) dyn->insts[ninst].up32_write64 |= (uint16_t)(1 << (TO_X64(r))); \ + } while (0) +#define UP32_WRITE32(r) \ + do { \ + if (IS_GPR(r)) { \ + UP32_WRITE64(r); \ + dyn->insts[ninst].up32_write32 |= (uint16_t)(1 << (TO_X64(r))); \ + } \ + } while (0) +#define UP32_READALL() \ + do { \ + dyn->insts[ninst].up32_read |= (uint16_t)0xFFFF; \ + } while (0) +#else +#define UP32_READ(r) ((void)(r)) +#define UP32_WRITE64(r) ((void)(r)) +#define UP32_WRITE32(r) ((void)(r)) +#define UP32_READALL() ((void)0) +#endif + +#if STEP == 1 +#define UP32_ZERO(r) \ + do { \ + if (IS_GPR(r)) dyn->insts[ninst].up32_zero |= (uint16_t)(1 << (TO_X64(r))); \ + } while (0) +#else +#define UP32_ZERO(r) ((void)(r)) +#endif + +#define ZEROUP_RESULT(r) \ + do { \ + ZEROUP(r); \ + UP32_ZERO(r); \ + } while (0) + +#define MARKREGd(r) \ + do { \ + if (rex.w) \ + UP32_WRITE64(r); \ + else \ + UP32_WRITE32(r); \ + } while (0) + +#define MARKREGdz(r) \ + do { \ + if (!rex.is32bits) \ + UP32_WRITE64(r); \ + else \ + UP32_WRITE32(r); \ + } while (0) + +#define MARKREGs(r) \ + do { \ + if (rex.w) UP32_READ(r); \ + } while (0) + +#define MARKREGsz(r) \ + do { \ + if (!rex.is32bits) UP32_READ(r); \ + } while (0) + +#define MARKREGsd(r) \ + do { \ + MARKREGs(r); \ + MARKREGd(r); \ + } while (0) + +#define MARKREGsdz(r) \ + do { \ + MARKREGsz(r); \ + MARKREGdz(r); \ + } while (0) + +#define NEED_ZEROUP32(r) \ + (!(IS_GPR(r)) || !((dyn->insts[ninst].up32_skip >> (TO_X64(r))) & 1)) +#define NEED_ZEROUP(r) (!rex.w && NEED_ZEROUP32(r)) + +#define ZEROUP32_RESULT(r) \ + do { \ + UP32_WRITE32(r); \ + if (NEED_ZEROUP32(r)) ZEROUP_RESULT(r); \ + } while (0) + // GETGD get x64 register in gd -#define GETGD gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)) -#define GETVD vd = TO_NAT(vex.v) +#define GETGDw gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)) +#define GETGDs \ + do { \ + GETGDw; \ + MARKREGs(gd); \ + } while (0) +#define GETGD GETGDs +#define GETGDd \ + do { \ + GETGDw; \ + MARKREGd(gd); \ + } while (0) +#define GETGDsd \ + do { \ + GETGDs; \ + MARKREGd(gd); \ + } while (0) +#define GETVDs \ + do { \ + vd = TO_NAT(vex.v); \ + MARKREGs(vd); \ + } while (0) +#define GETVDsd \ + do { \ + vd = TO_NAT(vex.v); \ + MARKREGsd(vd); \ + } while (0) +#define GETVD GETVDs // GETED can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI #define GETED(D) \ if (MODREG) { \ ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ + MARKREGs(ed); \ wback = 0; \ } else { \ SMREAD(); \ @@ -51,10 +168,16 @@ LDxw(x1, wback, fixedaddress); \ ed = x1; \ } +#define GETEDsd(D) \ + do { \ + GETED(D); \ + if (MODREG) MARKREGd(ed); \ + } while (0) // GETSED can use r1 for ed, and r2 for wback. ed will be sign extended! #define GETSED(D) \ if (MODREG) { \ ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ + MARKREGs(ed); \ wback = 0; \ if (!rex.w) { \ ADDW(x1, ed, xZR); \ @@ -73,6 +196,7 @@ #define GETEDx(D) \ if (MODREG) { \ ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ + UP32_READ(ed); \ wback = 0; \ } else { \ SMREAD(); \ @@ -83,6 +207,7 @@ #define GETEDz(D) \ if (MODREG) { \ ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ + MARKREGs(ed); \ wback = 0; \ } else { \ SMREAD(); \ @@ -94,6 +219,7 @@ #define GETEDH(hint, ret, D) \ if (MODREG) { \ ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ + MARKREGs(ed); \ wback = 0; \ } else { \ SMREAD(); \ @@ -105,6 +231,7 @@ #define GETEDW(hint, ret, D) \ if (MODREG) { \ ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ + MARKREGs(ed); \ MV(ret, ed); \ wback = 0; \ } else { \ @@ -1257,11 +1384,17 @@ dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op1 = op1; \ dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op2 = op2; \ if (dyn->insts[ninst + 1].no_scratch_usage && IS_GPR(op1)) { \ - MV(s1, op1); \ + if (dyn->insts[ninst].up32_read & (1 << TO_X64(op1))) \ + MV(s1, op1); \ + else \ + ZEXTW2(s1, op1); \ dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op1 = s1; \ } \ if (dyn->insts[ninst + 1].no_scratch_usage && IS_GPR(op2)) { \ - MV(s2, op2); \ + if (dyn->insts[ninst].up32_read & (1 << TO_X64(op2))) \ + MV(s2, op2); \ + else \ + ZEXTW2(s2, op2); \ dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op2 = s2; \ } \ } while (0) diff --git a/src/dynarec/rv64/dynarec_rv64_pass0.h b/src/dynarec/rv64/dynarec_rv64_pass0.h index 9dfc12b3a..f31c93028 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass0.h +++ b/src/dynarec/rv64/dynarec_rv64_pass0.h @@ -63,6 +63,7 @@ } while (0) #define BARRIER(A) \ if (A != BARRIER_MAYBE) { \ + UP32_READALL(); \ fpu_purgecache(dyn, ninst, 0, x1, x2, x3); \ dyn->insts[ninst].x64.barrier = A; \ } else \ diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index 7877a7a02..99796863f 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -101,6 +101,10 @@ typedef enum flagcache_s { typedef struct callret_s callret_t; +#define RSP_CLASS_BARRIER 0 +#define RSP_CLASS_PUSH 1 +#define RSP_CLASS_POP 2 + typedef struct instruction_rv64_s { instruction_x64_t x64; uintptr_t address; // (start) address of the riscv emitted instruction @@ -141,6 +145,17 @@ typedef struct instruction_rv64_s { flagcache_t f_entry; // flags status before the instruction begin uint8_t vector_sew_entry; // sew status before the instruction begin uint8_t vector_sew_exit; // sew status at the end of instruction + int16_t rsp_entry; // pending rsp offset at entry + int16_t rsp_flush; // rsp offset to emit right after this push/pop + uint8_t rsp_merge:1; // this push/pop is emitted with merged rsp offset + uint8_t rsp_class:2; // RSP_* of this opcode (marked by the opcode handler) + uint8_t rsp_span; // push/pop depth of this opcode in bytes (0 = one delta, PUSHA/POPA = 32) + uint16_t up32_read; // bitmask of GPRs whose upper 32 bits are read by this instruction + uint16_t up32_write64; // bitmask of GPRs written as 64-bit by this instruction (upper 32 become defined) + uint16_t up32_write32; // bitmask of GPRs written as 32-bit by this instruction + uint16_t up32_zero; // bitmask of GPRs guaranteed to be zero-extended at instruction exit + uint16_t up32_skip; // bitmask of GPRs where the implicit zero-up after a 32-bit write can be skipped + uint16_t up32_pending; // bitmask of GPRs whose upper 32 bits are stale at entry to this instruction } instruction_rv64_t; typedef struct dynarec_rv64_s { diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index 53b9de273..1992318f0 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -114,20 +114,20 @@ // rd = rs1 + rs2 #define ADDxw(rd, rs1, rs2) EMIT(R_type(0b0000000, rs2, rs1, 0b000, rd, rex.w ? 0b0110011 : 0b0111011)) // rd = rs1 + rs2 -#define ADDz(rd, rs1, rs2) \ - do { \ - if (!rex.is32bits) { \ - ADD(rd, rs1, rs2); \ - } else { \ - ADDW(rd, rs1, rs2); \ - ZEROUP(rd); \ - } \ +#define ADDz(rd, rs1, rs2) \ + do { \ + if (!rex.is32bits) { \ + ADD(rd, rs1, rs2); \ + } else { \ + ADDW(rd, rs1, rs2); \ + ZEROUP32_RESULT(rd); \ + } \ } while (0) #define ADDy(rd, rs1, rs2) \ do { \ if (rex.is32bits || rex.is67) { \ ADDW(rd, rs1, rs2); \ - ZEROUP(rd); \ + ZEROUP32_RESULT(rd); \ } else { \ ADD(rd, rs1, rs2); \ } \ @@ -148,14 +148,14 @@ // rd = rs1 - rs2 #define SUBxw(rd, rs1, rs2) EMIT(R_type(0b0100000, rs2, rs1, 0b000, rd, rex.w ? 0b0110011 : 0b0111011)) // rd = rs1 - rs2 -#define SUBz(rd, rs1, rs2) \ - do { \ - if (!rex.is32bits) { \ - SUB(rd, rs1, rs2); \ - } else { \ - SUB(rd, rs1, rs2); \ - ZEROUP(rd); \ - } \ +#define SUBz(rd, rs1, rs2) \ + do { \ + if (!rex.is32bits) { \ + SUB(rd, rs1, rs2); \ + } else { \ + SUB(rd, rs1, rs2); \ + ZEROUP32_RESULT(rd); \ + } \ } while (0) // rd = rs1<>rs2 logical #define SRL(rd, rs1, rs2) EMIT(R_type(0b0000000, rs2, rs1, 0b101, rd, 0b0110011)) @@ -519,6 +519,64 @@ PUSH1(reg); \ } +#define PUSH1mz(reg) \ + do { \ + if ((reg) != xRSP) \ + dyn->insts[ninst].rsp_class = RSP_CLASS_PUSH; \ + if (dyn->insts[ninst].rsp_merge) { \ + int entry = dyn->insts[ninst].rsp_entry; \ + int flush = dyn->insts[ninst].rsp_flush; \ + int imm5 = flush / (rex.is32bits ? 4 : 8); \ + if (flush && !entry) { \ + if (rex.is32bits) \ + PUSH1_32(reg); \ + else \ + PUSH1(reg); \ + } else if (flush && cpuext.xtheadmemidx && imm5 >= -16 && imm5 <= 15) { \ + if (rex.is32bits) \ + TH_SWIB(reg, xRSP, imm5, 2); \ + else \ + TH_SDIB(reg, xRSP, imm5, 3); \ + } else { \ + if (rex.is32bits) \ + SW(reg, xRSP, entry - 4); \ + else \ + SD(reg, xRSP, entry - 8); \ + if (flush) ADDI(xRSP, xRSP, flush); \ + } \ + } else if (rex.is32bits) { \ + PUSH1_32(reg); \ + } else { \ + PUSH1(reg); \ + } \ + } while (0) + +#define POP1mz(reg) \ + do { \ + if ((reg) != xRSP) \ + dyn->insts[ninst].rsp_class = RSP_CLASS_POP; \ + if (dyn->insts[ninst].rsp_merge) { \ + int entry = dyn->insts[ninst].rsp_entry; \ + int flush = dyn->insts[ninst].rsp_flush; \ + if (flush && !entry) { \ + if (rex.is32bits) \ + POP1_32(reg); \ + else \ + POP1(reg); \ + } else { \ + if (rex.is32bits) \ + LWU(reg, xRSP, entry); \ + else \ + LD(reg, xRSP, entry); \ + if (flush) ADDI(xRSP, xRSP, flush); \ + } \ + } else if (rex.is32bits) { \ + POP1_32(reg); \ + } else { \ + POP1(reg); \ + } \ + } while (0) + #define PUSH1_16(reg) \ do { \ if (cpuext.xtheadmemidx && reg != xRSP) { \ @@ -601,14 +659,14 @@ ADDI(rd, rs1, imm12); \ } else { \ ADDIW(rd, rs1, imm12); \ - ZEROUP(rd); \ + ZEROUP32_RESULT(rd); \ } \ } while (0) #define ADDIy(rd, rs1, imm12) \ do { \ if (rex.is32bits || rex.is67) { \ ADDIW(rd, rs1, imm12); \ - ZEROUP(rd); \ + ZEROUP32_RESULT(rd); \ } else { \ ADDI(rd, rs1, imm12); \ } \ @@ -629,7 +687,7 @@ #define ADDSLy(rd, rs1, rs2, imm2, scratch) \ if (rex.is32bits || rex.is67) { \ ADDSL(rd, rs1, rs2, imm2, scratch); \ - ZEROUP(rd); \ + ZEROUP32_RESULT(rd); \ } else { \ ADDSL(rd, rs1, rs2, imm2, scratch); \ } @@ -649,7 +707,8 @@ SLL(rd, rs1, rs2); \ } else { \ SLLW(rd, rs1, rs2); \ - ZEROUP(rd); \ + UP32_WRITE32(rd); \ + ZEROUP_RESULT(rd); \ } \ } while (0) @@ -659,7 +718,8 @@ SRL(rd, rs1, rs2); \ } else { \ SRLW(rd, rs1, rs2); \ - ZEROUP(rd); \ + UP32_WRITE32(rd); \ + ZEROUP_RESULT(rd); \ } \ } while (0) @@ -669,7 +729,8 @@ SRA(rd, rs1, rs2); \ } else { \ SRAW(rd, rs1, rs2); \ - ZEROUP(rd); \ + UP32_WRITE32(rd); \ + ZEROUP_RESULT(rd); \ } \ } while (0) @@ -682,14 +743,16 @@ SLLI(rd, rs1, imm); \ } else { \ SLLIW(rd, rs1, imm); \ - ZEROUP(rd); \ + UP32_WRITE32(rd); \ + ZEROUP_RESULT(rd); \ } \ } while (0) #define SLLIy(rd, rs1, imm) \ do { \ if (rex.is32bits || rex.is67) { \ SLLIW(rd, rs1, imm); \ - ZEROUP(rd); \ + UP32_WRITE32(rd); \ + ZEROUP_RESULT(rd); \ } else { \ SLLI(rd, rs1, imm); \ } \ @@ -697,14 +760,17 @@ // Shift Right Logical Immediate, 32-bit, sign-extended #define SRLIW(rd, rs1, imm5) EMIT(I_type(imm5, rs1, 0b101, rd, 0b0011011)) // Shift Right Logical Immediate -#define SRLIxw(rd, rs1, imm) \ - do { \ - if (rex.w) { \ - SRLI(rd, rs1, imm); \ - } else { \ - SRLIW(rd, rs1, imm); \ - if ((imm) == 0) ZEROUP(rd); \ - } \ +#define SRLIxw(rd, rs1, imm) \ + do { \ + if (rex.w) { \ + SRLI(rd, rs1, imm); \ + } else { \ + SRLIW(rd, rs1, imm); \ + if ((imm) == 0) { \ + UP32_WRITE32(rd); \ + ZEROUP_RESULT(rd); \ + } \ + } \ } while (0) // Shift Right Arithmetic Immediate, 32-bit, sign-extended #define SRAIW(rd, rs1, imm5) EMIT(I_type((imm5) | (0b0100000 << 5), rs1, 0b101, rd, 0b0011011)) @@ -715,7 +781,8 @@ SRAI(rd, rs1, imm); \ } else { \ SRAIW(rd, rs1, imm); \ - ZEROUP(rd); \ + UP32_WRITE32(rd); \ + ZEROUP_RESULT(rd); \ } \ } while (0) diff --git a/src/dynarec/rv64/rv64_mapping.h b/src/dynarec/rv64/rv64_mapping.h index 814ad87e8..d5c16876c 100644 --- a/src/dynarec/rv64/rv64_mapping.h +++ b/src/dynarec/rv64/rv64_mapping.h @@ -69,6 +69,8 @@ x31 t6 x6 Temporary Scratch // convert a x86 register to native according to the register mapping #define TO_NAT(A) (((uint8_t[]) { 16, 13, 12, 24, 9, 8, 11, 10, 14, 15, 26, 27, 18, 19, 20, 21 })[(A)]) +// convert a native register to x86 GPR (or -1 if not a GPR), reverse of TO_NAT +#define TO_X64(A) (((int8_t[]) { -1, -1, -1, -1, -1, -1, -1, -1, 5, 4, 7, 6, 2, 1, 8, 9, 0, -1, 12, 13, 14, 15, -1, -1, 3, -1, 10, 11, -1, -1, -1, -1 })[(A)]) #define IS_GPR(A) (((uint8_t[]) { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0 })[(A)]) #define IS_SCRATCH(A) (((uint8_t[]) { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 })[(A)]) From 630c40324c3ccabb708e66a780ae36c714bc4853 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sat, 10 Oct 2026 16:13:55 +0800 Subject: [PATCH 022/156] [RV64_DYNAREC] Replaced fpu_purgecache with BARRIER_FLOAT (#4552) --- src/dynarec/rv64/dynarec_rv64_00_1.c | 1 - src/dynarec/rv64/dynarec_rv64_00_3.c | 5 ++--- src/dynarec/rv64/dynarec_rv64_0f.c | 9 ++++----- src/dynarec/rv64/dynarec_rv64_avx.c | 12 ++++++------ src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c | 2 +- src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c | 6 +++--- src/dynarec/rv64/dynarec_rv64_d9.c | 8 ++++---- src/dynarec/rv64/dynarec_rv64_dd.c | 4 ++-- 8 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_00_1.c b/src/dynarec/rv64/dynarec_rv64_00_1.c index 06fe32736..cc15e9281 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_1.c +++ b/src/dynarec/rv64/dynarec_rv64_00_1.c @@ -452,7 +452,6 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int #define GO(GETFLAGS, NO, YES, NATNO, NATYES, F) \ READFLAGS_FUSION(F, x1, x2, x3, x4, x5); \ i8 = F8S; \ - BARRIER(BARRIER_MAYBE); \ JUMP(addr + i8, 1); \ if (!dyn->insts[ninst].nat_flags_fusion) { \ GETFLAGS; \ diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 2d387731d..4d3401583 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -1151,7 +1151,6 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int addr = dynarec64_DF(dyn, addr, ip, ninst, rex, ok, need_epilog); break; #define GO(Z, R) \ - BARRIER(BARRIER_MAYBE); \ JUMP(addr + i8, 1); \ if (dyn->insts[ninst].x64.jmp_insts == -1 || CHECK_CACHE()) { \ /* out of the block */ \ @@ -1344,7 +1343,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } else { MOV64x(x2, addr); } - fpu_purgecache(dyn, ninst, 0, x1, x3, x4); + BARRIER(BARRIER_FLOAT); PUSH1z(x2); int can_continue = (addr < (dyn->start + dyn->isize)); if (BOX64DRENV(dynarec_callret)) { @@ -1415,7 +1414,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int JUMP((uintptr_t)getAlternate((void*)j64), 0); if (dyn->insts[ninst].x64.jmp_insts == -1) { // out of the block - fpu_purgecache(dyn, ninst, 1, x1, x2, x3); + BARRIER(BARRIER_FLOAT); jump_to_next(dyn, (uintptr_t)getAlternate((void*)j64), 0, ninst, rex.is32bits); } else { // inside the block diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index 16cc94958..f0a17b005 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -1974,7 +1974,6 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni j64 = (uint32_t)(addr + i32_); \ else \ j64 = addr + i32_; \ - BARRIER(BARRIER_MAYBE); \ JUMP(j64, 1); \ if (!dyn->insts[ninst].nat_flags_fusion) { \ GETFLAGS; \ @@ -2209,7 +2208,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("FXSAVE Ed"); MESSAGE(LOG_DUMP, "Need Optimization\n"); SKIPTEST(x1); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); addr = geted(dyn, addr, ninst, nextop, &ed, x1, x3, &fixedaddress, rex, NULL, 0, 0); CALL(rex.is32bits ? (const_fpu_fxsave32) : (const_fpu_fxsave64), -1, ed, 0); break; @@ -2217,7 +2216,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("FXRSTOR Ed"); MESSAGE(LOG_DUMP, "Need Optimization\n"); SKIPTEST(x1); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); addr = geted(dyn, addr, ninst, nextop, &ed, x1, x3, &fixedaddress, rex, NULL, 0, 0); CALL(rex.is32bits ? (const_fpu_fxrstor32) : (const_fpu_fxrstor64), -1, ed, 0); break; @@ -2290,7 +2289,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 4: INST_NAME("XSAVE Ed"); MESSAGE(LOG_DUMP, "Need Optimization\n"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0); MOV32w(x2, rex.is32bits); CALL(const_fpu_xsave, -1, ed, x2); @@ -2298,7 +2297,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 5: INST_NAME("XRSTOR Ed"); MESSAGE(LOG_DUMP, "Need Optimization\n"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0); MOV32w(x2, rex.is32bits); CALL(const_fpu_xrstor, -1, ed, x2); diff --git a/src/dynarec/rv64/dynarec_rv64_avx.c b/src/dynarec/rv64/dynarec_rv64_avx.c index f62c272d2..bd5f8b194 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx.c +++ b/src/dynarec/rv64/dynarec_rv64_avx.c @@ -59,7 +59,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); } else { addr = vaddr; - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); } } addr = retaddr ? retaddr : dynarec64_AVX_0F(dyn, addr, ip, ninst, vex, ok, need_epilog); @@ -72,7 +72,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); } else { addr = vaddr; - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); } } addr = retaddr ? retaddr : dynarec64_AVX_66_0F(dyn, addr, ip, ninst, vex, ok, need_epilog); @@ -85,7 +85,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); } else { addr = vaddr; - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); } } addr = retaddr ? retaddr : dynarec64_AVX_F2_0F(dyn, addr, ip, ninst, vex, ok, need_epilog); @@ -98,7 +98,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); } else { addr = vaddr; - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); } } addr = retaddr ? retaddr : dynarec64_AVX_F3_0F(dyn, addr, ip, ninst, vex, ok, need_epilog); @@ -111,7 +111,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); } else { addr = vaddr; - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); } } addr = retaddr ? retaddr : dynarec64_AVX_66_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog); @@ -130,7 +130,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); } else { addr = vaddr; - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); } } addr = retaddr ? retaddr : dynarec64_AVX_66_0F3A(dyn, addr, ip, ninst, vex, ok, need_epilog); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index 232abe931..208f7af59 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -390,7 +390,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t UDF(); break; } - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); if (vex.l) { INST_NAME("VZEROALL"); for (int i = 0; i < (rex.is32bits ? 8 : 16); ++i) { diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c index 1c14dbe33..855894266 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c @@ -42,7 +42,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint switch (opcode) { case 0x00: INST_NAME("VPSHUFB Gx, Vx, Ex"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); nextop = F8; GETVY_vector(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); @@ -1081,11 +1081,11 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint break; case 0xDC: case 0xDD: - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); return 0; case 0x13: if (!cpuext.zvfh) { - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); return 0; } INST_NAME("VCVTPH2PS Gx, Ex"); diff --git a/src/dynarec/rv64/dynarec_rv64_d9.c b/src/dynarec/rv64/dynarec_rv64_d9.c index b4f497455..c7dc92735 100644 --- a/src/dynarec/rv64/dynarec_rv64_d9.c +++ b/src/dynarec/rv64/dynarec_rv64_d9.c @@ -320,7 +320,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0xF6: INST_NAME("FDECSTP"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); LW(x2, xEmu, offsetof(x64emu_t, top)); SUBI(x2, x2, 1); ANDI(x2, x2, 7); @@ -328,7 +328,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0xF7: INST_NAME("FINCSTP"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); LW(x2, xEmu, offsetof(x64emu_t, top)); ADDI(x2, x2, 1); ANDI(x2, x2, 7); @@ -548,7 +548,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 4: INST_NAME("FLDENV Ed"); MESSAGE(LOG_DUMP, "Need Optimization\n"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE? + BARRIER(BARRIER_FLOAT); // maybe only x87, not SSE? addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0); MOV32w(x2, 0); CALL(const_fpu_loadenv, -1, ed, x2); @@ -566,7 +566,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 6: INST_NAME("FNSTENV Ed"); MESSAGE(LOG_DUMP, "Need Optimization\n"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE? + BARRIER(BARRIER_FLOAT); // maybe only x87, not SSE? addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0); MOV32w(x2, 0); CALL(const_fpu_savenv, -1, ed, x2); diff --git a/src/dynarec/rv64/dynarec_rv64_dd.c b/src/dynarec/rv64/dynarec_rv64_dd.c index c9916aebc..4991277c2 100644 --- a/src/dynarec/rv64/dynarec_rv64_dd.c +++ b/src/dynarec/rv64/dynarec_rv64_dd.c @@ -152,14 +152,14 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 4: INST_NAME("FRSTOR m108byte"); MESSAGE(LOG_DUMP, "Need Optimization (FRSTOR)\n"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); addr = geted(dyn, addr, ninst, nextop, &ed, x4, x6, &fixedaddress, rex, NULL, 0, 0); CALL(const_native_frstor, -1, ed, 0); break; case 6: INST_NAME("FNSAVE m108byte"); MESSAGE(LOG_DUMP, "Need Optimization\n"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); addr = geted(dyn, addr, ninst, nextop, &ed, x4, x6, &fixedaddress, rex, NULL, 0, 0); CALL(const_native_fsave, -1, ed, 0); NATIVE_RESTORE_X87PC(); From c5ddad2a1faec41d1904ce5ddca38557d57c56c6 Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Sat, 10 Oct 2026 16:23:55 +0800 Subject: [PATCH 023/156] [RV64_DYNAREC] Fix ADDI(x1, x1, 0xffff) and ANDI(x1, x1, 0xffff) (#4555) ``` ADDI(x1, x1, 0xffff) -> addi x1, x1, -1 ANDI(x1, x1, 0xffff) -> andi x1, x1, -1 ``` 1. Zero-extend ADC16 results before testing for zero in d_adc16 and d_adc16b. `ANDI(x4, x1, 0xffff)` may retain the upper bits. 2. Replace ANDI 0xffff masks with ZEXTH for AAM/AAD operands. 3. Use MOV32w to load the VPHMINPOSUW initial minimum explicitly as 0xffff. --- src/dynarec/rv64/dynarec_rv64_00_3.c | 6 +++--- src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c | 2 +- src/dynarec/rv64/updateflags_rv64_pass.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 4d3401583..6bce1aca7 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -1048,7 +1048,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int u8 = F8; MOV32w(x2, u8); CALL(const_aam16, x1, x1, x2); - ANDI(x1, x1, 0xffff); + ZEXTH(x1, x1); SRLI(x3, xRAX, 16); SLLI(x3, x3, 16); OR(xRAX, x3, x1); @@ -1069,11 +1069,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (rex.is32bits) { INST_NAME("AAD Ib"); SETFLAGS(X_ALL, SF_SET_DF, NAT_FLAGS_NOFUSION); - ANDI(x1, xRAX, 0xffff); + ZEXTH(x1, xRAX); u8 = F8; MOV32w(x2, u8); CALL(const_aad16, x1, x1, x2); - ANDI(x1, x1, 0xffff); + ZEXTH(x1, x1); SRLI(x3, xRAX, 16); SLLI(x3, x3, 16); OR(xRAX, x3, x1); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c index ca38759b1..db9caf816 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c @@ -1818,7 +1818,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i nextop = F8; GETEX(x2, 0, 14); GETGX(); - ADDI(x6, xZR, 0xffff); + MOV32w(x6, 0xffff); ADDI(x7, xZR, 0); for (int i = 0; i < 8; ++i) { LHU(x3, wback, fixedaddress + 2 * i); diff --git a/src/dynarec/rv64/updateflags_rv64_pass.c b/src/dynarec/rv64/updateflags_rv64_pass.c index b8ef119f8..4f447affa 100644 --- a/src/dynarec/rv64/updateflags_rv64_pass.c +++ b/src/dynarec/rv64/updateflags_rv64_pass.c @@ -645,7 +645,7 @@ SETMARK(d_adc16); LHU(x3, xEmu, offsetof(x64emu_t, op2)); SRLI(x4, x1, 16); PUTFLAG(x4, F_CF); // CF from bit 16 of the 17 bits result - ANDI(x4, x1, 0xffff); + ZEXTH(x4, x1); SRLI(x5, x4, 15); PUTFLAG(x5, F_SF); SEQZ(x5, x4); @@ -676,7 +676,7 @@ SETMARK(d_adc16b); ADD(x1, x1, x4); // recompute res as 17 bits SRLI(x4, x1, 16); PUTFLAG(x4, F_CF); - ANDI(x4, x1, 0xffff); + ZEXTH(x4, x1); SRLI(x5, x4, 15); PUTFLAG(x5, F_SF); SEQZ(x5, x4); From 343ff5f1bc1683b54dace9df83bcd0ba5bec1f66 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sat, 10 Oct 2026 22:55:48 +0800 Subject: [PATCH 024/156] [RV64_DYNAREC] Added a few more opcodes (#4556) * [RV64_DYNAREC] Added a few more opcodes * fix --- src/dynarec/rv64/dynarec_rv64_0f_vector.c | 22 +++ src/dynarec/rv64/dynarec_rv64_avx_66_0f.c | 13 ++ src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c | 31 ++++ src/dynarec/rv64/dynarec_rv64_de.c | 150 +++++++++++++++++++- src/dynarec/rv64/dynarec_rv64_f20f_vector.c | 37 +++++ 5 files changed, 251 insertions(+), 2 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_0f_vector.c index 372a9996c..52455a19a 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_0f_vector.c @@ -274,6 +274,28 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, SMWRITE2(); } break; + case 0x2C: + if (!BOX64ENV(dynarec_fastround)) return 0; + INST_NAME("CVTTPS2PI Gm, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); + GETG; + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + v1 = sse_get_reg_vector(dyn, ninst, x1, ed, 0, VECTOR_SEW32); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); + v1 = fpu_get_scratch(dyn); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 0.5); + LD(x4, ed, fixedaddress); + VMV_S_X(v1, x4); + } + v0 = mmx_get_reg_empty_vector(dyn, ninst, x1, x2, x3, gd); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 0.5); + VFCVT_RTZ_X_F_V(v0, v1, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); + break; case 0x2E: case 0x2F: return 0; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c index 14dab7efc..18d88bf72 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c @@ -171,6 +171,19 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, SD(x3, gback, gdoffset + 8); YMM0(gd); break; + case 0x17: + INST_NAME("VMOVHPD Ex, Gx"); + nextop = F8; + if (MODREG) { + DEFAULT; + return addr; + } + GETGX(); + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0); + LD(x3, gback, gdoffset + 8); + SD(x3, wback, fixedaddress); + SMWRITE2(); + break; case 0x28: INST_NAME("VMOVAPD Gx, Ex"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c index e634722a3..e386336c0 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c @@ -249,6 +249,37 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, } } break; + case 0x2D: + INST_NAME("VCVTSS2SI Gd, Ex"); + nextop = F8; + GETGDd; + d0 = fpu_get_scratch(dyn); + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + sse_forget_reg(dyn, ninst, x1, ed); + FLW(d0, xEmu, offsetof(x64emu_t, xmm[ed])); + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 0); + FLW(d0, wback, fixedaddress); + } + if (!BOX64ENV(dynarec_fastround)) { + FSFLAGSI(0); + } + u8 = sse_setround(dyn, ninst, x5, x6); + FCVTSxw(gd, d0, RD_DYN); + x87_restoreround(dyn, ninst, u8); + if (!rex.w) ZEROUP(gd); + if (!BOX64ENV(dynarec_fastround)) { + FRFLAGS(x5); + ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); + CBZ_NEXT(x5); + if (rex.w) { + MOV64x(gd, 0x8000000000000000LL); + } else { + MOV32w(gd, 0x80000000); + } + } + break; case 0x58: INST_NAME("VADDSS Gx, Vx, Ex"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_de.c b/src/dynarec/rv64/dynarec_rv64_de.c index d9cc1492e..fb971f587 100644 --- a/src/dynarec/rv64/dynarec_rv64_de.c +++ b/src/dynarec/rv64/dynarec_rv64_de.c @@ -30,10 +30,13 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni uint8_t nextop = F8; uint8_t wback; uint8_t u8; + uint8_t ed; int64_t fixedaddress; int v1, v2, s1, s2; int64_t j64; + MAYUSE(ed); + MAYUSE(v2); MAYUSE(v1); @@ -260,8 +263,151 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } else switch ((nextop >> 3) & 7) { - default: - DEFAULT; + case 0: + INST_NAME("FIADD ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5); + if (!BOX64ENV(dynarec_fastnan)) { + s1 = fpu_get_scratch(dyn); + s2 = fpu_get_scratch(dyn); + FMVD(s1, v1); + FMVD(s2, v2); + } + FADDD(v1, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + X87_ARITH_NAN_FIX_D(v1, s1, s2, x5, x6, x4); + } + X87_CHECK_PRECISION(v1); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); + break; + case 1: + INST_NAME("FIMUL ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5); + if (!BOX64ENV(dynarec_fastnan)) { + s1 = fpu_get_scratch(dyn); + s2 = fpu_get_scratch(dyn); + FMVD(s1, v1); + FMVD(s2, v2); + } + FMULD(v1, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + X87_ARITH_NAN_FIX_D(v1, s1, s2, x5, x6, x4); + } + X87_CHECK_PRECISION(v1); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); + break; + case 2: + INST_NAME("FICOM ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + FCOMD(v1, v2, x1, x2, x3, x4, x5); + break; + case 3: + INST_NAME("FICOMP ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + FCOMD(v1, v2, x1, x2, x3, x4, x5); + X87_POP_OR_FAIL(dyn, ninst, x3); + break; + case 4: + INST_NAME("FISUB ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5); + if (!BOX64ENV(dynarec_fastnan)) { + s1 = fpu_get_scratch(dyn); + s2 = fpu_get_scratch(dyn); + FMVD(s1, v1); + FMVD(s2, v2); + } + FSUBD(v1, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + X87_ARITH_NAN_FIX_D(v1, s1, s2, x5, x6, x4); + } + X87_CHECK_PRECISION(v1); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); + break; + case 5: + INST_NAME("FISUBR ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5); + if (!BOX64ENV(dynarec_fastnan)) { + s1 = fpu_get_scratch(dyn); + s2 = fpu_get_scratch(dyn); + FMVD(s1, v2); + FMVD(s2, v1); + } + FSUBD(v1, v2, v1); + if (!BOX64ENV(dynarec_fastnan)) { + X87_ARITH_NAN_FIX_D(v1, s1, s2, x5, x6, x4); + } + X87_CHECK_PRECISION(v1); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); + break; + case 6: + INST_NAME("FIDIV ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5); + if (!BOX64ENV(dynarec_fastnan)) { + s1 = fpu_get_scratch(dyn); + s2 = fpu_get_scratch(dyn); + FMVD(s1, v1); + FMVD(s2, v2); + } + FDIVD(v1, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + X87_ARITH_NAN_FIX_D(v1, s1, s2, x5, x6, x4); + } + X87_CHECK_PRECISION(v1); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); + break; + case 7: + INST_NAME("FIDIVR ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5); + if (!BOX64ENV(dynarec_fastnan)) { + s1 = fpu_get_scratch(dyn); + s2 = fpu_get_scratch(dyn); + FMVD(s1, v2); + FMVD(s2, v1); + } + FDIVD(v1, v2, v1); + if (!BOX64ENV(dynarec_fastnan)) { + X87_ARITH_NAN_FIX_D(v1, s1, s2, x5, x6, x4); + } + X87_CHECK_PRECISION(v1); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); + break; } return addr; } diff --git a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c index fc0d5bfed..0aec26e6f 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c @@ -475,6 +475,43 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VNSRL_WX(d1, v0, x4, VECTOR_UNMASKED); VFADD_VV(q0, d1, d0, VECTOR_UNMASKED); break; + case 0x7D: + INST_NAME("HSUBPS Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); + GETGX_vector(q0, 1, VECTOR_SEW32); + GETEX_vector(q1, 0, 0, VECTOR_SEW32); + v0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + d1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + VMV_V_V(v0, q0); + if (q1 & 1) VMV_V_V(d1, q1); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL2, 2); + VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); + ADDI(x4, xZR, 32); + VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); // first of each pair + VNSRL_WX(d1, v0, x4, VECTOR_UNMASKED); // second of each pair + VFSUB_VV(q0, d0, d1, VECTOR_UNMASKED); + if (!BOX64ENV(dynarec_fastnan)) { + MOV32w(x5, 0x00400000); + VOR_VX(d1, d1, x5, VECTOR_UNMASKED); // quiet(second), still NaN + VMFEQ_VV(VMASK, d1, d1, VECTOR_UNMASKED); + VMERGE_VVM(q0, d1, q0); // second is NaN -> quiet(second) + VOR_VX(d0, d0, x5, VECTOR_UNMASKED); // quiet(first), still NaN + VMFEQ_VV(VMASK, d0, d0, VECTOR_UNMASKED); + VMERGE_VVM(q0, d0, q0); // first is NaN -> quiet(first), priority + VMFEQ_VV(VMASK, d0, d0, VECTOR_UNMASKED); + VMFEQ_VV(v0, d1, d1, VECTOR_UNMASKED); + VMAND_MM(VMASK, VMASK, v0); + VMFEQ_VV(v0, q0, q0, VECTOR_UNMASKED); + VMNAND_MM(v0, v0, v0); + VMAND_MM(VMASK, VMASK, v0); // both non-NaN and result is NaN + MOV32w(x5, 0x80000000); + VOR_VX(v0, q0, x5, VECTOR_UNMASKED); + VMERGE_VVM(q0, q0, v0); // NAN -> -NAN + } + break; case 0xC2: INST_NAME("CMPSD Gx, Ex, Ib"); nextop = F8; From 397f1f1594158c6511f880b628e0972602f29f23 Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Sat, 10 Oct 2026 22:58:23 +0800 Subject: [PATCH 025/156] [RV64_DYNAREC] Optimize VMAXPS family opcodes (#4557) Use vmerge.vvm to reduce instruction counts for vmaxps family opcodes. --- src/dynarec/rv64/dynarec_rv64_0f_vector.c | 6 ++---- src/dynarec/rv64/dynarec_rv64_660f_vector.c | 6 ++---- src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c | 8 ++------ src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c | 8 ++------ 4 files changed, 8 insertions(+), 20 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_0f_vector.c index 52455a19a..c89a2c89e 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_0f_vector.c @@ -664,8 +664,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETGX_vector(q0, 1, VECTOR_SEW32); GETEX_vector(q1, 0, 0, VECTOR_SEW32); VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1F, VECTOR_UNMASKED); - VADD_VX(q0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(q0, q1, q0); break; case 0x5E: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -683,8 +682,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETGX_vector(q0, 1, VECTOR_SEW32); GETEX_vector(q1, 0, 0, VECTOR_SEW32); VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1F, VECTOR_UNMASKED); - VADD_VX(q0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(q0, q1, q0); break; case 0x60: INST_NAME("PUNPCKLBW Gm, Em"); diff --git a/src/dynarec/rv64/dynarec_rv64_660f_vector.c b/src/dynarec/rv64/dynarec_rv64_660f_vector.c index a925c548e..92b0bdd9b 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_660f_vector.c @@ -1204,8 +1204,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETGX_vector(q0, 1, VECTOR_SEW64); GETEX_vector(q1, 0, 0, VECTOR_SEW64); VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1F, VECTOR_UNMASKED); - VADD_VX(q0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(q0, q1, q0); break; case 0x5E: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -1223,8 +1222,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETGX_vector(q0, 1, VECTOR_SEW64); GETEX_vector(q1, 0, 0, VECTOR_SEW64); VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1F, VECTOR_UNMASKED); - VADD_VX(q0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(q0, q1, q0); break; case 0x60: INST_NAME("PUNPCKLBW Gx, Ex"); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index 208f7af59..c6ec7c876 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -357,10 +357,8 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t GETVY_vector(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); - VMV_V_V(v0, q0); VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1f, VECTOR_UNMASKED); - VADD_VX(v0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(v0, q1, q0); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x5E: @@ -379,10 +377,8 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t GETVY_vector(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); - VMV_V_V(v0, q0); VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1f, VECTOR_UNMASKED); - VADD_VX(v0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(v0, q1, q0); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x77: diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index 92278d489..d9d2497a1 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -318,10 +318,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt GETVY_vector(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); - VMV_V_V(v0, q0); VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1f, VECTOR_UNMASKED); - VADD_VX(v0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(v0, q1, q0); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x5E: @@ -340,10 +338,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt GETVY_vector(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); - VMV_V_V(v0, q0); VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1f, VECTOR_UNMASKED); - VADD_VX(v0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(v0, q1, q0); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x60: From c6a8c4472f74f9ad204d35195f084b5f996b12e3 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sun, 11 Oct 2026 00:08:03 +0800 Subject: [PATCH 026/156] [RV64_DYNAREC] Fixed a few lock opcodes (#4558) --- src/dynarec/rv64/dynarec_rv64_f0.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_f0.c b/src/dynarec/rv64/dynarec_rv64_f0.c index 72c3ce996..fd1c7276b 100644 --- a/src/dynarec/rv64/dynarec_rv64_f0.c +++ b/src/dynarec/rv64/dynarec_rv64_f0.c @@ -598,12 +598,12 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni B_MARK3_nocond; MARK; SLLI(x3, x3, 3); - ADDI(x4, xZR, 0xff); ANDI(x1, wback, ~3); // aligning address (into scratch, wback may be a live guest reg) - SLL(x4, x4, x3); // x4 = byte mask - NOT(x5, x4); // x5 = ~mask SLL(x2, x2, x3); // x2 = extented Gb MARK2; + ADDI(x4, xZR, 0xff); // x4 = byte mask (recomputed on SC retry: x4/x5 are clobbered in the loop) + SLL(x4, x4, x3); + NOT(x5, x4); // x5 = ~mask LR_W(x6, x1, 1, 1); // x6 = Ed AND(x7, x6, x4); // x7 = extended Ed.b[dest] AND(x6, x6, x5); // x6 = clear Ed.b[dest] @@ -825,12 +825,12 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); addr = geted(dyn, addr, ninst, nextop, &wback, x5, x1, &fixedaddress, rex, LOCK_LOCK, 0, 1); u8 = F8; - ANDI(x6, xFlags, 1 << F_CF); // carry-in, read once - ADDI(x7, x6, u8); // imm + carry ANDI(x2, wback, 3); SLLI(x2, x2, 3); // offset in bits ANDI(x3, wback, ~3); // aligned addr MARKLOCK; + ANDI(x7, xFlags, 1 << F_CF); // carry-in (recomputed on SC retry: x7 is clobbered in the loop) + ADDI(x7, x7, u8); // imm + carry LR_W(x4, x3, 1, 1); SRL(x6, x4, x2); ANDI(x6, x6, 0xFF); // x6 = old byte @@ -890,12 +890,12 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); addr = geted(dyn, addr, ninst, nextop, &wback, x5, x1, &fixedaddress, rex, LOCK_LOCK, 0, 1); u8 = F8; - ANDI(x6, xFlags, 1 << F_CF); // borrow-in, read once - ADDI(x7, x6, u8); // imm + borrow ANDI(x2, wback, 3); SLLI(x2, x2, 3); // offset in bits ANDI(x3, wback, ~3); // aligned addr MARKLOCK; + ANDI(x7, xFlags, 1 << F_CF); // borrow-in (recomputed on SC retry: x7 is clobbered in the loop) + ADDI(x7, x7, u8); // imm + borrow LR_W(x4, x3, 1, 1); SRL(x6, x4, x2); ANDI(x6, x6, 0xFF); // x6 = old byte From ee03a07a17d79e0e3163b30f17eb47b531abe8d4 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 12 Oct 2026 14:46:03 +0800 Subject: [PATCH 027/156] [RV64_DYNAREC] Fixed some recently introduced issues (#4560) * [RV64_DYNAREC] Fixed HSUBPS !fastnan handling * [RV64_DYNAREC] Fixed a missing up32 marker * [RV64_DYNAREC] Fixed a few scalar AVX GETEX offsets * [RV64_DYNAREC] Fixed MARKF confliction --- src/dynarec/rv64/dynarec_rv64_0f.c | 1 + src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c | 8 +++--- src/dynarec/rv64/dynarec_rv64_f20f_vector.c | 25 ++++++++----------- src/dynarec/rv64/dynarec_rv64_helper.h | 27 ++++++++++++--------- src/dynarec/rv64/dynarec_rv64_private.h | 1 + 5 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index f0a17b005..b1e3cf741 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -2397,6 +2397,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); nextop = F8; GETGD; + MARKREGs(xRAX); MVxw(x7, xRAX); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c index db9caf816..967fca6f0 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c @@ -1484,7 +1484,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i INST_NAME("VPMINSB Gx, Vx, Ex"); nextop = F8; GETGX(); - GETEX(x2, 0, vex.l ? 28 : 12); + GETEX(x2, 0, vex.l ? 31 : 15); GETVX(); GETGY(); GETVY(); @@ -1554,7 +1554,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i INST_NAME("VPMINUW Gx, Vx, Ex"); nextop = F8; GETGX(); - GETEX(x2, 0, vex.l ? 28 : 12); + GETEX(x2, 0, vex.l ? 30 : 14); GETVX(); GETGY(); GETVY(); @@ -1624,7 +1624,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i INST_NAME("VPMAXSB Gx, Vx, Ex"); nextop = F8; GETGX(); - GETEX(x2, 0, vex.l ? 28 : 12); + GETEX(x2, 0, vex.l ? 31 : 15); GETVX(); GETGY(); GETVY(); @@ -1694,7 +1694,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i INST_NAME("VPMAXUW Gx, Vx, Ex"); nextop = F8; GETGX(); - GETEX(x2, 0, vex.l ? 28 : 12); + GETEX(x2, 0, vex.l ? 30 : 14); GETVX(); GETGY(); GETVY(); diff --git a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c index 0aec26e6f..e634df71b 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c @@ -494,22 +494,17 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VNSRL_WX(d1, v0, x4, VECTOR_UNMASKED); // second of each pair VFSUB_VV(q0, d0, d1, VECTOR_UNMASKED); if (!BOX64ENV(dynarec_fastnan)) { - MOV32w(x5, 0x00400000); - VOR_VX(d1, d1, x5, VECTOR_UNMASKED); // quiet(second), still NaN - VMFEQ_VV(VMASK, d1, d1, VECTOR_UNMASKED); - VMERGE_VVM(q0, d1, q0); // second is NaN -> quiet(second) - VOR_VX(d0, d0, x5, VECTOR_UNMASKED); // quiet(first), still NaN - VMFEQ_VV(VMASK, d0, d0, VECTOR_UNMASKED); - VMERGE_VVM(q0, d0, q0); // first is NaN -> quiet(first), priority - VMFEQ_VV(VMASK, d0, d0, VECTOR_UNMASKED); - VMFEQ_VV(v0, d1, d1, VECTOR_UNMASKED); - VMAND_MM(VMASK, VMASK, v0); - VMFEQ_VV(v0, q0, q0, VECTOR_UNMASKED); - VMNAND_MM(v0, v0, v0); - VMAND_MM(VMASK, VMASK, v0); // both non-NaN and result is NaN MOV32w(x5, 0x80000000); - VOR_VX(v0, q0, x5, VECTOR_UNMASKED); - VMERGE_VVM(q0, q0, v0); // NAN -> -NAN + VMFEQ_VV(VMASK, q0, q0, VECTOR_UNMASKED); + VMNAND_MM(VMASK, VMASK, VMASK); + VOR_VX(q0, q0, x5, VECTOR_MASKED); + MOV32w(x5, 0x00400000); + VMFNE_VV(VMASK, d1, d1, VECTOR_UNMASKED); // isnan(second), on the original value + VOR_VX(d1, d1, x5, VECTOR_UNMASKED); // quiet(second) + VMERGE_VVM(q0, q0, d1); // second is NaN -> quiet(second) + VMFNE_VV(VMASK, d0, d0, VECTOR_UNMASKED); // isnan(first), on the original value + VOR_VX(d0, d0, x5, VECTOR_UNMASKED); // quiet(first) + VMERGE_VVM(q0, q0, d0); // first is NaN -> quiet(first), priority } break; case 0xC2: diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index a6e304ffd..b291eec5a 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -892,6 +892,9 @@ #define MARKF2 MARKFi(1) #define GETMARKF2 GETMARKFi(1) +#define MARKFNAN dyn->insts[ninst].markfnan = dyn->native_size +#define GETMARKFNAN dyn->insts[ninst].markfnan + #define MARKSEG dyn->insts[ninst].markseg = dyn->native_size #define GETMARKSEG dyn->insts[ninst].markseg #define MARKLOCK dyn->insts[ninst].marklock = dyn->native_size @@ -1047,7 +1050,7 @@ BNE_MARK2(xs, xZR); \ FEQS(xt, vb, vb); \ FMVS(v1, va); \ - Bxx_gen(NE, MARKF, xt, xZR); \ + Bxx_gen(NE, MARKFNAN, xt, xZR); \ FMVXW(xs, va); \ SLLIW(xs, xs, 9); \ SRLIW(xs, xs, 9); \ @@ -1058,25 +1061,25 @@ BEQ_MARKLOCK(xs, xt); \ Bxx_gen(LTU, MARKLOCK2, xs, xt); \ FMVS(v1, va); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARKLOCK2; \ FMVS(v1, vb); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARKLOCK; \ FMVXW(xs, va); \ SRLIW(xs, xs, 31); \ BNEZ_MARKLOCK2(xs); \ FMVS(v1, va); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARK2; \ FEQS(xt, vb, vb); \ BNE_MARK3(xt, xZR); \ FMVS(v1, vb); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARK3; \ FNEGS(v1, v1); \ Bxx_gen(__, MARK, 0, 0); \ - MARKF; \ + MARKFNAN; \ FMVXW(xs, v1); \ BSETI(xs, xs, 22, xq); \ FMVWX(v1, xs); \ @@ -1091,7 +1094,7 @@ BNE_MARK2(xs, xZR); \ FEQD(xt, vb, vb); \ FMVD(v1, va); \ - Bxx_gen(NE, MARKF, xt, xZR); \ + Bxx_gen(NE, MARKFNAN, xt, xZR); \ FMVXD(xs, va); \ SLLI(xs, xs, 12); \ BSETI(xs, xs, 63, xq); \ @@ -1100,25 +1103,25 @@ BEQ_MARKLOCK(xs, xt); \ Bxx_gen(LTU, MARKLOCK2, xs, xt); \ FMVD(v1, va); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARKLOCK2; \ FMVD(v1, vb); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARKLOCK; \ FMVXD(xs, va); \ SRLI(xs, xs, 63); \ BNEZ_MARKLOCK2(xs); \ FMVD(v1, va); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARK2; \ FEQD(xt, vb, vb); \ BNE_MARK3(xt, xZR); \ FMVD(v1, vb); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARK3; \ FNEGD(v1, v1); \ Bxx_gen(__, MARK, 0, 0); \ - MARKF; \ + MARKFNAN; \ FMVXD(xs, v1); \ BSETI(xs, xs, 51, xq); \ FMVDX(v1, xs); \ diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index 99796863f..c34fc131f 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -115,6 +115,7 @@ typedef struct instruction_rv64_s { int *pred; // predecessor array uintptr_t mark[4]; uintptr_t markf[2]; + uintptr_t markfnan; uintptr_t markseg; uintptr_t marklock; uintptr_t marklock2; From 7de6142c989c1854fa2c1feeeac6a2e41b6a8010 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 12 Oct 2026 18:15:14 +0800 Subject: [PATCH 028/156] [DYNAREC] Write back the fpu cache before an instruction following unused opcodes (#4561) No code is emitted for the unused opcodes, so the native registers keep their live values across them. The fpu cache state used to be dropped there, so those live values could not be written back when a block was left on a fault (like a write to a protected code page): the cached x87/mmx/sse registers were lost. Write the dirty registers back to emu right before the next emitted instruction runs, keeping the cache valid (next=1). The write back is emitted at that instruction entry, so a jump to it runs it too. --- src/dynarec/dynarec_native_pass.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index 2c159beec..a681c1e30 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -119,6 +119,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int fpu_reset(dyn); ARCH_INIT(); int reset_n = -1; // -1 no reset; -2 reset to 0; else reset to the state of reset_n + int pending_fpu_purge = 0; // fpu cache must be written back before the next emitted instruction #if defined(HAVE_LEAFCALL) dyn->last_ip = (dyn->inline_leaf || alternate || (dyn->insts && dyn->insts[0].pred_sz)) ? 0 : ip; // RIP is always set at start of ordinary blocks unless there is a predecessor! #else @@ -226,6 +227,14 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int if(dyn->insts[ninst].x64.alive && dyn->insts[ninst].x64.self_loop) CALLRET_LOOP(); #endif + if (pending_fpu_purge) { + pending_fpu_purge = 0; + #if defined(RV64) || defined(LA64) || defined(PPC64LE) + fpu_purgecache(dyn, ninst, 1, x1, x2, x3); + #else + fpu_purgecache(dyn, ninst, 1, x1, x2, x3, 0); + #endif + } if(!ninst) { GOTEST(x1, x2); } @@ -386,6 +395,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int addr += dyn->insts[ninst].x64.size; INST_EPILOG; } + pending_fpu_purge = 1; } if((dyn->insts[ninst+1].x64.barrier&BARRIER_FULL)==BARRIER_FULL) reset_n = -2; // hack to say Barrier! From 0684e43871c642f218f20aa8df5816ca755e49aa Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Mon, 12 Oct 2026 18:47:29 +0800 Subject: [PATCH 029/156] [RV64_DYNAREC] Fix PUSHAD and signal state recovery if rsp_merge is enabled (#4562) 1. Save the sp value in PUSHAD by using the pending rsp_entry offset instead of the stale xRSP value if rsp_merge is enabled. 2. During signal recovery, use the `arch` entry for `ninst` when restoring rsp/up32, and the `prev_arch` entry for `ninst-1` when restoring FPU. --- src/dynarec/rv64/dynarec_rv64_00_1.c | 1 + src/dynarec/rv64/dynarec_rv64_arch.c | 17 ++++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_00_1.c b/src/dynarec/rv64/dynarec_rv64_00_1.c index cc15e9281..fe786fdc9 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_1.c +++ b/src/dynarec/rv64/dynarec_rv64_00_1.c @@ -119,6 +119,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ZEXTW2(x1, xRSP); if (dyn->insts[ninst].rsp_merge && !(cpuext.xtheadmemidx && dyn->insts[ninst].rsp_flush && !dyn->insts[ninst].rsp_entry)) { int entry = dyn->insts[ninst].rsp_entry; + if (entry) ADDIW(x1, x1, entry); SW(xRAX, xRSP, entry - 4); SW(xRCX, xRSP, entry - 8); SW(xRDX, xRSP, entry - 12); diff --git a/src/dynarec/rv64/dynarec_rv64_arch.c b/src/dynarec/rv64/dynarec_rv64_arch.c index 4b926664c..15d163816 100644 --- a/src/dynarec/rv64/dynarec_rv64_arch.c +++ b/src/dynarec/rv64/dynarec_rv64_arch.c @@ -306,7 +306,7 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) return; int ninst = getX64AddressInst(db, x64pc); dynarec_log(LOG_INFO, "adjust_arch(...), db=%p, x64pc=%p, nints=%d", db, (void*)x64pc, ninst); - if(ninst<0) { + if(ninst<0 || ninst >= db->isize) { dynarec_log(LOG_INFO, "\n"); return; } @@ -315,23 +315,26 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) CHECK_FLAGS(emu); return; } - // look for state at ninst-1 + // look for state at ninst. arch_arch_t* arch = db->arch; + // look for state at ninst-1. + arch_arch_t* prev_arch = arch; arch_arch_t* next = arch; #define GO(A) arch_##A##_t* A = NULL; SUPER() #undef GO - int i = 0; - while(iseq; dynarec_log(LOG_INFO, "[ seq=%d%s%s%s%s%s ] ", arch->seq, arch->flags?" Flags":"", arch->x87?" x87":"", arch->mmx?" MMX":"", arch->sse?" SSE":"", arch->ymm?" YMM":""); next = (arch_arch_t*)((uintptr_t)next + sizeof_arch(arch)); } int sz = sizeof(arch_arch_t); #define GO(A) \ - if(arch->A) { \ - A = (arch_##A##_t*)((uintptr_t)arch + sz); \ + if(prev_arch->A) { \ + A = (arch_##A##_t*)((uintptr_t)prev_arch + sz); \ sz+=sizeof(arch_##A##_t); \ } SUPER() @@ -412,7 +415,7 @@ int arch_unaligned(dynablock_t* db, uintptr_t x64pc) if(!db->arch_size || !db->arch) return 0; int ninst = getX64AddressInst(db, x64pc); - if(ninst<0) { + if(ninst<0 || ninst >= db->isize) { return 0; } // look for state at ninst From 93cda37aa6c060a34090cf6464e6c768394630be Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 13 Oct 2026 14:00:15 +0800 Subject: [PATCH 030/156] [INTERP] Fixed some over reads in cosim (#4563) --- src/emu/modrm.h | 8 +- src/emu/x64run0f.c | 16 +- src/emu/x64run660f.c | 378 +++++++++++++++++++-------------------- src/emu/x64run_private.c | 26 +++ src/emu/x64run_private.h | 2 + src/emu/x64runf30f.c | 16 +- 6 files changed, 240 insertions(+), 206 deletions(-) diff --git a/src/emu/modrm.h b/src/emu/modrm.h index b46576428..7bc144c91 100644 --- a/src/emu/modrm.h +++ b/src/emu/modrm.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT #include #define F8 *(uint8_t*)(addr++) @@ -25,6 +25,8 @@ #ifdef TEST_INTERPRETER #define GETED(D) oped=TestEd(test, &addr, rex, nextop, D) +#define GETE1(D) oped=TestEd1(test, &addr, rex, nextop, D) +#define GETE2(D) oped=TestEd2(test, &addr, rex, nextop, D) #define GETE4(D) oped=TestEd4(test, &addr, rex, nextop, D) #define GETE8(D) oped=TestEd8(test, &addr, rex, nextop, D) #define GETET(D) oped=TestEdt(test, &addr, rex, nextop, D) @@ -35,6 +37,7 @@ #define GETEW(D) oped=TestEw(test, &addr, rex, nextop, D) #define GETGW opgd=GetGw(test->emu, &addr, rex, nextop) #define GETEX(D) opex=TestEx(test, &addr, rex, nextop, D, 16) +#define GETEX2(D) opex=TestEx(test, &addr, rex, nextop, D, 2) #define GETEX4(D) opex=TestEx(test, &addr, rex, nextop, D, 4) #define GETEX8(D) opex=TestEx(test, &addr, rex, nextop, D, 8) #define GETGX opgx=GetGx(test->emu, &addr, rex, nextop) @@ -47,6 +50,8 @@ #define GETVD opvd=&test->emu->regs[vex.v] #else #define GETED(D) oped=GetEd(emu, &addr, rex, nextop, D) +#define GETE1(D) GETED(D) +#define GETE2(D) GETED(D) #define GETE4(D) GETED(D) #define GETE8(D) GETED(D) #define GETET(D) GETED(D) @@ -57,6 +62,7 @@ #define GETEW(D) oped=GetEw(emu, &addr, rex, nextop, D) #define GETGW opgd=GetGw(emu, &addr, rex, nextop) #define GETEX(D) opex=GetEx(emu, &addr, rex, nextop, D) +#define GETEX2(D) GETEX(D) #define GETEX4(D) GETEX(D) #define GETEX8(D) GETEX(D) #define GETGX opgx=GetGx(emu, &addr, rex, nextop) diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c index 23a97dee2..5efea698a 100644 --- a/src/emu/x64run0f.c +++ b/src/emu/x64run0f.c @@ -271,7 +271,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) if(MODREG) { EmitSignal(emu, X64_SIGILL, (void*)R_RIP, 0); } else { - GETEX(0); + GETEX8(0); GETGX; EX->q[0] = GX->q[0]; } @@ -295,7 +295,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) break; case 0x16: /* MOVHPS Gx,Ex */ nextop = F8; /* MOVLHPS Gx,Ex (Ex==reg) */ - GETEX(0); + GETEX8(0); GETGX; GX->q[1] = EX->q[0]; break; @@ -304,7 +304,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) if(MODREG) { EmitSignal(emu, X64_SIGILL, (void*)R_RIP, 0); } else { - GETEX(0); + GETEX8(0); GETGX; EX->q[0] = GX->q[1]; } @@ -385,7 +385,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) break; case 0x2C: /* CVTTPS2PI Gm, Ex */ nextop = F8; - GETEX(0); + GETEX8(0); GETGM; tmp64s = EX->f[1]; if (tmp64s==(int32_t)tmp64s && !isnanf(EX->f[1])) @@ -405,7 +405,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) case 0x2D: /* CVTPS2PI Gm, Ex */ // rounding should be done; and indefinite integer should also be assigned if overflow or NaN/Inf nextop = F8; - GETEX(0); + GETEX8(0); GETGM; for(int i=1; i>=0; --i) { if(isnanf(EX->f[i])) @@ -442,7 +442,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) case 0x2F: /* COMISS Gx, Ex */ RESET_FLAGS(emu); nextop = F8; - GETEX(0); + GETEX4(0); GETGX; if(isnanf(GX->f[0]) || isnanf(EX->f[0])) { SET_FLAG(F_ZF); SET_FLAG(F_PF); SET_FLAG(F_CF); @@ -887,7 +887,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) break; case 0x5A: /* CVTPS2PD Gx, Ex */ nextop = F8; - GETEX(0); + GETEX8(0); GETGX; #ifdef RV64 for(int i=1; i>=0; --i) { @@ -1839,7 +1839,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) break; case 0xC4: /* PINSRW Gm,Ew,Ib */ nextop = F8; - GETED(1); + GETE2(1); GETGM; tmp8u = F8; GM->uw[tmp8u&3] = ED->word[0]; // only low 16bits diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c index 7da72c75a..a6bb2f8e3 100644 --- a/src/emu/x64run660f.c +++ b/src/emu/x64run660f.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT #define _GNU_SOURCE #include #include @@ -28,7 +28,7 @@ #include "modrm.h" #include "x64compstrings.h" -#include "random.h" +#include "random.h" static uint8_t ff_mult(uint8_t a, uint8_t b) { @@ -285,7 +285,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0x2F: /* COMISD Gx, Ex */ RESET_FLAGS(emu); nextop = F8; - GETEX(0); + GETEX8(0); GETGX; if(isnan(GX->d[0]) || isnan(EX->d[0])) { SET_FLAG(F_ZF); SET_FLAG(F_PF); SET_FLAG(F_CF); @@ -520,35 +520,35 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 0x21: /* PMOVSXBD Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; for(int i=3; i>=0; --i) GX->sd[i] = EX->sb[i]; break; case 0x22: /* PMOVSXBQ Gx, Ex */ nextop = F8; - GETEX(0); + GETEX2(0); GETGX; for(int i=1; i>=0; --i) GX->sq[i] = EX->sb[i]; break; case 0x23: /* PMOVSXWD Gx, Ex */ nextop = F8; - GETEX(0); + GETEX8(0); GETGX; for(int i=3; i>=0; --i) GX->sd[i] = EX->sw[i]; break; case 0x24: /* PMOVSXWQ Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; for(int i=1; i>=0; --i) GX->sq[i] = EX->sw[i]; break; case 0x25: /* PMOVSXDQ Gx, Ex */ nextop = F8; - GETEX(0); + GETEX8(0); GETGX; for(int i=1; i>=0; --i) GX->sq[i] = EX->sd[i]; @@ -599,35 +599,35 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 0x31: /* PMOVZXBD Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; for(int i=3; i>=0; --i) GX->ud[i] = EX->ub[i]; break; case 0x32: /* PMOVZXBQ Gx, Ex */ nextop = F8; - GETEX(0); + GETEX2(0); GETGX; for(int i=1; i>=0; --i) GX->q[i] = EX->ub[i]; break; case 0x33: /* PMOVZXWD Gx, Ex */ nextop = F8; - GETEX(0); + GETEX8(0); GETGX; for(int i=3; i>=0; --i) GX->ud[i] = EX->uw[i]; break; case 0x34: /* PMOVZXWQ Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; for(int i=1; i>=0; --i) GX->q[i] = EX->uw[i]; break; case 0x35: /* PMOVZXDQ Gx, Ex */ nextop = F8; - GETEX(0); + GETEX8(0); GETGX; for(int i=1; i>=0; --i) GX->q[i] = EX->ud[i]; @@ -897,45 +897,45 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) tmp8u &= 3; switch(tmp8u) { case ROUND_Nearest: { - int round = fegetround(); - fesetround(FE_TONEAREST); - for(int i=0; i<4; ++i) - #ifdef RV64 - if(isnanf(EX->f[i])) - GX->ud[i] = EX->ud[i] | 0x00400000; - else - #endif - GX->f[i] = nearbyintf(EX->f[i]); - fesetround(round); - break; - } - case ROUND_Down: - for(int i=0; i<4; ++i) - #ifdef RV64 - if(isnanf(EX->f[i])) - GX->ud[i] = EX->ud[i] | 0x00400000; - else - #endif - GX->f[i] = floorf(EX->f[i]); - break; - case ROUND_Up: - for(int i=0; i<4; ++i) - #ifdef RV64 - if(isnanf(EX->f[i])) - GX->ud[i] = EX->ud[i] | 0x00400000; - else - #endif - GX->f[i] = ceilf(EX->f[i]); - break; - case ROUND_Chop: - for(int i=0; i<4; ++i) - #ifdef RV64 - if(isnanf(EX->f[i])) - GX->ud[i] = EX->ud[i] | 0x00400000; - else - #endif - GX->f[i] = truncf(EX->f[i]); - break; + int round = fegetround(); + fesetround(FE_TONEAREST); + for(int i=0; i<4; ++i) + #ifdef RV64 + if(isnanf(EX->f[i])) + GX->ud[i] = EX->ud[i] | 0x00400000; + else + #endif + GX->f[i] = nearbyintf(EX->f[i]); + fesetround(round); + break; + } + case ROUND_Down: + for(int i=0; i<4; ++i) + #ifdef RV64 + if(isnanf(EX->f[i])) + GX->ud[i] = EX->ud[i] | 0x00400000; + else + #endif + GX->f[i] = floorf(EX->f[i]); + break; + case ROUND_Up: + for(int i=0; i<4; ++i) + #ifdef RV64 + if(isnanf(EX->f[i])) + GX->ud[i] = EX->ud[i] | 0x00400000; + else + #endif + GX->f[i] = ceilf(EX->f[i]); + break; + case ROUND_Chop: + for(int i=0; i<4; ++i) + #ifdef RV64 + if(isnanf(EX->f[i])) + GX->ud[i] = EX->ud[i] | 0x00400000; + else + #endif + GX->f[i] = truncf(EX->f[i]); + break; } break; case 0x09: // ROUNDPD Gx, Ex, u8 @@ -948,46 +948,46 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) else tmp8u &= 3; switch(tmp8u) { - case ROUND_Nearest: { - int round = fegetround(); - fesetround(FE_TONEAREST); - for(int i=0; i<2; ++i) - #ifdef RV64 - if(isnan(EX->d[i])) - GX->q[i] = EX->q[i] | 0x0008000000000000ULL; - else - #endif - GX->d[i] = nearbyint(EX->d[i]); - fesetround(round); - break; - } - case ROUND_Down: - for(int i=0; i<2; ++i) - #ifdef RV64 - if(isnan(EX->d[i])) - GX->q[i] = EX->q[i] | 0x0008000000000000ULL; - else - #endif - GX->d[i] = floor(EX->d[i]); - break; - case ROUND_Up: - for(int i=0; i<2; ++i) - #ifdef RV64 - if(isnan(EX->d[i])) - GX->q[i] = EX->q[i] | 0x0008000000000000ULL; - else - #endif - GX->d[i] = ceil(EX->d[i]); - break; - case ROUND_Chop: - for(int i=0; i<2; ++i) - #ifdef RV64 - if(isnan(EX->d[i])) - GX->q[i] = EX->q[i] | 0x0008000000000000ULL; - else - #endif - GX->d[i] = trunc(EX->d[i]); - break; + case ROUND_Nearest: { + int round = fegetround(); + fesetround(FE_TONEAREST); + for(int i=0; i<2; ++i) + #ifdef RV64 + if(isnan(EX->d[i])) + GX->q[i] = EX->q[i] | 0x0008000000000000ULL; + else + #endif + GX->d[i] = nearbyint(EX->d[i]); + fesetround(round); + break; + } + case ROUND_Down: + for(int i=0; i<2; ++i) + #ifdef RV64 + if(isnan(EX->d[i])) + GX->q[i] = EX->q[i] | 0x0008000000000000ULL; + else + #endif + GX->d[i] = floor(EX->d[i]); + break; + case ROUND_Up: + for(int i=0; i<2; ++i) + #ifdef RV64 + if(isnan(EX->d[i])) + GX->q[i] = EX->q[i] | 0x0008000000000000ULL; + else + #endif + GX->d[i] = ceil(EX->d[i]); + break; + case ROUND_Chop: + for(int i=0; i<2; ++i) + #ifdef RV64 + if(isnan(EX->d[i])) + GX->q[i] = EX->q[i] | 0x0008000000000000ULL; + else + #endif + GX->d[i] = trunc(EX->d[i]); + break; } break; case 0x0A: // ROUNDSS Gx, Ex, u8 @@ -1024,18 +1024,18 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) break; } break; - case 0x0B: // ROUNDSD Gx, Ex, u8 - nextop = F8; - GETEX(1); - GETGX; - tmp8u = F8; // ignoring bit 3 interupt thingy - #ifdef RV64 - if(isnan(EX->d[0])) { - GX->q[0] = EX->q[0] | 0x0008000000000000ULL; - break; - } - #endif - if(tmp8u&4) + case 0x0B: // ROUNDSD Gx, Ex, u8 + nextop = F8; + GETEX(1); + GETGX; + tmp8u = F8; // ignoring bit 3 interupt thingy + #ifdef RV64 + if(isnan(EX->d[0])) { + GX->q[0] = EX->q[0] | 0x0008000000000000ULL; + break; + } + #endif + if(tmp8u&4) tmp8u = emu->mxcsr.f.MXCSR_RC; else tmp8u &= 3; @@ -1150,7 +1150,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0x20: // PINSRB GX, ED, u8 nextop = F8; - GETED(1); // It's ED, and not EB + GETE1(1); GETGX; tmp8u = F8; GX->ub[tmp8u&0xf] = ED->byte[0]; @@ -1177,11 +1177,11 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) GX->ud[tmp8u&0x3] = ED->dword[0]; break; - case 0x40: { /* DPPS Gx, Ex, Ib */ + case 0x40: { /* DPPS Gx, Ex, Ib */ nextop = F8; GETEX(1); GETGX; - int oldround = mxcsr_setround(emu); + int oldround = mxcsr_setround(emu); tmp8u = F8; tmpf = 0.0f; for(int i=0; i<4; ++i) @@ -1189,14 +1189,14 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) tmpf += GX->f[i]*EX->f[i]; for(int i=0; i<4; ++i) GX->f[i] = (tmp8u&(1<d[1]*EX->d[1]; GX->d[0] = (tmp8u&(1<<(0)))?tmpd:0.0; GX->d[1] = (tmp8u&(1<<(1)))?tmpd:0.0; - fesetround(oldround); - } - break; + fesetround(oldround); + } + break; case 0x42: /* MPSADBW Gx, Ex, Ib */ nextop = F8; GETEX(1); @@ -1435,28 +1435,28 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) fesetround(oldround); } break; - case 0x5A: { /* CVTPD2PS Gx, Ex */ - nextop = F8; - GETEX(0); - GETGX; - int oldround = mxcsr_setround(emu); - #ifdef RV64 - for (int i = 0; i < 2; ++i) { - if (isnan(EX->d[i])) - GX->ud[i] = ((EX->q[i] >> 32) & 0x80000000) - | ((EX->q[i] >> 29) & 0x007fffff) - | 0x7fc00000; - else - GX->f[i] = EX->d[i]; - } - #else - GX->f[0] = EX->d[0]; - GX->f[1] = EX->d[1]; - #endif - GX->q[1] = 0; - fesetround(oldround); - } - break; + case 0x5A: { /* CVTPD2PS Gx, Ex */ + nextop = F8; + GETEX(0); + GETGX; + int oldround = mxcsr_setround(emu); + #ifdef RV64 + for (int i = 0; i < 2; ++i) { + if (isnan(EX->d[i])) + GX->ud[i] = ((EX->q[i] >> 32) & 0x80000000) + | ((EX->q[i] >> 29) & 0x007fffff) + | 0x7fc00000; + else + GX->f[i] = EX->d[i]; + } + #else + GX->f[0] = EX->d[0]; + GX->f[1] = EX->d[1]; + #endif + GX->q[1] = 0; + fesetround(oldround); + } + break; case 0x5B: /* CVTPS2DQ Gx, Ex */ nextop = F8; GETEX(0); @@ -1850,11 +1850,11 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) } break; - case 0x7C: { /* HADDPD Gx, Ex */ + case 0x7C: { /* HADDPD Gx, Ex */ nextop = F8; GETEX(0); GETGX; - int oldround = mxcsr_setround(emu); + int oldround = mxcsr_setround(emu); if(isnan(GX->d[0])) { GX->q[0] |= 0x0008000000000000ULL; } else if(isnan(GX->d[1])) { @@ -1862,12 +1862,12 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) } else { GX->d[0] += GX->d[1]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; - } - if(EX==GX) { - GX->q[1] = GX->q[0]; - } else { - if(isnan(EX->d[0])) { - GX->q[1] = EX->q[0] | 0x0008000000000000ULL; + } + if(EX==GX) { + GX->q[1] = GX->q[0]; + } else { + if(isnan(EX->d[0])) { + GX->q[1] = EX->q[0] | 0x0008000000000000ULL; } else if(isnan(EX->d[1])) { GX->q[1] = EX->q[1] | 0x0008000000000000ULL; } else { @@ -1875,14 +1875,14 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) if(isnan(GX->d[1])) GX->q[1] |= 0x8000000000000000ULL; } } - fesetround(oldround); - } - break; - case 0x7D: { /* HSUBPD Gx, Ex */ + fesetround(oldround); + } + break; + case 0x7D: { /* HSUBPD Gx, Ex */ nextop = F8; GETEX(0); GETGX; - int oldround = mxcsr_setround(emu); + int oldround = mxcsr_setround(emu); if(isnan(GX->d[0])) { GX->q[0] |= 0x0008000000000000ULL; } else if(isnan(GX->d[1])) { @@ -1890,12 +1890,12 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) } else { GX->d[0] -= GX->d[1]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; - } - if(EX==GX) { - GX->q[1] = GX->q[0]; - } else { - if(isnan(EX->d[0])) { - GX->q[1] = EX->q[0] | 0x0008000000000000ULL; + } + if(EX==GX) { + GX->q[1] = GX->q[0]; + } else { + if(isnan(EX->d[0])) { + GX->q[1] = EX->q[0] | 0x0008000000000000ULL; } else if(isnan(EX->d[1])) { GX->q[1] = EX->q[1] | 0x0008000000000000ULL; } else { @@ -1903,9 +1903,9 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) if(isnan(GX->d[1])) GX->q[1] |= 0x8000000000000000ULL; } } - fesetround(oldround); - } - break; + fesetround(oldround); + } + break; case 0x7E: /* MOVD Ed, Gx */ nextop = F8; GETED(0); @@ -2379,7 +2379,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xC4: /* PINSRW Gx,Ew,Ib */ nextop = F8; - GETED(1); + GETE2(1); GETGX; tmp8u = F8; GX->uw[tmp8u&7] = ED->word[0]; // only low 16bits @@ -2402,30 +2402,30 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) GX->q[1] = eax1.q[1]; break; - case 0xC7: - CHECK_FLAGS(emu); - nextop = F8; - GETE8xw(0); - if (MODREG) - switch ((nextop >> 3) & 7) { - case 6: /* RDRAND Ew */ - case 7: /* RDSEED Ew */ - RESET_FLAGS(emu); - CLEAR_FLAG(F_OF); - CLEAR_FLAG(F_SF); - CLEAR_FLAG(F_PF); - CLEAR_FLAG(F_ZF); - CLEAR_FLAG(F_AF); - SET_FLAG(F_CF); - EW->word[0] = (uint16_t)get_random32(); - break; - default: - return 0; - } - else - return 0; - break; - + case 0xC7: + CHECK_FLAGS(emu); + nextop = F8; + GETE8xw(0); + if (MODREG) + switch ((nextop >> 3) & 7) { + case 6: /* RDRAND Ew */ + case 7: /* RDSEED Ew */ + RESET_FLAGS(emu); + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_PF); + CLEAR_FLAG(F_ZF); + CLEAR_FLAG(F_AF); + SET_FLAG(F_CF); + EW->word[0] = (uint16_t)get_random32(); + break; + default: + return 0; + } + else + return 0; + break; + case 0xC8: case 0xC9: case 0xCA: @@ -2442,19 +2442,19 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) emu->regs[tmp8u].word[0] = 0; } break; - case 0xD0: { /* ADDSUBPD Gx, Ex */ + case 0xD0: { /* ADDSUBPD Gx, Ex */ nextop = F8; GETEX(0); GETGX; - int oldround = mxcsr_setround(emu); + int oldround = mxcsr_setround(emu); for(int i=0; i<2; ++i) { if(isnan(GX->d[i])) GX->q[i] |= 0x0008000000000000ULL; else if(isnan(EX->d[i])) GX->q[i] = EX->q[i] | 0x0008000000000000ULL; else { if(i==0) GX->d[0] -= EX->d[0]; else GX->d[1] += EX->d[1]; if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL; } } - fesetround(oldround); - } - break; + fesetround(oldround); + } + break; case 0xD1: /* PSRLW Gx, Ex */ nextop = F8; GETEX(0); diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index 23fe838af..f7748992c 100644 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -403,6 +403,32 @@ reg64_t* TestEd(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t return (reg64_t*)test->mem; } } +reg64_t* TestEd1(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &test->emu->regs[(m&0x07)+(rex.b<<3)]; + } else { + reg64_t* ret = GetECommon(test->emu, addr, rex, m, delta); + test->memsize = 1; + test->memaddr = (uintptr_t)ret; + *(uint8_t*)test->mem = ret->byte[0]; + return (reg64_t*)test->mem; + } +} +reg64_t* TestEd2(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &test->emu->regs[(m&0x07)+(rex.b<<3)]; + } else { + reg64_t* ret = GetECommon(test->emu, addr, rex, m, delta); + test->memsize = 2; + test->memaddr = (uintptr_t)ret; + *(uint16_t*)test->mem = ret->word[0]; + return (reg64_t*)test->mem; + } +} reg64_t* TestEd4(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta) { if(rex.is67 && rex.is32bits) { diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h index d244d203f..f5903d8f6 100644 --- a/src/emu/x64run_private.h +++ b/src/emu/x64run_private.h @@ -131,6 +131,8 @@ reg64_t* GetEbO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t de reg64_t* TestEbO(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); reg64_t* GetEd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); reg64_t* TestEd(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); +reg64_t* TestEd1(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); +reg64_t* TestEd2(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); reg64_t* TestEd4(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); reg64_t* TestEd4O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); reg64_t* TestEd8(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); diff --git a/src/emu/x64runf30f.c b/src/emu/x64runf30f.c index eaea9e18a..3a99ebf63 100644 --- a/src/emu/x64runf30f.c +++ b/src/emu/x64runf30f.c @@ -109,7 +109,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) break; case 0x2C: /* CVTTSS2SI Gd, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGD; if (rex.w) { if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { @@ -128,7 +128,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) break; case 0x2D: /* CVTSS2SI Gd, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGD; if(rex.w) { if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { @@ -284,7 +284,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) break; case 0x59: /* MULSS Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000; else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; @@ -296,7 +296,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) break; case 0x5A: /* CVTSS2SD Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; #ifdef RV64 if(isnanf(EX->f[0])) @@ -328,7 +328,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) break; case 0x5C: /* SUBSS Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000; else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; @@ -340,14 +340,14 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) break; case 0x5D: /* MINSS Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; if(isnan(GX->f[0]) || isnan(EX->f[0]) || islessequal(EX->f[0], GX->f[0])) GX->f[0] = EX->f[0]; break; case 0x5E: /* DIVSS Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000; else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; @@ -359,7 +359,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) break; case 0x5F: /* MAXSS Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; if (isnan(GX->f[0]) || isnan(EX->f[0]) || isgreaterequal(EX->f[0], GX->f[0])) GX->f[0] = EX->f[0]; From a95f10cb662dc522ea9adedd7d30bffef845646f Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 13 Oct 2026 14:02:50 +0800 Subject: [PATCH 031/156] [RV64_DYNAREC] Fixed vector PINSRD opcode and added vector PINSRB opcode (#4564) * [RV64_DYNAREC] Fixed vector PINSRD opcode and added vector PINSRB opcode * fix --- src/dynarec/rv64/dynarec_rv64_660f_vector.c | 60 ++++++++++++++++++--- src/dynarec/rv64/dynarec_rv64_helper.h | 3 +- 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_660f_vector.c b/src/dynarec/rv64/dynarec_rv64_660f_vector.c index 92b0bdd9b..fb86b1d8a 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_660f_vector.c @@ -1010,6 +1010,36 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i SMWRITE2(); } break; + case 0x20: + INST_NAME("PINSRB Gx, Ed, Ib"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); + GETGX_vector(q0, 1, dyn->vector_eew); + if (MODREG) { + u8 = (F8) & 0xF; + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 1); + u8 = (F8) & 0xF; + LB(x4, ed, fixedaddress); + ed = x4; + } + if (cpuext.xtheadvector) { + VECTOR_LOAD_VMASK(1 << u8, x5, 1); + v0 = fpu_get_scratch(dyn); + VMERGE_VXM(v0, q0, ed); + VMV_V_V(q0, v0); + } else if (u8 == 0) { + VMV_S_X(q0, ed); + } else { + v0 = fpu_get_scratch(dyn); + VMV_S_X(v0, ed); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, (u8 + 1) / 16.0f); + VSLIDEUP_VI(q0, v0, u8, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, dyn->vector_sew, VECTOR_LMUL1, 1); + } + break; case 0x22: INST_NAME("PINSRD Gx, Ed, Ib"); nextop = F8; @@ -1018,6 +1048,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i if (MODREG) { u8 = (F8) & (rex.w ? 1 : 3); ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGs(ed); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 1); @@ -1025,12 +1056,29 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i LDxw(x4, ed, fixedaddress); ed = x4; } - v0 = fpu_get_scratch(dyn); - VID_V(v0, VECTOR_UNMASKED); - VMSEQ_VI(VMASK, v0, u8, VECTOR_UNMASKED); - VMERGE_VXM(v0, q0, ed); - VMV_V_V(q0, v0); - sse_forget_reg_vector(dyn, ninst, x1, gd); + if (cpuext.xtheadvector) { + v0 = fpu_get_scratch(dyn); + if (rex.w) { + SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); + VECTOR_LOAD_VMASK(1 << (u8 * 2), x5, 1); + VMERGE_VXM(v0, q0, ed); + SRLI(x4, ed, 32); + VECTOR_LOAD_VMASK(1 << (u8 * 2 + 1), x5, 1); + VMERGE_VXM(q0, v0, x4); + } else { + VECTOR_LOAD_VMASK(1 << u8, x5, 1); + VMERGE_VXM(v0, q0, ed); + VMV_V_V(q0, v0); + } + } else if (u8 == 0) { + VMV_S_X(q0, ed); + } else { + v0 = fpu_get_scratch(dyn); + VMV_S_X(v0, ed); + vector_vsetvli(dyn, ninst, x1, dyn->vector_sew, VECTOR_LMUL1, (u8 + 1) / (float)(rex.w ? 2 : 4)); + VSLIDEUP_VI(q0, v0, u8, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, dyn->vector_sew, VECTOR_LMUL1, 1); + } break; case 0x40: INST_NAME("DPPS Gx, Ex, Ib"); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index b291eec5a..829670fe9 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1543,7 +1543,8 @@ do { \ if ((sew) == VECTOR_SEWANY && dyn->vector_sew != VECTOR_SEWNA) { \ dyn->vector_eew = dyn->vector_sew; \ - } else if ((sew) == dyn->vector_sew) { \ + } else if ((sew) == dyn->vector_sew && (unsigned)(sew) < 4 && \ + dyn->inst_vl == (uint32_t)(16u >> (sew))) { \ dyn->vector_eew = dyn->vector_sew; \ } else { \ dyn->vector_eew = vector_vsetvli(dyn, ninst, s1, (sew), VECTOR_LMUL1, 1); \ From ef7005d9eacc4626c20ef052e9e16b83468673ef Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Tue, 13 Oct 2026 11:43:21 +0200 Subject: [PATCH 032/156] [DYNAREC] Small refactor on STRONGMEM handling --- src/dynarec/arm64/dynarec_arm64_pass0.h | 3 +- src/dynarec/dynarec_helper.h | 2 +- src/dynarec/dynarec_private.h | 1 + src/dynarec/la64/dynarec_la64_pass0.h | 39 +++++++++++---------- src/dynarec/ppc64le/dynarec_ppc64le_pass0.h | 1 + src/dynarec/rv64/dynarec_rv64_pass0.h | 1 + 6 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_pass0.h b/src/dynarec/arm64/dynarec_arm64_pass0.h index 4b6283583..f10458958 100644 --- a/src/dynarec/arm64/dynarec_arm64_pass0.h +++ b/src/dynarec/arm64/dynarec_arm64_pass0.h @@ -38,7 +38,8 @@ dyn->n.combined1 = dyn->n.combined2 = 0;\ dyn->n.swapped = 0; dyn->n.barrier = 0; \ dyn->insts[ninst].f_entry = dyn->f; \ - if(ninst) {dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr;} \ + dyn->insts[ninst].x64.strongmem = ((box64_wine && VolatileRangesContains(ip)) ? 0 : BOX64DRENV(dynarec_strongmem)); \ + if(ninst) {dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr;} \ AREFLAGSNEEDED() #define INST_EPILOG \ diff --git a/src/dynarec/dynarec_helper.h b/src/dynarec/dynarec_helper.h index 192b188e5..96d9ec998 100644 --- a/src/dynarec/dynarec_helper.h +++ b/src/dynarec/dynarec_helper.h @@ -38,7 +38,7 @@ #define STRONGMEM_SEQ_WRITE 3 // The level of a barrier at every third memory store will be put #define STRONGMEM_QEMU 4 // The level of a mimic to QEMU's strong memory model -#define STRONGMEM_LEVEL() ((box64_wine && VolatileRangesContains(ip)) ? 0 : BOX64DRENV(dynarec_strongmem)) +#define STRONGMEM_LEVEL() (dyn->insts[ninst].x64.strongmem) #if STEP == 1 diff --git a/src/dynarec/dynarec_private.h b/src/dynarec/dynarec_private.h index e44ac0e07..bbd8e7350 100644 --- a/src/dynarec/dynarec_private.h +++ b/src/dynarec/dynarec_private.h @@ -65,6 +65,7 @@ typedef struct instruction_x64_s { uint8_t leaf_kind; uint8_t leaf_rsp; uintptr_t leaf_target; + uint8_t strongmem:3; // strongmem model at the opcode } instruction_x64_t; #endif //__DYNAREC_PRIVATE_H_ diff --git a/src/dynarec/la64/dynarec_la64_pass0.h b/src/dynarec/la64/dynarec_la64_pass0.h index ab33f177b..9c34c057f 100644 --- a/src/dynarec/la64/dynarec_la64_pass0.h +++ b/src/dynarec/la64/dynarec_la64_pass0.h @@ -78,25 +78,26 @@ } while (0) #define MARK_LEAF_RET() dyn->insts[ninst].x64.leaf_kind = LEAF_KIND_RET #define MARK_LEAF_RSP(F) dyn->insts[ninst].x64.leaf_rsp |= (F) -#define NEW_INST \ - ++dyn->size; \ - dyn->insts[ninst].x64.addr = ip; \ - dyn->lsx.combined1 = dyn->lsx.combined2 = 0; \ - dyn->lsx.swapped = 0; \ - dyn->lsx.barrier = 0; \ - dyn->insts[ninst].up32_read = 0; \ - dyn->insts[ninst].up32_write64 = 0; \ - dyn->insts[ninst].up32_write32 = 0; \ - dyn->insts[ninst].up32_zero = 0; \ - dyn->insts[ninst].up32_skip = 0; \ - dyn->insts[ninst].up32_pending = 0; \ - dyn->insts[ninst].vector_liveness = (vector_liveness_t) { 0 }; \ - dyn->insts[ninst].comis_fusion = -1; \ - dyn->insts[ninst].comis_mark = 0; \ - dyn->insts[ninst].host_call = 0; \ - dyn->insts[ninst].call_window = 0; \ - dyn->insts[ninst].f_entry = dyn->f; \ - if (ninst) { dyn->insts[ninst - 1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst - 1].x64.addr; } \ +#define NEW_INST \ + ++dyn->size; \ + dyn->insts[ninst].x64.addr = ip; \ + dyn->lsx.combined1 = dyn->lsx.combined2 = 0; \ + dyn->lsx.swapped = 0; \ + dyn->lsx.barrier = 0; \ + dyn->insts[ninst].up32_read = 0; \ + dyn->insts[ninst].up32_write64 = 0; \ + dyn->insts[ninst].up32_write32 = 0; \ + dyn->insts[ninst].up32_zero = 0; \ + dyn->insts[ninst].up32_skip = 0; \ + dyn->insts[ninst].up32_pending = 0; \ + dyn->insts[ninst].vector_liveness = (vector_liveness_t) { 0 }; \ + dyn->insts[ninst].comis_fusion = -1; \ + dyn->insts[ninst].comis_mark = 0; \ + dyn->insts[ninst].host_call = 0; \ + dyn->insts[ninst].call_window = 0; \ + dyn->insts[ninst].f_entry = dyn->f; \ + dyn->insts[ninst].x64.strongmem = ((box64_wine && VolatileRangesContains(ip)) ? 0 : BOX64DRENV(dynarec_strongmem)); \ + if (ninst) { dyn->insts[ninst - 1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst - 1].x64.addr; } \ AREFLAGSNEEDED() #define INST_EPILOG \ diff --git a/src/dynarec/ppc64le/dynarec_ppc64le_pass0.h b/src/dynarec/ppc64le/dynarec_ppc64le_pass0.h index 3514c6adf..4e8f8d276 100644 --- a/src/dynarec/ppc64le/dynarec_ppc64le_pass0.h +++ b/src/dynarec/ppc64le/dynarec_ppc64le_pass0.h @@ -64,6 +64,7 @@ dyn->v.combined1 = dyn->v.combined2 = 0;\ dyn->v.swapped = 0; dyn->v.barrier = 0; \ dyn->insts[ninst].f_entry = dyn->f; \ + dyn->insts[ninst].x64.strongmem = ((box64_wine && VolatileRangesContains(ip)) ? 0 : BOX64DRENV(dynarec_strongmem));\ if(ninst) {dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr;} \ AREFLAGSNEEDED() diff --git a/src/dynarec/rv64/dynarec_rv64_pass0.h b/src/dynarec/rv64/dynarec_rv64_pass0.h index f31c93028..db6d747ce 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass0.h +++ b/src/dynarec/rv64/dynarec_rv64_pass0.h @@ -83,6 +83,7 @@ dyn->inst_sew = dyn->vector_sew; \ dyn->inst_vlmul = VECTOR_LMUL1; \ dyn->inst_vl = 0; \ + dyn->insts[ninst].x64.strongmem = ((box64_wine && VolatileRangesContains(ip)) ? 0 : BOX64DRENV(dynarec_strongmem));\ if (ninst) \ dyn->insts[ninst - 1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst - 1].x64.addr;\ AREFLAGSNEEDED() From 45f85efc52d7bd3a3c8642bfc5093ce7932f6c23 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Tue, 13 Oct 2026 12:33:54 +0200 Subject: [PATCH 033/156] [ARM64] Added LRCPC, LRCPC2 and LRCPC3 detection --- src/include/hostext.h | 3 +++ src/os/hostext_common.c | 6 ++++++ src/os/hostext_linux.c | 15 +++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/src/include/hostext.h b/src/include/hostext.h index 513e3029d..6faed3463 100644 --- a/src/include/hostext.h +++ b/src/include/hostext.h @@ -20,6 +20,9 @@ typedef union cpu_ext_s { uint64_t frintts : 1; uint64_t afp : 1; uint64_t rndr : 1; + uint64_t lrcpc : 1; + uint64_t lrcpc2 : 1; + uint64_t lrcpc3 : 1; #elif defined(RV64) uint64_t vlen : 8; // Not *8, 8bits should be enugh? that's 2048 vector uint64_t zba : 1; diff --git a/src/os/hostext_common.c b/src/os/hostext_common.c index 723fd724f..7ddac4423 100644 --- a/src/os/hostext_common.c +++ b/src/os/hostext_common.c @@ -22,6 +22,10 @@ void PrintHostCpuFeatures(void) printf_log_prefix(0, LOG_INFO, " USCAT"); if(cpuext.flagm) printf_log_prefix(0, LOG_INFO, " FLAGM"); + if(cpuext.lrcpc) + printf_log_prefix(0, LOG_INFO, " LRCPC"); + if(cpuext.lrcpc2) + printf_log_prefix(0, LOG_INFO, " LRCPC2"); if(cpuext.flagm2) printf_log_prefix(0, LOG_INFO, " FLAGM2"); if(cpuext.frintts) @@ -30,6 +34,8 @@ void PrintHostCpuFeatures(void) printf_log_prefix(0, LOG_INFO, " AFP"); if(cpuext.rndr) printf_log_prefix(0, LOG_INFO, " RNDR"); + if(cpuext.lrcpc3) + printf_log_prefix(0, LOG_INFO, " LRCPC3"); printf_log_prefix(0, LOG_INFO, "\n"); #elif defined(LA64) printf_log(LOG_INFO, "Dynarec for LoongArch with extension LSX"); diff --git a/src/os/hostext_linux.c b/src/os/hostext_linux.c index 6aed44c0a..a1b3b6c6d 100644 --- a/src/os/hostext_linux.c +++ b/src/os/hostext_linux.c @@ -228,6 +228,14 @@ int DetectHostCpuFeatures(void) if(hwcap&HWCAP_FLAGM) cpuext.flagm = 1; #endif + #ifdef HWCAP_LRCPC + if(hwcap&HWCAP_LRCPC) + cpuext.lrcpc = 1; + #endif + #ifdef HWCAP_ILRCPC + if(hwcap&HWCAP_ILRCPC) + cpuext.lrcpc2 = 1; + #endif unsigned long hwcap2 = real_getauxval(AT_HWCAP2); #ifdef HWCAP2_FLAGM2 if(hwcap2&HWCAP2_FLAGM2) @@ -245,6 +253,10 @@ int DetectHostCpuFeatures(void) if(hwcap2&HWCAP2_RNG) cpuext.rndr = 1; #endif + #ifdef HWCAP2_LRCPC3 + if(hwcap2&HWCAP2_LRCPC3) + cpuext.lrcpc3 = 1; + #endif if (p) { p = strtok(p, ","); while (p) { @@ -256,10 +268,13 @@ int DetectHostCpuFeatures(void) if (!strcasecmp(p, "sha2")) cpuext.sha2 = 0; if (!strcasecmp(p, "uscat")) cpuext.uscat = 0; if (!strcasecmp(p, "flagm")) cpuext.flagm = 0; + if (!strcasecmp(p, "lrcpc")) cpuext.lrcpc = 0; + if (!strcasecmp(p, "lrcpc2")) cpuext.lrcpc2 = 0; if (!strcasecmp(p, "flagm2")) cpuext.flagm2 = 0; if (!strcasecmp(p, "frintts")) cpuext.frintts = 0; if (!strcasecmp(p, "afp")) cpuext.afp = 0; if (!strcasecmp(p, "rndr")) cpuext.rndr = 0; + if (!strcasecmp(p, "lrcpc3")) cpuext.lrcpc3 = 0; p = strtok(NULL, ","); } } From 868e020d594c336164470fca70f8004cd49249b9 Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Tue, 13 Oct 2026 19:58:39 +0800 Subject: [PATCH 034/156] [RV64_DYNAREC] Fix incorrect bit position of IE bit in MXCSR (#4565) MXCSR IE bit is at bit 0, not bit 1. --- src/dynarec/rv64/dynarec_rv64_0f.c | 2 +- src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index b1e3cf741..5be40c51c 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -2281,7 +2281,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni OR(x4, x4, x5); // x4 = x4 | (x3 & 0b10000) >> 4; SRLIW(x5, x3, 4); - ANDI(x5, x5, 2); + ANDI(x5, x5, 1); OR(x4, x4, x5); } SW(x4, wback, fixedaddress); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index c6ec7c876..6d9d84b10 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -452,7 +452,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ANDI(x5, x5, 4); OR(x4, x4, x5); SRLIW(x5, x3, 4); - ANDI(x5, x5, 2); + ANDI(x5, x5, 1); OR(x4, x4, x5); } SW(x4, ed, fixedaddress); From 986c69cc3eccaa5520c54da18f5b4fb8cee1f592 Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Tue, 13 Oct 2026 19:59:00 +0800 Subject: [PATCH 035/156] [RV64_DYNAREC] Fix MMX cache corruption in VPERMILPS (#4566) Allocate the gather scratch register once and reuse it across loop iterations. Calling `fpu_get_scratch` for every element advanced the scratch allocator into v26 and higher, which overlap the registers used by the MMX cache. This could corrupt live MMX values. VRGATHER overwrites the scratch register on every iteration, so a single register can be safely reused. --- src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c index 599f4b07b..500a52e1c 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c @@ -95,11 +95,11 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETGY_empty_vector(v0); u8 = F8; VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + q1 = fpu_get_scratch(dyn); for (int i = 0; i < (4 << vex.l); ++i) { int lane = i & ~3; int selector = lane + ((u8 >> ((i & 3) * 2)) & 3); MOV32w(x4, selector); - q1 = fpu_get_scratch(dyn); VRGATHER_VX(q1, q0, x4, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1 << i, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v0, q1); @@ -113,11 +113,11 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETGY_empty_vector(v0); u8 = F8; VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + q1 = fpu_get_scratch(dyn); for (int i = 0; i < (2 << vex.l); ++i) { int lane = i & ~1; int selector = lane + ((u8 >> i) & 1); MOV32w(x4, selector); - q1 = fpu_get_scratch(dyn); VRGATHER_VX(q1, q0, x4, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1 << i, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v0, q1); From 4437c9b8b1307409261500915ada9012aa04def8 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Tue, 13 Oct 2026 19:01:55 +0200 Subject: [PATCH 036/156] [ARM64_DYNAREC] Use LRCPC2 for the UnityHack if LRCPC2 and USCAT cpu extension are available --- src/dynarec/arm64/arm64_emitter.h | 62 ++++++++++++++++------- src/dynarec/arm64/dynarec_arm64_00.c | 22 +++++--- src/dynarec/arm64/dynarec_arm64_helper.c | 2 + src/dynarec/arm64/dynarec_arm64_private.h | 1 + src/libtools/sigtools.c | 59 +++++++++++++++++++++ 5 files changed, 121 insertions(+), 25 deletions(-) diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h index 592a24727..edf344909 100644 --- a/src/dynarec/arm64/arm64_emitter.h +++ b/src/dynarec/arm64/arm64_emitter.h @@ -230,25 +230,25 @@ int convert_bitmask(uint64_t bitmask); #define LDURSBx_I9(Rt, Rn, imm9) EMIT(LDU_gen(0b00, 0b10, imm9, Rn, Rt)) #define LDURSBxw_I9(Rt, Rn, imm9) EMIT(LDU_gen(0b00, (rex.w)?0b10:0b11, imm9, Rn, Rt)) -#define LDxw(A, B, C) if(unscaled) {LDURxw_I9(A, B, C);} else {LDRxw_U12(A, B, C);} -#define LDz(A, B, C) if(unscaled) {LDURz_I9(A, B, C);} else {LDRz_U12(A, B, C);} -#define LDx(A, B, C) if(unscaled) {LDURx_I9(A, B, C);} else {LDRx_U12(A, B, C);} -#define LDW(A, B, C) if(unscaled) {LDURw_I9(A, B, C);} else {LDRw_U12(A, B, C);} -#define LDH(A, B, C) if(unscaled) {LDURH_I9(A, B, C);} else {LDRH_U12(A, B, C);} -#define LDB(A, B, C) if(unscaled) {LDURB_I9(A, B, C);} else {LDRB_U12(A, B, C);} -#define LDSW(A, B, C) if(unscaled) {LDURSW_I9(A, B, C);} else {LDRSW_U12(A, B, C);} -#define LDSHxw(A, B, C) if(unscaled) {LDURSHxw_I9(A, B, C);} else {LDRSHxw_U12(A, B, C);} -#define LDSHx(A, B, C) if(unscaled) {LDURSHx_I9(A, B, C);} else {LDRSHx_U12(A, B, C);} -#define LDSHw(A, B, C) if(unscaled) {LDURSHw_I9(A, B, C);} else {LDRSHw_U12(A, B, C);} -#define LDSBxw(A, B, C) if(unscaled) {LDURSBxw_I9(A, B, C);} else {LDRSBxw_U12(A, B, C);} -#define LDSBx(A, B, C) if(unscaled) {LDURSBx_I9(A, B, C);} else {LDRSBx_U12(A, B, C);} -#define LDSBw(A, B, C) if(unscaled) {LDURSBw_I9(A, B, C);} else {LDRSBw_U12(A, B, C);} -#define STxw(A, B, C) if(unscaled) {STURxw_I9(A, B, C);} else {STRxw_U12(A, B, C);} -#define STz(A, B, C) if(unscaled) {STURz_I9(A, B, C);} else {STRz_U12(A, B, C);} -#define STx(A, B, C) if(unscaled) {STURx_I9(A, B, C);} else {STRx_U12(A, B, C);} -#define STW(A, B, C) if(unscaled) {STURw_I9(A, B, C);} else {STRw_U12(A, B, C);} -#define STH(A, B, C) if(unscaled) {STURH_I9(A, B, C);} else {STRH_U12(A, B, C);} -#define STB(A, B, C) if(unscaled) {STURB_I9(A, B, C);} else {STRB_U12(A, B, C);} +#define LDxw(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURxw(A, B, C);} else if(unscaled) {LDURxw_I9(A, B, C);} else {LDRxw_U12(A, B, C);}} while(0) +#define LDz(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURz(A, B, C);} else if(unscaled) {LDURz_I9(A, B, C);} else {LDRz_U12(A, B, C);}} while(0) +#define LDx(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURx(A, B, C);} else if(unscaled) {LDURx_I9(A, B, C);} else {LDRx_U12(A, B, C);}} while(0) +#define LDW(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURw(A, B, C);} else if(unscaled) {LDURw_I9(A, B, C);} else {LDRw_U12(A, B, C);}} while(0) +#define LDH(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURH(A, B, C);} else if(unscaled) {LDURH_I9(A, B, C);} else {LDRH_U12(A, B, C);}} while(0) +#define LDB(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURB(A, B, C);} else if(unscaled) {LDURB_I9(A, B, C);} else {LDRB_U12(A, B, C);}} while(0) +#define LDSW(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURSW(A, B, C);} else if(unscaled) {LDURSW_I9(A, B, C);} else {LDRSW_U12(A, B, C);}} while (0) +#define LDSHxw(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURSHxw(A, B, C);} else if(unscaled) {LDURSHxw_I9(A, B, C);} else {LDRSHxw_U12(A, B, C);}} while (0) +#define LDSHx(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURSHx(A, B, C);} else if(unscaled) {LDURSHx_I9(A, B, C);} else {LDRSHx_U12(A, B, C);}} while (0) +#define LDSHw(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURSHw(A, B, C);} else if(unscaled) {LDURSHw_I9(A, B, C);} else {LDRSHw_U12(A, B, C);}} while (0) +#define LDSBxw(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURSBxw(A, B, C);} else if(unscaled) {LDURSBxw_I9(A, B, C);} else {LDRSBxw_U12(A, B, C);}} while (0) +#define LDSBx(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURSBx(A, B, C);} else if(unscaled) {LDURSBx_I9(A, B, C);} else {LDRSBx_U12(A, B, C);}} while (0) +#define LDSBw(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURSBw(A, B, C);} else if(unscaled) {LDURSBw_I9(A, B, C);} else {LDRSBw_U12(A, B, C);}} while (0) +#define STxw(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {STLURxw(A, B, C);} else if(unscaled) {STURxw_I9(A, B, C);} else {STRxw_U12(A, B, C);}} while(0) +#define STz(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {STLURz(A, B, C);} else if(unscaled) {STURz_I9(A, B, C);} else {STRz_U12(A, B, C);}} while(0) +#define STx(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {STLURx(A, B, C);} else if(unscaled) {STURx_I9(A, B, C);} else {STRx_U12(A, B, C);}} while(0) +#define STW(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {STLURw(A, B, C);} else if(unscaled) {STURw_I9(A, B, C);} else {STRw_U12(A, B, C);}} while(0) +#define STH(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {STLURH(A, B, C);} else if(unscaled) {STURH_I9(A, B, C);} else {STRH_U12(A, B, C);}} while(0) +#define STB(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {STLURB(A, B, C);} else if(unscaled) {STURB_I9(A, B, C);} else {STRB_U12(A, B, C);}} while(0) // STR #define STR_gen(size, op1, imm9, op2, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b00<<22 | (imm9)<<12 | (op2)<<10 | (Rn)<<5 | (Rt)) @@ -2380,4 +2380,28 @@ int convert_bitmask(uint64_t bitmask); #define LDAPRH(Rt, Rn) EMIT(LDAPR_gen(0b01, Rn, Rt)) #define LDAPRB(Rt, Rn) EMIT(LDAPR_gen(0b00, Rn, Rt)) +// LRCPC2 extension + +#define LRCPC2_gen(sz, opc, imm9, Rn, Rt) ((sz)<<30 | 0b011001<<24 | (opc)<<22 | ((imm9)&0b111111111)<<12 | (Rn)<<5 | (Rt)) +#define STLURx(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b11, 0b00, imm9, Rn, Rt)) +#define STLURw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b10, 0b00, imm9, Rn, Rt)) +#define STLURxw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b10+rex.w, 0b00, imm9, Rn, Rt)) +#define STLURz(Rt, Rn, imm9) EMIT(LRCPC2_gen(rex.is32bits?0b10:0b11, 0b00, imm9, Rn, Rt)) +#define STLURH(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, 0b00, imm9, Rn, Rt)) +#define STLURB(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, 0b00, imm9, Rn, Rt)) + +#define LDAPURx(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b11, 0b01, imm9, Rn, Rt)) +#define LDAPURw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b10, 0b01, imm9, Rn, Rt)) +#define LDAPURxw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b10+rex.w, 0b01, imm9, Rn, Rt)) +#define LDAPURz(Rt, Rn, imm9) EMIT(LRCPC2_gen(rex.is32bits?0b10:0b11, 0b01, imm9, Rn, Rt)) +#define LDAPURH(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, 0b01, imm9, Rn, Rt)) +#define LDAPURB(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, 0b01, imm9, Rn, Rt)) +#define LDAPURSW(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b10, 0b10, imm9, Rn, Rt)) +#define LDAPURSHw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, 0b10, imm9, Rn, Rt)) +#define LDAPURSHx(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, 0b11, imm9, Rn, Rt)) +#define LDAPURSHxw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, 0b10+rex.w, imm9, Rn, Rt)) +#define LDAPURSBw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, 0b10, imm9, Rn, Rt)) +#define LDAPURSBx(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, 0b11, imm9, Rn, Rt)) +#define LDAPURSBxw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, 0b10+rex.w, imm9, Rn, Rt)) + #endif //__ARM64_EMITTER_H__ diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 8fc276575..67b861b93 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -1610,15 +1610,22 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin wback = x2; } for(int i=0; i<(1<<(2+rex.w)); ++i) { - STURB_I9(gd, wback, i); + if(dyn->insts[ninst].use_lrcpc) + STLURB(gd, wback, i); + else + STURB_I9(gd, wback, i); RORxw(gd, gd, 8); } // gd restored after that } else { addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff << (2 + rex.w), (1 << (2 + rex.w)) - 1, rex, &lock, 0, 0); - if(!lock && BOX64ENV(unity) && !VolatileRangesContains(ip) && ((fixedaddress==0x80) || (fixedaddress==0x84) || (fixedaddress==0xc0) || (fixedaddress==0xc4))) { - DMB_ISH(); - lock = 1; + if(!lock && !dyn->insts[ninst].use_lrcpc && BOX64ENV(unity) && !VolatileRangesContains(ip) && ((fixedaddress==0x80) || (fixedaddress==0x84) || (fixedaddress==0xc0) || (fixedaddress==0xc4))) { + if(!dyn->insts[ninst].x64.strongmem && cpuext.lrcpc && cpuext.lrcpc2 && cpuext.uscat) + dyn->insts[ninst].use_lrcpc = 1; + else { + DMB_ISH(); + lock = 1; + } } STxw(gd, ed, fixedaddress); } @@ -1667,8 +1674,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVxw_REG(gd, TO_NAT((nextop & 7) + (rex.b << 3))); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0); - if(!lock && BOX64ENV(unity) && !VolatileRangesContains(ip) && ((fixedaddress==0x80) || (fixedaddress==0x84) || (fixedaddress==0xc0) || (fixedaddress==0xc4))) { - lock = 1; + if(!lock && !dyn->insts[ninst].use_lrcpc && BOX64ENV(unity) && !VolatileRangesContains(ip) && ((fixedaddress==0x80) || (fixedaddress==0x84) || (fixedaddress==0xc0) || (fixedaddress==0xc4))) { + if(!dyn->insts[ninst].x64.strongmem && cpuext.lrcpc && cpuext.lrcpc2 && cpuext.uscat) + dyn->insts[ninst].use_lrcpc = 1; + else + lock = 1; } SMREADLOCK(lock); LDxw(gd, ed, fixedaddress); diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index d0038c09f..c719175c1 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -35,6 +35,8 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u int lock = l?((l==LOCK_LOCK)?1:2):0; if(lock==2) *l = 0; + if(dyn->insts[ninst].use_lrcpc) { absmax = 0; mask=0;}// there is no "Scaled" version, only Unscaled + if(rex.is32bits && rex.is67) return geted16(dyn, addr, ninst, nextop, ed, hint, fixaddress, unscaled, absmax, mask, rex, s); diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h index 772723ef2..62d2d440d 100644 --- a/src/dynarec/arm64/dynarec_arm64_private.h +++ b/src/dynarec/arm64/dynarec_arm64_private.h @@ -156,6 +156,7 @@ typedef struct instruction_arm64_s { unsigned x87_used:1; // no fine tracking, just a global "any reg used" unsigned fpu_used:1; // any xmm/ymm/x87/mmx reg used unsigned fpupurge:1; // this opcode will purge all fpu regs + unsigned use_lrcpc:1;// use the various lrcpc opcode here instead of regular LD/ST + memory barrier flagcache_t f_exit; // flags status at end of instruction neoncache_t n; // neoncache at end of instruction (but before poping) flagcache_t f_entry; // flags status before the instruction begin diff --git a/src/libtools/sigtools.c b/src/libtools/sigtools.c index 612b22348..0355fa5f7 100644 --- a/src/libtools/sigtools.c +++ b/src/libtools/sigtools.c @@ -172,6 +172,27 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, p->uc_mcontext.pc+=4; // go to next opcode return 1; } + if((opcode&0b10111111111000000000110000000000) == 0b10011001000000000000000000000000) { + // this is a STLUR that SIGBUS if accessing unaligned device memory + int size = 1<<((opcode>>30)&3); + int val = opcode&31; + int dest = (opcode>>5)&31; + int64_t offset = (opcode>>12)&0b111111111; + if((offset>>(9-1))&1) + offset |= (0xffffffffffffffffll<<9); + volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); + if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); + CHECK_ALIGNED(addr, size); + uint64_t value = p->uc_mcontext.regs[val]; + if(size==8 && (((uintptr_t)addr)&3)==0) { + for(int i=0; i<2; ++i) + ((volatile uint32_t*)addr)[i] = (value>>(i*32))&0xffffffff; + } else + for(int i=0; i>(i*8))&0xff; + p->uc_mcontext.pc+=4; // go to next opcode + return 1; + } if((opcode&0b00111111010000000000000000000000)==0b00111101000000000000000000000000) { // this is VSTR int scale = (opcode>>30)&3; @@ -323,6 +344,28 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, p->uc_mcontext.pc+=4; // go to next opcode return 1; } + if((opcode&0b10111111111000000000110000000000) == 0b10011001010000000000000000000000) { + // this is a LDAPUR + int size = 1<<((opcode>>30)&3); + int val = opcode&31; + int dest = (opcode>>5)&31; + int64_t offset = (opcode>>12)&0b111111111; + if((offset>>(9-1))&1) + offset |= (0xffffffffffffffffll<<9); + volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); + if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); + CHECK_ALIGNED(addr, size); + uint64_t value = 0; + if(size==8 && (((uintptr_t)addr)&3)==0) { + for(int i=0; i<2; ++i) + value |= ((uint64_t)((volatile uint32_t*)addr)[i]) << (i*32); + } else + for(int i=0; iuc_mcontext.regs[val] = value; + p->uc_mcontext.pc+=4; // go to next opcode + return 1; + } if((opcode&0b11111111110000000000000000000000)==0b01111001000000000000000000000000) { // this is STRH int scale = (opcode>>30)&3; @@ -355,6 +398,22 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, p->uc_mcontext.pc+=4; // go to next opcode return 1; } + if((opcode&0b11111111111000000000110000000000)==0b00110010000000000000000000000000) { + // this is STLURH + int val = opcode&31; + int dest = (opcode>>5)&31; + int64_t offset = (opcode>>12)&0b111111111; + if((offset>>(9-1))&1) + offset |= (0xffffffffffffffffll<<9); + volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); + if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); + CHECK_ALIGNED(addr, 2); + uint64_t value = p->uc_mcontext.regs[val]; + for(int i=0; i<2; ++i) + addr[i] = (value>>(i*8))&0xff; + p->uc_mcontext.pc+=4; // go to next opcode + return 1; + } if((opcode&0b11111111111000000000110000000000)==0b01111000001000000000100000000000) { // this is STRH reg, reg int scale = (opcode>>30)&3; From 1f7fd2afb02372a44e7e8e05c1f3d1f68de595a8 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 14 Oct 2026 15:22:34 +0800 Subject: [PATCH 037/156] [INTERP] Fixed more over reads in cosim (#4568) --- src/emu/x64runavx660f38.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/emu/x64runavx660f38.c b/src/emu/x64runavx660f38.c index d9292be82..eeeb59238 100644 --- a/src/emu/x64runavx660f38.c +++ b/src/emu/x64runavx660f38.c @@ -674,7 +674,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) case 0x20: /* VPMOVSXBW Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX(0); else GETEX8(0); GETGX; GETGY; if(vex.l) @@ -687,7 +687,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x21: /* VPMOVSXBD Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX8(0); else GETEX4(0); GETGX; GETGY; if(vex.l) @@ -700,7 +700,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x22: /* VPMOVSXBQ Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX4(0); else GETEX2(0); GETGX; GETGY; if(vex.l) @@ -713,7 +713,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x23: /* VPMOVSXWD Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX(0); else GETEX8(0); GETGX; GETGY; if(vex.l) @@ -726,7 +726,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x24: /* VPMOVSXWQ Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX8(0); else GETEX4(0); GETGX; GETGY; if(vex.l) @@ -739,7 +739,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x25: /* VPMOVSXDQ Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX(0); else GETEX8(0); GETGX; GETGY; if(vex.l) @@ -914,7 +914,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x30: /* VPMOVZXBW Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX(0); else GETEX8(0); GETGX; GETGY; if(vex.l) @@ -927,7 +927,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x31: /* VPMOVZXBD Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX8(0); else GETEX4(0); GETGX; GETGY; if(vex.l) @@ -940,7 +940,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x32: /* VPMOVZXBQ Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX4(0); else GETEX2(0); GETGX; GETGY; if(vex.l) @@ -953,7 +953,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x33: /* VPMOVZXWD Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX(0); else GETEX8(0); GETGX; GETGY; if(vex.l) @@ -966,7 +966,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x34: /* VPMOVZXWQ Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX8(0); else GETEX4(0); GETGX; GETGY; if(vex.l) @@ -979,7 +979,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x35: /* VPMOVZXDQ Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX(0); else GETEX8(0); GETGX; GETGY; if(vex.l) From c51e58b34a57c26330ba7bd6041c11b023103fcf Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Wed, 14 Oct 2026 11:26:20 +0200 Subject: [PATCH 038/156] =?UTF-8?q?Revert=20"[DYNAREC]=20Write=20back=20th?= =?UTF-8?q?e=20fpu=20cache=20before=20an=20instruction=20following=20un?= =?UTF-8?q?=E2=80=A6"=20(#4570)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 7de6142c989c1854fa2c1feeeac6a2e41b6a8010. --- src/dynarec/dynarec_native_pass.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index a681c1e30..2c159beec 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -119,7 +119,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int fpu_reset(dyn); ARCH_INIT(); int reset_n = -1; // -1 no reset; -2 reset to 0; else reset to the state of reset_n - int pending_fpu_purge = 0; // fpu cache must be written back before the next emitted instruction #if defined(HAVE_LEAFCALL) dyn->last_ip = (dyn->inline_leaf || alternate || (dyn->insts && dyn->insts[0].pred_sz)) ? 0 : ip; // RIP is always set at start of ordinary blocks unless there is a predecessor! #else @@ -227,14 +226,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int if(dyn->insts[ninst].x64.alive && dyn->insts[ninst].x64.self_loop) CALLRET_LOOP(); #endif - if (pending_fpu_purge) { - pending_fpu_purge = 0; - #if defined(RV64) || defined(LA64) || defined(PPC64LE) - fpu_purgecache(dyn, ninst, 1, x1, x2, x3); - #else - fpu_purgecache(dyn, ninst, 1, x1, x2, x3, 0); - #endif - } if(!ninst) { GOTEST(x1, x2); } @@ -395,7 +386,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int addr += dyn->insts[ninst].x64.size; INST_EPILOG; } - pending_fpu_purge = 1; } if((dyn->insts[ninst+1].x64.barrier&BARRIER_FULL)==BARRIER_FULL) reset_n = -2; // hack to say Barrier! From d653d0ebefeba2c9abe13a5c4c13663bbd242549 Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Wed, 14 Oct 2026 17:40:09 +0800 Subject: [PATCH 039/156] [RV64_DYNAREC] Fix VMOVQ vl (#4569) The `width` argument of `avx_set_vector_width` is measured in bits rather than bytes. This bug results in `vl` being computed as zero. --- src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index d9d2497a1..3e578fd82 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -908,7 +908,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (MODREG) { ed = (nextop & 7) + (rex.b << 3); q1 = fpu_get_scratch(dyn); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 2); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16); VXOR_VV(q1, q1, q1, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1, x4, 1); VMERGE_VVM(q1, q1, q0); From 157dd83ef3e5757f1c110d6f32f47dfaca1a5fca Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Thu, 15 Oct 2026 13:04:27 +0200 Subject: [PATCH 040/156] Improved log for Special SIGBUS fixing --- src/dynarec/dynarec_arch.h | 4 ++++ src/libtools/signals.c | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/dynarec/dynarec_arch.h b/src/dynarec/dynarec_arch.h index d5468cdc9..e31923e9b 100644 --- a/src/dynarec/dynarec_arch.h +++ b/src/dynarec/dynarec_arch.h @@ -46,6 +46,7 @@ extern void arm64_next_invalid(); #define ARCH_NOP 0b11010101000000110010000000011111 #define ARCH_UDF 0xcafe #define JMPNEXT_SIZE (4*sizeof(void*)) +#define PRINT_OPCODE(C, A) arm64_print(C, A) #elif defined(LA64) #define HAVE_LEAFCALL @@ -89,6 +90,7 @@ extern void la64_crc_autocrc(); // same as la64_crc, but not using regular ABI #define ADDITIONNAL_CHECKS() #define ARCH_CRC_INLINE extern void la64_next_invalid(); +#define PRINT_OPCODE(C, A) la64_print(C, A) #elif defined(RV64) @@ -130,6 +132,7 @@ extern void la64_next_invalid(); #define ADDITIONNAL_CHECKS() extern void* create_updateflags(); #define ARCH_UPDATEFLAGS() create_updateflags() +#define PRINT_OPCODE(C, A) rv64_print(C, A) #elif defined(PPC64LE) @@ -168,6 +171,7 @@ extern void* create_updateflags(); // so the jmpnext area needs 5 void* slots (40 bytes) instead of the default 4 (32 bytes). #define JMPNEXT_SIZE (5*sizeof(void*)) #define ADDITIONNAL_CHECKS() +#define PRINT_OPCODE(C, A) ppc64le_print(C, A) #else #error Unsupported platform diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 0575a8bdb..c48a41fe8 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -882,6 +882,9 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) void * pc = NULL; // unknow arch... void* fpsimd = NULL; #warning Unhandled architecture +#endif +#ifndef PRINT_OPCODE +#define PRINT_OPCODE(C, A) "???" #endif dynablock_t* db = NULL; int db_searched = 0; @@ -909,9 +912,9 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) old_pc_i = 0; uint8_t* x64 = (uint8_t*)x64pc; if(db) - printf_log(LOG_INFO, "Special unaligned case fixed @%p, opcode=%08x (addr=%p, db=%p, x64pc=%p[%02hhX %02hhX %02hhX %02hhX %02hhX])\n", pc, *(uint32_t*)pc, addr, db, x64pc, x64[0], x64[1], x64[2], x64[3], x64[4], x64[5]); + printf_log(LOG_INFO, "Special unaligned case fixed @%p, opcode=%08x(%s) (addr=%p, db=%p, x64pc=%p[%02hhX %02hhX %02hhX %02hhX %02hhX])\n", pc, *(uint32_t*)pc, PRINT_OPCODE(*(uint32_t*)pc, (uintptr_t)pc), addr, db, x64pc, x64[0], x64[1], x64[2], x64[3], x64[4], x64[5]); else - printf_log(LOG_INFO, "Special unaligned case fixed @%p, opcode=%08x (addr=%p)\n", pc, *(uint32_t*)pc, addr); + printf_log(LOG_INFO, "Special unaligned case fixed @%p, opcode=%08x(%s) (addr=%p)\n", pc, *(uint32_t*)pc, PRINT_OPCODE(*(uint32_t*)pc, (uintptr_t)pc), addr); } } return; From e296745e8252520ad17708ccb13a6b6a42182719 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Thu, 15 Oct 2026 13:06:52 +0200 Subject: [PATCH 041/156] [ARM64_DYNAREC] Fixes some opcode emitter and Special SIGBUS handler --- src/dynarec/arm64/arm64_emitter.h | 48 +++++++---- src/dynarec/arm64/arm64_printer.c | 66 +++++++++++++- src/libtools/sigtools.c | 138 ++++++++++++++++++++++-------- 3 files changed, 195 insertions(+), 57 deletions(-) diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h index edf344909..8558b5cfd 100644 --- a/src/dynarec/arm64/arm64_emitter.h +++ b/src/dynarec/arm64/arm64_emitter.h @@ -828,16 +828,16 @@ int convert_bitmask(uint64_t bitmask); #define VSTR64_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b11, 0b00, (imm9)&0b111111111, Rn, Vt)) #define VSTR128_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b00, 0b10, (imm9)&0b111111111, Rn, Vt)) -#define VLD128(A, B, C) if(unscaled) {VLDR128_I9(A, B, C);} else {VLDR128_U12(A, B, C);} -#define VLD64(A, B, C) if(unscaled) {VLDR64_I9(A, B, C);} else {VLDR64_U12(A, B, C);} -#define VLD32(A, B, C) if(unscaled) {VLDR32_I9(A, B, C);} else {VLDR32_U12(A, B, C);} -#define VLD16(A, B, C) if(unscaled) {VLDR16_I9(A, B, C);} else {VLDR16_U12(A, B, C);} -#define VLD8(A, B, C) if(unscaled) {VLDR8_I9(A, B, C);} else {VLDR8_U12(A, B, C);} -#define VST128(A, B, C) if(unscaled) {VSTR128_I9(A, B, C);} else {VSTR128_U12(A, B, C);} -#define VST64(A, B, C) if(unscaled) {VSTR64_I9(A, B, C);} else {VSTR64_U12(A, B, C);} -#define VST32(A, B, C) if(unscaled) {VSTR32_I9(A, B, C);} else {VSTR32_U12(A, B, C);} -#define VST16(A, B, C) if(unscaled) {VSTR16_I9(A, B, C);} else {VSTR16_U12(A, B, C);} -#define VST8(A, B, C) if(unscaled) {VSTR8_I9(A, B, C);} else {VSTR8_U12(A, B, C);} +#define VLD128(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VLDAPUR128(A, B, C);} else if(unscaled) {VLDR128_I9(A, B, C);} else {VLDR128_U12(A, B, C);}} while(0) +#define VLD64(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VLDAPUR64(A, B, C);} else if(unscaled) {VLDR64_I9(A, B, C);} else {VLDR64_U12(A, B, C);}} while(0) +#define VLD32(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VLDAPUR32(A, B, C);} else if(unscaled) {VLDR32_I9(A, B, C);} else {VLDR32_U12(A, B, C);}} while(0) +#define VLD16(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VLDAPUR16(A, B, C);} else if(unscaled) {VLDR16_I9(A, B, C);} else {VLDR16_U12(A, B, C);}} while(0) +#define VLD8(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VLDAPUR8(A, B, C);} else if(unscaled) {VLDR8_I9(A, B, C);} else {VLDR8_U12(A, B, C);}} while(0) +#define VST128(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VSTLUR128(A, B, C);} else if(unscaled) {VSTR128_I9(A, B, C);} else {VSTR128_U12(A, B, C);}} while (0) +#define VST64(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VSTLUR64(A, B, C);} else if(unscaled) {VSTR64_I9(A, B, C);} else {VSTR64_U12(A, B, C);}} while (0) +#define VST32(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VSTLUR32(A, B, C);} else if(unscaled) {VSTR32_I9(A, B, C);} else {VSTR32_U12(A, B, C);}} while (0) +#define VST16(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VSTLUR16(A, B, C);} else if(unscaled) {VSTR16_I9(A, B, C);} else {VSTR16_U12(A, B, C);}} while (0) +#define VST8(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VSTLUR8(A, B, C);} else if(unscaled) {VSTR8_I9(A, B, C);} else {VSTR8_U12(A, B, C);}} while (0) #define VMEMW_gen(size, opc, imm9, op2, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | (imm9)<<12 | (op2)<<10 | 0b01<<10 | (Rn)<<5 | (Rt)) #define VLDR64_S9_postindex(Rt, Rn, imm9) EMIT(VMEMW_gen(0b11, 0b01, (imm9)&0x1ff, 0b01, Rn, Rt)) @@ -2397,11 +2397,27 @@ int convert_bitmask(uint64_t bitmask); #define LDAPURH(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, 0b01, imm9, Rn, Rt)) #define LDAPURB(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, 0b01, imm9, Rn, Rt)) #define LDAPURSW(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b10, 0b10, imm9, Rn, Rt)) -#define LDAPURSHw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, 0b10, imm9, Rn, Rt)) -#define LDAPURSHx(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, 0b11, imm9, Rn, Rt)) -#define LDAPURSHxw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, 0b10+rex.w, imm9, Rn, Rt)) -#define LDAPURSBw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, 0b10, imm9, Rn, Rt)) -#define LDAPURSBx(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, 0b11, imm9, Rn, Rt)) -#define LDAPURSBxw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, 0b10+rex.w, imm9, Rn, Rt)) +#define LDAPURSHw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, 0b11, imm9, Rn, Rt)) +#define LDAPURSHx(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, 0b10, imm9, Rn, Rt)) +#define LDAPURSHxw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, rex.w?0b10:0b11, imm9, Rn, Rt)) +#define LDAPURSBw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, 0b11, imm9, Rn, Rt)) +#define LDAPURSBx(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, 0b10, imm9, Rn, Rt)) +#define LDAPURSBxw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, rex.w?0b10:0b11, imm9, Rn, Rt)) + +#define NOLRCPC() dyn->insts[ninst].use_lrcpc=0 + +// LRCPC3 extension +#define LRCPC3_gen(sz, opc, imm9, Rn, Rt) ((sz)<<30 | 0b011101<<24 | (opc)<<22 | ((imm9)&0b111111111)<<12 | 0b10<<10 | (Rn)<<5 | (Rt)) +#define VLDAPUR128(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b00, 0b11, imm9, Vn, Vt));} while(0) +#define VLDAPUR64(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b11, 0b01, imm9, Vn, Vt));} while(0) +#define VLDAPUR32(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b10, 0b01, imm9, Vn, Vt));} while(0) +#define VLDAPUR16(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b01, 0b01, imm9, Vn, Vt));} while(0) +#define VLDAPUR8(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b00, 0b01, imm9, Vn, Vt));} while(0) + +#define VSTLUR128(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b00, 0b10, imm9, Vn, Vt));} while(0) +#define VSTLUR64(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b11, 0b00, imm9, Vn, Vt));} while(0) +#define VSTLUR32(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b10, 0b00, imm9, Vn, Vt));} while(0) +#define VSTLUR16(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b01, 0b00, imm9, Vn, Vt));} while(0) +#define VSTLUR8(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b00, 0b00, imm9, Vn, Vt));} while(0) #endif //__ARM64_EMITTER_H__ diff --git a/src/dynarec/arm64/arm64_printer.c b/src/dynarec/arm64/arm64_printer.c index 22583cfa3..7565eaba7 100644 --- a/src/dynarec/arm64/arm64_printer.c +++ b/src/dynarec/arm64/arm64_printer.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT #include #include #include @@ -209,12 +209,12 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) } if(isMask(opcode, "001110001x0iiiiiiiii00nnnnnttttt", &a)) { int offset = signExtend(imm, 9); - snprintf(buff, sizeof(buff), "LDURSB %s, [%s, %s0x%x]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + snprintf(buff, sizeof(buff), "LDURSB %s, [%s, %s0x%x]", a.x?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); return buff; } if(isMask(opcode, "011110001x0iiiiiiiii00nnnnnttttt", &a)) { int offset = signExtend(imm, 9); - snprintf(buff, sizeof(buff), "LDURSH %s, [%s, %s0x%x]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + snprintf(buff, sizeof(buff), "LDURSH %s, [%s, %s0x%x]", a.x?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); return buff; } if(isMask(opcode, "10111000100iiiiiiiii00nnnnnttttt", &a)) { @@ -222,6 +222,37 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) snprintf(buff, sizeof(buff), "LDURSW %s, [%s, %s0x%x]", Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); return buff; } + if(isMask(opcode, "1x011001010iiiiiiiii00nnnnnttttt", &a)) { + int size = (opcode>>30)&3; + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "LDAPUR %s, [%s, %s0x%x]", (size==0b10)?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "00011001010iiiiiiiii00nnnnnttttt", &a)) { + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "LDAPURB %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "01011001010iiiiiiiii00nnnnnttttt", &a)) { + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "LDAPURH %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "000110011x0iiiiiiiii00nnnnnttttt", &a)) { + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "LDAPURSB %s, [%s, %s0x%x]", a.x?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "010110011x0iiiiiiiii00nnnnnttttt", &a)) { + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "LDAPURSH %s, [%s, %s0x%x]", a.x?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "10011001100iiiiiiiii00nnnnnttttt", &a)) { + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "LDAPURSW %s, [%s, %s0x%x]", Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } if(isMask(opcode, "1x111000000iiiiiiiii00nnnnnttttt", &a)) { int size = (opcode>>30)&3; int offset = signExtend(imm, 9); @@ -238,6 +269,22 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) snprintf(buff, sizeof(buff), "STURH %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); return buff; } + if(isMask(opcode, "1x011001000iiiiiiiii00nnnnnttttt", &a)) { + int size = (opcode>>30)&3; + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "STLUR %s, [%s, %s0x%x]", (size==0b10)?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "00011001000iiiiiiiii00nnnnnttttt", &a)) { + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "STLURB %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "01011001000iiiiiiiii00nnnnnttttt", &a)) { + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "STLURH %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } if(isMask(opcode, "1x11100101iiiiiiiiiiiinnnnnttttt", &a)) { int size = (opcode>>30)&3; int offset = (imm)<>30)&3; int val = opcode&31; int dest = (opcode>>5)&31; @@ -141,7 +141,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, 1<uc_mcontext.regs[val]; + uint64_t value = (val==xZR)?0:p->uc_mcontext.regs[val]; if(scale==3 && (((uintptr_t)addr)&3)==0) { for(int i=0; i<2; ++i) ((volatile uint32_t*)addr)[i] = (value>>(i*32))&0xffffffff; @@ -151,8 +151,8 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, p->uc_mcontext.pc+=4; // go to next opcode return 1; } - if((opcode&0b10111111111000000000110000000000) == 0b10111000000000000000000000000000) { - // this is a STUR that SIGBUS if accessing unaligned device memory + if((opcode&0b00111111111000000000110000000000) == 0b00111000000000000000000000000000) { + // this is a STUR(H/B) that SIGBUS if accessing unaligned device memory int size = 1<<((opcode>>30)&3); int val = opcode&31; int dest = (opcode>>5)&31; @@ -162,7 +162,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, size); - uint64_t value = p->uc_mcontext.regs[val]; + uint64_t value = (val==xZR)?0:p->uc_mcontext.regs[val]; if(size==8 && (((uintptr_t)addr)&3)==0) { for(int i=0; i<2; ++i) ((volatile uint32_t*)addr)[i] = (value>>(i*32))&0xffffffff; @@ -172,8 +172,8 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, p->uc_mcontext.pc+=4; // go to next opcode return 1; } - if((opcode&0b10111111111000000000110000000000) == 0b10011001000000000000000000000000) { - // this is a STLUR that SIGBUS if accessing unaligned device memory + if((opcode&0b00111111111000000000110000000000) == 0b00011001000000000000000000000000) { + // this is a STLUR(H/B) that SIGBUS if accessing unaligned device memory int size = 1<<((opcode>>30)&3); int val = opcode&31; int dest = (opcode>>5)&31; @@ -183,7 +183,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, size); - uint64_t value = p->uc_mcontext.regs[val]; + uint64_t value = (val==xZR)?0:p->uc_mcontext.regs[val]; if(size==8 && (((uintptr_t)addr)&3)==0) { for(int i=0; i<2; ++i) ((volatile uint32_t*)addr)[i] = (value>>(i*32))&0xffffffff; @@ -220,7 +220,34 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, return 1; } if((opcode&0b00111111011000000000110000000000)==0b00111100000000000000000000000000) { - // this is VSTRU + // this is VSTUR + int scale = (opcode>>30)&3; + if((opcode>>23)&1) + scale+=4; + if(scale>4) + return 0; + if(!fpsimd) + return 0; + int64_t offset = (opcode>>12)&0b111111111; + if((offset>>(9-1))&1) + offset |= (0xffffffffffffffffll<<9); + int val = opcode&31; + int dest = (opcode>>5)&31; + volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); + if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); + CHECK_ALIGNED(addr, 1<vregs[val]; + if(scale>2 && (((uintptr_t)addr)&3)==0) { + for(int i=0; i<(1<<(scale-2)); ++i) + ((volatile uint32_t*)addr)[i] = (value>>(i*32))&0xffffffff; + } else + for(int i=0; i<(1<>(i*8))&0xff; + p->uc_mcontext.pc+=4; // go to next opcode + return 1; + } + if((opcode&0b00111111011000000000110000000000)==0b00011101000000000000100000000000) { + // this is VSTLUR int scale = (opcode>>30)&3; if((opcode>>23)&1) scale+=4; @@ -274,7 +301,35 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, return 1; } if((opcode&0b00111111011000000000110000000000)==0b00111100010000000000000000000000) { - // this is VLDRU + // this is VLDUR + int scale = (opcode>>30)&3; + if((opcode>>23)&1) + scale+=4; + if(scale>4) + return 0; + if(!fpsimd) + return 0; + int64_t offset = (opcode>>12)&0b111111111; + if((offset>>(9-1))&1) + offset |= (0xffffffffffffffffll<<9); + int val = opcode&31; + int dest = (opcode>>5)&31; + volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); + if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); + CHECK_ALIGNED(addr, 1<2 && (((uintptr_t)addr)&3)==0) { + for(int i=0; i<(1<<(scale-2)); ++i) + value |= ((__uint128_t)(((volatile uint32_t*)addr)[i]))<<(i*32); + } else + for(int i=0; i<(1<vregs[val] = value; + p->uc_mcontext.pc+=4; // go to next opcode + return 1; + } + if((opcode&0b00111111011000000000110000000000)==0b00011101010000000000100000000000) { + // this is VLDAPUR int scale = (opcode>>30)&3; if((opcode>>23)&1) scale+=4; @@ -318,7 +373,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, } else for(int i=0; i<(1<uc_mcontext.regs[val] = value; + if(val!=xZR) p->uc_mcontext.regs[val] = value; p->uc_mcontext.pc+=4; // go to next opcode return 1; } @@ -340,7 +395,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, } else for(int i=0; iuc_mcontext.regs[val] = value; + if(val!=xZR) p->uc_mcontext.regs[val] = value; p->uc_mcontext.pc+=4; // go to next opcode return 1; } @@ -362,28 +417,30 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, } else for(int i=0; iuc_mcontext.regs[val] = value; + if(val!=xZR) p->uc_mcontext.regs[val] = value; p->uc_mcontext.pc+=4; // go to next opcode return 1; } - if((opcode&0b11111111110000000000000000000000)==0b01111001000000000000000000000000) { - // this is STRH - int scale = (opcode>>30)&3; + if((opcode&0b11111111111000000000110000000000) == 0b10011001100000000000000000000000) { + // this is a LDAPURSW + int size = 1<<((opcode>>30)&3); int val = opcode&31; int dest = (opcode>>5)&31; - uint64_t offset = (opcode>>10)&0b111111111111; - offset<<=scale; + int64_t offset = (opcode>>12)&0b111111111; + if((offset>>(9-1))&1) + offset |= (0xffffffffffffffffll<<9); volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); - CHECK_ALIGNED(addr, 1<uc_mcontext.regs[val]; - for(int i=0; i<(1<>(i*8))&0xff; + CHECK_ALIGNED(addr, size); + int32_t value = 0; + for(int i=0; iuc_mcontext.regs[val] = (int64_t)value; p->uc_mcontext.pc+=4; // go to next opcode return 1; } - if((opcode&0b11111111111000000000110000000000)==0b01111000000000000000000000000000) { - // this is STURH + if((opcode&0b11111111111000000000110000000000) == 0b01011001010000000000000000000000) { + // this is a LDAPURH int val = opcode&31; int dest = (opcode>>5)&31; int64_t offset = (opcode>>12)&0b111111111; @@ -392,14 +449,15 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, 2); - uint64_t value = p->uc_mcontext.regs[val]; + uint16_t value = 0; for(int i=0; i<2; ++i) - addr[i] = (value>>(i*8))&0xff; + value |= ((uint16_t)addr[i]) << (i*8); + if(val!=xZR) p->uc_mcontext.regs[val] = value; p->uc_mcontext.pc+=4; // go to next opcode return 1; } - if((opcode&0b11111111111000000000110000000000)==0b00110010000000000000000000000000) { - // this is STLURH + if((opcode&0b11111111101000000000110000000000) == 0b01011001100000000000000000000000) { + // this is a LDAPURSH int val = opcode&31; int dest = (opcode>>5)&31; int64_t offset = (opcode>>12)&0b111111111; @@ -408,9 +466,13 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, 2); - uint64_t value = p->uc_mcontext.regs[val]; + int16_t value = 0; for(int i=0; i<2; ++i) - addr[i] = (value>>(i*8))&0xff; + value |= ((int16_t)addr[i]) << (i*8); + if(val!=xZR) { + p->uc_mcontext.regs[val] = (int64_t)value; + if((opcode>>22)&1) p->uc_mcontext.regs[val]&=0xffffffffULL; + } p->uc_mcontext.pc+=4; // go to next opcode return 1; } @@ -424,11 +486,11 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, int S = (opcode>>12)&1; if(option!=0b011) return 0; // only LSL is supported - uint64_t offset = p->uc_mcontext.regs[dest2]<uc_mcontext.regs[dest2])<uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, 1<uc_mcontext.regs[val]; + uint64_t value = (val==xZR)?0:p->uc_mcontext.regs[val]; for(int i=0; i<(1<>(i*8))&0xff; p->uc_mcontext.pc+=4; // go to next opcode @@ -448,10 +510,10 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, if(is32bits) addr = addr&0xffffffff; CHECK_ALIGNED(addr, 1<uc_mcontext.regs[val1]; - ((volatile uint32_t*)addr)[1] = p->uc_mcontext.regs[val2]; + ((volatile uint32_t*)addr)[0] = (val1==xZR)?0:p->uc_mcontext.regs[val1]; + ((volatile uint32_t*)addr)[1] = (val2==xZR)?0:p->uc_mcontext.regs[val2]; } else { - __uint128_t value = ((__uint128_t)p->uc_mcontext.regs[val2])<<64 | p->uc_mcontext.regs[val1]; + __uint128_t value = ((__uint128_t)((val2==xZR)?0:p->uc_mcontext.regs[val2]))<<64 | ((val1==xZR)?0:p->uc_mcontext.regs[val1]); for(int i=0; i<(1<>(i*8))&0xff; } @@ -521,7 +583,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, } else for(int i=0; iuc_mcontext.regs[val] = value; + if(val!=xZR) p->uc_mcontext.regs[val] = value; p->uc_mcontext.regs[dest] += offset; p->uc_mcontext.pc+=4; // go to next opcode return 1; @@ -537,7 +599,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[src]); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, size); - uint64_t value = p->uc_mcontext.regs[val]; + uint64_t value = (val==xZR)?0:p->uc_mcontext.regs[val]; if(size==8 && (((uintptr_t)addr)&3)==0) { for(int i=0; i<2; ++i) ((volatile uint32_t*)addr)[i] = (value>>(i*32))&0xffffffff; From b99d44309e3c0102bfff40d1d680b915f565eb1f Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Fri, 16 Oct 2026 16:09:26 +0800 Subject: [PATCH 042/156] [RV64_DYNAREC] Refactored AVX register mapping and register allocation (#4567) --- src/dynarec/rv64/dynarec_rv64_00_3.c | 2 + src/dynarec/rv64/dynarec_rv64_0f_vector.c | 36 +-- src/dynarec/rv64/dynarec_rv64_660f_vector.c | 67 ++--- src/dynarec/rv64/dynarec_rv64_arch.c | 54 +++- src/dynarec/rv64/dynarec_rv64_avx.c | 22 +- src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c | 53 ++-- src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c | 10 +- .../rv64/dynarec_rv64_avx_66_0f38_vector.c | 185 ++++++------ .../rv64/dynarec_rv64_avx_66_0f3a_vector.c | 37 ++- .../rv64/dynarec_rv64_avx_66_0f_vector.c | 229 +++++++------- .../rv64/dynarec_rv64_avx_f2_0f_vector.c | 4 +- .../rv64/dynarec_rv64_avx_f3_0f_vector.c | 6 +- src/dynarec/rv64/dynarec_rv64_f20f_vector.c | 8 +- src/dynarec/rv64/dynarec_rv64_f30f_vector.c | 4 +- src/dynarec/rv64/dynarec_rv64_functions.c | 42 ++- src/dynarec/rv64/dynarec_rv64_functions.h | 2 +- src/dynarec/rv64/dynarec_rv64_helper.c | 279 +++++++++++------- src/dynarec/rv64/dynarec_rv64_helper.h | 133 ++++++++- src/dynarec/rv64/dynarec_rv64_private.h | 33 ++- 19 files changed, 734 insertions(+), 472 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 6bce1aca7..741a2fcba 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -1415,6 +1415,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (dyn->insts[ninst].x64.jmp_insts == -1) { // out of the block BARRIER(BARRIER_FLOAT); + fpu_purgecache(dyn, ninst, 0, x1, x2, x3); jump_to_next(dyn, (uintptr_t)getAlternate((void*)j64), 0, ninst, rex.is32bits); } else { // inside the block @@ -1457,6 +1458,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (box64_unittest_mode) { // HLT in unittest mode is an exit READFLAGS(X_ALL); BARRIER(BARRIER_FLOAT); + fpu_purgecache(dyn, ninst, 0, x1, x2, x3); MOV32w(x1, 1); SW(x1, xEmu, offsetof(x64emu_t, quit)); } else { diff --git a/src/dynarec/rv64/dynarec_rv64_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_0f_vector.c index c89a2c89e..21baf57fd 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_0f_vector.c @@ -152,7 +152,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, // Zvbb VWSLL would help here.... VWADDU_VX(v0, q0, xZR, VECTOR_UNMASKED); VWADDU_VX(v1, q1, xZR, VECTOR_UNMASKED); - VSLIDE1UP_VX(d0, v1, xZR, VECTOR_UNMASKED); + VSLIDE1UP_VX_SAFE(d0, v1, xZR, VECTOR_UNMASKED); VOR_VV(q0, v0, d0, VECTOR_UNMASKED); break; case 0x15: @@ -180,7 +180,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, // Zvbb VWSLL would help here.... VWADDU_VX(v0, q0, xZR, VECTOR_UNMASKED); VWADDU_VX(v1, q1, xZR, VECTOR_UNMASKED); - VSLIDE1UP_VX(d0, v1 + 1, xZR, VECTOR_UNMASKED); + VSLIDE1UP_VX_SAFE(d0, v1 + 1, xZR, VECTOR_UNMASKED); VOR_VV(q0, v0 + 1, d0, VECTOR_UNMASKED); } break; @@ -196,7 +196,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, v1 = fpu_get_scratch(dyn); VMV_V_V(v1, v0); } - VSLIDEUP_VI(v0, v1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, v1, 1, VECTOR_UNMASKED); } else { INST_NAME("MOVHPS Gx, Ex"); SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); @@ -206,7 +206,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, v1 = fpu_get_scratch(dyn); VECTOR_LOAD_VMASK(0xFF, x4, 1); VLE8_V(v1, ed, VECTOR_MASKED, VECTOR_NFIELD1); - VSLIDEUP_VI(v0, v1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, v1, 8, VECTOR_UNMASKED); } break; case 0x17: @@ -313,7 +313,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, v1 = fpu_get_scratch(dyn); ADDI(x4, xZR, 0b000010000111); VAND_VX(v0, q1, x4, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, v0, VECTOR_UNMASKED); // registers cannot be overlapped!! + VRGATHER_VV_SAFE(v1, q0, v0, VECTOR_UNMASKED); // registers cannot be overlapped!! VMV_V_V(q0, v1); break; case 0x01: @@ -328,7 +328,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); VADD_VV(q0, d1, d0, VECTOR_UNMASKED); @@ -345,7 +345,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 2, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 2, VECTOR_UNMASKED); ADDI(x4, xZR, 32); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); VNSRL_WX(d1, v0, x4, VECTOR_UNMASKED); @@ -363,7 +363,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); VSADD_VV(q0, d1, d0, VECTOR_UNMASKED); @@ -396,7 +396,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); VSUB_VV(q0, d0, d1, VECTOR_UNMASKED); @@ -413,7 +413,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 2, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 2, VECTOR_UNMASKED); ADDI(x4, xZR, 32); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); VNSRL_WX(d1, v0, x4, VECTOR_UNMASKED); @@ -431,7 +431,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); VSSUB_VV(q0, d0, d1, VECTOR_UNMASKED); @@ -739,7 +739,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(d0, v0); - VSLIDEUP_VI(d0, v1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, v1, 4, VECTOR_UNMASKED); SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); VNCLIP_WI(v0, d0, 0, VECTOR_UNMASKED); break; @@ -773,10 +773,10 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); if (q0 == q1) { VMV_V_V(d0, q0); - VSLIDEUP_VI(d0, q1, 4, VECTOR_UNMASKED); // splice q0 and q1 here! + VSLIDEUP_VI_SAFE(d0, q1, 4, VECTOR_UNMASKED); // splice q0 and q1 here! VMAX_VX(d0, d0, xZR, VECTOR_UNMASKED); } else { - VSLIDEUP_VI(q0, q1, 4, VECTOR_UNMASKED); // splice q0 and q1 here! + VSLIDEUP_VI_SAFE(q0, q1, 4, VECTOR_UNMASKED); // splice q0 and q1 here! VMAX_VX(d0, q0, xZR, VECTOR_UNMASKED); } SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); @@ -846,7 +846,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(d0, v0); - VSLIDEUP_VI(d0, v1, 2, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, v1, 2, VECTOR_UNMASKED); SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); VNCLIP_WI(v0, d0, 0, VECTOR_UNMASKED); break; @@ -1158,8 +1158,8 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, q1 = q0; } vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); - VRGATHER_VV(d0, v0, q0, VECTOR_UNMASKED); - VRGATHER_VV(d1, v1, q1, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(d0, v0, q0, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(d1, v1, q1, VECTOR_UNMASKED); } else { tmp64u0 = ((((uint64_t)u8 >> 2) & 3) << 16) | (u8 & 3); VECTOR_SPLAT_IMM(q0, tmp64u0, x4); @@ -1171,7 +1171,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, VRGATHEREI16_VV(d1, v1, q0, VECTOR_UNMASKED); } VMV_V_V(v0, d0); - VSLIDEUP_VI(v0, d1, 2, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, d1, 2, VECTOR_UNMASKED); break; case 0xD1: case 0xD2: diff --git a/src/dynarec/rv64/dynarec_rv64_660f_vector.c b/src/dynarec/rv64/dynarec_rv64_660f_vector.c index fb86b1d8a..0d356eff5 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_660f_vector.c @@ -131,7 +131,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i v1 = fpu_get_scratch(dyn); VMV_V_V(v1, v0); } - VSLIDEUP_VI(v0, v1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, v1, 1, VECTOR_UNMASKED); } else { q0 = fpu_get_scratch(dyn); VXOR_VV(q0, q0, q0, VECTOR_UNMASKED); @@ -184,7 +184,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i LD(x4, ed, fixedaddress); d0 = fpu_get_scratch(dyn); VMV_S_X(d0, x4); - VSLIDEUP_VI(v0, d0, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, d0, 1, VECTOR_UNMASKED); break; case 0x17: INST_NAME("MOVHPD Eq, Gx"); @@ -277,7 +277,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i v1 = fpu_get_scratch(dyn); ADDI(x4, xZR, 0b000010001111); VAND_VX(v0, q1, x4, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, v0, VECTOR_UNMASKED); // registers cannot be overlapped!! + VRGATHER_VV_SAFE(v1, q0, v0, VECTOR_UNMASKED); // registers cannot be overlapped!! VMV_V_V(q0, v1); break; case 0x01: @@ -292,7 +292,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 2); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 8, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); VNSRL_WI(d0, v0, 0, VECTOR_UNMASKED); VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); @@ -310,7 +310,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL2, 2); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); ADDI(x4, xZR, 32); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); @@ -329,7 +329,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 2); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 8, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); VNSRL_WI(d0, v0, 0, VECTOR_UNMASKED); VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); @@ -362,7 +362,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 2); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 8, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); VNSRL_WI(d0, v0, 0, VECTOR_UNMASKED); VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); @@ -671,7 +671,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VWMUL_VV(d0, v0, v1, VECTOR_UNMASKED); SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); - VSLIDEUP_VI(d0, d0 + 1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, d0 + 1, 1, VECTOR_UNMASKED); VMV_V_V(v0, d0); } break; @@ -701,7 +701,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i if (q0 != q1) VNCLIPU_WX(v0, d1, xZR, VECTOR_UNMASKED); SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); if (q0 == q1) VMV_V_V(v0, q0); - VSLIDEUP_VI(q0, v0, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q0, v0, 4, VECTOR_UNMASKED); break; case 0x30: INST_NAME("PMOVZXBW Gx, Ex"); @@ -949,7 +949,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i v0 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VSLIDEUP_VI(v0, q0, 16 - u8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, q0, 16 - u8, VECTOR_UNMASKED); if (cpuext.vlen >= 32) { // clear high bits before slidedown! d0 = fpu_get_scratch(dyn); @@ -1036,7 +1036,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i v0 = fpu_get_scratch(dyn); VMV_S_X(v0, ed); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, (u8 + 1) / 16.0f); - VSLIDEUP_VI(q0, v0, u8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q0, v0, u8, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, dyn->vector_sew, VECTOR_LMUL1, 1); } break; @@ -1076,7 +1076,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i v0 = fpu_get_scratch(dyn); VMV_S_X(v0, ed); vector_vsetvli(dyn, ninst, x1, dyn->vector_sew, VECTOR_LMUL1, (u8 + 1) / (float)(rex.w ? 2 : 4)); - VSLIDEUP_VI(q0, v0, u8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q0, v0, u8, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, dyn->vector_sew, VECTOR_LMUL1, 1); } break; @@ -1325,13 +1325,13 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i if (cpuext.vlen >= 32) { vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 2); // double the vl for slideup. VMV_V_V(d0, q0); - VSLIDEUP_VI(d0, q1, 8, VECTOR_UNMASKED); // splice q0 and q1 here! + VSLIDEUP_VI_SAFE(d0, q1, 8, VECTOR_UNMASKED); // splice q0 and q1 here! } else { d1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(d0, q0); VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 2); - VSLIDEUP_VI(d0, d1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, d1, 8, VECTOR_UNMASKED); } SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); VNCLIP_WI(q0, d0, 0, VECTOR_UNMASKED); @@ -1364,20 +1364,15 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); if (cpuext.vlen >= 32) { vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 2); // double the vl for slideup. - if (q0 == q1) { - VMV_V_V(d0, q0); - VSLIDEUP_VI(d0, q1, 8, VECTOR_UNMASKED); // splice q0 and q1 here! - VMAX_VX(d0, d0, xZR, VECTOR_UNMASKED); - } else { - VSLIDEUP_VI(q0, q1, 8, VECTOR_UNMASKED); // splice q0 and q1 here! - VMAX_VX(d0, q0, xZR, VECTOR_UNMASKED); - } + VMV_V_V(d0, q0); + VSLIDEUP_VI_SAFE(d0, q1, 8, VECTOR_UNMASKED); // splice q0 and q1 here! + VMAX_VX(d0, d0, xZR, VECTOR_UNMASKED); } else { d1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(d0, q0); VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 2); - VSLIDEUP_VI(d0, d1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, d1, 8, VECTOR_UNMASKED); VMAX_VX(d0, d0, xZR, VECTOR_UNMASKED); } SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); @@ -1432,13 +1427,13 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i if (cpuext.vlen >= 32) { vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 2); // double the vl for slideup. VMV_V_V(d0, q0); - VSLIDEUP_VI(d0, q1, 4, VECTOR_UNMASKED); // splice q0 and q1 here! + VSLIDEUP_VI_SAFE(d0, q1, 4, VECTOR_UNMASKED); // splice q0 and q1 here! } else { d1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(d0, q0); VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL2, 2); - VSLIDEUP_VI(d0, d1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, d1, 4, VECTOR_UNMASKED); } SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); VNCLIP_WI(q0, d0, 0, VECTOR_UNMASKED); @@ -1457,7 +1452,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i v1 = fpu_get_scratch(dyn); VMV_V_V(v1, v0); } - VSLIDEUP_VI(v0, v1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, v1, 1, VECTOR_UNMASKED); } else { q0 = fpu_get_scratch(dyn); VXOR_VV(q0, q0, q0, VECTOR_UNMASKED); @@ -1546,20 +1541,20 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); // clears upper bits! } if (tmp64u0 == tmp64u1) { - VSLIDE1UP_VX(v0, v1, x4, VECTOR_UNMASKED); + VSLIDE1UP_VX_SAFE(v0, v1, x4, VECTOR_UNMASKED); } else if (tmp64u0 == 0) { - VSLIDE1UP_VX(v0, v1, xZR, VECTOR_UNMASKED); + VSLIDE1UP_VX_SAFE(v0, v1, xZR, VECTOR_UNMASKED); } else { MOV64x(x4, tmp64u0); - VSLIDE1UP_VX(v0, v1, x4, VECTOR_UNMASKED); + VSLIDE1UP_VX_SAFE(v0, v1, x4, VECTOR_UNMASKED); } } SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); if (q0 == q1) { - VRGATHER_VV(v1, q1, v0, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q1, v0, VECTOR_UNMASKED); VMV_V_V(q0, v1); } else { - VRGATHER_VV(q0, q1, v0, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(q0, q1, v0, VECTOR_UNMASKED); } } else { tmp64u0 = ((tmp64u0 >> 6) << 48) | (((tmp64u0 >> 4) & 3) << 32) | (((tmp64u0 >> 2) & 3) << 16) | (tmp64u0 & 3); @@ -1732,7 +1727,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i } else { d0 = fpu_get_scratch(dyn); VXOR_VV(d0, d0, d0, VECTOR_UNMASKED); - VSLIDEUP_VI(d0, q0, u8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, q0, u8, VECTOR_UNMASKED); if (MODREG) { VMV_V_V(q0, d0); } else { @@ -1773,8 +1768,8 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); - v0 = sse_get_reg_empty_vector(dyn, ninst, x1, ed); v1 = sse_get_reg_vector(dyn, ninst, x1, gd, 0, dyn->vector_eew); + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, ed); VMV_V_V(v0, v1); } else { v1 = sse_get_reg_vector(dyn, ninst, x1, gd, 0, dyn->vector_eew); @@ -1895,7 +1890,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i d0 = v0; VMV_X_S(x4, d0); } - VSLIDE1UP_VX(v0, v1, x4, VECTOR_UNMASKED); + VSLIDE1UP_VX_SAFE(v0, v1, x4, VECTOR_UNMASKED); break; case 0xD1: case 0xD2: @@ -2306,7 +2301,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VWMULU_VV(d0, v0, v1, VECTOR_UNMASKED); SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); - VSLIDEUP_VI(d0, d0 + 1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, d0 + 1, 1, VECTOR_UNMASKED); VMV_V_V(v0, d0); } break; @@ -2346,7 +2341,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VSLIDEDOWN_VI(d0, v1, 8, VECTOR_UNMASKED); VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); VREDSUM_VS(v1, d0, v1, VECTOR_MASKED); // sum high 64 - VSLIDEUP_VI(v0, v1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, v1, 4, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 1); VMV_V_V(q0, v0); break; diff --git a/src/dynarec/rv64/dynarec_rv64_arch.c b/src/dynarec/rv64/dynarec_rv64_arch.c index 15d163816..2a7954e7a 100644 --- a/src/dynarec/rv64/dynarec_rv64_arch.c +++ b/src/dynarec/rv64/dynarec_rv64_arch.c @@ -141,6 +141,16 @@ static int arch_build(dynarec_rv64_t* dyn, int ninst, arch_build_t* arch) // pending x87 stack count if (e->x87stack) arch->x87_.delta = e->x87stack; + for (int i = 0; i < 32; ++i) { + if (e->extcache[i].t != EXT_CACHE_XMMR && e->extcache[i].t != EXT_CACHE_XMMW) + continue; + int xmm = e->extcache[i].n & 15; + if (e->ssecache[xmm].ymm) + arch->ymm_.ymm |= (uint16_t)(1 << xmm); + } + arch->ymm_.ymm0 = e->ymm0; + if (arch->ymm_.ymm || arch->ymm_.ymm0) + arch->ymm = 1; if (arch->x87_.x87 || arch->x87_.delta) arch->x87 = 1; if (arch->mmx_.mmx) @@ -208,20 +218,23 @@ static int sizeof_arch(arch_arch_t* arch) } -static void read_vector_reg(const void* vframe, size_t vlenb, int reg, void* buf) +static int read_vector_reg(const void* vframe, size_t vlenb, int reg, void* buf, size_t sz) { if (vframe) { - memcpy(buf, (const uint8_t*)vframe + (reg & 31) * vlenb, 16); - return; + if (vlenb < sz) return 0; + memcpy(buf, (const uint8_t*)vframe + (reg & 31) * vlenb, sz); + return 1; } // HACK: if vframe is absent, the live register is read instead. switch (reg & 31) { -#define VREG_CASE(N) \ - case N: \ - __asm__ volatile(".option push\n\t.option arch, +v\n\taddi t1, zero, 16\n\tvsetvli t0, t1, 0\n\tvse8.v v" #N ", (%0)\n\t.option pop\n\t" ::"r"(buf) \ - : "memory", "t0", "t1"); \ - break; +#define VREG_CASE(N) \ + case N: \ + __asm__ volatile(".option push\n\t.option arch, +v\n\tvsetvli t0, %1, 0\n\tvse8.v v" #N \ + ", (%0)\n\t.option pop\n\t" ::"r"(buf), \ + "r"(sz) \ + : "memory", "t0"); \ + return 1; VREG_CASE(0) VREG_CASE(1) VREG_CASE(2) @@ -256,6 +269,7 @@ static void read_vector_reg(const void* vframe, size_t vlenb, int reg, void* buf VREG_CASE(31) #undef VREG_CASE } + return 0; } static const void* get_vframe(const ucontext_t* p, size_t* vlenb) @@ -349,7 +363,7 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) dynarec_log(LOG_INFO, " rsp[%d] ", arch->rsp); emu->regs[_SP].q[0] += arch->rsp; } - if (sse || mmx) { + if (sse || mmx || ymm) { size_t vlenb = 0; const void* vframe = get_vframe(p, &vlenb); if (sse) { @@ -358,9 +372,9 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) if (!((sse->sse >> i) & 1)) continue; if ((sse->vector >> i) & 1) { - uint8_t vbuf[16]; - read_vector_reg(vframe, vlenb, sse->reg[i], vbuf); - memcpy(&emu->xmm[i], vbuf, 16); + uint8_t vbuf[32]; + if (read_vector_reg(vframe, vlenb, sse->reg[i], vbuf, 16)) + memcpy(&emu->xmm[i], vbuf, 16); } else if (sse->single[i]) { uint64_t raw = p->uc_mcontext.__fpregs.__d.__f[sse->reg[i] & 31]; *(uint32_t*)&emu->xmm[i] = (uint32_t)raw; @@ -369,6 +383,18 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) } } } + if (ymm) { + dynarec_log(LOG_INFO, " ymm[%x, 0=%x] ", ymm->ymm, ymm->ymm0); + for (int i = 0; i < 16; ++i) { + if (((ymm->ymm >> i) & 1) && sse && ((sse->vector >> i) & 1)) { + uint8_t vbuf[32]; + if (read_vector_reg(vframe, vlenb, sse->reg[i], vbuf, 32)) + memcpy(&emu->ymm[i], vbuf + 16, 16); + } + if ((ymm->ymm0 >> i) & 1) + emu->ymm[i].q[0] = emu->ymm[i].q[1] = 0; + } + } if (mmx) { dynarec_log(LOG_INFO, " mmx[%x, vector=%x] ", mmx->mmx, mmx->vector); for (int i = 0; i < 8; ++i) { @@ -376,8 +402,8 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) continue; if ((mmx->vector >> i) & 1) { uint8_t vbuf[16]; - read_vector_reg(vframe, vlenb, mmx->reg[i], vbuf); - emu->mmx[i].q = *(uint64_t*)vbuf; + if (read_vector_reg(vframe, vlenb, mmx->reg[i], vbuf, 8)) + emu->mmx[i].q = *(uint64_t*)vbuf; } else { emu->mmx[i].q = p->uc_mcontext.__fpregs.__d.__f[mmx->reg[i] & 31]; } diff --git a/src/dynarec/rv64/dynarec_rv64_avx.c b/src/dynarec/rv64/dynarec_rv64_avx.c index bd5f8b194..e34ef3f14 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx.c +++ b/src/dynarec/rv64/dynarec_rv64_avx.c @@ -62,6 +62,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n BARRIER(BARRIER_FLOAT); } } + if (!retaddr) avx_sync_upper_vector(dyn, ninst, x1, 0); addr = retaddr ? retaddr : dynarec64_AVX_0F(dyn, addr, ip, ninst, vex, ok, need_epilog); } else if ((vex.m == VEX_M_0F) && (vex.p == VEX_P_66)) { if (cpuext.vector && cpuext.vlen >= 32) { @@ -75,6 +76,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n BARRIER(BARRIER_FLOAT); } } + if (!retaddr) avx_sync_upper_vector(dyn, ninst, x1, 0); addr = retaddr ? retaddr : dynarec64_AVX_66_0F(dyn, addr, ip, ninst, vex, ok, need_epilog); } else if ((vex.m == VEX_M_0F) && (vex.p == VEX_P_F2)) { if (cpuext.vector && cpuext.vlen >= 32) { @@ -88,6 +90,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n BARRIER(BARRIER_FLOAT); } } + if (!retaddr) avx_sync_upper_vector(dyn, ninst, x1, 0); addr = retaddr ? retaddr : dynarec64_AVX_F2_0F(dyn, addr, ip, ninst, vex, ok, need_epilog); } else if ((vex.m == VEX_M_0F) && (vex.p == VEX_P_F3)) { if (cpuext.vector && cpuext.vlen >= 32) { @@ -101,6 +104,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n BARRIER(BARRIER_FLOAT); } } + if (!retaddr) avx_sync_upper_vector(dyn, ninst, x1, 0); addr = retaddr ? retaddr : dynarec64_AVX_F3_0F(dyn, addr, ip, ninst, vex, ok, need_epilog); } else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_66)) { if (cpuext.vector && cpuext.vlen >= 32) { @@ -114,14 +118,18 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n BARRIER(BARRIER_FLOAT); } } + if (!retaddr) avx_sync_upper_vector(dyn, ninst, x1, 0); addr = retaddr ? retaddr : dynarec64_AVX_66_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog); - } else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_NONE)) + } else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_NONE)) { + avx_sync_upper_vector(dyn, ninst, x1, 0); addr = dynarec64_AVX_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog); - else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_F2)) + } else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_F2)) { + avx_sync_upper_vector(dyn, ninst, x1, 0); addr = dynarec64_AVX_F2_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog); - else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_F3)) + } else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_F3)) { + avx_sync_upper_vector(dyn, ninst, x1, 0); addr = dynarec64_AVX_F3_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog); - else if ((vex.m == VEX_M_0F3A) && (vex.p == VEX_P_66)) { + } else if ((vex.m == VEX_M_0F3A) && (vex.p == VEX_P_66)) { if (cpuext.vector && cpuext.vlen >= 32) { uintptr_t vaddr = addr; retaddr = dynarec64_AVX_66_0F3A_vector(dyn, addr, ip, ninst, vex, ok, need_epilog); @@ -133,10 +141,12 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n BARRIER(BARRIER_FLOAT); } } + if (!retaddr) avx_sync_upper_vector(dyn, ninst, x1, 0); addr = retaddr ? retaddr : dynarec64_AVX_66_0F3A(dyn, addr, ip, ninst, vex, ok, need_epilog); - } else if ((vex.m == VEX_M_0F3A) && (vex.p == VEX_P_F2)) + } else if ((vex.m == VEX_M_0F3A) && (vex.p == VEX_P_F2)) { + avx_sync_upper_vector(dyn, ninst, x1, 0); addr = dynarec64_AVX_F2_0F3A(dyn, addr, ip, ninst, vex, ok, need_epilog); - else { + } else { DEFAULT; } diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index 6d9d84b10..e7c3c4c50 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -87,14 +87,14 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16); VSLIDEDOWN_VI(q2, q0, 1, VECTOR_UNMASKED); VMV_V_V(v0, q1); - VSLIDEUP_VI(v0, q2, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, q2, 1, VECTOR_UNMASKED); avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); break; case 0x13: INST_NAME("VMOVLPS Ex, Gx"); nextop = F8; if (MODREG) return 0; - GETGY_vector(q0, VECTOR_SEW64); + GETGY_vector_cached(q0, VECTOR_SEW64); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); VMV_X_S(x4, q0); SD(x4, ed, fixedaddress); @@ -103,7 +103,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x14: INST_NAME("VUNPCKLPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -113,8 +113,8 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t VAND_VI(v1, q2, 4, VECTOR_UNMASKED); VADD_VV(q2, q2, v1, VECTOR_UNMASKED); VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0xaa, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW32); @@ -122,7 +122,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x15: INST_NAME("VUNPCKHPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -133,8 +133,8 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t VADD_VV(q2, q2, v1, VECTOR_UNMASKED); VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); VADD_VI(q2, q2, 2, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0xaa, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW32); @@ -159,14 +159,14 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t GETGY_empty_vector(v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16); VMV_V_V(v0, q0); - VSLIDEUP_VI(v0, q1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, q1, 1, VECTOR_UNMASKED); avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); break; case 0x17: INST_NAME("VMOVHPS Ex, Gx"); nextop = F8; if (MODREG) return 0; - GETGY_vector(q0, VECTOR_SEW64); + GETGY_vector_cached(q0, VECTOR_SEW64); q1 = fpu_get_scratch(dyn); VSLIDEDOWN_VI(q1, q0, 1, VECTOR_UNMASKED); VMV_X_S(x4, q1); @@ -256,7 +256,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x54: INST_NAME("VANDPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VAND_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -265,7 +265,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x55: INST_NAME("VANDNPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VXOR_VI(v0, q0, 0x1f, VECTOR_UNMASKED); @@ -275,7 +275,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x56: INST_NAME("VORPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VOR_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -284,7 +284,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x57: INST_NAME("VXORPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VXOR_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -294,7 +294,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VADDPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VFADD_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -304,7 +304,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VMULPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VFMUL_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -345,7 +345,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VSUBPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VFSUB_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -354,7 +354,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x5D: INST_NAME("VMINPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); @@ -365,7 +365,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VDIVPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VFDIV_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -374,7 +374,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x5F: INST_NAME("VMAXPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); @@ -465,7 +465,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0xC2: INST_NAME("VCMPPS Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 1, VECTOR_SEW32); u8 = F8; GETGY_empty_vector(v0); @@ -522,7 +522,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0xC6: INST_NAME("VSHUFPS Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 1, VECTOR_SEW32); u8 = F8; selectors = 0; @@ -535,15 +535,16 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t } GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + v1 = fpu_get_scratch(dyn); + VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); for (int i = 0; i < (4 << vex.l); ++i) { int selector = selectors >> (i * 8); MOV32w(x4, selector & 0x1f); - VRGATHER_VX(q2, (selector & 0x80) ? q1 : q0, x4, VECTOR_UNMASKED); + VRGATHER_VX_SAFE(q2, (selector & 0x80) ? q1 : q0, x4, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1 << i, x4, vex.l ? 2 : 1); - VMERGE_VVM(v0, v0, q2); + VMERGE_VVM(v1, v1, q2); } - PUTGY_vector(v0, VECTOR_SEW32); + PUTGY_vector(v1, VECTOR_SEW32); break; default: DEFAULT_VECTOR; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c index 967fca6f0..57a406a90 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c @@ -2186,7 +2186,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDC: INST_NAME("VAESENC Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && (!vex.l || cpuext.vlen >= 32)) { + if (cpuext.zvkned && cpuext.vlen >= 32) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); @@ -2258,7 +2258,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDD: INST_NAME("VAESENCLAST Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && (!vex.l || cpuext.vlen >= 32)) { + if (cpuext.zvkned && cpuext.vlen >= 32) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); @@ -2333,7 +2333,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i if (vex.l) { DEFAULT; } - if (cpuext.zvkned) { + if (cpuext.zvkned && cpuext.vlen >= 32) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v1 = fpu_get_scratch(dyn); @@ -2365,7 +2365,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDE: INST_NAME("VAESDEC Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && (!vex.l || cpuext.vlen >= 32)) { + if (cpuext.zvkned && cpuext.vlen >= 32) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); @@ -2444,7 +2444,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDF: INST_NAME("VAESDECLAST Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && (!vex.l || cpuext.vlen >= 32)) { + if (cpuext.zvkned && cpuext.vlen >= 32) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c index 855894266..abd68ae01 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c @@ -44,7 +44,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VPSHUFB Gx, Vx, Ex"); BARRIER(BARRIER_FLOAT); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); v1 = fpu_get_scratch(dyn); @@ -59,14 +59,14 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VMV_V_V(v2, q1); VAND_VX(v2, v2, x5, VECTOR_UNMASKED); VSLIDEDOWN_VI(q2, v1, 16, VECTOR_UNMASKED); - VSLIDEUP_VI(v2, q2, 16, VECTOR_UNMASKED); - VRGATHER_VV(v0, q0, v2, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v2, q2, 16, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q0, v2, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0x08: INST_NAME("VPSIGNB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); VMV_V_V(v0, q0); @@ -79,7 +79,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x09: INST_NAME("VPSIGNW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); VMV_V_V(v0, q0); @@ -92,7 +92,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x0A: INST_NAME("VPSIGND Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VMV_V_V(v0, q0); @@ -105,7 +105,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x0B: INST_NAME("VPMULHRSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); @@ -120,7 +120,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x0C: INST_NAME("VPERMILPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -128,13 +128,13 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VAND_VI(q2, q2, 4, VECTOR_UNMASKED); VAND_VI(q1, q1, 3, VECTOR_UNMASKED); VADD_VV(q1, q1, q2, VECTOR_UNMASKED); - VRGATHER_VV(v0, q0, q1, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x0D: INST_NAME("VPERMILPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -143,7 +143,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VSRL_VI(q1, q1, 1, VECTOR_UNMASKED); VAND_VI(q1, q1, 1, VECTOR_UNMASKED); VADD_VV(q1, q1, q2, VECTOR_UNMASKED); - VRGATHER_VV(v0, q0, q1, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x0E: @@ -157,7 +157,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint } nextop = F8; SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); - GETGY_vector(q0, sew); + GETGY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); v0 = fpu_get_scratch(dyn); CLEAR_FLAGS(); @@ -185,21 +185,24 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VAND_VI(q0, q0, 7, VECTOR_UNMASKED); - VRGATHER_VV(v0, q1, q0, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q1, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x18: INST_NAME("VBROADCASTSS Gx, Ex"); nextop = F8; - GETGY_empty_vector(v0); if (MODREG) { q0 = fpu_get_scratch(dyn); ed = (nextop & 7) + (rex.b << 3); avx_load_reg_vector(dyn, ninst, x1, q0, ed, 16, VECTOR_SEW32); - VMV_X_S(x4, q0); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); + } + GETGY_empty_vector(v0); + if (MODREG) { + VMV_X_S(x4, q0); + } else { LW(x4, ed, fixedaddress); } SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); @@ -209,15 +212,18 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x19: INST_NAME("VBROADCASTSD Gx, Ex"); nextop = F8; - GETGY_empty_vector(v0); if (MODREG) { q0 = fpu_get_scratch(dyn); ed = (nextop & 7) + (rex.b << 3); avx_load_reg_vector(dyn, ninst, x1, q0, ed, 16, VECTOR_SEW64); - VMV_X_S(x4, q0); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); + } + GETGY_empty_vector(v0); + if (MODREG) { + VMV_X_S(x4, q0); + } else { LD(x4, ed, fixedaddress); } SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); @@ -241,7 +247,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETGY_empty_vector(v0); VMV_V_V(v0, q0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 32); - VSLIDEUP_VI(v0, q0, 16, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, q0, 16, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0x1C: @@ -331,15 +337,15 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x28: INST_NAME("VPMULDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); VID_V(v2, VECTOR_UNMASKED); VSLL_VI(v2, v2, 1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, v2, VECTOR_UNMASKED); - VRGATHER_VV(v0, q1, v2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, v2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q1, v2, VECTOR_UNMASKED); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VWMUL_VV(q2, v1, v0, VECTOR_UNMASKED); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); @@ -349,7 +355,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x29: INST_NAME("VPCMPEQQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMSEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); @@ -371,7 +377,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x2B: INST_NAME("VPACKUSDW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); @@ -383,18 +389,18 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); VSLIDEDOWN_VI(q2 + 1, q2, 4, VECTOR_UNMASKED); // hi[0..3] = a[4..7] avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 32); - VSLIDEUP_VI(q2, v1, 4, VECTOR_UNMASKED); // lo[4..7] = b[0..3] + VSLIDEUP_VI_SAFE(q2, v1, 4, VECTOR_UNMASKED); // lo[4..7] = b[0..3] vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); VSLIDEDOWN_VI(v1 + 1, v1, 4, VECTOR_UNMASKED); // v1 hi[0..3] = b[4..7] avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 32); - VSLIDEUP_VI(q2 + 1, v1 + 1, 4, VECTOR_UNMASKED); // hi[4..7] = b[4..7] + VSLIDEUP_VI_SAFE(q2 + 1, v1 + 1, 4, VECTOR_UNMASKED); // hi[4..7] = b[4..7] if (cpuext.vlen > 32) { vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 4); - VSLIDEUP_VI(q2, q2 + 1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q2, q2 + 1, 8, VECTOR_UNMASKED); } } else { vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 2); - VSLIDEUP_VI(q2, v1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q2, v1, 4, VECTOR_UNMASKED); } avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16 << vex.l); VNCLIPU_WI(v0, q2, 0, VECTOR_UNMASKED); @@ -403,8 +409,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x2C: INST_NAME("VMASKMOVPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETGY_empty_vector(v0); + if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMSLT_VX(VMASK, q0, xZR, VECTOR_UNMASKED); if (MODREG) { @@ -423,8 +430,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x2D: INST_NAME("VMASKMOVPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETGY_empty_vector(v0); + if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMSLT_VX(VMASK, q0, xZR, VECTOR_UNMASKED); if (MODREG) { @@ -526,13 +534,13 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VAND_VI(q0, q0, 7, VECTOR_UNMASKED); - VRGATHER_VV(v0, q1, q0, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q1, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x37: INST_NAME("VPCMPGTQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMSLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); @@ -543,7 +551,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x38: INST_NAME("VPMINSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); VMIN_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -552,7 +560,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x39: INST_NAME("VPMINSD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VMIN_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -561,7 +569,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x3D: INST_NAME("VPMAXSD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VMAX_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -570,7 +578,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x3A: INST_NAME("VPMINUW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); VMINU_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -579,7 +587,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x3B: INST_NAME("VPMINUD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VMINU_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -588,7 +596,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x3C: INST_NAME("VPMAXSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); VMAX_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -597,7 +605,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x3E: INST_NAME("VPMAXUW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); VMAXU_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -606,7 +614,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x3F: INST_NAME("VPMAXUD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VMAXU_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -615,7 +623,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x40: INST_NAME("VPMULLD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VMUL_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -625,18 +633,20 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VPSRLVD/Q Gx, Vx, Ex"); nextop = F8; if (rex.w) { - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); + if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); MOV32w(x4, 64); VMSLTU_VX(VMASK, q1, x4, VECTOR_UNMASKED); VSRL_VV(v0, q0, q1, VECTOR_MASKED); PUTGY_vector(v0, VECTOR_SEW64); } else { - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); + if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); MOV32w(x4, 32); VMSLTU_VX(VMASK, q1, x4, VECTOR_UNMASKED); @@ -648,7 +658,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (rex.w) return 0; INST_NAME("VPSRAVD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -661,18 +671,20 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VPSLLVD/Q Gx, Vx, Ex"); nextop = F8; if (rex.w) { - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); + if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); MOV32w(x4, 64); VMSLTU_VX(VMASK, q1, x4, VECTOR_UNMASKED); VSLL_VV(v0, q0, q1, VECTOR_MASKED); PUTGY_vector(v0, VECTOR_SEW64); } else { - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); + if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); MOV32w(x4, 32); VMSLTU_VX(VMASK, q1, x4, VECTOR_UNMASKED); @@ -683,7 +695,6 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x58: INST_NAME("VPBROADCASTD Gx, Ex"); nextop = F8; - GETGY_empty_vector(v0); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); q0 = fpu_get_scratch(dyn); @@ -694,6 +705,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); LW(x4, ed, fixedaddress); } + GETGY_empty_vector(v0); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); VMV_V_X(v0, x4); PUTGY_vector(v0, VECTOR_SEW32); @@ -701,7 +713,6 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x59: INST_NAME("VPBROADCASTQ Gx, Ex"); nextop = F8; - GETGY_empty_vector(v0); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); q0 = fpu_get_scratch(dyn); @@ -712,6 +723,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); LD(x4, ed, fixedaddress); } + GETGY_empty_vector(v0); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); VMV_V_X(v0, x4); PUTGY_vector(v0, VECTOR_SEW64); @@ -733,13 +745,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETGY_empty_vector(v0); VMV_V_V(v0, q0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 32); - VSLIDEUP_VI(v0, q0, 16, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, q0, 16, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0x78: INST_NAME("VPBROADCASTB Gx, Ex"); nextop = F8; - GETGY_empty_vector(v0); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); q0 = fpu_get_scratch(dyn); @@ -750,6 +761,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); LBU(x4, ed, fixedaddress); } + GETGY_empty_vector(v0); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW8); VMV_V_X(v0, x4); PUTGY_vector(v0, VECTOR_SEW8); @@ -757,7 +769,6 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x79: INST_NAME("VPBROADCASTW Gx, Ex"); nextop = F8; - GETGY_empty_vector(v0); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); q0 = fpu_get_scratch(dyn); @@ -768,6 +779,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); LHU(x4, ed, fixedaddress); } + GETGY_empty_vector(v0); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW16); VMV_V_X(v0, x4); PUTGY_vector(v0, VECTOR_SEW16); @@ -776,8 +788,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VPMASKMOVD/Q Gx, Vx, Ex"); nextop = F8; if (rex.w) { - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETGY_empty_vector(v0); + if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMSLT_VX(VMASK, q0, xZR, VECTOR_UNMASKED); if (MODREG) { @@ -793,8 +806,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint } PUTGY_vector(v0, VECTOR_SEW64); } else { - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETGY_empty_vector(v0); + if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMSLT_VX(VMASK, q0, xZR, VECTOR_UNMASKED); if (MODREG) { @@ -837,7 +851,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMADD132PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); @@ -849,7 +863,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMADDSUB132PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); @@ -866,7 +880,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMSUBADD132PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); @@ -883,7 +897,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMSUB132PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); @@ -895,7 +909,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFNMADD132PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); @@ -907,7 +921,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFNMSUB132PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); @@ -919,7 +933,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMADD213PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); @@ -931,7 +945,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMADDSUB213PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); @@ -948,7 +962,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMSUBADD213PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); @@ -965,7 +979,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMSUB213PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); @@ -977,7 +991,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFNMADD213PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); @@ -989,7 +1003,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFNMSUB213PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); @@ -1001,9 +1015,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMADD231PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); - GETGY_vector(q2, sew); + GETGY_vector_cached(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); VFMACC_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1013,9 +1027,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMADDSUB231PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); - GETGY_vector(q2, sew); + GETGY_vector_cached(q2, sew); GETGY_empty_vector(v0); v1 = fpu_get_scratch(dyn); VMV_V_V(v0, q2); @@ -1030,9 +1044,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMSUBADD231PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); - GETGY_vector(q2, sew); + GETGY_vector_cached(q2, sew); GETGY_empty_vector(v0); v1 = fpu_get_scratch(dyn); VMV_V_V(v0, q2); @@ -1047,9 +1061,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMSUB231PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); - GETGY_vector(q2, sew); + GETGY_vector_cached(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); VFMSAC_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1059,9 +1073,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFNMADD231PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); - GETGY_vector(q2, sew); + GETGY_vector_cached(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); VFNMSAC_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1071,9 +1085,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFNMSUB231PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector(q0, sew); + GETVY_vector_cached(q0, sew); GETEY_vector(q1, 0, sew); - GETGY_vector(q2, sew); + GETGY_vector_cached(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); VFNMACC_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1164,7 +1178,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector(q2, sew); + GETGY_vector_cached(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { @@ -1190,7 +1204,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector(q2, sew); + GETGY_vector_cached(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { @@ -1216,7 +1230,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector(q2, sew); + GETGY_vector_cached(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { @@ -1242,7 +1256,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector(q2, sew); + GETGY_vector_cached(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { @@ -1269,7 +1283,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector(q2, sew); + GETGY_vector_cached(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { @@ -1378,7 +1392,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector(q2, sew); + GETGY_vector_cached(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { @@ -1394,10 +1408,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VFSGNJN_VV(v0, v0, v0, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1, x4, 1); + VFSGNJN_VV(v0, v0, v0, VECTOR_MASKED); VFMACC_VV(v0, q0, q1, VECTOR_MASKED); - VMERGE_VVM(v0, q2, v0); PUTGY_vector(v0, sew); break; case 0xBD: @@ -1406,7 +1419,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector(q2, sew); + GETGY_vector_cached(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { @@ -1433,7 +1446,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector(q2, sew); + GETGY_vector_cached(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c index 500a52e1c..f34e8db62 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c @@ -153,7 +153,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VMV_V_V(q2, q0); } if (i) { - VSLIDEUP_VI(q1, q2, 16, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q1, q2, 16, VECTOR_UNMASKED); q2 = q1; } VECTOR_LOAD_VMASK(i ? 0xffff0000 : 0xffff, x4, 2); @@ -194,6 +194,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint gd = ((nextop & 0x38) >> 3) + (rex.r << 3); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); sse_forget_reg_vector(dyn, ninst, x1, gd); + sse_set_pending_zero(dyn, gd, 0); ADDI(x1, xEmu, offsetof(x64emu_t, xmm[gd])); if (u8 & 1) { VSE8_V(q0, x1, VECTOR_UNMASKED, VECTOR_NFIELD1); @@ -259,7 +260,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (u8 & 1) { v1 = fpu_get_scratch(dyn); VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); - VSLIDEUP_VI(v1, q1, 2, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v1, q1, 2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0b1100, x4, 2); VMERGE_VVM(v0, v0, v1); } else { @@ -299,19 +300,17 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x42: INST_NAME("VMPSADBW Gx, Vx, Ex, Ib"); nextop = F8; - mmx_purgecache(dyn, ninst, 0, x1); - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 1, VECTOR_SEW8); GETGY_empty_vector(v0); u8 = F8; - q2 = fpu_get_scratch(dyn); int q3 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); int q4 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); - int q5 = fpu_get_scratch(dyn); - int q6 = fpu_get_scratch(dyn); - int q7 = fpu_get_scratch(dyn); - int q8 = fpu_get_scratch(dyn); - int q9 = fpu_get_scratch(dyn); + int q2 = fpu_borrow_reg(dyn, ninst, x1, x2, 8); + int q5 = fpu_borrow_reg(dyn, ninst, x1, x2, 9); + int q6 = fpu_borrow_reg(dyn, ninst, x1, x2, 10); + int q7 = fpu_borrow_reg(dyn, ninst, x1, x2, 11); + int q8 = fpu_borrow_reg(dyn, ninst, x1, x2, 12); for (int pass = 0; pass < (vex.l ? 2 : 1); ++pass) { vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 2); @@ -333,8 +332,8 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (off5) VADD_VI(q5, q5, off5, VECTOR_UNMASKED); if (off6) VADD_VI(q6, q6, off6, VECTOR_UNMASKED); - VRGATHER_VV(q3, q7, q5, VECTOR_UNMASKED); - VRGATHER_VV(q4, q8, q6, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(q3, q7, q5, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(q4, q8, q6, VECTOR_UNMASKED); VMAXU_VV(q7, q3, q4, VECTOR_UNMASKED); VMINU_VV(q4, q3, q4, VECTOR_UNMASKED); VSUB_VV(q7, q7, q4, VECTOR_UNMASKED); @@ -358,7 +357,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VMV_V_V(v0, q2); if (vex.l) { avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); - VSLIDEUP_VI(v0, q3, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, q3, 8, VECTOR_UNMASKED); } PUTGY_vector(v0, VECTOR_SEW16); break; @@ -391,7 +390,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VMV_V_V(q2, q0); } if (i) { - VSLIDEUP_VI(q1, q2, 16, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q1, q2, 16, VECTOR_UNMASKED); q2 = q1; } VECTOR_LOAD_VMASK(i ? 0xffff0000 : 0xffff, x4, 2); @@ -682,9 +681,9 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (rex.w) return 0; INST_NAME("VPINSRB Gx, Vx, Ed, Ib"); nextop = F8; - GETGY_empty_vector(v0); q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW8); + GETGY_empty_vector(v0); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); ANDI(x5, ed, 0xFF); @@ -705,7 +704,6 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x21: INST_NAME("VINSERTPS Gx, Vx, Ex, Ib"); nextop = F8; - GETGY_empty_vector(v0); q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); @@ -716,6 +714,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 1); } + GETGY_empty_vector(v0); u8 = F8; q2 = fpu_get_scratch(dyn); if (MODREG) { @@ -740,7 +739,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x40: { INST_NAME("VDPPS Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 1, VECTOR_SEW32); GETGY_empty_vector(v0); u8 = F8; @@ -782,10 +781,10 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16 << vex.l, VECTOR_SEW8); GETEY_vector(q1, 1, VECTOR_SEW8); - GETGY_empty_vector(v0); u8 = F8; q2 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q2, (u8 >> 4) & 0xf, 16 << vex.l, VECTOR_SEW8); + GETGY_empty_vector(v0); VMSLT_VX(VMASK, q2, xZR, VECTOR_UNMASKED); VMERGE_VVM(v0, q0, q1); PUTGY_vector(v0, VECTOR_SEW8); @@ -796,10 +795,10 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16 << vex.l, VECTOR_SEW64); GETEY_vector(q1, 1, VECTOR_SEW64); - GETGY_empty_vector(v0); u8 = F8; q2 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q2, (u8 >> 4) & 0xf, 16 << vex.l, VECTOR_SEW64); + GETGY_empty_vector(v0); VMSLT_VX(VMASK, q2, xZR, VECTOR_UNMASKED); VMERGE_VVM(v0, q0, q1); PUTGY_vector(v0, VECTOR_SEW64); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index 3e578fd82..3ccfb31dd 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -67,24 +67,23 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x12: INST_NAME("VMOVLPD Gx, Vx, Ex"); nextop = F8; + if (MODREG) return 0; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); GETGY_empty_vector(v0); - avx_load_reg_vector(dyn, ninst, x1, v0, vex.v, 16, VECTOR_SEW64); - if (MODREG) { - return 0; - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); - LD(x2, ed, fixedaddress); - vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); - VMV_S_X(v0, x2); - } + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); + LD(x2, ed, fixedaddress); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + VMV_V_V(v0, q0); + VMV_S_X(v0, x2); avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); break; case 0x13: INST_NAME("VMOVLPD Ex, Gx"); nextop = F8; if (MODREG) return 0; - GETGY_vector(q0, VECTOR_SEW64); + GETGY_vector_cached(q0, VECTOR_SEW64); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); VMV_X_S(x4, q0); SD(x4, ed, fixedaddress); @@ -93,7 +92,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x14: INST_NAME("VUNPCKLPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -101,8 +100,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt v2 = fpu_get_scratch(dyn); VID_V(q2, VECTOR_UNMASKED); VAND_VI(q2, q2, 2, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0x0a, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW64); @@ -110,7 +109,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x15: INST_NAME("VUNPCKHPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -119,8 +118,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VID_V(q2, VECTOR_UNMASKED); VAND_VI(q2, q2, 2, VECTOR_UNMASKED); VADD_VI(q2, q2, 1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0x0a, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW64); @@ -144,14 +143,14 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt GETGY_empty_vector(v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16); VMV_V_V(v0, q0); - VSLIDEUP_VI(v0, q1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, q1, 1, VECTOR_UNMASKED); avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); break; case 0x17: INST_NAME("VMOVHPD Ex, Gx"); nextop = F8; if (MODREG) return 0; - GETGY_vector(q0, VECTOR_SEW64); + GETGY_vector_cached(q0, VECTOR_SEW64); q1 = fpu_get_scratch(dyn); VSLIDEDOWN_VI(q1, q0, 1, VECTOR_UNMASKED); VMV_X_S(x4, q1); @@ -216,7 +215,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x54: INST_NAME("VANDPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VAND_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -225,7 +224,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x55: INST_NAME("VANDNPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VXOR_VI(v0, q0, 0x1f, VECTOR_UNMASKED); @@ -235,7 +234,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x56: INST_NAME("VORPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VOR_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -244,7 +243,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x57: INST_NAME("VXORPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VXOR_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -254,7 +253,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VADDPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VFADD_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -264,7 +263,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VMULPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VFMUL_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -306,7 +305,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VSUBPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VFSUB_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -315,7 +314,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x5D: INST_NAME("VMINPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); @@ -326,7 +325,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VDIVPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VFDIV_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -335,7 +334,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x5F: INST_NAME("VMAXPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); @@ -345,7 +344,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x60: INST_NAME("VPUNPCKLBW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -357,8 +356,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VAND_VI(q2, q2, 15, VECTOR_UNMASKED); VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); VADD_VV(q2, q2, v1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0xaaaaaaaa, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW8); @@ -366,7 +365,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x61: INST_NAME("VPUNPCKLWD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -377,8 +376,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VAND_VI(q2, q2, 7, VECTOR_UNMASKED); VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); VADD_VV(q2, q2, v1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0xaaaa, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW16); @@ -386,7 +385,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x62: INST_NAME("VPUNPCKLDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -397,8 +396,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VAND_VI(q2, q2, 3, VECTOR_UNMASKED); VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); VADD_VV(q2, q2, v1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0xaa, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW32); @@ -407,13 +406,13 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (vex.l) return 0; INST_NAME("VPACKSSWB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); VMV_V_V(q2, q0); - VSLIDEUP_VI(q2, q1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q2, q1, 8, VECTOR_UNMASKED); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); VNCLIP_WI(v0, q2, 0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); @@ -421,7 +420,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x68: INST_NAME("VPUNPCKHBW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -434,8 +433,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); VADD_VI(q2, q2, 8, VECTOR_UNMASKED); VADD_VV(q2, q2, v1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0xaaaaaaaa, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW8); @@ -443,7 +442,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x69: INST_NAME("VPUNPCKHWD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -455,8 +454,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); VADD_VI(q2, q2, 4, VECTOR_UNMASKED); VADD_VV(q2, q2, v1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0xaaaa, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW16); @@ -464,7 +463,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x6A: INST_NAME("VPUNPCKHDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -476,8 +475,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); VADD_VI(q2, q2, 2, VECTOR_UNMASKED); VADD_VV(q2, q2, v1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0xaa, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW32); @@ -486,13 +485,13 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (vex.l) return 0; INST_NAME("VPACKSSDW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 32); VMV_V_V(q2, q0); - VSLIDEUP_VI(q2, q1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q2, q1, 4, VECTOR_UNMASKED); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16); VNCLIP_WI(v0, q2, 0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); @@ -501,7 +500,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (vex.l) return 0; INST_NAME("VPACKUSWB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); @@ -509,7 +508,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VMAX_VX(q2, q0, xZR, VECTOR_UNMASKED); v1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMAX_VX(v1, q1, xZR, VECTOR_UNMASKED); - VSLIDEUP_VI(q2, v1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q2, v1, 8, VECTOR_UNMASKED); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); VNCLIPU_WI(v0, q2, 0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); @@ -518,25 +517,25 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (vex.l) return 0; INST_NAME("VPUNPCKLQDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMV_V_V(v0, q0); - VSLIDEUP_VI(v0, q1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, q1, 1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x6D: if (vex.l) return 0; INST_NAME("VPUNPCKHQDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); VSLIDEDOWN_VI(q2, q0, 1, VECTOR_UNMASKED); VSLIDEDOWN_VI(v1, q1, 1, VECTOR_UNMASKED); - VSLIDEUP_VI(q2, v1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q2, v1, 1, VECTOR_UNMASKED); VMV_V_V(v0, q2); PUTGY_vector(v0, VECTOR_SEW64); break; @@ -578,7 +577,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt MOV64x(x5, 0x0004000400040004LL); ADD(x5, x4, x5); // x5 = lane1 selector VMV_S_X(s, x5); // s[0] = lane1 selector - VSLIDE1UP_VX(q2, s, x4, VECTOR_UNMASKED); // q2[0]=x4, q2[1]=s[0] + VSLIDE1UP_VX_SAFE(q2, s, x4, VECTOR_UNMASKED); // q2[0]=x4, q2[1]=s[0] } else { VMV_S_X(q2, x4); } @@ -593,8 +592,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 2: INST_NAME("VPSRLW Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW16); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 15) VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -605,8 +604,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 4: INST_NAME("VPSRAW Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW16); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 15) u8 = 15; VSRA_VI(v0, q1, u8, VECTOR_UNMASKED); @@ -615,8 +614,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 6: INST_NAME("VPSLLW Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW16); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 15) VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -634,8 +633,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 2: INST_NAME("VPSRLD Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW32); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 31) VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -646,8 +645,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 4: INST_NAME("VPSRAD Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW32); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 31) u8 = 31; VSRA_VI(v0, q1, u8, VECTOR_UNMASKED); @@ -656,8 +655,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 6: INST_NAME("VPSLLD Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW32); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 31) VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -675,8 +674,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 2: INST_NAME("VPSRLQ Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW64); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 63) VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -690,8 +689,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 3: INST_NAME("VPSRLDQ Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW8); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 15) { VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -706,15 +705,15 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt ADDI(x4, xZR, 16 - u8); VMSLTU_VX(VMASK, v1, x4, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VRGATHER_VV(v0, q1, q2, VECTOR_MASKED); + VRGATHER_VV_SAFE(v0, q1, q2, VECTOR_MASKED); } PUTGY_vector(v0, VECTOR_SEW8); break; case 7: INST_NAME("VPSLLDQ Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW8); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 15) { VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -730,15 +729,15 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt ADDI(x4, xZR, u8 - 1); VMSGTU_VX(VMASK, v1, x4, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VRGATHER_VV(v0, q1, q2, VECTOR_MASKED); + VRGATHER_VV_SAFE(v0, q1, q2, VECTOR_MASKED); } PUTGY_vector(v0, VECTOR_SEW8); break; case 6: INST_NAME("VPSLLQ Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW64); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 63) VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -756,7 +755,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x64: INST_NAME("VPCMPGTB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); VMSLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); @@ -767,7 +766,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x65: INST_NAME("VPCMPGTW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); VMSLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); @@ -778,7 +777,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x66: INST_NAME("VPCMPGTD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VMSLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); @@ -797,7 +796,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x74: INST_NAME("VPCMPEQB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); VMSEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); @@ -808,7 +807,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x75: INST_NAME("VPCMPEQW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); VMSEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); @@ -819,7 +818,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x76: INST_NAME("VPCMPEQD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VMSEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); @@ -847,7 +846,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VADDSUBPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -862,7 +861,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD1: INST_NAME("VPSRLW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY128_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMV_X_S(x4, q1); @@ -876,7 +875,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD2: INST_NAME("VPSRLD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY128_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMV_X_S(x4, q1); @@ -890,7 +889,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD3: INST_NAME("VPSRLQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY128_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMV_X_S(x4, q1); @@ -904,7 +903,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (vex.l) return 0; INST_NAME("VMOVQ Ex, Gx"); nextop = F8; - GETGY_vector(q0, VECTOR_SEW64); + GETGY_vector_cached(q0, VECTOR_SEW64); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); q1 = fpu_get_scratch(dyn); @@ -923,7 +922,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD4: INST_NAME("VPADDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VADD_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -932,7 +931,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD5: INST_NAME("VPMULLW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); VMUL_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -941,7 +940,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD8: INST_NAME("VPSUBUSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -954,7 +953,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD9: INST_NAME("VPSUBUSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -967,7 +966,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xDA: INST_NAME("VPMINUB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); VMINU_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -976,7 +975,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xDB: INST_NAME("VPAND Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VAND_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -985,7 +984,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xDC: INST_NAME("VPADDUSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); VSADDU_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -994,7 +993,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xDD: INST_NAME("VPADDUSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); VSADDU_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1003,7 +1002,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xDE: INST_NAME("VPMAXUB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); VMAXU_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1012,7 +1011,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xDF: INST_NAME("VPANDN Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VXOR_VI(v0, q0, 0x1f, VECTOR_UNMASKED); @@ -1022,7 +1021,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xE0: INST_NAME("VPAVGB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); CSRRWI(xZR, 0b00, 0x00A); @@ -1032,7 +1031,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xE3: INST_NAME("VPAVGW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); CSRRWI(xZR, 0b00, 0x00A); @@ -1042,7 +1041,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xE4: INST_NAME("VPMULHUW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); VMULHU_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1051,7 +1050,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xE5: INST_NAME("VPMULHW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); VMULH_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1070,7 +1069,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xE8: INST_NAME("VPSUBSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); VSSUB_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1079,7 +1078,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xE9: INST_NAME("VPSUBSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); VSSUB_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1088,7 +1087,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xEA: INST_NAME("VPMINSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); VMIN_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1097,7 +1096,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xEB: INST_NAME("VPOR Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VOR_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1106,7 +1105,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xEC: INST_NAME("VPADDSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); VSADD_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1115,7 +1114,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xED: INST_NAME("VPADDSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); VSADD_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1124,7 +1123,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xEE: INST_NAME("VPMAXSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); VMAX_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1133,7 +1132,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xEF: INST_NAME("VPXOR Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VXOR_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1142,7 +1141,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xF1: INST_NAME("VPSLLW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY128_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMV_X_S(x4, q1); @@ -1156,7 +1155,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xF2: INST_NAME("VPSLLD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY128_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMV_X_S(x4, q1); @@ -1170,7 +1169,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xF3: INST_NAME("VPSLLQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY128_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMV_X_S(x4, q1); @@ -1195,7 +1194,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xF5: INST_NAME("VPMADDWD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); @@ -1213,7 +1212,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xF8: INST_NAME("VPSUBB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1222,7 +1221,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xF9: INST_NAME("VPSUBW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1231,7 +1230,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xFA: INST_NAME("VPSUBD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1240,7 +1239,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xFB: INST_NAME("VPSUBQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); + GETVY_vector_cached(q0, VECTOR_SEW64); GETEY_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1249,7 +1248,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xFC: INST_NAME("VPADDB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector_cached(q0, VECTOR_SEW8); GETEY_vector(q1, 0, VECTOR_SEW8); GETGY_empty_vector(v0); VADD_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1258,7 +1257,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xFD: INST_NAME("VPADDW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); + GETVY_vector_cached(q0, VECTOR_SEW16); GETEY_vector(q1, 0, VECTOR_SEW16); GETGY_empty_vector(v0); VADD_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1267,7 +1266,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xFE: INST_NAME("VPADDD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); + GETVY_vector_cached(q0, VECTOR_SEW32); GETEY_vector(q1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); VADD_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -1277,9 +1276,9 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (vex.l) return 0; INST_NAME("VPINSRW Gx, Vx, Ed, Ib"); nextop = F8; - GETGY_empty_vector(v0); q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW16); + GETGY_empty_vector(v0); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); ZEXTH(x5, ed); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c index 8a2addb52..7013f36b1 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c @@ -121,7 +121,7 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (delta) VADD_VI(d0, q0, delta, VECTOR_UNMASKED); VMERGE_VVM(q2, q2, delta ? d0 : q0); } - VRGATHER_VV(v0, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q1, q2, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0x12: @@ -133,7 +133,7 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); VID_V(v2, VECTOR_UNMASKED); VAND_VI(v2, v2, 0x1e, VECTOR_UNMASKED); - VRGATHER_VV(v0, v1, v2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, v1, v2, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x51: diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c index 91d4044fa..ee3eaf600 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c @@ -53,7 +53,7 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); VID_V(v2, VECTOR_UNMASKED); VAND_VI(v2, v2, 0x1e, VECTOR_UNMASKED); - VRGATHER_VV(v0, v1, v2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, v1, v2, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x16: @@ -66,7 +66,7 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VID_V(v2, VECTOR_UNMASKED); VOR_VI(v2, v2, 1, VECTOR_UNMASKED); VAND_VI(v2, v2, 0x1f, VECTOR_UNMASKED); - VRGATHER_VV(v0, v1, v2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, v1, v2, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x6F: @@ -311,7 +311,7 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (delta) VADD_VI(d0, q0, delta, VECTOR_UNMASKED); VMERGE_VVM(q2, q2, delta ? d0 : q0); } - VRGATHER_VV(v0, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q1, q2, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xE6: diff --git a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c index e634df71b..c5efb122d 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c @@ -447,13 +447,13 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(d1, x5); tmp64u0 = ((((uint64_t)u8 >> 6) & 3) << 48) | ((((uint64_t)u8 >> 4) & 3) << 32) | (((u8 >> 2) & 3) << 16) | (u8 & 3); MOV64x(x5, tmp64u0); - VSLIDE1UP_VX(d0, d1, x5, VECTOR_UNMASKED); + VSLIDE1UP_VX_SAFE(d0, d1, x5, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); if (v0 == v1) { v1 = fpu_get_scratch(dyn); VMV_V_V(v1, v0); } - VRGATHER_VV(v0, v1, d0, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, v1, d0, VECTOR_UNMASKED); break; case 0x7C: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -468,7 +468,7 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL2, 2); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); ADDI(x4, xZR, 32); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); @@ -487,7 +487,7 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL2, 2); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); ADDI(x4, xZR, 32); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); // first of each pair diff --git a/src/dynarec/rv64/dynarec_rv64_f30f_vector.c b/src/dynarec/rv64/dynarec_rv64_f30f_vector.c index f4f2e2485..d27ae5946 100644 --- a/src/dynarec/rv64/dynarec_rv64_f30f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f30f_vector.c @@ -503,13 +503,13 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(d1, x5); tmp64u0 = 0x0003000200010000ULL; MOV64x(x5, tmp64u0); - VSLIDE1UP_VX(d0, d1, x5, VECTOR_UNMASKED); + VSLIDE1UP_VX_SAFE(d0, d1, x5, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); if (v0 == v1) { v1 = fpu_get_scratch(dyn); VMV_V_V(v1, v0); } - VRGATHER_VV(v0, v1, d0, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, v1, d0, VECTOR_UNMASKED); break; case 0x7E: INST_NAME("MOVQ Gx, Ex"); diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index 9b8f0f739..51e114098 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -38,9 +38,7 @@ static int fpu_scratch_vreg(int n) { if (n < 7) return SCRATCH0 + n; - if (n < 13) - return 26 + (n - 7); - return ((n - 13) & 1) + 1; + abort(); } // Get a FPU scratch reg @@ -79,6 +77,7 @@ int fpu_get_reg_x87(dynarec_rv64_t* dyn, int t, int n) dyn->e.fpuused[i] = 1; dyn->e.extcache[i].n = n; dyn->e.extcache[i].t = t; + dyn->e.extcache[i].y = 0; dyn->e.news |= (1 << i); return EXTREG(i); // return a Dx } @@ -99,6 +98,7 @@ int fpu_get_reg_emm(dynarec_rv64_t* dyn, int t, int emm) dyn->e.fpuused[i] = 1; dyn->e.extcache[i].t = t; dyn->e.extcache[i].n = emm; + dyn->e.extcache[i].y = 0; dyn->e.news |= (1 << (i)); return EXTREG(i); } @@ -110,6 +110,7 @@ int fpu_get_reg_xmm(dynarec_rv64_t* dyn, int t, int xmm) dyn->e.fpuused[i] = 1; dyn->e.extcache[i].t = t; dyn->e.extcache[i].n = xmm; + dyn->e.extcache[i].y = 0; dyn->e.news |= (1 << i); return EXTREG(i); } @@ -541,6 +542,8 @@ void extcacheUnwind(extcache_t* cache) cache->ssecache[cache->extcache[i].n].reg = EXTREG(i); cache->ssecache[cache->extcache[i].n].vector = 1; cache->ssecache[cache->extcache[i].n].write = (cache->extcache[i].t == EXT_CACHE_XMMW) ? 1 : 0; + cache->ssecache[cache->extcache[i].n].ymm = cache->extcache[i].y; + cache->ssecache[cache->extcache[i].n].ymm0 = (cache->ymm0 >> cache->extcache[i].n) & 1; break; case EXT_CACHE_ST_F: case EXT_CACHE_ST_D: @@ -947,13 +950,16 @@ void updateUpperLiveness(dynarec_rv64_t* dyn) size_t pending_size = (size_t)n * sizeof(uint16_t); size_t work_size = (size_t)n * sizeof(int); size_t list_size = (size_t)n * sizeof(uint8_t); - void* buffer = calloc(1, 2 * live_size + pending_size + work_size + list_size); + void* buffer = calloc(1, 5 * live_size + pending_size + work_size + list_size); if (!buffer) return; uint16_t* live_in = (uint16_t*)buffer; uint16_t* live_out = (uint16_t*)((char*)live_in + live_size); - uint16_t* pending_in = (uint16_t*)((char*)live_out + live_size); - int* work = (int*)((char*)pending_in + pending_size); + uint16_t* live_ymm_in = (uint16_t*)((char*)live_out + live_size); + uint16_t* live_ymm_out = (uint16_t*)((char*)live_ymm_in + live_size); + uint16_t* pending_in = (uint16_t*)((char*)live_ymm_out + live_size); + uint16_t* pend_ymm = (uint16_t*)((char*)pending_in + pending_size); + int* work = (int*)((char*)pend_ymm + live_size); uint8_t* on_list = (uint8_t*)((char*)work + work_size); int sp = 0; @@ -984,9 +990,23 @@ void updateUpperLiveness(dynarec_rv64_t* dyn) combined_out = UINT16_MAX; live_out[i] = combined_out; + uint16_t combined_ymm_out = 0; + if (inst->x64.has_next && i + 1 < n && dyn->insts[i + 1].x64.alive) + combined_ymm_out |= live_ymm_in[i + 1]; + if (inst->x64.jmp && inst->x64.jmp_insts >= 0 && inst->x64.jmp_insts < n) + combined_ymm_out |= live_ymm_in[inst->x64.jmp_insts]; + if ((!inst->x64.has_next && !has_internal_jump) || (inst->x64.jmp && inst->x64.jmp_insts < 0)) + combined_ymm_out = UINT16_MAX; + live_ymm_out[i] = combined_ymm_out; + + uint16_t live_ymm_in_val = inst->ymm_upper_use | (combined_ymm_out & (uint16_t)~inst->ymm_upper_def); + if ((inst->x64.barrier & BARRIER_FLOAT) || inst->x64.has_callret) + live_ymm_in_val = UINT16_MAX; + uint16_t live_in_val = inst->up32_read | (combined_out & (uint16_t)~inst->up32_write64); - if (live_in_val != live_in[i]) { + if ((live_in_val != live_in[i]) || (live_ymm_in_val != live_ymm_in[i])) { live_in[i] = live_in_val; + live_ymm_in[i] = live_ymm_in_val; for (int p = 0; p < inst->pred_sz; ++p) { int j = inst->pred[p]; if (!on_list[j]) { @@ -1000,6 +1020,7 @@ void updateUpperLiveness(dynarec_rv64_t* dyn) for (int i = 0; i < n; ++i) { instruction_rv64_t* inst = &dyn->insts[i]; inst->up32_skip = inst->up32_write32 & (uint16_t)~live_out[i]; + inst->ymm_upper_live = live_ymm_out[i]; } memset(on_list, 0, list_size); @@ -1019,13 +1040,17 @@ void updateUpperLiveness(dynarec_rv64_t* dyn) continue; uint16_t merged_pending = 0; + uint16_t merged_ymm = 0; for (int p = 0; p < inst->pred_sz; ++p) { int j = inst->pred[p]; const instruction_rv64_t* pred = &dyn->insts[j]; merged_pending |= (pending_in[j] & (uint16_t)~pred->up32_write64) | pred->up32_skip; + merged_ymm |= (pend_ymm[j] & (uint16_t)~pred->ymm_upper_def) | + (pred->ymm_zero & (uint16_t)~pred->ymm_upper_live); } - if (merged_pending != pending_in[i]) { + if ((merged_pending != pending_in[i]) || (merged_ymm != pend_ymm[i])) { pending_in[i] = merged_pending; + pend_ymm[i] = merged_ymm; if (inst->x64.has_next && i + 1 < n && dyn->insts[i + 1].x64.alive && !on_list[i + 1]) { work[sp++] = i + 1; on_list[i + 1] = 1; @@ -1041,6 +1066,7 @@ void updateUpperLiveness(dynarec_rv64_t* dyn) } for (int i = 0; i < n; ++i) { dyn->insts[i].up32_pending = pending_in[i]; + dyn->insts[i].ymm_pending = pend_ymm[i]; } free(buffer); diff --git a/src/dynarec/rv64/dynarec_rv64_functions.h b/src/dynarec/rv64/dynarec_rv64_functions.h index 507404d0f..1901c8409 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.h +++ b/src/dynarec/rv64/dynarec_rv64_functions.h @@ -7,7 +7,7 @@ typedef struct x64emu_s x64emu_t; typedef struct dynarec_rv64_s dynarec_rv64_t; -#define SCRATCH0 3 +#define SCRATCH0 1 #define VMASK 0 // Get an FPU scratch reg diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 0f4ae160f..2e17cf3a5 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -1455,6 +1455,25 @@ void mmx_forget_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a) mmx_flush_reg_preserve_vtype(dyn, ninst, s1, a); } +int fpu_borrow_reg(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int reg) +{ + int idx = EXTIDX(reg); + switch (dyn->e.extcache[idx].t) { + case EXT_CACHE_ST_F: + case EXT_CACHE_ST_D: + case EXT_CACHE_ST_I64: + x87_forget(dyn, ninst, s1, s2, dyn->e.extcache[idx].n); + break; + case EXT_CACHE_MM: + case EXT_CACHE_MMV: + mmx_forget_reg(dyn, ninst, s1, dyn->e.extcache[idx].n); + break; + default: + break; + } + return reg; +} + void mmx_flush_reg_preserve_vtype(dynarec_rv64_t* dyn, int ninst, int s1, int a) { if (dyn->e.mmxcache[a].v == -1) @@ -1653,6 +1672,8 @@ int sse_get_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single) int ret = dyn->e.ssecache[a].reg; dyn->e.ssecache[a].single = single; dyn->e.ssecache[a].vector = 0; + dyn->e.ssecache[a].ymm = 0; + sse_set_pending_zero(dyn, a, 0); if (dyn->e.ssecache[a].single) FLW(dyn->e.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a])); else @@ -1691,6 +1712,8 @@ int sse_get_reg_empty(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single) dyn->e.ssecache[a].reg = fpu_get_reg_xmm(dyn, single ? EXT_CACHE_SS : EXT_CACHE_SD, a); dyn->e.ssecache[a].single = single; dyn->e.ssecache[a].vector = 0; + dyn->e.ssecache[a].ymm = 0; + sse_set_pending_zero(dyn, a, 0); return dyn->e.ssecache[a].reg; } @@ -1715,6 +1738,8 @@ int sse_get_reg_size_changed(dynarec_rv64_t* dyn, int ninst, int s1, int a, int int ret = dyn->e.ssecache[a].reg; dyn->e.ssecache[a].single = single; dyn->e.ssecache[a].vector = 0; + dyn->e.ssecache[a].ymm = 0; + sse_set_pending_zero(dyn, a, 0); if (!single) // load happens before size changed FLW(dyn->e.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a])); else @@ -1771,12 +1796,12 @@ int sse_get_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int forwri dyn->e.ssecache[a].write = forwrite; dyn->e.ssecache[a].vector = 1; dyn->e.ssecache[a].single = 0; // just to be clean + dyn->e.ssecache[a].ymm = 0; + dyn->e.ssecache[a].ymm0 = (dyn->e.ymm0 >> a) & 1; ADDI(s1, xEmu, offsetof(x64emu_t, xmm[a])); VLE_V(ret, s1, sew, VECTOR_UNMASKED, VECTOR_NFIELD1); return ret; } - -// 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) { if (dyn->e.ssecache[a].v != -1) { @@ -1802,6 +1827,8 @@ int sse_get_reg_empty_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a) dyn->e.ssecache[a].vector = 1; dyn->e.ssecache[a].single = 0; // just to be clean dyn->e.ssecache[a].write = 1; // it will be write... + dyn->e.ssecache[a].ymm = 0; + sse_set_pending_zero(dyn, a, 0); return dyn->e.ssecache[a].reg; } @@ -1818,6 +1845,7 @@ void sse_forget_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a) vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); ADDI(s1, xEmu, offsetof(x64emu_t, xmm[a])); VSE8_V(dyn->e.ssecache[a].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + avx_flush_upper_vector(dyn, ninst, s1, a, dyn->e.ssecache[a].reg, 0); vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); } fpu_free_reg(dyn, dyn->e.ssecache[a].reg); @@ -1843,12 +1871,11 @@ void sse_purge07cache(dynarec_rv64_t* dyn, int ninst, int s1) ++old; } if (dyn->e.ssecache[i].vector) { - if (!flushed8) { - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); - flushed8 = 1; - } + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + flushed8 = 1; ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VSE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, 0); } else if (dyn->e.ssecache[i].single) FSW(dyn->e.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i])); else @@ -1877,14 +1904,13 @@ static void sse_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1) ++old; } if (dyn->e.ssecache[i].vector) { + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + flushed8 = 1; if (dyn->e.ssecache[i].write) { - if (!flushed8) { - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); - flushed8 = 1; - } ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VSE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); } + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, next); } else if (dyn->e.ssecache[i].single) FSW(dyn->e.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i])); else @@ -1901,6 +1927,7 @@ static void sse_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1) if (flushed8) vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); + avx_flush_pending_zero_vector(dyn, ninst, s1, next); if (old != -1) { MESSAGE(LOG_DUMP, "\t------ Purge SSE Cache\n"); } @@ -1914,12 +1941,11 @@ static void sse_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1) for (int i = 0; i < 16; ++i) if (dyn->e.ssecache[i].v != -1) { if (dyn->e.ssecache[i].vector) { - if (!flushed8) { - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); - flushed8 = 1; - } + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + flushed8 = 1; ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VSE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, 0); } else if (dyn->e.ssecache[i].single) FSW(dyn->e.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i])); else @@ -2002,12 +2028,11 @@ void fpu_pushcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07) for (int i = start; i < 16; ++i) if (dyn->e.ssecache[i].v != -1) { if (dyn->e.ssecache[i].vector) { - if (!flushed8) { - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); - flushed8 = 1; - } + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + flushed8 = 1; ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VSE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, 0); } } if (flushed8) @@ -2091,10 +2116,8 @@ void fpu_popcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07) for (int i = start; i < 16; ++i) if (dyn->e.ssecache[i].v != -1) { if (dyn->e.ssecache[i].vector) { - if (!flushed8) { - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); - flushed8 = 1; - } + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + flushed8 = 1; ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VLE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); } @@ -2145,11 +2168,8 @@ int fpu_needpurgecache(dynarec_rv64_t* dyn, int ninst) static int findCacheSlot(dynarec_rv64_t* dyn, int ninst, int t, int n, extcache_t* cache) { - ext_cache_t f; - f.n = n; - f.t = t; for (int i = 0; i < 24; ++i) { - if (cache->extcache[i].v == f.v) + if (cache->extcache[i].v && cache->extcache[i].t == t && cache->extcache[i].n == n) return i; if (cache->extcache[i].n == n) { switch (cache->extcache[i].t) { @@ -2345,6 +2365,7 @@ static void loadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, int } cache->extcache[i].n = n; cache->extcache[i].t = t; + cache->extcache[i].y = 0; } static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, int s2, int s3, int* s1_val, int* s2_val, int* s3_top, extcache_t* cache, int i, int t, int n) @@ -2419,12 +2440,34 @@ static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, i cache->extcache[i].v = 0; } +static void loadUpperCache(dynarec_rv64_t* dyn, int ninst, int s1, int a, int reg, int tozero) +{ + uint8_t sew0, vlmul0, vl0; + vector_save_vtype(dyn, &sew0, &vlmul0, &vl0); + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; + if (tozero) { + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW32, VECTOR_LMUL1, 2); + VECTOR_LOAD_VMASK(0xf0, s1, 2); + VMERGE_VXM(reg, reg, xZR); + } else { + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VECTOR_LOAD_VMASK(0xffff0000, s1, 2); + dyn->inst_vl = 0; // the mask load changed the real vl + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); + ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a]) - 16); + VLE8_V(reg, s1, VECTOR_MASKED, VECTOR_NFIELD1); + } + vector_restore_vtype(dyn, ninst, s1, sew0, vlmul0, vl0); +} + static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3) { int i2 = dyn->insts[ninst].x64.jmp_insts; if (i2 < 0) return; MESSAGE(LOG_DUMP, "\tCache Transform ---- ninst=%d -> %d\n", ninst, i2); + avx_sync_upper_vector(dyn, ninst, s1, 1); if ((!i2) || (dyn->insts[i2].x64.barrier & BARRIER_FLOAT)) { if (dyn->e.stack_next) { fpu_purgecache(dyn, ninst, 1, s1, s2, s3); @@ -2538,6 +2581,16 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in cache.extcache[i].t = EXT_CACHE_XMMR; } } + if ((cache.extcache[i].t == EXT_CACHE_XMMR || cache.extcache[i].t == EXT_CACHE_XMMW) + && (cache_i2.extcache[i].t == EXT_CACHE_XMMR || cache_i2.extcache[i].t == EXT_CACHE_XMMW) + && cache.extcache[i].y != cache_i2.extcache[i].y) { + int n = cache.extcache[i].n; + if (cache_i2.extcache[i].y) { + MESSAGE(LOG_DUMP, "\t - Loading upper half of %s\n", getCacheName(cache.extcache[i].t, n)); + loadUpperCache(dyn, ninst, s1, n, EXTREG(i), (cache_i2.ymm0 >> n) & 1); + } + cache.extcache[i].y = cache_i2.extcache[i].y; + } } } if (stack_cnt != cache_i2.stack || dyn->e.x87stack != cache_i2.x87stack) { @@ -2719,15 +2772,13 @@ void emit_pf(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4) void fpu_reset_cache(dynarec_rv64_t* dyn, int ninst, int reset_n) { MESSAGE(LOG_DEBUG, "Reset Caches with %d\n", reset_n); -#if STEP > 1 - // for STEP 2 & 3, just need to refresh with current, and undo the changes (push & swap) - dyn->e = dyn->insts[ninst].e; - dyn->vector_sew = dyn->insts[ninst].vector_sew_entry; - extcacheUnwind(&dyn->e); -#else dyn->e = dyn->insts[reset_n].e; dyn->vector_sew = dyn->insts[reset_n].vector_sew_exit; -#endif + dyn->e.ymm0 = dyn->insts[ninst].ymm_pending; + for (int i = 0; i < 16; ++i) + if (dyn->e.ssecache[i].v != -1) + dyn->e.ssecache[i].ymm0 = (dyn->e.ymm0 >> i) & 1; + extcacheUnwind(&dyn->e); #if STEP == 0 if (dyn->need_dump && dyn->need_dump != 3 && dyn->e.x87stack) dynarec_log(LOG_NONE, "New x87stack=%d at ResetCache in inst %d with %d\n", dyn->e.x87stack, ninst, reset_n); #endif @@ -2784,6 +2835,52 @@ void fpu_propagate_stack(dynarec_rv64_t* dyn, int ninst) dyn->e.swapped = 0; } +void avx_flush_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int reg, int next) +{ + uint8_t sew0, vlmul0, vl0; + vector_save_vtype(dyn, &sew0, &vlmul0, &vl0); + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; // real vtype here is unknown, never elide vsetvli + if (dyn->e.ssecache[a].ymm0) { + // the architectural upper half is zero: write it with scalar stores, no vector state needed + SD(xZR, xEmu, offsetof(x64emu_t, ymm[a]) + 0); + SD(xZR, xEmu, offsetof(x64emu_t, ymm[a]) + 8); + } else if (dyn->e.ssecache[a].ymm) { + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VECTOR_LOAD_VMASK(0xffff0000, s1, 2); + ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a]) - 16); + VSE8_V(reg, s1, VECTOR_MASKED, VECTOR_NFIELD1); + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + } else + return; + if (!next) dyn->e.ssecache[a].ymm = 0; + vector_restore_vtype(dyn, ninst, s1, sew0, vlmul0, vl0); +} + +// materialize the deferred zeros of YMM registers that are not in the cache anymore +void avx_flush_pending_zero_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next) +{ + if (!cpuext.vlen || cpuext.vlen < 32) + return; + for (int i = 0; i < 16; ++i) + if ((dyn->e.ymm0 >> i) & 1) { + SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 0); + SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 8); + if (!next) sse_set_pending_zero(dyn, i, 0); + } + dyn->inst_vl = 0; // force the next vsetvli to be emited +} + +void avx_sync_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next) +{ + if (!cpuext.vlen || cpuext.vlen < 32) + return; + for (int i = 0; i < 16; ++i) + if (dyn->e.ssecache[i].v != -1 && dyn->e.ssecache[i].vector) + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, next); + avx_flush_pending_zero_vector(dyn, ninst, s1, next); +} + void avx_set_vector_width(dynarec_rv64_t* dyn, int ninst, int s1, int sew, int width) { dyn->vector_sew = (width == 16) ? sew : VECTOR_SEWNA; @@ -2792,21 +2889,30 @@ void avx_set_vector_width(dynarec_rv64_t* dyn, int ninst, int s1, int sew, int w void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew) { + if (width == 32 && cpuext.vlen >= 32) + ymm_live_read(dyn, ninst, a); avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 16); int low = sse_get_reg_vector(dyn, ninst, s1, a, 0, VECTOR_SEW8); - if (low != vreg) - VMV_V_V(vreg, low); - if (width == 32) { - if (cpuext.vlen == 16) { - ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a])); - VLE8_V(vreg + 1, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + if (width == 32 && !dyn->e.ssecache[a].ymm) { + if (dyn->e.ssecache[a].ymm0) { + avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW32, 32); + VECTOR_LOAD_VMASK(0xf0, s1, 2); + VMERGE_VXM(low, low, xZR); } else { - int upper = fpu_get_scratch(dyn); - ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a])); - VLE8_V(upper, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); - avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 32); - VSLIDEUP_VI(vreg, upper, 16, VECTOR_UNMASKED); + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; // real vtype here is unknown, never elide vsetvli + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VECTOR_LOAD_VMASK(0xffff0000, s1, 2); + dyn->inst_vl = 0; // the mask load changed the real vl + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); + ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a]) - 16); + VLE8_V(low, s1, VECTOR_MASKED, VECTOR_NFIELD1); } + dyn->e.ssecache[a].ymm = 1; + } + if (low != vreg) { + avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, width); + VMV_V_V(vreg, low); } avx_set_vector_width(dyn, ninst, s1, sew, width); } @@ -2814,25 +2920,24 @@ void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a void avx_store_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew) { avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 16); - sse_forget_reg_vector(dyn, ninst, s1, a); - ADDI(s1, xEmu, offsetof(x64emu_t, xmm[a])); - VSE8_V(vreg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); - if (width == 32) { - if (cpuext.vlen == 16) { - ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a])); - VSE8_V(vreg + 1, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + int cache = sse_get_reg_empty_vector(dyn, ninst, s1, a); + if (cache != vreg) { + avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, width); + VMV_V_V(cache, vreg); + } + if (cpuext.vlen >= 32) { + dyn->e.ssecache[a].ymm = 1; + dyn->e.extcache[EXTIDX(cache)].y = 1; + if (width == 16) { + avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW32, 32); + VECTOR_LOAD_VMASK(0xf0, s1, 2); + VMERGE_VXM(cache, cache, xZR); + sse_set_pending_zero(dyn, a, 1); + ymm_live_zero(dyn, ninst, a); } else { - int upper = (vreg == 1) ? 2 : 1; - // v1/v2 are also the fixed cache slots of MMX6/MMX7, so flush any live MMX cache there before using it as scratch - mmx_flush_reg_preserve_vtype(dyn, ninst, s1, upper == 1 ? 6 : 7); - avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 32); - VSLIDEDOWN_VI(upper, vreg, 16, VECTOR_UNMASKED); - avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 16); - ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a])); - VSE8_V(upper, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + sse_set_pending_zero(dyn, a, 0); + ymm_live_write(dyn, ninst, a); } - } else { - YMM0(a); } avx_set_vector_width(dyn, ninst, s1, sew, width); } @@ -3106,52 +3211,12 @@ void vector_loadmask(dynarec_rv64_t* dyn, int ninst, int vreg, uint64_t imm, int } else abort(); } else { - int sew = dyn->vector_eew; - int count; - int scratch; - int result; - int first; - int scratch_mark = dyn->e.fpu_scratch; - if (sew < VECTOR_SEW8 || sew > VECTOR_SEW64) - sew = VECTOR_SEW8; - count = (16 >> sew) * (int)multiple; - if (count > 32) - count = 32; - scratch = fpu_get_scratch(dyn); - result = fpu_get_scratch(dyn); - uint8_t cur_sew = dyn->inst_sew; - uint8_t cur_vlmul = dyn->inst_vlmul; - float cur_multiple = (cur_sew == VECTOR_SEWNA || (16 >> cur_sew) == 0) ? 1.0 : (float)dyn->inst_vl / (float)(16 >> cur_sew); - int need_wrap = (cur_sew != VECTOR_SEWNA && cur_vlmul != VECTOR_LMUL1); - if (need_wrap) vector_vsetvli(dyn, ninst, s1, cur_sew, VECTOR_LMUL1, cur_multiple); - first = 1; - VID_V(scratch, VECTOR_UNMASKED); - for (int i = 0; i < count; ++i) { - if (imm & (1ULL << i)) { - if (first) { - if (i < 16) { - VMSEQ_VI(vreg, scratch, i, VECTOR_UNMASKED); - } else { - ADDI(s1, xZR, i); - VMSEQ_VX(vreg, scratch, s1, VECTOR_UNMASKED); - } - first = 0; - } else { - if (i < 16) { - VMSEQ_VI(result, scratch, i, VECTOR_UNMASKED); - } else { - ADDI(s1, xZR, i); - VMSEQ_VX(result, scratch, s1, VECTOR_UNMASKED); - } - VMOR_MM(vreg, vreg, result); - } - } - } - if (first) - VMSNE_VV(vreg, scratch, scratch, VECTOR_UNMASKED); - if (need_wrap) - vector_vsetvli(dyn, ninst, s1, cur_sew, cur_vlmul, cur_multiple); - dyn->e.fpu_scratch = scratch_mark; + uint8_t sv_sew, sv_vlmul, sv_vl; + vector_save_vtype(dyn, &sv_sew, &sv_vlmul, &sv_vl); + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW64, VECTOR_LMUL1, 1); + MOV64x(s1, imm); + VMV_S_X(vreg, s1); + vector_restore_vtype(dyn, ninst, s1, sv_sew, sv_vlmul, sv_vl); } #endif } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 829670fe9..61bc9cf74 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -609,10 +609,33 @@ avx_load_reg_vector(dyn, ninst, x1, a, gd, 16 << vex.l, sew); \ } while (0) -#define GETGY_empty_vector(a) \ - do { \ - gd = ((nextop & 0x38) >> 3) + (rex.r << 3); \ - a = fpu_get_scratch(dyn); \ +#define GETVY_vector_cached(a, sew) \ + do { \ + if (vex.l) { \ + a = fpu_get_scratch(dyn); \ + avx_load_reg_vector(dyn, ninst, x1, a, vex.v, 16 << vex.l, sew); \ + } else { \ + avx_set_vector_width(dyn, ninst, x1, sew, 16); \ + a = sse_get_reg_vector(dyn, ninst, x1, vex.v, 0, sew); \ + } \ + } while (0) + +#define GETGY_vector_cached(a, sew) \ + do { \ + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); \ + if (vex.l) { \ + a = fpu_get_scratch(dyn); \ + avx_load_reg_vector(dyn, ninst, x1, a, gd, 16 << vex.l, sew); \ + } else { \ + avx_set_vector_width(dyn, ninst, x1, sew, 16); \ + a = sse_get_reg_vector(dyn, ninst, x1, gd, 0, sew); \ + } \ + } while (0) + +#define GETGY_empty_vector(a) \ + do { \ + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); \ + a = sse_get_reg_empty_vector(dyn, ninst, x1, gd); \ } while (0) #define GETEY_vector(a, D, sew) \ @@ -678,6 +701,60 @@ #define GETEX32_vector(a, w, D, sew) GETEX_PARTIAL_vector(a, w, D, sew, 0.25) #define GETEX16_vector(a, w, D, sew) GETEX_PARTIAL_vector(a, w, D, sew, 0.125) +#define VRGATHER_VX_SAFE(vd, vs2, rs1, vm) \ + do { \ + int d_ = (vd), s_ = (vs2); \ + if (d_ == s_) { \ + s_ = fpu_get_scratch(dyn); \ + VMV_V_V(s_, (vs2)); \ + } \ + VRGATHER_VX(d_, s_, (rs1), (vm)); \ + } while (0) + +#define VRGATHER_VV_SAFE(vd, vs2, vs1, vm) \ + do { \ + int d_ = (vd), s2_ = (vs2), s1_ = (vs1); \ + if (d_ == s2_) { \ + s2_ = fpu_get_scratch(dyn); \ + VMV_V_V(s2_, (vs2)); \ + } \ + if (d_ == s1_) { \ + s1_ = fpu_get_scratch(dyn); \ + VMV_V_V(s1_, (vs1)); \ + } \ + VRGATHER_VV(d_, s2_, s1_, (vm)); \ + } while (0) + +#define VSLIDEUP_VI_SAFE(vd, vs2, imm, vm) \ + do { \ + int d_ = (vd), s_ = (vs2); \ + if (d_ == s_) { \ + s_ = fpu_get_scratch(dyn); \ + VMV_V_V(s_, (vs2)); \ + } \ + VSLIDEUP_VI(d_, s_, (imm), (vm)); \ + } while (0) + +#define VSLIDEUP_VX_SAFE(vd, vs2, rs1, vm) \ + do { \ + int d_ = (vd), s_ = (vs2); \ + if (d_ == s_) { \ + s_ = fpu_get_scratch(dyn); \ + VMV_V_V(s_, (vs2)); \ + } \ + VSLIDEUP_VX(d_, s_, (rs1), (vm)); \ + } while (0) + +#define VSLIDE1UP_VX_SAFE(vd, vs2, rs1, vm) \ + do { \ + int d_ = (vd), s_ = (vs2); \ + if (d_ == s_) { \ + s_ = fpu_get_scratch(dyn); \ + VMV_V_V(s_, (vs2)); \ + } \ + VSLIDE1UP_VX(d_, s_, (rs1), (vm)); \ + } while (0) + // Put Back EX if it was a memory and not an emm register #define PUTEX_vector(a, sew) \ if (!MODREG) { \ @@ -1482,9 +1559,10 @@ #define TABLE64_(A, V) #endif -#define ARCH_INIT() \ - SMSTART(); \ - dyn->vector_sew = VECTOR_SEWNA; +#define ARCH_INIT() \ + SMSTART(); \ + dyn->vector_sew = VECTOR_SEWNA; \ + dyn->e.ymm0 = 0; #define ARCH_RESET() \ dyn->vector_sew = VECTOR_SEWNA; @@ -1766,6 +1844,7 @@ #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 fpu_borrow_reg STEPNAME(fpu_borrow_reg) #define mmx_flush_reg_preserve_vtype STEPNAME(mmx_flush_reg_preserve_vtype) #define sse_get_reg STEPNAME(sse_get_reg) #define sse_get_reg_empty STEPNAME(sse_get_reg_empty) @@ -1782,6 +1861,9 @@ #define avx_set_vector_width STEPNAME(avx_set_vector_width) #define avx_load_reg_vector STEPNAME(avx_load_reg_vector) #define avx_store_reg_vector STEPNAME(avx_store_reg_vector) +#define avx_flush_upper_vector STEPNAME(avx_flush_upper_vector) +#define avx_sync_upper_vector STEPNAME(avx_sync_upper_vector) +#define avx_flush_pending_zero_vector STEPNAME(avx_flush_pending_zero_vector) #define fpu_pushcache STEPNAME(fpu_pushcache) #define fpu_popcache STEPNAME(fpu_popcache) @@ -2023,6 +2105,7 @@ int mmx_get_reg_empty(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, in int mmx_get_reg_empty_vector(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int a); // forget float register for a MMX reg, create the entry if needed void mmx_forget_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a); +int fpu_borrow_reg(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int reg); void mmx_flush_reg_preserve_vtype(dynarec_rv64_t* dyn, int ninst, int s1, int a); // SSE/SSE2 helpers @@ -2045,11 +2128,45 @@ void sse_purge07cache(dynarec_rv64_t* dyn, int ninst, int s1); // Push current value to the cache void sse_reflect_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a); -// Cache-neutral helpers for Box64's split XMM/YMM register storage. +void avx_flush_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int reg, int next); +void avx_sync_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next); +void avx_flush_pending_zero_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next); void avx_set_vector_width(dynarec_rv64_t* dyn, int ninst, int s1, int sew, int width); void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew); void avx_store_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew); +static inline void sse_set_pending_zero(dynarec_rv64_t* dyn, int a, int pending) +{ + if (dyn->e.ssecache[a].v != -1) + dyn->e.ssecache[a].ymm0 = pending ? 1 : 0; + if (pending) + dyn->e.ymm0 |= (1 << a); + else + dyn->e.ymm0 &= ~(1 << a); +} + +static inline void ymm_live_read(dynarec_rv64_t* dyn, int ninst, int reg) +{ +#if STEP == 0 + dyn->insts[ninst].ymm_upper_use |= (uint16_t)(1 << reg); +#endif +} + +static inline void ymm_live_write(dynarec_rv64_t* dyn, int ninst, int reg) +{ +#if STEP == 0 + dyn->insts[ninst].ymm_upper_def |= (uint16_t)(1 << reg); +#endif +} + +static inline void ymm_live_zero(dynarec_rv64_t* dyn, int ninst, int reg) +{ +#if STEP == 0 + ymm_live_write(dyn, ninst, reg); + dyn->insts[ninst].ymm_zero |= (uint16_t)(1 << reg); +#endif +} + // common coproc helpers // reset the cache with n void fpu_reset_cache(dynarec_rv64_t* dyn, int ninst, int reset_n); diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index c34fc131f..5776e78d9 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -30,10 +30,11 @@ typedef struct box64env_s box64env_t; #define EXT_CACHE_OLD_XMMR 3 typedef union ext_cache_s { - int8_t v; + int16_t v; struct { - uint8_t t:4; // reg type - uint8_t n:4; // reg number + uint16_t t : 4; // reg type + uint16_t n : 4; // reg number + uint16_t y : 1; // register holds the whole ymm }; } ext_cache_t; @@ -46,12 +47,14 @@ typedef union mmx_cache_s { } mmx_cache_t; typedef union sse_cache_s { - int16_t v; + int32_t v; struct { - uint16_t reg : 13; - uint16_t vector : 1; - uint16_t single : 1; - uint16_t write : 1; + uint32_t reg : 13; + uint32_t vector : 1; + uint32_t single : 1; + uint32_t write : 1; + uint32_t ymm : 1; // register holds the whole ymm + uint32_t ymm0 : 1; // architectural upper half of the ymm is zero }; } sse_cache_t; @@ -90,6 +93,7 @@ typedef struct extcache_s { int8_t x87stack; // cache stack counter int8_t mmxcount; // number of mmx register used (not both mmx and x87 at the same time) int8_t fpu_scratch; // scratch counter + uint16_t ymm0; // upper 128bits are zero and not held in memory } extcache_t; typedef enum flagcache_s { @@ -157,6 +161,11 @@ typedef struct instruction_rv64_s { uint16_t up32_zero; // bitmask of GPRs guaranteed to be zero-extended at instruction exit uint16_t up32_skip; // bitmask of GPRs where the implicit zero-up after a 32-bit write can be skipped uint16_t up32_pending; // bitmask of GPRs whose upper 32 bits are stale at entry to this instruction + uint16_t ymm_upper_use; // bitmask of YMM upper halves read by this instruction + uint16_t ymm_upper_def; // bitmask of YMM upper halves written by this instruction + uint16_t ymm_upper_live; // bitmask of YMM upper halves live after this instruction + uint16_t ymm_zero; // bitmask of YMM upper halves deferred-zeroed by this instruction + uint16_t ymm_pending; // bitmask of pending YMM upper-half zeros on entry to this instruction } instruction_rv64_t; typedef struct dynarec_rv64_s { @@ -215,10 +224,10 @@ typedef struct dynarec_rv64_s { } dynarec_rv64_t; // v0 is hardware wired to vector mask register, which should be always reserved -// convert idx (0..23) to reg index (10..31 1..2) -#define EXTREG(A) (((A) + 10 + ((A) > 21)) & 31) -// convert reg index (10..31 1..2) to idx (0..23) -#define EXTIDX(A) (((A) - 10 - ((A) < 3)) & 31) +// convert idx (0..23) to reg index +#define EXTREG(A) (((A) < 16) ? (16 + (A)) : ((A) - 8)) +// convert reg index (8..31) to idx (0..23) +#define EXTIDX(A) (((A) >= 16) ? ((A) - 16) : ((A) + 8)) void add_next(dynarec_rv64_t *dyn, uintptr_t addr); uintptr_t get_closest_next(dynarec_rv64_t *dyn, uintptr_t addr); From 4e91870c51f7ce10ff48043e850673a9eff32cb5 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sat, 17 Oct 2026 04:00:04 +0800 Subject: [PATCH 043/156] [DYNAREC] Fixed fpu cache not written back after unused opcodes (again) (#4575) No code is emitted for unused (unreachable) opcodes, and the fpu cache state is reset there, so the live x87/mmx/sse registers would never be written back and are lost if the block is left on a fault before the next cache purge. Mark the instruction following the unused opcodes as a float barrier, as it starts with no cache, and the cache is then written back before entering it. --- src/dynarec/dynarec_native_pass.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index 2c159beec..774160890 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -386,6 +386,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int addr += dyn->insts[ninst].x64.size; INST_EPILOG; } + if ((ninst + 1) < dyn->size) dyn->insts[ninst + 1].x64.barrier |= BARRIER_FLOAT; } if((dyn->insts[ninst+1].x64.barrier&BARRIER_FULL)==BARRIER_FULL) reset_n = -2; // hack to say Barrier! From 437900559af7ce8600204cb4a11e7143569d91b7 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sat, 17 Oct 2026 13:21:00 +0800 Subject: [PATCH 044/156] [RV64_DYNAREC] Purge at merge point with different YMM state (#4576) --- src/dynarec/rv64/dynarec_rv64_arch.c | 10 ++- src/dynarec/rv64/dynarec_rv64_functions.c | 40 +++++++-- src/dynarec/rv64/dynarec_rv64_helper.c | 101 +++++++++++++++------- src/dynarec/rv64/dynarec_rv64_pass0.h | 1 + src/dynarec/rv64/dynarec_rv64_pass1.h | 1 + src/dynarec/rv64/dynarec_rv64_pass2.h | 1 + src/dynarec/rv64/dynarec_rv64_pass3.h | 1 + src/dynarec/rv64/dynarec_rv64_private.h | 24 +++++ 8 files changed, 141 insertions(+), 38 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_arch.c b/src/dynarec/rv64/dynarec_rv64_arch.c index 2a7954e7a..b5a60bb04 100644 --- a/src/dynarec/rv64/dynarec_rv64_arch.c +++ b/src/dynarec/rv64/dynarec_rv64_arch.c @@ -125,10 +125,13 @@ static int arch_build(dynarec_rv64_t* dyn, int ninst, arch_build_t* arch) case EXT_CACHE_SS: case EXT_CACHE_SD: case EXT_CACHE_XMMR: - case EXT_CACHE_XMMW: { + case EXT_CACHE_XMMW: + case EXT_CACHE_YMMR: + case EXT_CACHE_YMMW: { int xmm = e->extcache[i].n & 15; arch->sse_.sse |= (uint16_t)(1 << xmm); - if (e->extcache[i].t == EXT_CACHE_XMMR || e->extcache[i].t == EXT_CACHE_XMMW) + if (e->extcache[i].t == EXT_CACHE_XMMR || e->extcache[i].t == EXT_CACHE_XMMW + || e->extcache[i].t == EXT_CACHE_YMMR || e->extcache[i].t == EXT_CACHE_YMMW) arch->sse_.vector |= (uint16_t)(1 << xmm); arch->sse_.reg[xmm] = (uint8_t)reg; arch->sse_.single[xmm] = (e->extcache[i].t == EXT_CACHE_SS) ? 1 : 0; @@ -142,7 +145,8 @@ static int arch_build(dynarec_rv64_t* dyn, int ninst, arch_build_t* arch) if (e->x87stack) arch->x87_.delta = e->x87stack; for (int i = 0; i < 32; ++i) { - if (e->extcache[i].t != EXT_CACHE_XMMR && e->extcache[i].t != EXT_CACHE_XMMW) + if (e->extcache[i].t != EXT_CACHE_XMMR && e->extcache[i].t != EXT_CACHE_XMMW + && e->extcache[i].t != EXT_CACHE_YMMR && e->extcache[i].t != EXT_CACHE_YMMW) continue; int xmm = e->extcache[i].n & 15; if (e->ssecache[xmm].ymm) diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index 51e114098..eaf43497d 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -404,6 +404,7 @@ int fpuCacheNeedsTransform(dynarec_rv64_t* dyn, int ninst) if (dyn->insts[ninst].e.extcache[i].n != cache_i2.extcache[i].n) { // not the same x64 reg ret = 1; } else if (dyn->insts[ninst].e.extcache[i].t == EXT_CACHE_XMMR && cache_i2.extcache[i].t == EXT_CACHE_XMMW) { /* nothing */ + } else if (dyn->insts[ninst].e.extcache[i].t == EXT_CACHE_YMMR && cache_i2.extcache[i].t == EXT_CACHE_YMMW) { /* nothing */ } else ret = 1; } @@ -539,10 +540,12 @@ void extcacheUnwind(extcache_t* cache) break; case EXT_CACHE_XMMR: case EXT_CACHE_XMMW: + case EXT_CACHE_YMMR: + case EXT_CACHE_YMMW: cache->ssecache[cache->extcache[i].n].reg = EXTREG(i); cache->ssecache[cache->extcache[i].n].vector = 1; - cache->ssecache[cache->extcache[i].n].write = (cache->extcache[i].t == EXT_CACHE_XMMW) ? 1 : 0; - cache->ssecache[cache->extcache[i].n].ymm = cache->extcache[i].y; + cache->ssecache[cache->extcache[i].n].write = (cache->extcache[i].t == EXT_CACHE_XMMW || cache->extcache[i].t == EXT_CACHE_YMMW) ? 1 : 0; + cache->ssecache[cache->extcache[i].n].ymm = (cache->extcache[i].t == EXT_CACHE_YMMR || cache->extcache[i].t == EXT_CACHE_YMMW) ? 1 : cache->extcache[i].y; cache->ssecache[cache->extcache[i].n].ymm0 = (cache->ymm0 >> cache->extcache[i].n) & 1; break; case EXT_CACHE_ST_F: @@ -561,6 +564,7 @@ void extcacheUnwind(extcache_t* cache) cache->fpuused[i] = 0; } } + sse_sync_all_cache_types(cache); } // will go badly if address is unaligned @@ -630,6 +634,8 @@ const char* getCacheName(int t, int n) case EXT_CACHE_SCR: sprintf(buff, "Scratch"); break; case EXT_CACHE_XMMW: sprintf(buff, "XMM%d", n); break; case EXT_CACHE_XMMR: sprintf(buff, "xmm%d", n); break; + case EXT_CACHE_YMMW: sprintf(buff, "YMM%d", n); break; + case EXT_CACHE_YMMR: sprintf(buff, "ymm%d", n); break; case EXT_CACHE_NONE: buff[0] = '\0'; break; } return buff; @@ -756,6 +762,8 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r case EXT_CACHE_SD: length += sprintf(buf + length, " f%d:%s", EXTREG(ii), getCacheName(dyn->insts[ninst].e.extcache[ii].t, dyn->insts[ninst].e.extcache[ii].n)); break; case EXT_CACHE_XMMR: length += sprintf(buf + length, " v%d:%s", EXTREG(ii), getCacheName(dyn->insts[ninst].e.extcache[ii].t, dyn->insts[ninst].e.extcache[ii].n)); break; case EXT_CACHE_XMMW: length += sprintf(buf + length, " v%d:%s", EXTREG(ii), getCacheName(dyn->insts[ninst].e.extcache[ii].t, dyn->insts[ninst].e.extcache[ii].n)); break; + case EXT_CACHE_YMMR: length += sprintf(buf + length, " v%d:%s", EXTREG(ii), getCacheName(dyn->insts[ninst].e.extcache[ii].t, dyn->insts[ninst].e.extcache[ii].n)); break; + case EXT_CACHE_YMMW: length += sprintf(buf + length, " v%d:%s", EXTREG(ii), getCacheName(dyn->insts[ninst].e.extcache[ii].t, dyn->insts[ninst].e.extcache[ii].n)); break; case EXT_CACHE_SCR: length += sprintf(buf + length, " f%d:%s", EXTREG(ii), getCacheName(dyn->insts[ninst].e.extcache[ii].t, dyn->insts[ninst].e.extcache[ii].n)); break; case EXT_CACHE_NONE: default: break; @@ -962,6 +970,26 @@ void updateUpperLiveness(dynarec_rv64_t* dyn) int* work = (int*)((char*)pend_ymm + live_size); uint8_t* on_list = (uint8_t*)((char*)work + work_size); + for (int i = 0; i < n; ++i) { + instruction_rv64_t* inst = &dyn->insts[i]; + if (!inst->x64.alive || inst->pred_sz < 2 || (inst->x64.barrier & BARRIER_FLOAT)) + continue; + const extcache_t* first = &dyn->insts[inst->pred[0]].e; + for (int p = 1; p < inst->pred_sz; ++p) { + const extcache_t* pe = &dyn->insts[inst->pred[p]].e; + int diff = (first->ymm0 != pe->ymm0); + for (int r = 0; r < 16 && !diff; ++r) + if (first->ssecache[r].v != -1 && pe->ssecache[r].v != -1 + && (first->ssecache[r].ymm != pe->ssecache[r].ymm + || first->ssecache[r].ymm0 != pe->ssecache[r].ymm0)) + diff = 1; + if (diff) { + inst->x64.barrier |= BARRIER_FLOAT; + break; + } + } + } + int sp = 0; for (int i = n - 1; i >= 0; --i) { if (dyn->insts[i].x64.alive) { @@ -1023,6 +1051,9 @@ void updateUpperLiveness(dynarec_rv64_t* dyn) inst->ymm_upper_live = live_ymm_out[i]; } + // forward analysis + memset(pending_in, 0, pending_size); + memset(pend_ymm, 0, live_size); memset(on_list, 0, list_size); sp = 0; for (int i = 0; i < n; ++i) { @@ -1031,7 +1062,6 @@ void updateUpperLiveness(dynarec_rv64_t* dyn) on_list[i] = 1; } } - // forward analysis while (sp > 0) { int i = work[--sp]; on_list[i] = 0; @@ -1045,9 +1075,9 @@ void updateUpperLiveness(dynarec_rv64_t* dyn) int j = inst->pred[p]; const instruction_rv64_t* pred = &dyn->insts[j]; merged_pending |= (pending_in[j] & (uint16_t)~pred->up32_write64) | pred->up32_skip; - merged_ymm |= (pend_ymm[j] & (uint16_t)~pred->ymm_upper_def) | - (pred->ymm_zero & (uint16_t)~pred->ymm_upper_live); + merged_ymm |= (pend_ymm[j] & (uint16_t)~pred->ymm_upper_def) | (pred->ymm_zero & (uint16_t)~pred->ymm_upper_live); } + if (inst->x64.barrier & BARRIER_FLOAT) merged_ymm = 0; if ((merged_pending != pending_in[i]) || (merged_ymm != pend_ymm[i])) { pending_in[i] = merged_pending; pend_ymm[i] = merged_ymm; diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 2e17cf3a5..58f47c265 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -1839,7 +1839,8 @@ void sse_forget_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a) return; if (dyn->e.ssecache[a].vector == 0) return sse_forget_reg(dyn, ninst, s1, a); - if (dyn->e.extcache[EXTIDX(dyn->e.ssecache[a].reg)].t == EXT_CACHE_XMMW) { + if (dyn->e.extcache[EXTIDX(dyn->e.ssecache[a].reg)].t == EXT_CACHE_XMMW + || dyn->e.extcache[EXTIDX(dyn->e.ssecache[a].reg)].t == EXT_CACHE_YMMW) { uint8_t sew, vlmul, vl; vector_save_vtype(dyn, &sew, &vlmul, &vl); vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); @@ -2199,6 +2200,14 @@ static int findCacheSlot(dynarec_rv64_t* dyn, int ninst, int t, int n, extcache_ if (t == EXT_CACHE_XMMR) return i; break; + case EXT_CACHE_YMMR: + if (t == EXT_CACHE_YMMW) + return i; + break; + case EXT_CACHE_YMMW: + if (t == EXT_CACHE_YMMR) + return i; + break; } } } @@ -2210,7 +2219,9 @@ static void swapCache(dynarec_rv64_t* dyn, int ninst, int s1, int i, int j, extc if (i == j) return; if (cache->extcache[i].t == EXT_CACHE_XMMR || cache->extcache[i].t == EXT_CACHE_XMMW - || cache->extcache[j].t == EXT_CACHE_XMMR || cache->extcache[j].t == EXT_CACHE_XMMW) { + || cache->extcache[i].t == EXT_CACHE_YMMR || cache->extcache[i].t == EXT_CACHE_YMMW + || cache->extcache[j].t == EXT_CACHE_XMMR || cache->extcache[j].t == EXT_CACHE_XMMW + || cache->extcache[j].t == EXT_CACHE_YMMR || cache->extcache[j].t == EXT_CACHE_YMMW) { SET_CACHE_VECTOR_WIDTH(s1); int reg_i = EXTREG(i); int reg_j = EXTREG(j); @@ -2266,10 +2277,31 @@ static void swapCache(dynarec_rv64_t* dyn, int ninst, int s1, int i, int j, extc cache->extcache[j].v = tmp.v; } +static void loadUpperCache(dynarec_rv64_t* dyn, int ninst, int s1, int a, int reg, int tozero) +{ + uint8_t sew0, vlmul0, vl0; + vector_save_vtype(dyn, &sew0, &vlmul0, &vl0); + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; + if (tozero) { + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW32, VECTOR_LMUL1, 2); + VECTOR_LOAD_VMASK(0xf0, s1, 2); + VMERGE_VXM(reg, reg, xZR); + } else { + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VECTOR_LOAD_VMASK(0xffff0000, s1, 2); + dyn->inst_vl = 0; // the mask load changed the real vl + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); + ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a]) - 16); + VLE8_V(reg, s1, VECTOR_MASKED, VECTOR_NFIELD1); + } + vector_restore_vtype(dyn, ninst, s1, sew0, vlmul0, vl0); +} + static void loadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, int s2, int s3, int* s1_val, int* s2_val, int* s3_top, extcache_t* cache, int i, int t, int n) { int reg = EXTREG(i); - if (cache->extcache[i].v && (cache->extcache[i].t == EXT_CACHE_XMMR || cache->extcache[i].t == EXT_CACHE_XMMW)) { + if (cache->extcache[i].v && (cache->extcache[i].t == EXT_CACHE_XMMR || cache->extcache[i].t == EXT_CACHE_XMMW || cache->extcache[i].t == EXT_CACHE_YMMR || cache->extcache[i].t == EXT_CACHE_YMMW)) { SET_CACHE_VECTOR_WIDTH(s1); int j = i + 1; while (j < 24 && cache->extcache[j].v) @@ -2312,6 +2344,14 @@ static void loadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, int ADDI(s1, xEmu, offsetof(x64emu_t, xmm[n])); VLE_V(reg, s1, dyn->vector_eew, VECTOR_UNMASKED, VECTOR_NFIELD1); break; + case EXT_CACHE_YMMR: + case EXT_CACHE_YMMW: + MESSAGE(LOG_DUMP, "\t - Loading %s\n", getCacheName(t, n)); + SET_CACHE_VECTOR_WIDTH(s1); + ADDI(s1, xEmu, offsetof(x64emu_t, xmm[n])); + VLE_V(reg, s1, dyn->vector_eew, VECTOR_UNMASKED, VECTOR_NFIELD1); + loadUpperCache(dyn, ninst, s1, n, reg, (cache->ymm0 >> n) & 1); + break; case EXT_CACHE_SS: MESSAGE(LOG_DUMP, "\t - Loading %s\n", getCacheName(t, n)); FLW(reg, xEmu, offsetof(x64emu_t, xmm[n])); @@ -2365,7 +2405,7 @@ static void loadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, int } cache->extcache[i].n = n; cache->extcache[i].t = t; - cache->extcache[i].y = 0; + cache->extcache[i].y = (t == EXT_CACHE_YMMR || t == EXT_CACHE_YMMW) ? 1 : 0; } static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, int s2, int s3, int* s1_val, int* s2_val, int* s3_top, extcache_t* cache, int i, int t, int n) @@ -2373,9 +2413,11 @@ static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, i int reg = EXTREG(i); switch (t) { case EXT_CACHE_XMMR: + case EXT_CACHE_YMMR: MESSAGE(LOG_DUMP, "\t - ignoring %s\n", getCacheName(t, n)); break; case EXT_CACHE_XMMW: + case EXT_CACHE_YMMW: MESSAGE(LOG_DUMP, "\t - Unloading %s\n", getCacheName(t, n)); { uint8_t sew, vlmul, vl; @@ -2385,6 +2427,8 @@ static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, i VSE8_V(reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); } + if (t == EXT_CACHE_YMMW) + avx_flush_upper_vector(dyn, ninst, s1, n, reg, 1); break; case EXT_CACHE_SS: MESSAGE(LOG_DUMP, "\t - Unloading %s\n", getCacheName(t, n)); @@ -2440,27 +2484,6 @@ static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, i cache->extcache[i].v = 0; } -static void loadUpperCache(dynarec_rv64_t* dyn, int ninst, int s1, int a, int reg, int tozero) -{ - uint8_t sew0, vlmul0, vl0; - vector_save_vtype(dyn, &sew0, &vlmul0, &vl0); - dyn->inst_sew = VECTOR_SEWNA; - dyn->inst_vl = 0; - if (tozero) { - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW32, VECTOR_LMUL1, 2); - VECTOR_LOAD_VMASK(0xf0, s1, 2); - VMERGE_VXM(reg, reg, xZR); - } else { - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); - VECTOR_LOAD_VMASK(0xffff0000, s1, 2); - dyn->inst_vl = 0; // the mask load changed the real vl - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); - ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a]) - 16); - VLE8_V(reg, s1, VECTOR_MASKED, VECTOR_NFIELD1); - } - vector_restore_vtype(dyn, ninst, s1, sew0, vlmul0, vl0); -} - static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3) { int i2 = dyn->insts[ninst].x64.jmp_insts; @@ -2514,6 +2537,9 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in j = findCacheSlot(dyn, ninst, EXT_CACHE_XMMW, i, &cache); if (j >= 0 && findCacheSlot(dyn, ninst, EXT_CACHE_XMMW, i, &cache_i2) == -1) unloadCache(dyn, ninst, stack_cnt, s1, s2, s3, &s1_val, &s2_val, &s3_top, &cache, j, cache.extcache[j].t, cache.extcache[j].n); + j = findCacheSlot(dyn, ninst, EXT_CACHE_YMMW, i, &cache); + if (j >= 0 && findCacheSlot(dyn, ninst, EXT_CACHE_YMMW, i, &cache_i2) == -1) + unloadCache(dyn, ninst, stack_cnt, s1, s2, s3, &s1_val, &s2_val, &s3_top, &cache, j, cache.extcache[j].t, cache.extcache[j].n); } for (int i = 0; i < 8; ++i) { int j = findCacheSlot(dyn, ninst, EXT_CACHE_MM, i, &cache); @@ -2572,6 +2598,18 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in cache.extcache[i].t = EXT_CACHE_ST_D; } else if (cache.extcache[i].t == EXT_CACHE_XMMR && cache_i2.extcache[i].t == EXT_CACHE_XMMW) { cache.extcache[i].t = EXT_CACHE_XMMW; + } else if (cache.extcache[i].t == EXT_CACHE_YMMR && cache_i2.extcache[i].t == EXT_CACHE_YMMW) { + cache.extcache[i].t = EXT_CACHE_YMMW; + cache.ssecache[cache.extcache[i].n].write = 1; + } else if (cache.extcache[i].t == EXT_CACHE_YMMW && cache_i2.extcache[i].t == EXT_CACHE_YMMR) { + MESSAGE(LOG_DUMP, "\t - Store %s\n", getCacheName(cache.extcache[i].t, cache.extcache[i].n)); + avx_flush_upper_vector(dyn, ninst, s1, cache.extcache[i].n, EXTREG(i), 1); + SET_CACHE_VECTOR_WIDTH(s1); + ADDI(s1, xEmu, offsetof(x64emu_t, xmm[cache.extcache[i].n])); + VSE_V(EXTREG(i), s1, dyn->vector_eew, VECTOR_UNMASKED, VECTOR_NFIELD1); + cache.extcache[i].t = EXT_CACHE_YMMR; + cache.ssecache[cache.extcache[i].n].write = 0; + cache.ssecache[cache.extcache[i].n].ymm0 = 0; } else if (cache.extcache[i].t == EXT_CACHE_XMMW && cache_i2.extcache[i].t == EXT_CACHE_XMMR) { // refresh cache... MESSAGE(LOG_DUMP, "\t - Refreh %s\n", getCacheName(cache.extcache[i].t, cache.extcache[i].n)); @@ -2581,15 +2619,18 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in cache.extcache[i].t = EXT_CACHE_XMMR; } } - if ((cache.extcache[i].t == EXT_CACHE_XMMR || cache.extcache[i].t == EXT_CACHE_XMMW) - && (cache_i2.extcache[i].t == EXT_CACHE_XMMR || cache_i2.extcache[i].t == EXT_CACHE_XMMW) - && cache.extcache[i].y != cache_i2.extcache[i].y) { + int src_ymm = (cache.extcache[i].t == EXT_CACHE_YMMR || cache.extcache[i].t == EXT_CACHE_YMMW); + int dst_ymm = (cache_i2.extcache[i].t == EXT_CACHE_YMMR || cache_i2.extcache[i].t == EXT_CACHE_YMMW); + if (src_ymm != dst_ymm && cache.extcache[i].n == cache_i2.extcache[i].n) { int n = cache.extcache[i].n; - if (cache_i2.extcache[i].y) { + if (dst_ymm) { MESSAGE(LOG_DUMP, "\t - Loading upper half of %s\n", getCacheName(cache.extcache[i].t, n)); loadUpperCache(dyn, ninst, s1, n, EXTREG(i), (cache_i2.ymm0 >> n) & 1); + } else if (src_ymm) { + MESSAGE(LOG_DUMP, "\t - Storing upper half of %s\n", getCacheName(cache.extcache[i].t, n)); + avx_flush_upper_vector(dyn, ninst, s1, n, EXTREG(i), 1); } - cache.extcache[i].y = cache_i2.extcache[i].y; + cache.extcache[i].y = dst_ymm; } } } diff --git a/src/dynarec/rv64/dynarec_rv64_pass0.h b/src/dynarec/rv64/dynarec_rv64_pass0.h index db6d747ce..67ff9b1cb 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass0.h +++ b/src/dynarec/rv64/dynarec_rv64_pass0.h @@ -90,6 +90,7 @@ #define INST_EPILOG \ dyn->insts[ninst].f_exit = dyn->f; \ + sse_sync_all_cache_types(&dyn->e); \ dyn->insts[ninst].e = dyn->e; \ dyn->insts[ninst].vector_sew_exit = dyn->vector_sew; \ dyn->insts[ninst].x64.has_next = (ok > 0) ? 1 : 0; diff --git a/src/dynarec/rv64/dynarec_rv64_pass1.h b/src/dynarec/rv64/dynarec_rv64_pass1.h index 8fd3a9b19..f04e48530 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass1.h +++ b/src/dynarec/rv64/dynarec_rv64_pass1.h @@ -21,6 +21,7 @@ AREFLAGSNEEDED() #define INST_EPILOG \ + sse_sync_all_cache_types(&dyn->e); \ dyn->insts[ninst].e = dyn->e; \ dyn->insts[ninst].f_exit = dyn->f; \ dyn->insts[ninst].vector_sew_exit = dyn->vector_sew; diff --git a/src/dynarec/rv64/dynarec_rv64_pass2.h b/src/dynarec/rv64/dynarec_rv64_pass2.h index 304c99bc5..3d64efca1 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass2.h +++ b/src/dynarec/rv64/dynarec_rv64_pass2.h @@ -27,6 +27,7 @@ AREFLAGSNEEDED() #define INST_EPILOG \ dyn->insts[ninst].epilog = dyn->native_size; \ + sse_sync_all_cache_types(&dyn->e); \ dyn->vector_sew = dyn->insts[ninst].vector_sew_exit; \ dyn->inst_sew = dyn->vector_sew; \ dyn->inst_vlmul = VECTOR_LMUL1; \ diff --git a/src/dynarec/rv64/dynarec_rv64_pass3.h b/src/dynarec/rv64/dynarec_rv64_pass3.h index ad9eb262d..715480434 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass3.h +++ b/src/dynarec/rv64/dynarec_rv64_pass3.h @@ -26,6 +26,7 @@ addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst - 1].x64.size, dyn->insts[ninst - 1].size / 4); \ dyn->insts[ninst].ymm0_pass3 = dyn->ymm_zero; \ } \ + sse_sync_all_cache_types(&dyn->e); \ AREFLAGSNEEDED() #define INST_EPILOG \ dyn->vector_sew = dyn->insts[ninst].vector_sew_exit; \ diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index 5776e78d9..572291277 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -23,6 +23,8 @@ typedef struct box64env_s box64env_t; #define EXT_CACHE_XMMW 8 #define EXT_CACHE_XMMR 9 #define EXT_CACHE_MMV 10 +#define EXT_CACHE_YMMW 11 +#define EXT_CACHE_YMMR 12 #define EXT_CACHE_OLD_SD 0 #define EXT_CACHE_OLD_SS 1 @@ -229,6 +231,28 @@ typedef struct dynarec_rv64_s { // convert reg index (8..31) to idx (0..23) #define EXTIDX(A) (((A) >= 16) ? ((A) - 16) : ((A) + 8)) +static inline void sse_sync_cache_type(extcache_t* cache, int a) +{ + sse_cache_t* e = &cache->ssecache[a]; + if (e->v == -1) + return; + if (!e->vector) { + cache->extcache[EXTIDX(e->reg)].t = e->single ? EXT_CACHE_SS : EXT_CACHE_SD; + return; + } + int dirty = e->write || e->ymm0; + if (e->ymm) + cache->extcache[EXTIDX(e->reg)].t = dirty ? EXT_CACHE_YMMW : EXT_CACHE_YMMR; + else + cache->extcache[EXTIDX(e->reg)].t = dirty ? EXT_CACHE_XMMW : EXT_CACHE_XMMR; +} + +static inline void sse_sync_all_cache_types(extcache_t* cache) +{ + for (int i = 0; i < 16; ++i) + sse_sync_cache_type(cache, i); +} + void add_next(dynarec_rv64_t *dyn, uintptr_t addr); uintptr_t get_closest_next(dynarec_rv64_t *dyn, uintptr_t addr); void add_jump(dynarec_rv64_t *dyn, int ninst); From 27860e6aee72dd33c2588d081652d6e9becc1089 Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Sat, 17 Oct 2026 13:24:09 +0800 Subject: [PATCH 045/156] [RV64_DYNAREC] Fix VCVTPD2PS result clearing (#4572) Use SEW=32, LMUL=1, VL=4 to clear the low 128 bits for vcvtpd2ps, which require clearing bit[127:64] to zero. --- src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index 3ccfb31dd..1d130ac5c 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -285,6 +285,9 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VLE64_V(d0, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); } v0 = fpu_get_scratch(dyn); + if (!vex.l && !cpuext.xtheadvector) { + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + } vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, vex.l ? 1 : 0.5); u8 = sse_setround(dyn, ninst, x6, x4); VFNCVT_F_F_W(v0, d0, VECTOR_UNMASKED); From 66dafa53302efc771352a6f7b4ca74869dc8c276 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sun, 18 Oct 2026 16:22:01 +0800 Subject: [PATCH 046/156] [RV64_DYNAREC] Added and refined more opcodes (#4578) --- src/dynarec/rv64/dynarec_rv64_0f.c | 144 +++++++++-- src/dynarec/rv64/dynarec_rv64_0f_vector.c | 17 +- src/dynarec/rv64/dynarec_rv64_660f.c | 12 +- src/dynarec/rv64/dynarec_rv64_avx_0f.c | 58 ++--- src/dynarec/rv64/dynarec_rv64_avx_66_0f.c | 58 ++--- .../rv64/dynarec_rv64_avx_66_0f3a_vector.c | 95 +++++++ .../rv64/dynarec_rv64_avx_66_0f_vector.c | 31 +++ src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c | 20 +- .../rv64/dynarec_rv64_avx_f2_0f_vector.c | 236 ++++++++++++++++++ src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c | 20 +- .../rv64/dynarec_rv64_avx_f3_0f_vector.c | 157 ++++++++++++ src/dynarec/rv64/dynarec_rv64_f20f.c | 20 +- src/dynarec/rv64/dynarec_rv64_f20f_vector.c | 64 ++--- src/dynarec/rv64/dynarec_rv64_f30f.c | 20 +- src/dynarec/rv64/dynarec_rv64_f30f_vector.c | 64 ++--- src/dynarec/rv64/dynarec_rv64_helper.c | 12 +- 16 files changed, 766 insertions(+), 262 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index 5be40c51c..e86f8f2ca 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -900,7 +900,6 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni d1 = fpu_get_scratch(dyn); q1 = fpu_get_scratch(dyn); int vz = fpu_get_scratch(dyn); - VXOR_VV(vz, vz, vz, 1); switch (u8) { case 0xC8: VROR_VI(d0, v0, 2, 1); @@ -911,13 +910,12 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0xC9: VSLIDEDOWN_VI(d0, v1, 2, 1); - VSLIDEUP_VI(d0, vz, 2, 1); VSLIDEUP_VI(d0, v0, 2, 1); VXOR_VV(v0, v0, d0, 1); break; case 0xCA: - VSLIDEUP_VI(d0, vz, 0, 1); - VSLIDEUP_VI(d0, v1, 1, 1); + VXOR_VV(vz, vz, vz, 1); + VSLIDE1UP_VX(d0, v1, xZR, 1); VXOR_VV(d0, d0, v0, 1); VROR_VI(v0, d0, 31, 1); VSLIDEDOWN_VI(d1, v0, 3, 1); @@ -936,6 +934,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni VADD_VV(v0, v0, d1, 1); break; case 0xCD: + VXOR_VV(vz, vz, vz, 1); VSLIDEDOWN_VI(d0, v1, 2, 1); VSLIDEUP_VI(d0, vz, 2, 1); VROR_VI(d1, d0, 17, 1); @@ -1048,30 +1047,127 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } } break; - case 0xCC: + case 0xCC: { INST_NAME("SHA1RNDS4 Gx, Ex, Ib"); nextop = F8; + if (!cpuext.vector || !cpuext.zvbb) { + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + sse_reflect_reg(dyn, ninst, x6, ed); + ADDI(x2, xEmu, offsetof(x64emu_t, xmm[ed])); + wback = x2; + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 1); + if (wback != x2 || fixedaddress) { + ADDI(x2, wback, fixedaddress); + wback = x2; + } + } + u8 = F8; + GETG; + sse_forget_reg(dyn, ninst, x6, gd); + ADDI(x1, xEmu, offsetof(x64emu_t, xmm[gd])); + MOV32w(x3, u8); + CALL4(const_sha1rnds4, -1, x1, wback, x3, 0); + break; + } + static const uint32_t sha1_k[4] = { + 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 + }; + int qA = fpu_get_scratch(dyn); + int qB = fpu_get_scratch(dyn); + int qC = fpu_get_scratch(dyn); + int qD = fpu_get_scratch(dyn); + int qT = fpu_get_scratch(dyn); + int qU = fpu_get_scratch(dyn); + int qM = fpu_get_scratch(dyn); + GETG; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); - sse_reflect_reg(dyn, ninst, x6, ed); - ADDI(x2, xEmu, offsetof(x64emu_t, xmm[ed])); - wback = x2; + u8 = F8; + q0 = sse_get_reg_vector(dyn, ninst, x1, gd, 0, VECTOR_SEW32); + q1 = sse_get_reg_vector(dyn, ninst, x1, ed, 0, VECTOR_SEW32); + VMV_V_V(qM, q1); } else { SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 1); - // the address is passed as an argument to the helper, so it must not stay in a guest register - if (wback != x2 || fixedaddress) { - ADDI(x2, wback, fixedaddress); - wback = x2; - } + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 1); + u8 = F8; + q0 = sse_get_reg_vector(dyn, ninst, x1, gd, 0, VECTOR_SEW32); + VLE32_V(qM, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); } - u8 = F8; - GETG; - sse_forget_reg(dyn, ninst, x6, gd); - ADDI(x1, xEmu, offsetof(x64emu_t, xmm[gd])); - MOV32w(x3, u8); - CALL4(const_sha1rnds4, -1, x1, wback, x3, 0); + MOV32w(x7, sha1_k[u8 & 3]); + VADD_VX(qM, qM, x7, VECTOR_UNMASKED); + VSLIDEDOWN_VI(qA, q0, 3, VECTOR_UNMASKED); + VSLIDEDOWN_VI(qB, q0, 2, VECTOR_UNMASKED); + VSLIDEDOWN_VI(qC, q0, 1, VECTOR_UNMASKED); + +#define SHA1_F(dst, vb, vc, vd, tmp) \ + do { \ + switch (u8 & 3) { \ + case 0: \ + VXOR_VV(tmp, vc, vd, VECTOR_UNMASKED); \ + VAND_VV(tmp, vb, tmp, VECTOR_UNMASKED); \ + VXOR_VV(dst, tmp, vd, VECTOR_UNMASKED); \ + break; \ + case 1: \ + case 3: \ + VXOR_VV(dst, vb, vc, VECTOR_UNMASKED); \ + VXOR_VV(dst, dst, vd, VECTOR_UNMASKED); \ + break; \ + default: \ + VXOR_VV(dst, vb, vc, VECTOR_UNMASKED); \ + VAND_VV(dst, dst, vd, VECTOR_UNMASKED); \ + VAND_VV(tmp, vb, vc, VECTOR_UNMASKED); \ + VXOR_VV(dst, dst, tmp, VECTOR_UNMASKED); \ + break; \ + } \ + } while (0) + + SHA1_F(qD, qB, qC, q0, qT); + VROR_VI(qB, qB, 2, VECTOR_UNMASKED); + SHA1_F(qU, qA, qB, qC, qT); + VROR_VI(qT, qA, 2, VECTOR_UNMASKED); + VADD_VV(qU, qU, q0, VECTOR_UNMASKED); + VSLIDEDOWN_VI(q0, qM, 3, VECTOR_UNMASKED); + VADD_VV(qD, qD, q0, VECTOR_UNMASKED); + VSLIDEDOWN_VI(q0, qM, 2, VECTOR_UNMASKED); + VADD_VV(qU, qU, q0, VECTOR_UNMASKED); + VROR_VI(qA, qA, 27, VECTOR_UNMASKED); + VSLIDEDOWN_VI(q0, qM, 1, VECTOR_UNMASKED); + VADD_VV(qC, qC, q0, VECTOR_UNMASKED); + VADD_VV(qA, qA, qD, VECTOR_UNMASKED); + + VROR_VI(qD, qA, 27, VECTOR_UNMASKED); + VADD_VV(qD, qD, qU, VECTOR_UNMASKED); + SHA1_F(qU, qA, qT, qB, q0); + VADD_VV(qU, qU, qC, VECTOR_UNMASKED); + VADD_VV(qB, qB, qM, VECTOR_UNMASKED); + + VROR_VI(qA, qA, 2, VECTOR_UNMASKED); + VROR_VI(qM, qD, 2, VECTOR_UNMASKED); + SHA1_F(qC, qD, qA, qT, q0); + VROR_VI(q0, qD, 27, VECTOR_UNMASKED); + VADD_VV(qC, qC, qB, VECTOR_UNMASKED); + VADD_VV(q0, q0, qU, VECTOR_UNMASKED); + VROR_VI(qD, q0, 27, VECTOR_UNMASKED); + VADD_VV(qD, qD, qC, VECTOR_UNMASKED); + +#undef SHA1_F + + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); + VMV_X_S(x7, qA); + VMV_X_S(x6, qM); + VMV_X_S(x5, q0); + VMV_X_S(x4, qD); + VMV_S_X(qT, x4); + VSLIDE1UP_VX(v0, qT, x5, VECTOR_UNMASKED); + VSLIDE1UP_VX(qT, v0, x6, VECTOR_UNMASKED); + VSLIDE1UP_VX(v0, qT, x7, VECTOR_UNMASKED); break; + } default: DEFAULT; } @@ -1468,12 +1564,8 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni for (int i = 0; i < 4; ++i) { FLW(s0, wback, fixedaddress + i * 4); FLW(s1, gback, gdoffset + i * 4); - FEQS(x3, s0, s0); - FEQS(x4, s1, s1); - AND(x3, x3, x4); - BEQZ(x3, 12); - FLES(x3, s1, s0); - BEQZ(x3, 8); + FLTS(x3, s0, s1); + BNEZ(x3, 8); FSW(s0, gback, gdoffset + i * 4); } break; diff --git a/src/dynarec/rv64/dynarec_rv64_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_0f_vector.c index 21baf57fd..7227510ee 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_0f_vector.c @@ -523,13 +523,26 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, } break; case 0x51: - if (!BOX64ENV(dynarec_fastround) || !BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("SQRTPS Gx, Ex"); nextop = F8; SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); GETEX_vector(v0, 0, 0, VECTOR_SEW32); GETGX_empty_vector(v1); - VFSQRT_V(v1, v0, VECTOR_UNMASKED); + if (!BOX64ENV(dynarec_fastnan)) { + v2 = fpu_get_scratch(dyn); + q0 = fpu_get_scratch(dyn); + MOV32w(x4, 0x00400000); + VMV_V_X(v2, x4); + VOR_VV(v2, v0, v2, VECTOR_UNMASKED); + MOV32w(x4, 0xFFC00000); + VMV_V_X(q0, x4); + VMFEQ_VV(VMASK, v0, v0, VECTOR_UNMASKED); + VMERGE_VVM(v2, v2, q0); + VFSQRT_V(v1, v0, VECTOR_UNMASKED); + VMFNE_VV(VMASK, v1, v1, VECTOR_UNMASKED); + VMERGE_VVM(v1, v1, v2); + } else + VFSQRT_V(v1, v0, VECTOR_UNMASKED); break; case 0x52: if (!BOX64ENV(dynarec_fastnan)) return 0; diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index 6dc7cb954..31b7a6ecb 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -534,10 +534,6 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int for (int i = 0; i < 2; ++i) { FLD(d0, gback, gdoffset + 8 * i); FLD(d1, wback, fixedaddress + 8 * i); - FEQD(x3, d0, d0); - FEQD(x4, d1, d1); - AND(x3, x3, x4); - BEQ(x3, xZR, 12); FLTD(x3, d0, d1); BNE(x3, xZR, 8); // continue FSD(d1, gback, gdoffset + 8 * i); @@ -584,12 +580,8 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int for (int i = 0; i < 2; ++i) { FLD(d0, gback, gdoffset + 8 * i); FLD(d1, wback, fixedaddress + 8 * i); - FEQD(x3, d0, d0); - FEQD(x4, d1, d1); - AND(x3, x3, x4); - BEQ(x3, xZR, 12); - FLED(x3, d0, d1); - BEQ(x3, xZR, 8); // continue + FLTD(x3, d1, d0); + BNE(x3, xZR, 8); // continue FSD(d1, gback, gdoffset + 8 * i); } break; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_0f.c index f40b53e30..c744fbbea 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f.c @@ -940,40 +940,20 @@ uintptr_t dynarec64_AVX_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in for (int i = 0; i < 4; ++i) { FLW(s0, wback, fixedaddress + i * 4); FLW(s1, vback, vxoffset + i * 4); - if (!BOX64ENV(dynarec_fastnan)) { - FEQS(x3, s0, s0); - FEQS(x4, s1, s1); - AND(x3, x3, x4); - FLTS(x5, s1, s0); - AND(x3, x3, x5); - BNEZ(x3, 4 + 4 * 2); - FSW(s0, gback, gdoffset + i * 4); - B(4 + 4); - FSW(s1, gback, gdoffset + i * 4); - } else { - FMINS(s1, s1, s0); - FSW(s1, gback, gdoffset + i * 4); - } + FLTS(x3, s1, s0); + BNEZ(x3, 8); + FMVS(s1, s0); + FSW(s1, gback, gdoffset + i * 4); } if (vex.l) { GETEY(); for (int i = 0; i < 4; ++i) { FLW(s0, wback, fixedaddress + i * 4); FLW(s1, vback, vyoffset + i * 4); - if (!BOX64ENV(dynarec_fastnan)) { - FEQS(x3, s0, s0); - FEQS(x4, s1, s1); - AND(x3, x3, x4); - FLTS(x5, s1, s0); - AND(x3, x3, x5); - BNEZ(x3, 4 + 4 * 2); - FSW(s0, gback, gyoffset + i * 4); - B(4 + 4); - FSW(s1, gback, gyoffset + i * 4); - } else { - FMINS(s1, s1, s0); - FSW(s1, gback, gyoffset + i * 4); - } + FLTS(x3, s1, s0); + BNEZ(x3, 8); + FMVS(s1, s0); + FSW(s1, gback, gyoffset + i * 4); } } else YMM0(gd); @@ -1051,14 +1031,9 @@ uintptr_t dynarec64_AVX_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in for (int i = 0; i < 4; ++i) { FLW(s0, wback, fixedaddress + i * 4); FLW(s1, vback, vxoffset + i * 4); - FEQS(x3, s0, s0); - FEQS(x4, s1, s1); - AND(x3, x3, x4); - FLTS(x5, s0, s1); - AND(x3, x3, x5); - BNEZ(x3, 4 + 4 * 2); - FSW(s0, gback, gdoffset + i * 4); - B(4 + 4); + FLTS(x3, s0, s1); + BNEZ(x3, 8); + FMVS(s1, s0); FSW(s1, gback, gdoffset + i * 4); } if (vex.l) { @@ -1066,14 +1041,9 @@ uintptr_t dynarec64_AVX_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in for (int i = 0; i < 4; ++i) { FLW(s0, wback, fixedaddress + i * 4); FLW(s1, vback, vyoffset + i * 4); - FEQS(x3, s0, s0); - FEQS(x4, s1, s1); - AND(x3, x3, x4); - FLTS(x5, s0, s1); - AND(x3, x3, x5); - BNEZ(x3, 4 + 4 * 2); - FSW(s0, gback, gyoffset + i * 4); - B(4 + 4); + FLTS(x3, s0, s1); + BNEZ(x3, 8); + FMVS(s1, s0); FSW(s1, gback, gyoffset + i * 4); } } else diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c index 18d88bf72..d0fa8a6b1 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c @@ -751,28 +751,20 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, v0 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); for (int i = 0; i < 2; ++i) { - FLD(v0, vback, vxoffset + 8 * i); - FLD(v1, wback, fixedaddress + 8 * i); - FEQD(x3, v0, v0); - FEQD(x4, v1, v1); - AND(x3, x3, x4); - BEQ(x3, xZR, 4 + 3 * 4); - FLTD(x3, v0, v1); - BEQ(x3, xZR, 4 + 4); // continue + FLD(v0, wback, fixedaddress + 8 * i); + FLD(v1, vback, vxoffset + 8 * i); + FLTD(x3, v1, v0); + BNEZ(x3, 8); FMVD(v1, v0); FSD(v1, gback, gdoffset + 8 * i); } if (vex.l) { GETEY(); for (int i = 0; i < 2; ++i) { - FLD(v0, vback, vyoffset + 8 * i); - FLD(v1, wback, fixedaddress + 8 * i); - FEQD(x3, v0, v0); - FEQD(x4, v1, v1); - AND(x3, x3, x4); - BEQ(x3, xZR, 4 + 3 * 4); - FLTD(x3, v0, v1); - BEQ(x3, xZR, 4 + 4); // continue + FLD(v0, wback, fixedaddress + 8 * i); + FLD(v1, vback, vyoffset + 8 * i); + FLTD(x3, v1, v0); + BNEZ(x3, 8); FMVD(v1, v0); FSD(v1, gback, gyoffset + 8 * i); } @@ -850,28 +842,20 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, v0 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); for (int i = 0; i < 2; ++i) { - FLD(v0, vback, vxoffset + 8 * i); - FLD(v1, wback, fixedaddress + 8 * i); - FEQD(x3, v0, v0); - FEQD(x4, v1, v1); - AND(x3, x3, x4); - BEQ(x3, xZR, 4 + 3 * 4); - FLTD(x3, v1, v0); - BEQ(x3, xZR, 4 + 4); // continue + FLD(v0, wback, fixedaddress + 8 * i); + FLD(v1, vback, vxoffset + 8 * i); + FLTD(x3, v0, v1); + BNEZ(x3, 8); FMVD(v1, v0); FSD(v1, gback, gdoffset + 8 * i); } if (vex.l) { GETEY(); for (int i = 0; i < 2; ++i) { - FLD(v0, vback, vyoffset + 8 * i); - FLD(v1, wback, fixedaddress + 8 * i); - FEQD(x3, v0, v0); - FEQD(x4, v1, v1); - AND(x3, x3, x4); - BEQ(x3, xZR, 4 + 3 * 4); - FLTD(x3, v1, v0); - BEQ(x3, xZR, 4 + 4); // continue + FLD(v0, wback, fixedaddress + 8 * i); + FLD(v1, vback, vyoffset + 8 * i); + FLTD(x3, v0, v1); + BNEZ(x3, 8); FMVD(v1, v0); FSD(v1, gback, gyoffset + 8 * i); } @@ -3673,7 +3657,10 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FLD(d0, wback, fixedaddress + 8 * i); FCVTLD(x3, d0, RD_RTZ); SEXT_W(x5, x3); - BEQ(x5, x3, 8); + BEQ(x5, x3, 20); + LWU(x5, xEmu, offsetof(x64emu_t, mxcsr)); + ORI(x5, x5, 1); + SW(x5, xEmu, offsetof(x64emu_t, mxcsr)); LUI(x3, 0x80000); SW(x3, gback, gdoffset + 4 * i); } @@ -3683,7 +3670,10 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FLD(d0, wback, fixedaddress + 8 * i); FCVTLD(x3, d0, RD_RTZ); SEXT_W(x5, x3); - BEQ(x5, x3, 8); + BEQ(x5, x3, 20); + LWU(x5, xEmu, offsetof(x64emu_t, mxcsr)); + ORI(x5, x5, 1); + SW(x5, xEmu, offsetof(x64emu_t, mxcsr)); LUI(x3, 0x80000); SW(x3, gback, gdoffset + 8 + 4 * i); } diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c index f34e8db62..2f6964e7e 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c @@ -652,6 +652,65 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint SMWRITE2(); } break; + case 0x15: + INST_NAME("VPEXTRW Ew, Gx, Ib"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, ((nextop & 0x38) >> 3) + (rex.r << 3), 16, VECTOR_SEW16); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW16); + if (MODREG) { + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 1); + } + u8 = F8; + q1 = fpu_get_scratch(dyn); + VSLIDEDOWN_VI(q1, q0, u8 & 7, VECTOR_UNMASKED); + VMV_X_S(x4, q1); + if (MODREG) { + ZEXTH(ed, x4); + } else { + SH(x4, ed, fixedaddress); + SMWRITE2(); + } + break; + case 0x16: + if (rex.w) { + INST_NAME("VPEXTRQ Ed, Gx, Ib"); + } else { + INST_NAME("VPEXTRD Ed, Gx, Ib"); + } + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, ((nextop & 0x38) >> 3) + (rex.r << 3), 16, rex.w ? VECTOR_SEW64 : VECTOR_SEW32); + SET_AVX_VECTOR_WIDTH(x1, rex.w ? VECTOR_SEW64 : VECTOR_SEW32); + if (MODREG) { + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 1); + } + u8 = F8; + q1 = fpu_get_scratch(dyn); + VSLIDEDOWN_VI(q1, q0, rex.w ? (u8 & 1) : (u8 & 3), VECTOR_UNMASKED); + VMV_X_S(x4, q1); + if (MODREG) { + if (rex.w) { + MV(ed, x4); + } else { + MV(ed, x4); + ZEROUP(ed); + } + } else { + if (rex.w) { + SD(x4, ed, fixedaddress); + } else { + SW(x4, ed, fixedaddress); + } + SMWRITE2(); + } + break; case 0x17: if (rex.w) return 0; INST_NAME("VEXTRACTPS Em, Gx, Ib"); @@ -701,6 +760,42 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VMERGE_VVM(q2, q0, q1); avx_store_reg_vector(dyn, ninst, x1, q2, gd, 16, VECTOR_SEW8); break; + case 0x22: + if (rex.w) { + INST_NAME("VPINSRQ Gx, Vx, ED, Ib"); + } else { + INST_NAME("VPINSRD Gx, Vx, ED, Ib"); + } + nextop = F8; + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, rex.w ? VECTOR_SEW64 : VECTOR_SEW32); + if (MODREG) { + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 1); + if (rex.w) { + LD(x5, ed, fixedaddress); + } else { + LWU(x5, ed, fixedaddress); + } + ed = x5; + } + u8 = F8; + if (rex.w) { + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); + VECTOR_LOAD_VMASK(1 << (u8 & 1), x4, 1); + } else { + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); + VECTOR_LOAD_VMASK(1 << (u8 & 3), x4, 1); + } + q1 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch(dyn); + VMV_V_X(q1, ed); + VMERGE_VVM(q2, q0, q1); + avx_store_reg_vector(dyn, ninst, x1, q2, gd, 16, rex.w ? VECTOR_SEW64 : VECTOR_SEW32); + break; case 0x21: INST_NAME("VINSERTPS Gx, Vx, Ex, Ib"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index 1d130ac5c..ceeca6545 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -1338,6 +1338,37 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt ZEXTH(gd, gd); } break; + case 0xC6: + INST_NAME("VSHUFPD Gx, Vx, Ex, Ib"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + q1 = fpu_get_scratch(dyn); + v1 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch(dyn); + v2 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16 << vex.l, VECTOR_SEW64); + if (MODREG) { + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16 << vex.l, VECTOR_SEW64); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, 1); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); + VLE64_V(q1, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + } + GETGY_empty_vector(v0); + u8 = F8; + selectors = 0; + for (int i = 0; i < (2 << vex.l); ++i) + selectors |= (uint64_t)((i >> 1) * 2 + ((u8 >> i) & 1)) << (i * 16); + MOV64x(x4, selectors); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); + VMV_V_X(v1, x4); + VRGATHEREI16_VV(q2, q0, v1, VECTOR_UNMASKED); + VRGATHEREI16_VV(v2, q1, v1, VECTOR_UNMASKED); + VECTOR_LOAD_VMASK(0xa, x4, vex.l ? 2 : 1); + VMERGE_VVM(v0, q2, v2); + PUTGY_vector(v0, VECTOR_SEW64); + break; default: DEFAULT_VECTOR; } diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c index c107e90cb..a3a5e0bc7 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c @@ -336,15 +336,9 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, v1 = fpu_get_scratch(dyn); FLD(v0, vback, vxoffset + 0); FLD(v1, wback, fixedaddress + 0); - FEQD(x2, v0, v0); - FEQD(x3, v1, v1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLED(x2, v1, v0); - BEQ_MARK2(x2, xZR); - MARK; + FLTD(x2, v0, v1); + BNEZ(x2, 8); FMVD(v0, v1); - MARK2; FSD(v0, gback, gdoffset + 0); if (gd != vex.v) { LD(x3, vback, vxoffset + 8); @@ -435,15 +429,9 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, v1 = fpu_get_scratch(dyn); FLD(v0, vback, vxoffset + 0); FLD(v1, wback, fixedaddress + 0); - FEQD(x2, v0, v0); - FEQD(x3, v1, v1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLED(x2, v0, v1); - BEQ_MARK2(x2, xZR); - MARK; + FLTD(x2, v1, v0); + BNEZ(x2, 8); FMVD(v0, v1); - MARK2; FSD(v0, gback, gdoffset + 0); if (gd != vex.v) { LD(x3, vback, vxoffset + 8); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c index 7013f36b1..8745457d5 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c @@ -44,6 +44,242 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt MAYUSE(j64); switch (opcode) { + case 0x10: + INST_NAME("VMOVSD Gx, [Vx,] Ex"); + nextop = F8; + d0 = fpu_get_scratch(dyn); + if (MODREG) { + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); + VFMV_F_S(d0, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLD(d0, ed, fixedaddress); + } + GETGY_empty_vector(v0); + if (MODREG) { + if (v0 != q0) + VMV_V_V(v0, q0); + } else { + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + } + VFMV_S_F(v0, d0); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + break; + case 0x11: + INST_NAME("VMOVSD Ex, [Vx,] Gx"); + nextop = F8; + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, gd, 16, VECTOR_SEW64); + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + q2 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q2, vex.v, 16, VECTOR_SEW64); + VFMV_F_S(d0 = fpu_get_scratch(dyn), q0); + VFMV_S_F(q2, d0); + avx_store_reg_vector(dyn, ninst, x1, q2, ed, 16, VECTOR_SEW64); + } else { + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + VFMV_F_S(d0 = fpu_get_scratch(dyn), q0); + FSD(d0, ed, fixedaddress); + SMWRITE2(); + } + break; + case 0x58: + if (!BOX64ENV(dynarec_fastnan)) return 0; + INST_NAME("VADDSD Gx, Vx, Ex"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); + d1 = fpu_get_scratch(dyn); + if (MODREG) { + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); + VFMV_F_S(d1, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLD(d1, ed, fixedaddress); + } + d0 = fpu_get_scratch(dyn); + VFMV_F_S(d0, q0); + FADDD(d0, d0, d1); + GETGY_empty_vector(v0); + if (v0 != q0) + VMV_V_V(v0, q0); + VFMV_S_F(v0, d0); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + break; + case 0x59: + if (!BOX64ENV(dynarec_fastnan)) return 0; + INST_NAME("VMULSD Gx, Vx, Ex"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); + d1 = fpu_get_scratch(dyn); + if (MODREG) { + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); + VFMV_F_S(d1, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLD(d1, ed, fixedaddress); + } + d0 = fpu_get_scratch(dyn); + VFMV_F_S(d0, q0); + FMULD(d0, d0, d1); + GETGY_empty_vector(v0); + if (v0 != q0) + VMV_V_V(v0, q0); + VFMV_S_F(v0, d0); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + break; + case 0x5C: + if (!BOX64ENV(dynarec_fastnan)) return 0; + INST_NAME("VSUBSD Gx, Vx, Ex"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); + d1 = fpu_get_scratch(dyn); + if (MODREG) { + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); + VFMV_F_S(d1, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLD(d1, ed, fixedaddress); + } + d0 = fpu_get_scratch(dyn); + VFMV_F_S(d0, q0); + FSUBD(d0, d0, d1); + GETGY_empty_vector(v0); + if (v0 != q0) + VMV_V_V(v0, q0); + VFMV_S_F(v0, d0); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + break; + case 0x5D: + INST_NAME("VMINSD Gx, Vx, Ex"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); + d1 = fpu_get_scratch(dyn); + if (MODREG) { + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); + VFMV_F_S(d1, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLD(d1, ed, fixedaddress); + } + d0 = fpu_get_scratch(dyn); + VFMV_F_S(d0, q0); + FLTD(x2, d0, d1); + BNEZ(x2, 8); + FMVD(d0, d1); + GETGY_empty_vector(v0); + if (v0 != q0) + VMV_V_V(v0, q0); + VFMV_S_F(v0, d0); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + break; + case 0x5E: + if (!BOX64ENV(dynarec_fastnan)) return 0; + INST_NAME("VDIVSD Gx, Vx, Ex"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); + d1 = fpu_get_scratch(dyn); + if (MODREG) { + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); + VFMV_F_S(d1, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLD(d1, ed, fixedaddress); + } + d0 = fpu_get_scratch(dyn); + VFMV_F_S(d0, q0); + FDIVD(d0, d0, d1); + GETGY_empty_vector(v0); + if (v0 != q0) + VMV_V_V(v0, q0); + VFMV_S_F(v0, d0); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + break; + case 0x5F: + INST_NAME("VMAXSD Gx, Vx, Ex"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); + d1 = fpu_get_scratch(dyn); + if (MODREG) { + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); + VFMV_F_S(d1, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLD(d1, ed, fixedaddress); + } + d0 = fpu_get_scratch(dyn); + VFMV_F_S(d0, q0); + FLTD(x2, d1, d0); + BNEZ(x2, 8); + FMVD(d0, d1); + GETGY_empty_vector(v0); + if (v0 != q0) VMV_V_V(v0, q0); + VFMV_S_F(v0, d0); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + break; + case 0x5A: + INST_NAME("VCVTSD2SS Gx, Vx, Ex"); + nextop = F8; + d0 = fpu_get_scratch(dyn); + if (MODREG) { + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); + VFMV_F_S(d0, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLD(d0, ed, fixedaddress); + } + d1 = fpu_get_scratch(dyn); + FCVTSD(d1, d0); + if (!BOX64ENV(dynarec_fastnan)) { + FEQD(x3, d0, d0); + FMVXD(x4, d0); + BNEZ_MARK(x3); + SRLI(x6, x4, 63); + SLLI(x6, x6, 31); + SRLI(x4, x4, 29); + MOV32w(x5, 0x007fffff); + AND(x4, x4, x5); + LUI(x5, 0x7fc00); + OR(x4, x4, x5); + OR(x4, x4, x6); + FMVWX(d1, x4); + MARK; + } + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); + GETGY_empty_vector(v0); + if (v0 != q0) + VMV_V_V(v0, q0); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); + VFMV_S_F(v0, d1); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + break; case 0x2A: INST_NAME("VCVTSI2SD Gx, Vx, Ed"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c index e386336c0..649cc950d 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c @@ -451,15 +451,9 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d1 = fpu_get_scratch(dyn); FLW(d0, vback, vxoffset); FLW(d1, wback, fixedaddress); - FEQS(x2, d0, d0); - FEQS(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLES(x2, d1, d0); - BEQ_MARK2(x2, xZR); - MARK; + FLTS(x2, d0, d1); + BNEZ(x2, 8); FMVS(d0, d1); - MARK2; FSW(d0, gback, gdoffset); if (gd != vex.v) { LWU(x2, vback, vxoffset + 4); @@ -480,15 +474,9 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d1 = fpu_get_scratch(dyn); FLW(d0, vback, vxoffset); FLW(d1, wback, fixedaddress); - FEQS(x2, d0, d0); - FEQS(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLES(x2, d0, d1); - BEQ_MARK2(x2, xZR); - MARK; + FLTS(x2, d1, d0); + BNEZ(x2, 8); FMVS(d0, d1); - MARK2; FSW(d0, gback, gdoffset); if (gd != vex.v) { LWU(x2, vback, vxoffset + 4); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c index ee3eaf600..dda251f5d 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c @@ -44,6 +44,111 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt MAYUSE(j64); switch (opcode) { + case 0x10: + INST_NAME("VMOVSS Gx, [Vx,] Ex"); + nextop = F8; + d0 = fpu_get_scratch(dyn); + if (MODREG) { + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); + VFMV_F_S(d0, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLW(d0, ed, fixedaddress); + } + GETGY_empty_vector(v0); + if (MODREG) { + if (v0 != q0) + VMV_V_V(v0, q0); + } else { + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + } + VFMV_S_F(v0, d0); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + break; + case 0x11: + INST_NAME("VMOVSS Ex, [Vx,] Gx"); + nextop = F8; + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, gd, 16, VECTOR_SEW32); + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, VECTOR_SEW32); + q2 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q2, vex.v, 16, VECTOR_SEW32); + VFMV_F_S(d0 = fpu_get_scratch(dyn), q0); + VFMV_S_F(q2, d0); + avx_store_reg_vector(dyn, ninst, x1, q2, ed, 32, VECTOR_SEW32); + } else { + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + VFMV_F_S(d0 = fpu_get_scratch(dyn), q0); + FSW(d0, ed, fixedaddress); + SMWRITE2(); + } + break; + case 0x5A: + INST_NAME("VCVTSS2SD Gx, Vx, Ex"); + nextop = F8; + d0 = fpu_get_scratch(dyn); + if (MODREG) { + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); + VFMV_F_S(d0, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLW(d0, ed, fixedaddress); + } + d1 = fpu_get_scratch(dyn); + FCVTDS(d1, d0); + if (!BOX64ENV(dynarec_fastnan)) { + FEQS(x3, d0, d0); + FMVXW(x4, d0); + BNEZ_MARK(x3); + SRLIW(x5, x4, 31); + SLLI(x5, x5, 63); + SLLI(x4, x4, 41); + SRLI(x4, x4, 12); + OR(x4, x4, x5); + MOV64x(x5, 0x7ff8000000000000ULL); + OR(x4, x4, x5); + FMVDX(d1, x4); + MARK; + } + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); + GETGY_empty_vector(v0); + if (v0 != q0) + VMV_V_V(v0, q0); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); + VFMV_S_F(v0, d1); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + break; + case 0x7E: + INST_NAME("VMOVQ Gx, Ex"); + nextop = F8; + if (MODREG) { + v1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, v1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); + VMV_X_S(x5, v1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + LD(x5, ed, fixedaddress); + } + GETGY_empty_vector(v0); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + VMV_S_X(v0, x5); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + break; case 0x12: INST_NAME("VMOVSLDUP Gx, Ex"); nextop = F8; @@ -268,6 +373,32 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VFMV_S_F(v0, d0); avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); break; + case 0x5D: + INST_NAME("VMINSS Gx, Vx, Ex"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); + d1 = fpu_get_scratch(dyn); + if (MODREG) { + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); + VFMV_F_S(d1, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLW(d1, ed, fixedaddress); + } + d0 = fpu_get_scratch(dyn); + VFMV_F_S(d0, q0); + FLTS(x2, d0, d1); + BNEZ(x2, 8); + FMVS(d0, d1); + GETGY_empty_vector(v0); + if (v0 != q0) + VMV_V_V(v0, q0); + VFMV_S_F(v0, d0); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + break; case 0x5E: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VDIVSS Gx, Vx, Ex"); @@ -293,6 +424,32 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VFMV_S_F(v0, d0); avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); break; + case 0x5F: + INST_NAME("VMAXSS Gx, Vx, Ex"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); + d1 = fpu_get_scratch(dyn); + if (MODREG) { + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); + VFMV_F_S(d1, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLW(d1, ed, fixedaddress); + } + d0 = fpu_get_scratch(dyn); + VFMV_F_S(d0, q0); + FLTS(x2, d1, d0); + BNEZ(x2, 8); + FMVS(d0, d1); + GETGY_empty_vector(v0); + if (v0 != q0) + VMV_V_V(v0, q0); + VFMV_S_F(v0, d0); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + break; case 0x70: INST_NAME("VPSHUFHW Gx, Ex, Ib"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c index 6dda8c52a..0b5011d79 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f.c @@ -340,15 +340,9 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int nextop = F8; GETGXSD(v0); GETEXSD(v1, 0); - FEQD(x2, v0, v0); - FEQD(x3, v1, v1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLED(x2, v1, v0); - BEQ_MARK2(x2, xZR); - MARK; + FLTD(x2, v0, v1); + BNEZ(x2, 8); FMVD(v0, v1); - MARK2; break; case 0x5E: INST_NAME("DIVSD Gx, Ex"); @@ -384,15 +378,9 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int nextop = F8; GETGXSD(v0); GETEXSD(v1, 0); - FEQD(x2, v0, v0); - FEQD(x3, v1, v1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLED(x2, v0, v1); - BEQ_MARK2(x2, xZR); - MARK; + FLTD(x2, v1, v0); + BNEZ(x2, 8); FMVD(v0, v1); - MARK2; break; case 0x70: // TODO: Optimize this! INST_NAME("PSHUFLW Gx, Ex, Ib"); diff --git a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c index c5efb122d..5b7d473fa 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c @@ -356,25 +356,19 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW64); } - d0 = fpu_get_scratch(dyn); - d1 = fpu_get_scratch(dyn); - VFMV_F_S(d0, v0); - VFMV_F_S(d1, v1); - FEQD(x2, d0, d0); - FEQD(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLED(x2, d1, d0); - BEQ_MARK2(x2, xZR); - MARK; - FMVD(d0, d1); - MARK2; - if (cpuext.xtheadvector) { - VFMV_S_F(d0, d0); - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VMERGE_VVM(v0, v0, d0); // implies VMASK - } else { - VFMV_S_F(v0, d0); + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFMV_F_S(d0, v0); + VFMV_F_S(d1, v1); + FLTD(x2, d0, d1); + BNEZ(x2, 8); + FMVD(d0, d1); + if (cpuext.xtheadvector) { + VFMV_S_F(d0, d0); + VECTOR_LOAD_VMASK(0b0001, x4, 1); + VMERGE_VVM(v0, v0, d0); // implies VMASK + } else { + VFMV_S_F(v0, d0); } break; case 0x5E: @@ -411,25 +405,19 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW64); } - d0 = fpu_get_scratch(dyn); - d1 = fpu_get_scratch(dyn); - VFMV_F_S(d0, v0); - VFMV_F_S(d1, v1); - FEQD(x2, d0, d0); - FEQD(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLED(x2, d0, d1); - BEQ_MARK2(x2, xZR); - MARK; - FMVD(d0, d1); - MARK2; - if (cpuext.xtheadvector) { - VFMV_S_F(d0, d0); - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VMERGE_VVM(v0, v0, d0); // implies VMASK - } else { - VFMV_S_F(v0, d0); + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFMV_F_S(d0, v0); + VFMV_F_S(d1, v1); + FLTD(x2, d1, d0); + BNEZ(x2, 8); + FMVD(d0, d1); + if (cpuext.xtheadvector) { + VFMV_S_F(d0, d0); + VECTOR_LOAD_VMASK(0b0001, x4, 1); + VMERGE_VVM(v0, v0, d0); // implies VMASK + } else { + VFMV_S_F(v0, d0); } break; case 0x70: diff --git a/src/dynarec/rv64/dynarec_rv64_f30f.c b/src/dynarec/rv64/dynarec_rv64_f30f.c index a10fd880c..a815f038e 100644 --- a/src/dynarec/rv64/dynarec_rv64_f30f.c +++ b/src/dynarec/rv64/dynarec_rv64_f30f.c @@ -425,15 +425,9 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int nextop = F8; GETGXSS(d0); GETEXSS(d1, 0); - FEQS(x2, d0, d0); - FEQS(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLES(x2, d1, d0); - BEQ_MARK2(x2, xZR); - MARK; + FLTS(x2, d0, d1); + BNEZ(x2, 8); FMVS(d0, d1); - MARK2; break; case 0x5E: INST_NAME("DIVSS Gx, Ex"); @@ -467,15 +461,9 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int nextop = F8; GETGXSS(d0); GETEXSS(d1, 0); - FEQS(x2, d0, d0); - FEQS(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLES(x2, d0, d1); - BEQ_MARK2(x2, xZR); - MARK; + FLTS(x2, d1, d0); + BNEZ(x2, 8); FMVS(d0, d1); - MARK2; break; case 0x6F: INST_NAME("MOVDQU Gx,Ex"); diff --git a/src/dynarec/rv64/dynarec_rv64_f30f_vector.c b/src/dynarec/rv64/dynarec_rv64_f30f_vector.c index d27ae5946..3b3a46410 100644 --- a/src/dynarec/rv64/dynarec_rv64_f30f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f30f_vector.c @@ -393,25 +393,19 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - d0 = fpu_get_scratch(dyn); - d1 = fpu_get_scratch(dyn); - VFMV_F_S(d0, v0); - VFMV_F_S(d1, v1); - FEQS(x2, d0, d0); - FEQS(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLES(x2, d1, d0); - BEQ_MARK2(x2, xZR); - MARK; - FMVS(d0, d1); - MARK2; - if (cpuext.xtheadvector) { - VFMV_S_F(d0, d0); - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VMERGE_VVM(v0, v0, d0); // implies VMASK - } else { - VFMV_S_F(v0, d0); + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFMV_F_S(d0, v0); + VFMV_F_S(d1, v1); + FLTS(x2, d0, d1); + BNEZ(x2, 8); + FMVS(d0, d1); + if (cpuext.xtheadvector) { + VFMV_S_F(d0, d0); + VECTOR_LOAD_VMASK(0b0001, x4, 1); + VMERGE_VVM(v0, v0, d0); + } else { + VFMV_S_F(v0, d0); } break; case 0x5E: @@ -448,25 +442,19 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - d0 = fpu_get_scratch(dyn); - d1 = fpu_get_scratch(dyn); - VFMV_F_S(d0, v0); - VFMV_F_S(d1, v1); - FEQS(x2, d0, d0); - FEQS(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLES(x2, d0, d1); - BEQ_MARK2(x2, xZR); - MARK; - FMVS(d0, d1); - MARK2; - if (cpuext.xtheadvector) { - VFMV_S_F(d0, d0); - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VMERGE_VVM(v0, v0, d0); // implies VMASK - } else { - VFMV_S_F(v0, d0); + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFMV_F_S(d0, v0); + VFMV_F_S(d1, v1); + FLTS(x2, d1, d0); + BNEZ(x2, 8); + FMVS(d0, d1); + if (cpuext.xtheadvector) { + VFMV_S_F(d0, d0); + VECTOR_LOAD_VMASK(0b0001, x4, 1); + VMERGE_VVM(v0, v0, d0); // implies VMASK + } else { + VFMV_S_F(v0, d0); } break; case 0x6F: diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 58f47c265..3deb9f25b 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -2285,8 +2285,8 @@ static void loadUpperCache(dynarec_rv64_t* dyn, int ninst, int s1, int a, int re dyn->inst_vl = 0; if (tozero) { vector_vsetvli(dyn, ninst, s1, VECTOR_SEW32, VECTOR_LMUL1, 2); - VECTOR_LOAD_VMASK(0xf0, s1, 2); - VMERGE_VXM(reg, reg, xZR); + VXOR_VV(VMASK, VMASK, VMASK, VECTOR_UNMASKED); + VSLIDEUP_VI(reg, VMASK, 4, VECTOR_UNMASKED); } else { vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); VECTOR_LOAD_VMASK(0xffff0000, s1, 2); @@ -2937,8 +2937,8 @@ void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a if (width == 32 && !dyn->e.ssecache[a].ymm) { if (dyn->e.ssecache[a].ymm0) { avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW32, 32); - VECTOR_LOAD_VMASK(0xf0, s1, 2); - VMERGE_VXM(low, low, xZR); + VXOR_VV(VMASK, VMASK, VMASK, VECTOR_UNMASKED); + VSLIDEUP_VI(low, VMASK, 4, VECTOR_UNMASKED); } else { dyn->inst_sew = VECTOR_SEWNA; dyn->inst_vl = 0; // real vtype here is unknown, never elide vsetvli @@ -2971,8 +2971,8 @@ void avx_store_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int dyn->e.extcache[EXTIDX(cache)].y = 1; if (width == 16) { avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW32, 32); - VECTOR_LOAD_VMASK(0xf0, s1, 2); - VMERGE_VXM(cache, cache, xZR); + VXOR_VV(VMASK, VMASK, VMASK, VECTOR_UNMASKED); + VSLIDEUP_VI(cache, VMASK, 4, VECTOR_UNMASKED); sse_set_pending_zero(dyn, a, 1); ymm_live_zero(dyn, ninst, a); } else { From 75ff158c4ca9fd72ed4094a376a56fd62e5701ce Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Mon, 19 Oct 2026 15:09:44 +0200 Subject: [PATCH 047/156] [ARM64_DYNAREC] Enlarged a buffer --- src/dynarec/arm64/dynarec_arm64_functions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dynarec/arm64/dynarec_arm64_functions.c b/src/dynarec/arm64/dynarec_arm64_functions.c index 271391e82..d8ec21222 100644 --- a/src/dynarec/arm64/dynarec_arm64_functions.c +++ b/src/dynarec/arm64/dynarec_arm64_functions.c @@ -767,7 +767,7 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r return; } - static char buf[4096]; + static char buf[8192]; int length = sprintf(buf, "barrier=%d state=%d/%s(%s->%s)/%c, set=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d/%d)", dyn->insts[ninst].x64.barrier, dyn->insts[ninst].x64.state_flags, From 3ee377b4448d991341943b0c45ccd7952b568f8f Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 20 Oct 2026 02:44:38 +0800 Subject: [PATCH 048/156] [RV64_DYNAREC] Added XMM/YMM preload support --- src/dynarec/dynarec_arch.h | 2 +- src/dynarec/dynarec_native_pass.c | 4 +- src/dynarec/rv64/dynarec_rv64_functions.c | 103 +++++++++++++++++++++- src/dynarec/rv64/dynarec_rv64_functions.h | 1 + src/dynarec/rv64/dynarec_rv64_helper.c | 25 ++++++ src/dynarec/rv64/dynarec_rv64_helper.h | 2 + src/dynarec/rv64/dynarec_rv64_private.h | 8 ++ 7 files changed, 139 insertions(+), 6 deletions(-) diff --git a/src/dynarec/dynarec_arch.h b/src/dynarec/dynarec_arch.h index e31923e9b..729e24d39 100644 --- a/src/dynarec/dynarec_arch.h +++ b/src/dynarec/dynarec_arch.h @@ -116,7 +116,7 @@ extern void la64_next_invalid(); #define RAZ_SPECIFIC(A, N) #define UPDATE_SPECIFICS(A) #define PREUPDATE_SPECIFICS(A) updateNativeFlags(A) -#define POSTUPDATE_SPECIFICS(A) +#define POSTUPDATE_SPECIFICS(A) updatePreloads(A) #define ARCH_SIZE(A) get_size_arch(A) #define ARCH_FILL(A, B, C) populate_arch(A, B, C) diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index 774160890..d5ce776ca 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -192,6 +192,8 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int if(!ninst) { if (BOX64DRENV(dynarec_callret) >= 2) doEnterBlock(dyn, 0, x1, x2, x3); + if (dyn->insts[0].preload_xmmymm) + doPreload(dyn, 0); } #endif fpu_propagate_stack(dyn, ninst); @@ -333,7 +335,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int else if (is_opcode_volatile && dyn->insts[ninst].will_read) DMB_ISHLD(); #endif - #if defined(ARM64) || defined(LA64) + #if defined(ARM64) || defined(LA64) || defined(RV64) if(dyn->insts[ninst].x64.has_next && dyn->insts[ninst+1].preload_xmmymm) { doPreload(dyn, ninst+1); } diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index eaf43497d..bd986bc95 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -30,10 +30,6 @@ #include "gdbjit.h" #include "perfmap.h" -#define XMM0 0 -#define X870 XMM0 + 16 -#define EMM0 XMM0 + 16 - static int fpu_scratch_vreg(int n) { if (n < 7) @@ -948,6 +944,105 @@ int isUpper32Zero(dynarec_rv64_t* dyn, int ninst, int reg) return 0; } +static uint32_t getUsedVectorMask(const dynarec_rv64_t* dyn, int first, int last) +{ + uint32_t ret = 0; + for (int i = first; i <= last && i < dyn->size; ++i) + ret |= dyn->insts[i].vec_used; + return ret; +} + +static int getFirstVectorUse(const dynarec_rv64_t* dyn, int first, int last, int reg) +{ + for (int i = first; i <= last && i < dyn->size; ++i) + if (dyn->insts[i].vec_used & (1u << reg)) + return i; + return -1; +} + +static void applyPreloadState(dynarec_rv64_t* dyn, int first, int first_use, int reg) +{ + for (int i = first; i < first_use; ++i) { + extcache_t* e = &dyn->insts[i].e; + sse_cache_t* s = &e->ssecache[reg]; + s->reg = VREG(reg); + s->vector = 1; + s->single = 0; + s->write = 0; + s->ymm = 0; + s->ymm0 = (e->ymm0 >> reg) & 1; + e->fpuused[EXTIDX(VREG(reg))] = 1; + sse_sync_cache_type(e, reg); + } +} + +void updatePreloads(dynarec_rv64_t* dyn) +{ + if (!cpuext.vector) + return; + for (int first = 0; first < dyn->size; ++first) { + if (dyn->insts[first].preload_xmmymm) + continue; + if (first) { + if (dyn->insts[first].pred_sz <= 1) + continue; + int has_linear = 0; + for (int j = 0; j < dyn->insts[first].pred_sz; ++j) + if (dyn->insts[first].pred[j] == first - 1) + has_linear = 1; + if (!has_linear) + continue; + } else if (!dyn->insts[first].pred_sz) { + continue; + } + int last = dyn->size + 1; + for (int j = 0; j < dyn->insts[first].pred_sz; ++j) { + int pred = dyn->insts[first].pred[j]; + if (pred != first - 1 && pred < last) + last = pred; + } + if (last > dyn->size || last <= first) + continue; + if (first && !dyn->insts[first - 1].x64.has_next) + continue; + int straight = 1; + for (int i = first; i < last && straight; ++i) { + const instruction_rv64_t* inst = &dyn->insts[i]; + if (!inst->x64.has_next || (inst->x64.barrier & BARRIER_FLOAT) + || inst->x64.has_callret) + straight = 0; + } + if (!straight) + continue; + uint32_t preload = getUsedVectorMask(dyn, first, last); + if (!preload) + continue; + uint32_t accepted = 0; + for (int reg = 0; reg < 16; ++reg) { + if (!(preload & (1u << reg))) + continue; + int first_use = getFirstVectorUse(dyn, first, last, reg); + if (first_use < 0) + continue; + int ok = 1; + int prev = first - 1; + if (prev >= 0 && dyn->insts[prev].e.ssecache[reg].v != -1) + ok = 0; + for (int i = first; i < first_use && ok; ++i) + if (dyn->insts[i].e.ssecache[reg].v != -1) + ok = 0; + if (ok && dyn->insts[first_use].e.ssecache[reg].v == -1) + ok = 0; + if (!ok) + continue; + applyPreloadState(dyn, first, first_use, reg); + accepted |= 1u << reg; + } + if (accepted) + dyn->insts[first].preload_xmmymm = accepted; + } +} + void updateUpperLiveness(dynarec_rv64_t* dyn) { int n = dyn->size; diff --git a/src/dynarec/rv64/dynarec_rv64_functions.h b/src/dynarec/rv64/dynarec_rv64_functions.h index 1901c8409..c59b858ff 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.h +++ b/src/dynarec/rv64/dynarec_rv64_functions.h @@ -71,6 +71,7 @@ int fpu_is_st_freed(dynarec_native_t* dyn, int ninst, int st); void updateNativeFlags(dynarec_rv64_t* dyn); void updateUpperLiveness(dynarec_rv64_t* dyn); +void updatePreloads(dynarec_rv64_t* dyn); int isUpper32Zero(dynarec_rv64_t* dyn, int ninst, int reg); void updateRspMerge(dynarec_rv64_t* dyn, int is32bits); void get_free_scratch(dynarec_rv64_t* dyn, int ninst, uint8_t* tmp1, uint8_t* tmp2, uint8_t* tmp3, uint8_t s1, uint8_t s2, uint8_t s3, uint8_t s4, uint8_t s5); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 3deb9f25b..5653d1667 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -1644,10 +1644,17 @@ static void mmx_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1) vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); } +static void sse_mark_used(dynarec_rv64_t* dyn, int ninst, int a) +{ + if (ninst >= 0 && ninst < dyn->size && a >= 0 && a < 16) + dyn->insts[ninst].vec_used |= 1u << a; +} + // SSE / SSE2 helpers // get ext register for a SSE reg, create the entry if needed int sse_get_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single) { + sse_mark_used(dyn, ninst, a); if (dyn->e.ssecache[a].v != -1) { if (dyn->e.ssecache[a].vector == 1) { // it's in the fpu, forget it first... @@ -1684,6 +1691,7 @@ int sse_get_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single) // get ext 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) { + sse_mark_used(dyn, ninst, a); if (dyn->e.ssecache[a].v != -1) { if (dyn->e.ssecache[a].vector == 1) { // it's in the vpu, forget it first... @@ -1770,6 +1778,7 @@ void sse_forget_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a) // get rvv register for a SSE reg, create the entry if needed int sse_get_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int forwrite, int sew) { + sse_mark_used(dyn, ninst, a); if (dyn->e.ssecache[a].v != -1) { if (dyn->e.ssecache[a].vector == 0) { // it's in the fpu, forget it first... @@ -1804,6 +1813,7 @@ int sse_get_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int forwri } int sse_get_reg_empty_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a) { + sse_mark_used(dyn, ninst, a); if (dyn->e.ssecache[a].v != -1) { if (dyn->e.ssecache[a].vector == 0) { // it's in the fpu, forget it first... @@ -2930,6 +2940,7 @@ void avx_set_vector_width(dynarec_rv64_t* dyn, int ninst, int s1, int sew, int w void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew) { + sse_mark_used(dyn, ninst, a); if (width == 32 && cpuext.vlen >= 32) ymm_live_read(dyn, ninst, a); avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 16); @@ -2960,6 +2971,7 @@ void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a void avx_store_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew) { + sse_mark_used(dyn, ninst, a); avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 16); int cache = sse_get_reg_empty_vector(dyn, ninst, s1, a); if (cache != vreg) { @@ -2983,6 +2995,19 @@ void avx_store_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int avx_set_vector_width(dyn, ninst, s1, sew, width); } +void doPreload(dynarec_rv64_t* dyn, int ninst) +{ + uint32_t preload = dyn->insts[ninst].preload_xmmymm; + if (!preload) + return; + MESSAGE(LOG_INFO, "Preload XMM/YMM -------- %x\n", preload); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); + for (int i = 0; i < 16; ++i) + if (preload & (1u << i)) + sse_get_reg_vector(dyn, ninst, x1, i, 0, VECTOR_SEW8); + MESSAGE(LOG_INFO, "-------- Preload XMM/YMM\n"); +} + // Simple wrapper for vsetvli, may use s1 as scratch int vector_vsetvli(dynarec_rv64_t* dyn, int ninst, int s1, int sew, int vlmul, float multiple) { diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 61bc9cf74..9fc88b9a8 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1863,6 +1863,7 @@ #define avx_store_reg_vector STEPNAME(avx_store_reg_vector) #define avx_flush_upper_vector STEPNAME(avx_flush_upper_vector) #define avx_sync_upper_vector STEPNAME(avx_sync_upper_vector) +#define doPreload STEPNAME(doPreload) #define avx_flush_pending_zero_vector STEPNAME(avx_flush_pending_zero_vector) #define fpu_pushcache STEPNAME(fpu_pushcache) @@ -2131,6 +2132,7 @@ void sse_reflect_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a); void avx_flush_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int reg, int next); void avx_sync_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next); void avx_flush_pending_zero_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next); +void doPreload(dynarec_rv64_t* dyn, int ninst); void avx_set_vector_width(dynarec_rv64_t* dyn, int ninst, int s1, int sew, int width); void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew); void avx_store_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew); diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index 572291277..cd724441d 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -163,6 +163,9 @@ typedef struct instruction_rv64_s { uint16_t up32_zero; // bitmask of GPRs guaranteed to be zero-extended at instruction exit uint16_t up32_skip; // bitmask of GPRs where the implicit zero-up after a 32-bit write can be skipped uint16_t up32_pending; // bitmask of GPRs whose upper 32 bits are stale at entry to this instruction + uint32_t vec_used; // bitmask of XMM/YMM registers touched by this instruction + uint32_t preload_xmmymm; // registers to preload at this instruction + int preload_from; // last instruction of the region that uses them uint16_t ymm_upper_use; // bitmask of YMM upper halves read by this instruction uint16_t ymm_upper_def; // bitmask of YMM upper halves written by this instruction uint16_t ymm_upper_live; // bitmask of YMM upper halves live after this instruction @@ -231,6 +234,11 @@ typedef struct dynarec_rv64_s { // convert reg index (8..31) to idx (0..23) #define EXTIDX(A) (((A) >= 16) ? ((A) - 16) : ((A) + 8)) +#define XMM0 0 +#define X870 (XMM0 + 16) +#define EMM0 (XMM0 + 16) +#define VREG(A) EXTREG(XMM0 + (A)) + static inline void sse_sync_cache_type(extcache_t* cache, int a) { sse_cache_t* e = &cache->ssecache[a]; From b9bf3c344dc9e3f1840e1fd8a748fbc479b2011d Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 20 Oct 2026 02:44:49 +0800 Subject: [PATCH 049/156] [RV64_DYNAREC] Raised MXCSR invalid flag on overflow --- src/dynarec/rv64/dynarec_rv64_0f.c | 2 ++ src/dynarec/rv64/dynarec_rv64_660f.c | 3 +++ src/dynarec/rv64/dynarec_rv64_f30f.c | 3 +++ src/dynarec/rv64/dynarec_rv64_helper.h | 7 +++++++ 4 files changed, 15 insertions(+) diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index e86f8f2ca..178b30f16 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -428,6 +428,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQ_MARKi(x5, xZR, i); + emit_mxcsr_raise_invalid(x5); MOV32w(x1, 0x80000000); MARKi(i); } @@ -451,6 +452,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQ_MARKi(x5, xZR, i); + emit_mxcsr_raise_invalid(x5); MOV32w(x1, 0x80000000); MARKi(i); } diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index 31b7a6ecb..60007c7de 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -209,6 +209,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQ_MARKi(x5, xZR, i); + emit_mxcsr_raise_invalid(x5); MOV32w(x1, 0x80000000); MARKi(i); } @@ -232,6 +233,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQ_MARKi(x5, xZR, i); + emit_mxcsr_raise_invalid(x5); MOV32w(x1, 0x80000000); MARKi(i); } @@ -2337,6 +2339,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQ_MARK(x5, xZR); + emit_mxcsr_raise_invalid(x5); MOV32w(x3, 0x80000000); MARK; FSFLAGSI(0); // // reset all bits diff --git a/src/dynarec/rv64/dynarec_rv64_f30f.c b/src/dynarec/rv64/dynarec_rv64_f30f.c index a815f038e..ef87cefe4 100644 --- a/src/dynarec/rv64/dynarec_rv64_f30f.c +++ b/src/dynarec/rv64/dynarec_rv64_f30f.c @@ -146,6 +146,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); CBZ_NEXT(x5); + emit_mxcsr_raise_invalid(x5); if (rex.w) { MOV64x(gd, 0x8000000000000000LL); } else { @@ -170,6 +171,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); CBZ_NEXT(x5); + emit_mxcsr_raise_invalid(x5); if (rex.w) { MOV64x(gd, 0x8000000000000000LL); } else { @@ -387,6 +389,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQZ_MARKi(x5, i); + emit_mxcsr_raise_invalid(x5); MOV32w(x3, 0x80000000); MARKi(i); } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 9fc88b9a8..838263e37 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -2137,6 +2137,13 @@ void avx_set_vector_width(dynarec_rv64_t* dyn, int ninst, int s1, int sew, int w void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew); void avx_store_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew); +#define emit_mxcsr_raise_invalid(s1) \ + do { \ + LW(s1, xEmu, offsetof(x64emu_t, mxcsr)); \ + ORI(s1, s1, 1); \ + SW(s1, xEmu, offsetof(x64emu_t, mxcsr)); \ + } while (0) + static inline void sse_set_pending_zero(dynarec_rv64_t* dyn, int a, int pending) { if (dyn->e.ssecache[a].v != -1) From 30449e9255143751d0aaf79a0b6a3ec2ee315ca6 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 20 Oct 2026 02:45:12 +0800 Subject: [PATCH 050/156] [RV64_DYNAREC] Fixed YMM upper 128-bit writeback --- src/dynarec/rv64/dynarec_rv64_helper.c | 46 ++++++++++++++++---------- src/dynarec/rv64/dynarec_rv64_helper.h | 2 +- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 5653d1667..0a4756f1e 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -1856,7 +1856,7 @@ void sse_forget_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a) vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); ADDI(s1, xEmu, offsetof(x64emu_t, xmm[a])); VSE8_V(dyn->e.ssecache[a].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); - avx_flush_upper_vector(dyn, ninst, s1, a, dyn->e.ssecache[a].reg, 0); + avx_flush_upper_vector(dyn, ninst, s1, a, dyn->e.ssecache[a].reg, 0, 1); vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); } fpu_free_reg(dyn, dyn->e.ssecache[a].reg); @@ -1886,7 +1886,7 @@ void sse_purge07cache(dynarec_rv64_t* dyn, int ninst, int s1) flushed8 = 1; ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VSE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); - avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, 0); + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, 0, 1); } else if (dyn->e.ssecache[i].single) FSW(dyn->e.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i])); else @@ -1921,7 +1921,7 @@ static void sse_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1) ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VSE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); } - avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, next); + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, next, !next); } else if (dyn->e.ssecache[i].single) FSW(dyn->e.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i])); else @@ -1956,7 +1956,7 @@ static void sse_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1) flushed8 = 1; ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VSE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); - avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, 0); + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, 0, 1); } else if (dyn->e.ssecache[i].single) FSW(dyn->e.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i])); else @@ -2043,7 +2043,7 @@ void fpu_pushcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07) flushed8 = 1; ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VSE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); - avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, 0); + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, 0, 1); } } if (flushed8) @@ -2438,7 +2438,7 @@ static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, i vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); } if (t == EXT_CACHE_YMMW) - avx_flush_upper_vector(dyn, ninst, s1, n, reg, 1); + avx_flush_upper_vector(dyn, ninst, s1, n, reg, 1, 1); break; case EXT_CACHE_SS: MESSAGE(LOG_DUMP, "\t - Unloading %s\n", getCacheName(t, n)); @@ -2613,7 +2613,7 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in cache.ssecache[cache.extcache[i].n].write = 1; } else if (cache.extcache[i].t == EXT_CACHE_YMMW && cache_i2.extcache[i].t == EXT_CACHE_YMMR) { MESSAGE(LOG_DUMP, "\t - Store %s\n", getCacheName(cache.extcache[i].t, cache.extcache[i].n)); - avx_flush_upper_vector(dyn, ninst, s1, cache.extcache[i].n, EXTREG(i), 1); + avx_flush_upper_vector(dyn, ninst, s1, cache.extcache[i].n, EXTREG(i), 1, 0); SET_CACHE_VECTOR_WIDTH(s1); ADDI(s1, xEmu, offsetof(x64emu_t, xmm[cache.extcache[i].n])); VSE_V(EXTREG(i), s1, dyn->vector_eew, VECTOR_UNMASKED, VECTOR_NFIELD1); @@ -2638,7 +2638,7 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in loadUpperCache(dyn, ninst, s1, n, EXTREG(i), (cache_i2.ymm0 >> n) & 1); } else if (src_ymm) { MESSAGE(LOG_DUMP, "\t - Storing upper half of %s\n", getCacheName(cache.extcache[i].t, n)); - avx_flush_upper_vector(dyn, ninst, s1, n, EXTREG(i), 1); + avx_flush_upper_vector(dyn, ninst, s1, n, EXTREG(i), 1, 0); } cache.extcache[i].y = dst_ymm; } @@ -2886,22 +2886,32 @@ void fpu_propagate_stack(dynarec_rv64_t* dyn, int ninst) dyn->e.swapped = 0; } -void avx_flush_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int reg, int next) +void avx_flush_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int reg, int next, int dead) { uint8_t sew0, vlmul0, vl0; vector_save_vtype(dyn, &sew0, &vlmul0, &vl0); - dyn->inst_sew = VECTOR_SEWNA; - dyn->inst_vl = 0; // real vtype here is unknown, never elide vsetvli if (dyn->e.ssecache[a].ymm0) { // the architectural upper half is zero: write it with scalar stores, no vector state needed SD(xZR, xEmu, offsetof(x64emu_t, ymm[a]) + 0); SD(xZR, xEmu, offsetof(x64emu_t, ymm[a]) + 8); - } else if (dyn->e.ssecache[a].ymm) { - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); - VECTOR_LOAD_VMASK(0xffff0000, s1, 2); - ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a]) - 16); - VSE8_V(reg, s1, VECTOR_MASKED, VECTOR_NFIELD1); - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + } else if (dyn->e.ssecache[a].ymm && dyn->e.ssecache[a].write) { + if (dead || dyn->e.fpu_scratch < 7) { + int sp = dyn->e.fpu_scratch; + int tmp = dead ? reg : fpu_get_scratch(dyn); + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + VSLIDEDOWN_VI(tmp, reg, 16, VECTOR_UNMASKED); + ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a])); + VSE8_V(tmp, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + dyn->e.fpu_scratch = sp; + } else { + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VECTOR_LOAD_VMASK(0xffff0000, s1, 2); + ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a]) - 16); + VSE8_V(reg, s1, VECTOR_MASKED, VECTOR_NFIELD1); + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + } } else return; if (!next) dyn->e.ssecache[a].ymm = 0; @@ -2928,7 +2938,7 @@ void avx_sync_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next) return; for (int i = 0; i < 16; ++i) if (dyn->e.ssecache[i].v != -1 && dyn->e.ssecache[i].vector) - avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, next); + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, next, 0); avx_flush_pending_zero_vector(dyn, ninst, s1, next); } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 838263e37..3680a42eb 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -2129,7 +2129,7 @@ void sse_purge07cache(dynarec_rv64_t* dyn, int ninst, int s1); // Push current value to the cache void sse_reflect_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a); -void avx_flush_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int reg, int next); +void avx_flush_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int reg, int next, int dead); void avx_sync_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next); void avx_flush_pending_zero_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next); void doPreload(dynarec_rv64_t* dyn, int ninst); From d166be5dcc387c487c64eabb5f9e017c0c344a96 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 20 Oct 2026 02:46:43 +0800 Subject: [PATCH 051/156] [RV64_DYNAREC] Restricted AES vector path to 128-bit operands --- src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c index 57a406a90..7eb30d766 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c @@ -2186,7 +2186,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDC: INST_NAME("VAESENC Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && cpuext.vlen >= 32) { + if (cpuext.zvkned && cpuext.vlen >= 32 && !vex.l) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); @@ -2258,7 +2258,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDD: INST_NAME("VAESENCLAST Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && cpuext.vlen >= 32) { + if (cpuext.zvkned && cpuext.vlen >= 32 && !vex.l) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); @@ -2333,7 +2333,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i if (vex.l) { DEFAULT; } - if (cpuext.zvkned && cpuext.vlen >= 32) { + if (cpuext.zvkned && cpuext.vlen >= 32 && !vex.l) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v1 = fpu_get_scratch(dyn); @@ -2365,7 +2365,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDE: INST_NAME("VAESDEC Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && cpuext.vlen >= 32) { + if (cpuext.zvkned && cpuext.vlen >= 32 && !vex.l) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); @@ -2444,7 +2444,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDF: INST_NAME("VAESDECLAST Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && cpuext.vlen >= 32) { + if (cpuext.zvkned && cpuext.vlen >= 32 && !vex.l) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); From d11def2d5be76d8a3ab53590f96f39b7b08d6650 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 20 Oct 2026 02:46:43 +0800 Subject: [PATCH 052/156] [RV64_DYNAREC] Kept vtype across linear instructions --- src/dynarec/rv64/dynarec_rv64_pass2.h | 21 +++++++++++---------- src/dynarec/rv64/dynarec_rv64_pass3.h | 17 +++++++++-------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_pass2.h b/src/dynarec/rv64/dynarec_rv64_pass2.h index 3d64efca1..933f3581f 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass2.h +++ b/src/dynarec/rv64/dynarec_rv64_pass2.h @@ -15,23 +15,24 @@ dyn->native_size += 4; \ } while (0) #define NEW_INST \ + if (!(ninst > 0 && dyn->insts[ninst].pred_sz == 1 && dyn->insts[ninst].pred[0] == ninst - 1 \ + && dyn->insts[ninst - 1].x64.has_next && !dyn->insts[ninst - 1].x64.jmp \ + && !(dyn->insts[ninst - 1].x64.barrier & BARRIER_FLOAT) && !dyn->insts[ninst - 1].x64.has_callret)) { \ + dyn->inst_sew = dyn->insts[ninst].vector_sew_entry; \ + dyn->inst_vlmul = VECTOR_LMUL1; \ + dyn->inst_vl = 0; \ + } \ dyn->vector_sew = dyn->insts[ninst].vector_sew_entry; \ - dyn->inst_sew = dyn->vector_sew; \ - dyn->inst_vlmul = VECTOR_LMUL1; \ - dyn->inst_vl = 0; \ if (ninst) { \ dyn->insts[ninst].address = (dyn->insts[ninst - 1].address + dyn->insts[ninst - 1].size); \ dyn->insts_size += 1 + ((dyn->insts[ninst - 1].x64.size > (dyn->insts[ninst - 1].size / 4)) ? dyn->insts[ninst - 1].x64.size : (dyn->insts[ninst - 1].size / 4)) / 15; \ dyn->insts[ninst].ymm0_pass2 = dyn->ymm_zero; \ } \ AREFLAGSNEEDED() -#define INST_EPILOG \ - dyn->insts[ninst].epilog = dyn->native_size; \ - sse_sync_all_cache_types(&dyn->e); \ - dyn->vector_sew = dyn->insts[ninst].vector_sew_exit; \ - dyn->inst_sew = dyn->vector_sew; \ - dyn->inst_vlmul = VECTOR_LMUL1; \ - dyn->inst_vl = 0; +#define INST_EPILOG \ + dyn->insts[ninst].epilog = dyn->native_size; \ + sse_sync_all_cache_types(&dyn->e); \ + dyn->vector_sew = dyn->insts[ninst].vector_sew_exit; #define INST_NAME(name) #define TABLE64(A, V) \ do { \ diff --git a/src/dynarec/rv64/dynarec_rv64_pass3.h b/src/dynarec/rv64/dynarec_rv64_pass3.h index 715480434..7dd58213a 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass3.h +++ b/src/dynarec/rv64/dynarec_rv64_pass3.h @@ -18,21 +18,22 @@ if (dyn->need_dump && dyn->need_dump != 3) dynarec_log(LOG_NONE, __VA_ARGS__); \ } while (0) #define NEW_INST \ + if (!(ninst > 0 && dyn->insts[ninst].pred_sz == 1 && dyn->insts[ninst].pred[0] == ninst - 1 \ + && dyn->insts[ninst - 1].x64.has_next && !dyn->insts[ninst - 1].x64.jmp \ + && !(dyn->insts[ninst - 1].x64.barrier & BARRIER_FLOAT) && !dyn->insts[ninst - 1].x64.has_callret)) { \ + dyn->inst_sew = dyn->insts[ninst].vector_sew_entry; \ + dyn->inst_vlmul = VECTOR_LMUL1; \ + dyn->inst_vl = 0; \ + } \ dyn->vector_sew = dyn->insts[ninst].vector_sew_entry; \ - dyn->inst_sew = dyn->vector_sew; \ - dyn->inst_vlmul = VECTOR_LMUL1; \ - dyn->inst_vl = 0; \ if (ninst) { \ addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst - 1].x64.size, dyn->insts[ninst - 1].size / 4); \ dyn->insts[ninst].ymm0_pass3 = dyn->ymm_zero; \ } \ sse_sync_all_cache_types(&dyn->e); \ AREFLAGSNEEDED() -#define INST_EPILOG \ - dyn->vector_sew = dyn->insts[ninst].vector_sew_exit; \ - dyn->inst_sew = dyn->vector_sew; \ - dyn->inst_vlmul = VECTOR_LMUL1; \ - dyn->inst_vl = 0; +#define INST_EPILOG \ + dyn->vector_sew = dyn->insts[ninst].vector_sew_exit; #define INST_NAME(name) inst_name_pass3(dyn, ninst, name, rex) #define TABLE64(A, V) \ From 2c3ac5ff080efd729e507f5e6558b3954c9201b6 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 20 Oct 2026 02:46:43 +0800 Subject: [PATCH 053/156] [RV64_DYNAREC] Forced vsetvli in SSE cache purge --- src/dynarec/rv64/dynarec_rv64_helper.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 0a4756f1e..b30770fb2 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -1908,6 +1908,8 @@ static void sse_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1) uint8_t sew, vlmul, vl; int flushed8 = 0; vector_save_vtype(dyn, &sew, &vlmul, &vl); + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; for (int i = 0; i < 16; ++i) if (dyn->e.ssecache[i].v != -1) { if (old == -1) { From 259ba9f5544110c3c2cd5b4cea9214433f1c5434 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 20 Oct 2026 02:47:04 +0800 Subject: [PATCH 054/156] [RV64_DYNAREC] Used encoded registers for AVX vector operands --- .../rv64/dynarec_rv64_avx_66_0f38_vector.c | 12 +++++ .../rv64/dynarec_rv64_avx_66_0f_vector.c | 3 +- src/dynarec/rv64/dynarec_rv64_helper.h | 48 ++++++++----------- 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c index abd68ae01..b54b6bef6 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c @@ -285,6 +285,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 8 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_SAFE(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16 << vex.l); VSEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); @@ -294,6 +295,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 4 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_SAFE(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VSEXT_VF4(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -303,6 +305,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 2 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_SAFE(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VSEXT_VF8(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -312,6 +315,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW16, 8 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_SAFE(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VSEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -321,6 +325,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW16, 4 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_SAFE(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VSEXT_VF4(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -330,6 +335,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW32, 8 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_SAFE(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VSEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -477,6 +483,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 8 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_SAFE(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16 << vex.l); VZEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); @@ -486,6 +493,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 4 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_SAFE(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VZEXT_VF4(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -495,6 +503,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 2 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_SAFE(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VZEXT_VF8(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -504,6 +513,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW16, 8 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_SAFE(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VZEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -513,6 +523,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW16, 4 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_SAFE(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VZEXT_VF4(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -522,6 +533,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW32, 8 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_SAFE(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VZEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index ceeca6545..b4e205968 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -565,8 +565,9 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt nextop = F8; GETEY_vector(q1, 1, VECTOR_SEW32); GETGY_empty_vector(v0); + VEC_SRC_SAFE(q1, v0); u8 = F8; - q2 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL1); { uint32_t sel_lo = (u8 & 3) | (((u8 >> 2) & 3) << 16); uint32_t sel_hi = ((u8 >> 4) & 3) | (((u8 >> 6) & 3) << 16); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 3680a42eb..67f0add5a 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -598,40 +598,17 @@ #define GETVY_vector(a, sew) \ do { \ - a = fpu_get_scratch(dyn); \ + a = VREG(vex.v); \ avx_load_reg_vector(dyn, ninst, x1, a, vex.v, 16 << vex.l, sew); \ } while (0) #define GETGY_vector(a, sew) \ do { \ gd = ((nextop & 0x38) >> 3) + (rex.r << 3); \ - a = fpu_get_scratch(dyn); \ + a = VREG(gd); \ avx_load_reg_vector(dyn, ninst, x1, a, gd, 16 << vex.l, sew); \ } while (0) -#define GETVY_vector_cached(a, sew) \ - do { \ - if (vex.l) { \ - a = fpu_get_scratch(dyn); \ - avx_load_reg_vector(dyn, ninst, x1, a, vex.v, 16 << vex.l, sew); \ - } else { \ - avx_set_vector_width(dyn, ninst, x1, sew, 16); \ - a = sse_get_reg_vector(dyn, ninst, x1, vex.v, 0, sew); \ - } \ - } while (0) - -#define GETGY_vector_cached(a, sew) \ - do { \ - gd = ((nextop & 0x38) >> 3) + (rex.r << 3); \ - if (vex.l) { \ - a = fpu_get_scratch(dyn); \ - avx_load_reg_vector(dyn, ninst, x1, a, gd, 16 << vex.l, sew); \ - } else { \ - avx_set_vector_width(dyn, ninst, x1, sew, 16); \ - a = sse_get_reg_vector(dyn, ninst, x1, gd, 0, sew); \ - } \ - } while (0) - #define GETGY_empty_vector(a) \ do { \ gd = ((nextop & 0x38) >> 3) + (rex.r << 3); \ @@ -640,11 +617,12 @@ #define GETEY_vector(a, D, sew) \ do { \ - a = fpu_get_scratch(dyn); \ if (MODREG) { \ + a = VREG((nextop & 7) + (rex.b << 3)); \ avx_load_reg_vector(dyn, ninst, x1, a, (nextop & 7) + (rex.b << 3), \ 16 << vex.l, sew); \ } else { \ + a = fpu_get_scratch(dyn); \ SMREAD(); \ addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, D); \ SET_AVX_VECTOR_WIDTH(x1, sew); \ @@ -655,10 +633,11 @@ // Get EY as a 128bits vector, even if vex.l is set #define GETEY128_vector(a, D, sew) \ do { \ - a = fpu_get_scratch(dyn); \ if (MODREG) { \ - avx_load_reg_vector(dyn, ninst, x1, a, (nextop & 7) + (rex.b << 3), 16, sew); \ + a = VREG((nextop & 7) + (rex.b << 3)); \ + avx_load_reg_vector(dyn, ninst, x1, a, (nextop & 7) + (rex.b << 3), 16, sew); \ } else { \ + a = fpu_get_scratch(dyn); \ SMREAD(); \ addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, D); \ avx_set_vector_width(dyn, ninst, x1, sew, 16); \ @@ -667,13 +646,24 @@ SET_AVX_VECTOR_WIDTH(x1, sew); \ } while (0) +#define VEC_SRC_SAFE(a, dst) \ + do { \ + if ((a) == (dst)) { \ + int safe_ = fpu_get_scratch(dyn); \ + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16 << vex.l); \ + VMV_V_V(safe_, (a)); \ + (a) = safe_; \ + } \ + } while (0) + // Get EY as a vector of w bytes (for instructions whose source operand is narrower than the destination) #define GETEY_vector_w(a, D, sew, w) \ do { \ - a = fpu_get_scratch(dyn); \ if (MODREG) { \ + a = VREG((nextop & 7) + (rex.b << 3)); \ avx_load_reg_vector(dyn, ninst, x1, a, (nextop & 7) + (rex.b << 3), w, sew); \ } else { \ + a = fpu_get_scratch(dyn); \ SMREAD(); \ addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, D); \ avx_set_vector_width(dyn, ninst, x1, sew, w); \ From d0c7da583d4ec1fee3aee8bd3d10ce3a65303005 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 20 Oct 2026 02:47:17 +0800 Subject: [PATCH 055/156] [RV64_DYNAREC] Added combined VY/EY/GY vector load macros --- src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c | 48 +--- .../rv64/dynarec_rv64_avx_66_0f38_vector.c | 138 +++------- .../rv64/dynarec_rv64_avx_66_0f3a_vector.c | 51 ++-- .../rv64/dynarec_rv64_avx_66_0f_vector.c | 254 +++++------------- src/dynarec/rv64/dynarec_rv64_helper.h | 28 ++ 5 files changed, 178 insertions(+), 341 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index e7c3c4c50..a05bd39f4 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -103,9 +103,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x14: INST_NAME("VUNPCKLPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -122,9 +120,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x15: INST_NAME("VUNPCKHPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -256,18 +252,14 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x54: INST_NAME("VANDPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VAND_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x55: INST_NAME("VANDNPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW32); VXOR_VI(v0, q0, 0x1f, VECTOR_UNMASKED); VAND_VV(v0, v0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -275,18 +267,14 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x56: INST_NAME("VORPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VOR_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x57: INST_NAME("VXORPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VXOR_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; @@ -294,9 +282,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VADDPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VFADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; @@ -304,9 +290,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VMULPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VFMUL_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; @@ -345,18 +329,14 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VSUBPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VFSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x5D: INST_NAME("VMINPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); VMERGE_VVM(v0, q1, q0); PUTGY_vector(v0, VECTOR_SEW32); @@ -365,18 +345,14 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VDIVPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VFDIV_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x5F: INST_NAME("VMAXPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); VMERGE_VVM(v0, q1, q0); PUTGY_vector(v0, VECTOR_SEW32); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c index b54b6bef6..232364903 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c @@ -44,9 +44,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VPSHUFB Gx, Vx, Ex"); BARRIER(BARRIER_FLOAT); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); q2 = fpu_get_scratch(dyn); @@ -66,9 +64,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x08: INST_NAME("VPSIGNB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW8); VMV_V_V(v0, q0); VMSLT_VX(VMASK, q1, xZR, VECTOR_UNMASKED); VRSUB_VX(v0, q0, xZR, VECTOR_MASKED); @@ -79,9 +75,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x09: INST_NAME("VPSIGNW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW16); VMV_V_V(v0, q0); VMSLT_VX(VMASK, q1, xZR, VECTOR_UNMASKED); VRSUB_VX(v0, q0, xZR, VECTOR_MASKED); @@ -92,9 +86,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x0A: INST_NAME("VPSIGND Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW32); VMV_V_V(v0, q0); VMSLT_VX(VMASK, q1, xZR, VECTOR_UNMASKED); VRSUB_VX(v0, q0, xZR, VECTOR_MASKED); @@ -105,9 +97,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x0B: INST_NAME("VPMULHRSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VWMUL_VV(q2, q0, q1, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL2, 2 << vex.l); @@ -120,30 +110,28 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x0C: INST_NAME("VPERMILPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch(dyn); + q3 = fpu_get_scratch(dyn); VID_V(q2, VECTOR_UNMASKED); VAND_VI(q2, q2, 4, VECTOR_UNMASKED); - VAND_VI(q1, q1, 3, VECTOR_UNMASKED); - VADD_VV(q1, q1, q2, VECTOR_UNMASKED); - VRGATHER_VV_SAFE(v0, q0, q1, VECTOR_UNMASKED); + VAND_VI(q3, q1, 3, VECTOR_UNMASKED); + VADD_VV(q3, q3, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q0, q3, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x0D: INST_NAME("VPERMILPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); q2 = fpu_get_scratch(dyn); + q3 = fpu_get_scratch(dyn); VID_V(q2, VECTOR_UNMASKED); VAND_VI(q2, q2, 2, VECTOR_UNMASKED); - VSRL_VI(q1, q1, 1, VECTOR_UNMASKED); - VAND_VI(q1, q1, 1, VECTOR_UNMASKED); - VADD_VV(q1, q1, q2, VECTOR_UNMASKED); - VRGATHER_VV_SAFE(v0, q0, q1, VECTOR_UNMASKED); + VSRL_VI(q3, q1, 1, VECTOR_UNMASKED); + VAND_VI(q3, q3, 1, VECTOR_UNMASKED); + VADD_VV(q3, q3, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q0, q3, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x0E: @@ -181,11 +169,10 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (!vex.l) return 0; INST_NAME("VPERMPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); - VAND_VI(q0, q0, 7, VECTOR_UNMASKED); - VRGATHER_VV_SAFE(v0, q1, q0, VECTOR_UNMASKED); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + q2 = fpu_get_scratch(dyn); + VAND_VI(q2, q0, 7, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q1, q2, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x18: @@ -343,9 +330,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x28: INST_NAME("VPMULDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); VID_V(v2, VECTOR_UNMASKED); @@ -361,9 +346,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x29: INST_NAME("VPCMPEQQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VMSEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -383,9 +366,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x2B: INST_NAME("VPACKUSDW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VMAX_VX(q2, q0, xZR, VECTOR_UNMASKED); @@ -542,19 +523,16 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (!vex.l) return 0; INST_NAME("VPERMD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); - VAND_VI(q0, q0, 7, VECTOR_UNMASKED); - VRGATHER_VV_SAFE(v0, q1, q0, VECTOR_UNMASKED); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + q2 = fpu_get_scratch(dyn); + VAND_VI(q2, q0, 7, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q1, q2, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x37: INST_NAME("VPCMPGTQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VMSLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -563,81 +541,63 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x38: INST_NAME("VPMINSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VMIN_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0x39: INST_NAME("VPMINSD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMIN_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x3D: INST_NAME("VPMAXSD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMAX_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x3A: INST_NAME("VPMINUW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMINU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0x3B: INST_NAME("VPMINUD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMINU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x3C: INST_NAME("VPMAXSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VMAX_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0x3E: INST_NAME("VPMAXUW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMAXU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0x3F: INST_NAME("VPMAXUD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMAXU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x40: INST_NAME("VPMULLD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMUL_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; @@ -645,20 +605,14 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VPSRLVD/Q Gx, Vx, Ex"); nextop = F8; if (rex.w) { - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); - if (v0 == q0) v0 = fpu_get_scratch(dyn); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW64); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); MOV32w(x4, 64); VMSLTU_VX(VMASK, q1, x4, VECTOR_UNMASKED); VSRL_VV(v0, q0, q1, VECTOR_MASKED); PUTGY_vector(v0, VECTOR_SEW64); } else { - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); - if (v0 == q0) v0 = fpu_get_scratch(dyn); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW32); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); MOV32w(x4, 32); VMSLTU_VX(VMASK, q1, x4, VECTOR_UNMASKED); @@ -670,9 +624,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (rex.w) return 0; INST_NAME("VPSRAVD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch(dyn); MOV32w(x4, 31); VMINU_VX(q2, q1, x4, VECTOR_UNMASKED); @@ -683,20 +635,14 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VPSLLVD/Q Gx, Vx, Ex"); nextop = F8; if (rex.w) { - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); - if (v0 == q0) v0 = fpu_get_scratch(dyn); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW64); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); MOV32w(x4, 64); VMSLTU_VX(VMASK, q1, x4, VECTOR_UNMASKED); VSLL_VV(v0, q0, q1, VECTOR_MASKED); PUTGY_vector(v0, VECTOR_SEW64); } else { - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); - if (v0 == q0) v0 = fpu_get_scratch(dyn); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW32); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); MOV32w(x4, 32); VMSLTU_VX(VMASK, q1, x4, VECTOR_UNMASKED); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c index 2f6964e7e..09b0a1277 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c @@ -79,9 +79,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x02: INST_NAME("VPBLENDD Gx, Vx, Ex, Imm8"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 1, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW32, 1); u8 = F8; VECTOR_LOAD_VMASK(vex.l ? u8 : (u8 & 0xf), x4, vex.l ? 2 : 1); q2 = fpu_get_scratch(dyn); @@ -128,11 +126,20 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (!vex.l) return 0; INST_NAME("VPERM2F128 Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 1, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW8, 1); u8 = F8; q2 = fpu_get_scratch(dyn); + q3 = fpu_get_scratch(dyn); + if (q0 == v0) { + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q0); + q0 = q4; + } + if (q1 == v0) { + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q1); + q1 = q4; + } VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); for (int i = 0; i < 2; ++i) { int control = i ? (u8 >> 4) : u8; @@ -164,11 +171,8 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x0E: INST_NAME("VPBLENDW Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 1, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW16, 1); u8 = F8; - VMV_V_V(v0, q0); VECTOR_LOAD_VMASK(u8 | (vex.l ? (u8 << 8) : 0), x4, vex.l ? 2 : 1); VMERGE_VVM(v0, q0, q1); PUTGY_vector(v0, VECTOR_SEW16); @@ -300,9 +304,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x42: INST_NAME("VMPSADBW Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 1, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW8, 1); u8 = F8; int q3 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); int q4 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); @@ -365,11 +367,20 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (!vex.l) return 0; INST_NAME("VPERM2I128 Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 1, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW8, 1); u8 = F8; q2 = fpu_get_scratch(dyn); + q3 = fpu_get_scratch(dyn); + if (q0 == v0) { + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q0); + q0 = q4; + } + if (q1 == v0) { + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q1); + q1 = q4; + } VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); for (int i = 0; i < 2; ++i) { int control = i ? (u8 >> 4) : u8; @@ -620,9 +631,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x0C: INST_NAME("VBLENDPS Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 1, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW32, 1); u8 = F8; VECTOR_LOAD_VMASK(vex.l ? u8 : (u8 & 0xf), x4, vex.l ? 2 : 1); q2 = fpu_get_scratch(dyn); @@ -834,9 +843,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x40: { INST_NAME("VDPPS Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 1, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW32, 1); u8 = F8; SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); q3 = fpu_get_scratch(dyn); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index b4e205968..a17d2d0a1 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -92,9 +92,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x14: INST_NAME("VUNPCKLPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -109,9 +107,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x15: INST_NAME("VUNPCKHPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -215,18 +211,14 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x54: INST_NAME("VANDPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VAND_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x55: INST_NAME("VANDNPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW64); VXOR_VI(v0, q0, 0x1f, VECTOR_UNMASKED); VAND_VV(v0, v0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -234,18 +226,14 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x56: INST_NAME("VORPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VOR_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x57: INST_NAME("VXORPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VXOR_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; @@ -253,9 +241,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VADDPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VFADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; @@ -263,9 +249,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VMULPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VFMUL_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; @@ -308,18 +292,14 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VSUBPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VFSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x5D: INST_NAME("VMINPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); VMERGE_VVM(v0, q1, q0); PUTGY_vector(v0, VECTOR_SEW64); @@ -328,18 +308,14 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VDIVPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VFDIV_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x5F: INST_NAME("VMAXPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); VMERGE_VVM(v0, q1, q0); PUTGY_vector(v0, VECTOR_SEW64); @@ -347,9 +323,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x60: INST_NAME("VPUNPCKLBW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -368,9 +342,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x61: INST_NAME("VPUNPCKLWD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -388,9 +360,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x62: INST_NAME("VPUNPCKLDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -409,9 +379,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (vex.l) return 0; INST_NAME("VPACKSSWB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); VMV_V_V(q2, q0); @@ -423,9 +391,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x68: INST_NAME("VPUNPCKHBW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -445,9 +411,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x69: INST_NAME("VPUNPCKHWD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -466,9 +430,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x6A: INST_NAME("VPUNPCKHDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -488,9 +450,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (vex.l) return 0; INST_NAME("VPACKSSDW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 32); VMV_V_V(q2, q0); @@ -503,9 +463,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (vex.l) return 0; INST_NAME("VPACKUSWB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); VMAX_VX(q2, q0, xZR, VECTOR_UNMASKED); @@ -520,9 +478,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (vex.l) return 0; INST_NAME("VPUNPCKLQDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW64); VMV_V_V(v0, q0); VSLIDEUP_VI_SAFE(v0, q1, 1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -531,9 +487,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (vex.l) return 0; INST_NAME("VPUNPCKHQDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); VSLIDEDOWN_VI(q2, q0, 1, VECTOR_UNMASKED); @@ -759,9 +713,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x64: INST_NAME("VPCMPGTB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VMSLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -770,9 +722,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x65: INST_NAME("VPCMPGTW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMSLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -781,9 +731,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x66: INST_NAME("VPCMPGTD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMSLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -800,9 +748,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x74: INST_NAME("VPCMPEQB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VMSEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -811,9 +757,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x75: INST_NAME("VPCMPEQW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMSEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -822,9 +766,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x76: INST_NAME("VPCMPEQD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMSEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -850,9 +792,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VADDSUBPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); q2 = fpu_get_scratch(dyn); VID_V(q2, VECTOR_UNMASKED); VAND_VI(q2, q2, 1, VECTOR_UNMASKED); @@ -926,27 +866,21 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD4: INST_NAME("VPADDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0xD5: INST_NAME("VPMULLW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMUL_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xD8: INST_NAME("VPSUBUSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); q2 = fpu_get_scratch(dyn); VMSLTU_VV(VMASK, q0, q1, VECTOR_UNMASKED); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -957,9 +891,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD9: INST_NAME("VPSUBUSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch(dyn); VMSLTU_VV(VMASK, q0, q1, VECTOR_UNMASKED); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -970,54 +902,42 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xDA: INST_NAME("VPMINUB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VMINU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0xDB: INST_NAME("VPAND Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VAND_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0xDC: INST_NAME("VPADDUSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VSADDU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0xDD: INST_NAME("VPADDUSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VSADDU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xDE: INST_NAME("VPMAXUB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VMAXU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0xDF: INST_NAME("VPANDN Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW64); VXOR_VI(v0, q0, 0x1f, VECTOR_UNMASKED); VAND_VV(v0, v0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -1025,9 +945,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xE0: INST_NAME("VPAVGB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); CSRRWI(xZR, 0b00, 0x00A); VAADDU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); @@ -1035,9 +953,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xE3: INST_NAME("VPAVGW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); CSRRWI(xZR, 0b00, 0x00A); VAADDU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); @@ -1045,18 +961,14 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xE4: INST_NAME("VPMULHUW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMULHU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xE5: INST_NAME("VPMULHW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMULH_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; @@ -1073,79 +985,63 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xE8: INST_NAME("VPSUBSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VSSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0xE9: INST_NAME("VPSUBSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VSSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xEA: INST_NAME("VPMINSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMIN_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xEB: INST_NAME("VPOR Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VOR_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0xEC: INST_NAME("VPADDSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VSADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0xED: INST_NAME("VPADDSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VSADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xEE: INST_NAME("VPMAXSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMAX_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xEF: INST_NAME("VPXOR Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VXOR_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0xF1: INST_NAME("VPSLLW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); + GETVY_vector(q0, VECTOR_SEW16); GETEY128_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMV_X_S(x4, q1); @@ -1186,21 +1082,19 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xF4: INST_NAME("VPMULUDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); MOV64x(x2, 0xffffffffULL); - VAND_VX(q0, q0, x2, VECTOR_UNMASKED); - VAND_VX(q1, q1, x2, VECTOR_UNMASKED); - VMUL_VV(v0, q0, q1, VECTOR_UNMASKED); + q2 = fpu_get_scratch(dyn); + d0 = fpu_get_scratch(dyn); + VAND_VX(q2, q0, x2, VECTOR_UNMASKED); + VAND_VX(d0, q1, x2, VECTOR_UNMASKED); + VMUL_VV(v0, q2, d0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0xF5: INST_NAME("VPMADDWD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); d0 = fpu_get_scratch(dyn); d1 = fpu_get_scratch(dyn); @@ -1216,63 +1110,49 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xF8: INST_NAME("VPSUBB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0xF9: INST_NAME("VPSUBW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xFA: INST_NAME("VPSUBD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0xFB: INST_NAME("VPSUBQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0xFC: INST_NAME("VPADDB Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0xFD: INST_NAME("VPADDW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xFE: INST_NAME("VPADDD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 67f0add5a..32b228b97 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -646,6 +646,34 @@ SET_AVX_VECTOR_WIDTH(x1, sew); \ } while (0) +#define VEC_SRC_KEEP(a, dst) \ + do { \ + if ((a) == (dst)) { \ + int keep_ = fpu_get_scratch(dyn); \ + VMV_V_V(keep_, (a)); \ + (a) = keep_; \ + } \ + } while (0) + +#define GETGY_empty_VYEY_vector_D(gx, vx, ex, sew, D) \ + do { \ + GETVY_vector(vx, sew); \ + GETEY_vector(ex, D, sew); \ + GETGY_empty_vector(gx); \ + } while (0) + +#define GETGY_empty_VYEY_vector(gx, vx, ex, sew) \ + GETGY_empty_VYEY_vector_D(gx, vx, ex, sew, 0) + +#define GETGY_empty_VYEY_vector_safe(gx, vx, ex, sew) \ + do { \ + GETVY_vector(vx, sew); \ + GETEY_vector(ex, 0, sew); \ + GETGY_empty_vector(gx); \ + VEC_SRC_KEEP(vx, gx); \ + VEC_SRC_KEEP(ex, gx); \ + } while (0) + #define VEC_SRC_SAFE(a, dst) \ do { \ if ((a) == (dst)) { \ From d07e3def9ccb4da836c0bb83d9db3abf0ab419fe Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 20 Oct 2026 02:47:37 +0800 Subject: [PATCH 056/156] [RV64_DYNAREC] Fixed AVX source/destination aliasing --- src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c | 8 +- .../rv64/dynarec_rv64_avx_66_0f38_vector.c | 180 +++++++++++++----- .../rv64/dynarec_rv64_avx_66_0f3a_vector.c | 22 ++- .../rv64/dynarec_rv64_avx_66_0f_vector.c | 20 +- 4 files changed, 168 insertions(+), 62 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index a05bd39f4..6f863f300 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -94,7 +94,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t INST_NAME("VMOVLPS Ex, Gx"); nextop = F8; if (MODREG) return 0; - GETGY_vector_cached(q0, VECTOR_SEW64); + GETGY_vector(q0, VECTOR_SEW64); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); VMV_X_S(x4, q0); SD(x4, ed, fixedaddress); @@ -162,7 +162,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t INST_NAME("VMOVHPS Ex, Gx"); nextop = F8; if (MODREG) return 0; - GETGY_vector_cached(q0, VECTOR_SEW64); + GETGY_vector(q0, VECTOR_SEW64); q1 = fpu_get_scratch(dyn); VSLIDEDOWN_VI(q1, q0, 1, VECTOR_UNMASKED); VMV_X_S(x4, q1); @@ -441,7 +441,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0xC2: INST_NAME("VCMPPS Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); + GETVY_vector(q0, VECTOR_SEW32); GETEY_vector(q1, 1, VECTOR_SEW32); u8 = F8; GETGY_empty_vector(v0); @@ -498,7 +498,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0xC6: INST_NAME("VSHUFPS Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); + GETVY_vector(q0, VECTOR_SEW32); GETEY_vector(q1, 1, VECTOR_SEW32); u8 = F8; selectors = 0; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c index 232364903..4bc8e5b9e 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c @@ -27,6 +27,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint uint8_t opcode = F8; uint8_t nextop; uint8_t gd, ed; + uint8_t u8; int v0, v1, v2; int q0, q1, q2, q3, q4, q5; int sew; @@ -35,6 +36,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint rex_t rex = vex.rex; MAYUSE(v1); + MAYUSE(u8); MAYUSE(q0); MAYUSE(q1); MAYUSE(q2); @@ -145,7 +147,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint } nextop = F8; SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); - GETGY_vector_cached(q0, sew); + GETGY_vector(q0, sew); GETEY_vector(q1, 0, sew); v0 = fpu_get_scratch(dyn); CLEAR_FLAGS(); @@ -396,7 +398,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x2C: INST_NAME("VMASKMOVPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); + GETVY_vector(q0, VECTOR_SEW32); GETGY_empty_vector(v0); if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -417,7 +419,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x2D: INST_NAME("VMASKMOVPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); + GETVY_vector(q0, VECTOR_SEW64); GETGY_empty_vector(v0); if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -746,7 +748,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VPMASKMOVD/Q Gx, Vx, Ex"); nextop = F8; if (rex.w) { - GETVY_vector_cached(q0, VECTOR_SEW64); + GETVY_vector(q0, VECTOR_SEW64); GETGY_empty_vector(v0); if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -764,7 +766,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint } PUTGY_vector(v0, VECTOR_SEW64); } else { - GETVY_vector_cached(q0, VECTOR_SEW32); + GETVY_vector(q0, VECTOR_SEW32); GETGY_empty_vector(v0); if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -805,14 +807,63 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint SMWRITE2(); } break; + case 0x92: + INST_NAME("VGATHERDPS Gx, VSIB, Vx"); + nextop = F8; + if (rex.w || ((nextop & 7) != 4) || MODREG) return 0; + u8 = F8; + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + if ((u8 & 7) == 5 && !(nextop & 0xC0)) { + int64_t i64 = F32S64; + MOV64x(x5, i64); + } else { + ed = TO_NAT((u8 & 7) + (rex.b << 3)); + MV(x5, ed); + } + if (nextop & 0x40) + j64 = F8S; + else if (nextop & 0x80) + j64 = F32S; + else + j64 = 0; + if (j64) { + if (j64 >= -2048 && j64 < 2048) { + ADDI(x5, x5, j64); + } else { + MOV64x(x4, j64); + ADD(x5, x5, x4); + } + } + ed = ((u8 >> 3) & 7) + (rex.x << 3); + SMREAD(); + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16 << vex.l, VECTOR_SEW32); + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16 << vex.l, VECTOR_SEW32); + GETGY_vector(q2, VECTOR_SEW32); + q4 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL2, vex.l ? 4 : 2); + VSEXT_VF2(q4, q1, VECTOR_UNMASKED); + if (u8 >> 6) VSLL_VI(q4, q4, u8 >> 6, VECTOR_UNMASKED); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); + VMSLT_VX(VMASK, q0, xZR, VECTOR_UNMASKED); + VLUXEI64_V(q2, q4, x5, VECTOR_MASKED, VECTOR_NFIELD1); + VAND_VX(q0, q0, xZR, VECTOR_MASKED); + PUTGY_vector(q2, VECTOR_SEW32); + gd = vex.v; + PUTGY_vector(q0, VECTOR_SEW32); + break; case 0x98: INST_NAME("VFMADD132PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q0); VFMACC_VV(v0, q2, q1, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -821,12 +872,15 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMADDSUB132PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); - v1 = fpu_get_scratch(dyn); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q0); + v1 = fpu_get_scratch(dyn); VFMACC_VV(v0, q2, q1, VECTOR_UNMASKED); VMV_V_V(v1, q0); VFMSAC_VV(v1, q2, q1, VECTOR_UNMASKED); @@ -838,12 +892,15 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMSUBADD132PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); - v1 = fpu_get_scratch(dyn); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q0); + v1 = fpu_get_scratch(dyn); VFMSAC_VV(v0, q2, q1, VECTOR_UNMASKED); VMV_V_V(v1, q0); VFMACC_VV(v1, q2, q1, VECTOR_UNMASKED); @@ -855,10 +912,13 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMSUB132PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q0); VFMSAC_VV(v0, q2, q1, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -867,10 +927,13 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFNMADD132PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q0); VFNMSAC_VV(v0, q2, q1, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -879,10 +942,13 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFNMSUB132PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q0); VFNMACC_VV(v0, q2, q1, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -891,10 +957,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMADD213PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q1); VFMACC_VV(v0, q0, q2, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -903,12 +971,15 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMADDSUB213PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); - v1 = fpu_get_scratch(dyn); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q1); + v1 = fpu_get_scratch(dyn); VFMACC_VV(v0, q0, q2, VECTOR_UNMASKED); VMV_V_V(v1, q1); VFMSAC_VV(v1, q0, q2, VECTOR_UNMASKED); @@ -920,12 +991,15 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMSUBADD213PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); - v1 = fpu_get_scratch(dyn); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q1); + v1 = fpu_get_scratch(dyn); VFMSAC_VV(v0, q0, q2, VECTOR_UNMASKED); VMV_V_V(v1, q1); VFMACC_VV(v1, q0, q2, VECTOR_UNMASKED); @@ -937,10 +1011,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMSUB213PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q1); VFMSAC_VV(v0, q0, q2, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -949,10 +1025,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFNMADD213PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q1); VFNMSAC_VV(v0, q0, q2, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -961,10 +1039,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFNMSUB213PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q1); VFNMACC_VV(v0, q0, q2, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -973,10 +1053,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMADD231PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); - GETGY_vector_cached(q2, sew); + GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); VMV_V_V(v0, q2); VFMACC_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -985,12 +1067,15 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMADDSUB231PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); - GETGY_vector_cached(q2, sew); + GETGY_vector(q2, sew); GETGY_empty_vector(v0); - v1 = fpu_get_scratch(dyn); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q2); + v1 = fpu_get_scratch(dyn); VFMACC_VV(v0, q0, q1, VECTOR_UNMASKED); VMV_V_V(v1, q2); VFMSAC_VV(v1, q0, q1, VECTOR_UNMASKED); @@ -1002,12 +1087,15 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMSUBADD231PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); - GETGY_vector_cached(q2, sew); + GETGY_vector(q2, sew); GETGY_empty_vector(v0); - v1 = fpu_get_scratch(dyn); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q2); + v1 = fpu_get_scratch(dyn); VFMSAC_VV(v0, q0, q1, VECTOR_UNMASKED); VMV_V_V(v1, q2); VFMACC_VV(v1, q0, q1, VECTOR_UNMASKED); @@ -1019,10 +1107,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFMSUB231PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); - GETGY_vector_cached(q2, sew); + GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); VMV_V_V(v0, q2); VFMSAC_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -1031,10 +1121,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFNMADD231PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); - GETGY_vector_cached(q2, sew); + GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); VMV_V_V(v0, q2); VFNMSAC_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -1043,10 +1135,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFNMSUB231PS/D Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - GETVY_vector_cached(q0, sew); + GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); - GETGY_vector_cached(q2, sew); + GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); VMV_V_V(v0, q2); VFNMACC_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -1136,7 +1230,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector_cached(q2, sew); + GETGY_vector(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { @@ -1162,7 +1256,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector_cached(q2, sew); + GETGY_vector(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { @@ -1188,7 +1282,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector_cached(q2, sew); + GETGY_vector(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { @@ -1214,7 +1308,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector_cached(q2, sew); + GETGY_vector(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { @@ -1241,7 +1335,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector_cached(q2, sew); + GETGY_vector(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { @@ -1350,7 +1444,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector_cached(q2, sew); + GETGY_vector(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { @@ -1377,7 +1471,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector_cached(q2, sew); + GETGY_vector(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { @@ -1404,7 +1498,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); - GETGY_vector_cached(q2, sew); + GETGY_vector(q2, sew); GETGY_empty_vector(v0); VMV_V_V(v0, q2); if (MODREG) { diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c index 09b0a1277..133bf5200 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c @@ -59,7 +59,8 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q0, 1, VECTOR_SEW64); GETGY_empty_vector(v0); u8 = F8; - q2 = fpu_get_scratch(dyn); + q1 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch_lmul(dyn, vex.l ? VECTOR_LMUL1 : VECTOR_LMUL2); { uint64_t iota = (u8 & 3) | (((u8 >> 2) & 3) << 16); iota |= ((uint64_t)((u8 >> 4) & 3)) << 32; @@ -68,7 +69,6 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VECTOR_SPLAT_IMM(q2, iota, x4); } if (v0 == q0 || v0 == q2) { - q1 = fpu_get_scratch(dyn); VRGATHEREI16_VV(q1, q0, q2, VECTOR_UNMASKED); VMV_V_V(v0, q1); } else { @@ -92,6 +92,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q0, 1, VECTOR_SEW32); GETGY_empty_vector(v0); u8 = F8; + VEC_SRC_KEEP(q0, v0); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); q1 = fpu_get_scratch(dyn); for (int i = 0; i < (4 << vex.l); ++i) { @@ -110,6 +111,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q0, 1, VECTOR_SEW64); GETGY_empty_vector(v0); u8 = F8; + VEC_SRC_KEEP(q0, v0); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); q1 = fpu_get_scratch(dyn); for (int i = 0; i < (2 << vex.l); ++i) { @@ -160,8 +162,9 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VMV_V_V(q2, q0); } if (i) { - VSLIDEUP_VI_SAFE(q1, q2, 16, VECTOR_UNMASKED); - q2 = q1; + VMV_V_V(q3, q1); + VSLIDEUP_VI_SAFE(q3, q2, 16, VECTOR_UNMASKED); + q2 = q3; } VECTOR_LOAD_VMASK(i ? 0xffff0000 : 0xffff, x4, 2); VMERGE_VVM(v0, v0, q2); @@ -196,6 +199,12 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (!(u8 & 1)) v1 = fpu_get_scratch(dyn); gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + if (q0 == VREG(gd)) { + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 32); + q2 = fpu_get_scratch(dyn); + VMV_V_V(q2, q0); + q0 = q2; + } avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); sse_forget_reg_vector(dyn, ninst, x1, gd); sse_set_pending_zero(dyn, gd, 0); @@ -401,8 +410,9 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VMV_V_V(q2, q0); } if (i) { - VSLIDEUP_VI_SAFE(q1, q2, 16, VECTOR_UNMASKED); - q2 = q1; + VMV_V_V(q3, q1); + VSLIDEUP_VI_SAFE(q3, q2, 16, VECTOR_UNMASKED); + q2 = q3; } VECTOR_LOAD_VMASK(i ? 0xffff0000 : 0xffff, x4, 2); VMERGE_VVM(v0, v0, q2); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index a17d2d0a1..0efa99b37 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -83,7 +83,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt INST_NAME("VMOVLPD Ex, Gx"); nextop = F8; if (MODREG) return 0; - GETGY_vector_cached(q0, VECTOR_SEW64); + GETGY_vector(q0, VECTOR_SEW64); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); VMV_X_S(x4, q0); SD(x4, ed, fixedaddress); @@ -146,7 +146,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt INST_NAME("VMOVHPD Ex, Gx"); nextop = F8; if (MODREG) return 0; - GETGY_vector_cached(q0, VECTOR_SEW64); + GETGY_vector(q0, VECTOR_SEW64); q1 = fpu_get_scratch(dyn); VSLIDEDOWN_VI(q1, q0, 1, VECTOR_UNMASKED); VMV_X_S(x4, q1); @@ -662,6 +662,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VADD_VI(q2, q2, u8, VECTOR_UNMASKED); ADDI(x4, xZR, 16 - u8); VMSLTU_VX(VMASK, v1, x4, VECTOR_UNMASKED); + VEC_SRC_KEEP(q1, v0); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VRGATHER_VV_SAFE(v0, q1, q2, VECTOR_MASKED); } @@ -686,6 +687,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VSUB_VX(q2, q2, x4, VECTOR_UNMASKED); ADDI(x4, xZR, u8 - 1); VMSGTU_VX(VMASK, v1, x4, VECTOR_UNMASKED); + VEC_SRC_KEEP(q1, v0); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VRGATHER_VV_SAFE(v0, q1, q2, VECTOR_MASKED); } @@ -805,7 +807,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD1: INST_NAME("VPSRLW Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW16); + GETVY_vector(q0, VECTOR_SEW16); GETEY128_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMV_X_S(x4, q1); @@ -819,7 +821,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD2: INST_NAME("VPSRLD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); + GETVY_vector(q0, VECTOR_SEW32); GETEY128_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMV_X_S(x4, q1); @@ -833,7 +835,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD3: INST_NAME("VPSRLQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); + GETVY_vector(q0, VECTOR_SEW64); GETEY128_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMV_X_S(x4, q1); @@ -847,7 +849,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (vex.l) return 0; INST_NAME("VMOVQ Ex, Gx"); nextop = F8; - GETGY_vector_cached(q0, VECTOR_SEW64); + GETGY_vector(q0, VECTOR_SEW64); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); q1 = fpu_get_scratch(dyn); @@ -1055,7 +1057,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xF2: INST_NAME("VPSLLD Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW32); + GETVY_vector(q0, VECTOR_SEW32); GETEY128_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMV_X_S(x4, q1); @@ -1069,7 +1071,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xF3: INST_NAME("VPSLLQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector_cached(q0, VECTOR_SEW64); + GETVY_vector(q0, VECTOR_SEW64); GETEY128_vector(q1, 0, VECTOR_SEW64); GETGY_empty_vector(v0); VMV_X_S(x4, q1); @@ -1224,9 +1226,9 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt nextop = F8; q0 = fpu_get_scratch(dyn); q1 = fpu_get_scratch(dyn); - v1 = fpu_get_scratch(dyn); q2 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); + v1 = fpu_get_scratch_lmul(dyn, vex.l ? VECTOR_LMUL1 : VECTOR_LMUL2); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16 << vex.l, VECTOR_SEW64); if (MODREG) { avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16 << vex.l, VECTOR_SEW64); From 3835fe369ed65c0e0036c00a30db91cba4014e67 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 20 Oct 2026 02:47:37 +0800 Subject: [PATCH 057/156] [RV64_DYNAREC] Used vl=1 RVV for scalar SSE/AVX opcodes --- .../rv64/dynarec_rv64_avx_f2_0f_vector.c | 173 +++-------------- .../rv64/dynarec_rv64_avx_f3_0f_vector.c | 174 +++--------------- src/dynarec/rv64/dynarec_rv64_f20f_vector.c | 56 +++--- src/dynarec/rv64/dynarec_rv64_f30f_vector.c | 62 ++++--- src/dynarec/rv64/dynarec_rv64_helper.h | 61 ++++-- 5 files changed, 171 insertions(+), 355 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c index 8745457d5..1ec3b4fc3 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c @@ -94,152 +94,49 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VADDSD Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLD(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FADDD(d0, d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW64); + VFADD_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW64); break; case 0x59: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VMULSD Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLD(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FMULD(d0, d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW64); + VFMUL_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW64); break; case 0x5C: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VSUBSD Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLD(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FSUBD(d0, d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW64); + VFSUB_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW64); break; case 0x5D: INST_NAME("VMINSD Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLD(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FLTD(x2, d0, d1); - BNEZ(x2, 8); - FMVD(d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW64); + VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); + VMERGE_VVM(v0, q1, q0); + AVX_SCALAR_OP_STORE(VECTOR_SEW64); break; case 0x5E: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VDIVSD Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLD(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FDIVD(d0, d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW64); + VFDIV_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW64); break; case 0x5F: INST_NAME("VMAXSD Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLD(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FLTD(x2, d1, d0); - BNEZ(x2, 8); - FMVD(d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW64); + VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); + VMERGE_VVM(v0, q1, q0); + AVX_SCALAR_OP_STORE(VECTOR_SEW64); break; case 0x5A: INST_NAME("VCVTSD2SS Gx, Vx, Ex"); @@ -283,7 +180,7 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x2A: INST_NAME("VCVTSI2SD Gx, Vx, Ed"); nextop = F8; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); @@ -304,8 +201,11 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt FCVTDW(d0, ed, RD_DYN); x87_restoreround(dyn, ninst, u8); GETGY_empty_vector(v0); - if (v0 != q0) + if (v0 != q0) { + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16); VMV_V_V(v0, q0); + } + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); VFMV_S_F(v0, d0); avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); break; @@ -315,7 +215,7 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt GETGDd; d0 = fpu_get_scratch(dyn); if (MODREG) { - q0 = fpu_get_scratch(dyn); + q0 = VREG((nextop & 7) + (rex.b << 3)); avx_load_reg_vector(dyn, ninst, x1, q0, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); VFMV_F_S(d0, q0); } else { @@ -376,24 +276,9 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VSQRTSD Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); - d0 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); - VFMV_F_S(d0, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLD(d0, ed, fixedaddress); - } - FSQRTD(d0, d0); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW64); + VFSQRT_V(v0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW64); break; case 0xF0: INST_NAME("VLDDQU Gx, Ex"); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c index dda251f5d..8d4cd0031 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c @@ -199,7 +199,7 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x2A: INST_NAME("VCVTSI2SS Gx, Vx, Ed"); nextop = F8; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); @@ -220,8 +220,11 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt FCVTSW(d0, ed, RD_DYN); x87_restoreround(dyn, ninst, u8); GETGY_empty_vector(v0); - if (v0 != q0) + if (v0 != q0) { + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16); VMV_V_V(v0, q0); + } + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); VFMV_S_F(v0, d0); avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); break; @@ -231,7 +234,7 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt GETGDd; d0 = fpu_get_scratch(dyn); if (MODREG) { - q0 = fpu_get_scratch(dyn); + q0 = VREG((nextop & 7) + (rex.b << 3)); avx_load_reg_vector(dyn, ninst, x1, q0, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); VFMV_F_S(d0, q0); } else { @@ -256,74 +259,25 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VSQRTSS Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); - d0 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); - VFMV_F_S(d0, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLW(d0, ed, fixedaddress); - } - FSQRTS(d0, d0); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW32); + VFSQRT_V(v0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW32); break; case 0x58: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VADDSS Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLW(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FADDS(d0, d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW32); + VFADD_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW32); break; case 0x59: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VMULSS Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLW(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FMULS(d0, d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW32); + VFMUL_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW32); break; case 0x5B: INST_NAME("VCVTTPS2DQ Gx, Ex"); @@ -352,103 +306,33 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VSUBSS Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLW(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FSUBS(d0, d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW32); + VFSUB_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW32); break; case 0x5D: INST_NAME("VMINSS Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLW(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FLTS(x2, d0, d1); - BNEZ(x2, 8); - FMVS(d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW32); + VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); + VMERGE_VVM(v0, q1, q0); + AVX_SCALAR_OP_STORE(VECTOR_SEW32); break; case 0x5E: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VDIVSS Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLW(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FDIVS(d0, d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW32); + VFDIV_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW32); break; case 0x5F: INST_NAME("VMAXSS Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLW(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FLTS(x2, d1, d0); - BNEZ(x2, 8); - FMVS(d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW32); + VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); + VMERGE_VVM(v0, q1, q0); + AVX_SCALAR_OP_STORE(VECTOR_SEW32); break; case 0x70: INST_NAME("VPSHUFHW Gx, Ex, Ib"); diff --git a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c index 5b7d473fa..e67a744af 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c @@ -223,8 +223,8 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); } if (BOX64ENV(dynarec_fastnan)) { - VECTOR_LOAD_VMASK(0b01, x4, 1); - VFSQRT_V(v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); + VFSQRT_V(v0, v1, VECTOR_UNMASKED); } else { d0 = fpu_get_scratch(dyn); d1 = fpu_get_scratch(dyn); @@ -257,8 +257,8 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW64); } - VECTOR_LOAD_VMASK(0b01, x4, 1); - VFADD_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); + VFADD_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x59: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -276,8 +276,8 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW64); } - VECTOR_LOAD_VMASK(0b01, x4, 1); - VFMUL_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); + VFMUL_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x5A: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -338,8 +338,8 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW64); } - VECTOR_LOAD_VMASK(0b01, x4, 1); - VFSUB_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); + VFSUB_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x5D: INST_NAME("MINSD Gx, Ex"); @@ -356,19 +356,21 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW64); } - d0 = fpu_get_scratch(dyn); - d1 = fpu_get_scratch(dyn); - VFMV_F_S(d0, v0); - VFMV_F_S(d1, v1); - FLTD(x2, d0, d1); - BNEZ(x2, 8); - FMVD(d0, d1); if (cpuext.xtheadvector) { + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFMV_F_S(d0, v0); + VFMV_F_S(d1, v1); + FLTD(x2, d0, d1); + BNEZ(x2, 8); + FMVD(d0, d1); VFMV_S_F(d0, d0); VECTOR_LOAD_VMASK(0b0001, x4, 1); VMERGE_VVM(v0, v0, d0); // implies VMASK } else { - VFMV_S_F(v0, d0); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); + VMFLT_VV(VMASK, v0, v1, VECTOR_UNMASKED); + VMERGE_VVM(v0, v1, v0); } break; case 0x5E: @@ -387,8 +389,8 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW64); } - VECTOR_LOAD_VMASK(0b01, x4, 1); - VFDIV_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); + VFDIV_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x5F: INST_NAME("MAXSD Gx, Ex"); @@ -405,19 +407,21 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW64); } - d0 = fpu_get_scratch(dyn); - d1 = fpu_get_scratch(dyn); - VFMV_F_S(d0, v0); - VFMV_F_S(d1, v1); - FLTD(x2, d1, d0); - BNEZ(x2, 8); - FMVD(d0, d1); if (cpuext.xtheadvector) { + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFMV_F_S(d0, v0); + VFMV_F_S(d1, v1); + FLTD(x2, d1, d0); + BNEZ(x2, 8); + FMVD(d0, d1); VFMV_S_F(d0, d0); VECTOR_LOAD_VMASK(0b0001, x4, 1); VMERGE_VVM(v0, v0, d0); // implies VMASK } else { - VFMV_S_F(v0, d0); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); + VMFLT_VV(VMASK, v1, v0, VECTOR_UNMASKED); + VMERGE_VVM(v0, v1, v0); } break; case 0x70: diff --git a/src/dynarec/rv64/dynarec_rv64_f30f_vector.c b/src/dynarec/rv64/dynarec_rv64_f30f_vector.c index 3b3a46410..c8c320633 100644 --- a/src/dynarec/rv64/dynarec_rv64_f30f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f30f_vector.c @@ -232,8 +232,8 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VFSQRT_V(v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VFSQRT_V(v0, v1, VECTOR_UNMASKED); break; case 0x52: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -253,9 +253,9 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i } LUI(x4, 0x3f800); FMVWX(v1, x4); // 1.0f - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VFSQRT_V(v0, v1, VECTOR_MASKED); - VFRDIV_VF(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VFSQRT_V(v0, v1, VECTOR_UNMASKED); + VFRDIV_VF(v0, v0, v1, VECTOR_UNMASKED); break; case 0x53: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -294,8 +294,8 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VFADD_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VFADD_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x59: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -313,8 +313,8 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VFMUL_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VFMUL_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x5A: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -375,8 +375,8 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VFSUB_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VFSUB_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x5D: INST_NAME("MINSS Gx, Ex"); @@ -393,19 +393,21 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - d0 = fpu_get_scratch(dyn); - d1 = fpu_get_scratch(dyn); - VFMV_F_S(d0, v0); - VFMV_F_S(d1, v1); - FLTS(x2, d0, d1); - BNEZ(x2, 8); - FMVS(d0, d1); if (cpuext.xtheadvector) { + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFMV_F_S(d0, v0); + VFMV_F_S(d1, v1); + FLTS(x2, d0, d1); + BNEZ(x2, 8); + FMVS(d0, d1); VFMV_S_F(d0, d0); VECTOR_LOAD_VMASK(0b0001, x4, 1); VMERGE_VVM(v0, v0, d0); } else { - VFMV_S_F(v0, d0); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VMFLT_VV(VMASK, v0, v1, VECTOR_UNMASKED); + VMERGE_VVM(v0, v1, v0); } break; case 0x5E: @@ -424,8 +426,8 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VFDIV_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VFDIV_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x5F: INST_NAME("MAXSS Gx, Ex"); @@ -442,19 +444,21 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - d0 = fpu_get_scratch(dyn); - d1 = fpu_get_scratch(dyn); - VFMV_F_S(d0, v0); - VFMV_F_S(d1, v1); - FLTS(x2, d1, d0); - BNEZ(x2, 8); - FMVS(d0, d1); if (cpuext.xtheadvector) { + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFMV_F_S(d0, v0); + VFMV_F_S(d1, v1); + FLTS(x2, d1, d0); + BNEZ(x2, 8); + FMVS(d0, d1); VFMV_S_F(d0, d0); VECTOR_LOAD_VMASK(0b0001, x4, 1); VMERGE_VVM(v0, v0, d0); // implies VMASK } else { - VFMV_S_F(v0, d0); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VMFLT_VV(VMASK, v1, v0, VECTOR_UNMASKED); + VMERGE_VVM(v0, v1, v0); } break; case 0x6F: diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 32b228b97..b746ec6a3 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1635,20 +1635,59 @@ #define MODREG ((nextop & 0xC0) == 0xC0) #ifndef SET_ELEMENT_WIDTH -#define SET_ELEMENT_WIDTH(s1, sew, set) \ - do { \ - if ((sew) == VECTOR_SEWANY && dyn->vector_sew != VECTOR_SEWNA) { \ - dyn->vector_eew = dyn->vector_sew; \ - } else if ((sew) == dyn->vector_sew && (unsigned)(sew) < 4 && \ - dyn->inst_vl == (uint32_t)(16u >> (sew))) { \ - dyn->vector_eew = dyn->vector_sew; \ - } else { \ - dyn->vector_eew = vector_vsetvli(dyn, ninst, s1, (sew), VECTOR_LMUL1, 1); \ - } \ - if (set) dyn->vector_sew = dyn->vector_eew; \ +#define SET_ELEMENT_WIDTH(s1, sew, set) \ + do { \ + if ((sew) == VECTOR_SEWANY && (unsigned)dyn->vector_sew < 4 \ + && dyn->inst_vl == (uint32_t)(16u >> dyn->vector_sew)) { \ + dyn->vector_eew = dyn->vector_sew; \ + } else if ((sew) == dyn->vector_sew && (unsigned)(sew) < 4 && dyn->inst_vl == (uint32_t)(16u >> (sew))) { \ + dyn->vector_eew = dyn->vector_sew; \ + } else { \ + dyn->vector_eew = vector_vsetvli(dyn, ninst, s1, (sew), VECTOR_LMUL1, 1); \ + } \ + if (set) dyn->vector_sew = dyn->vector_eew; \ } while (0) #endif +#define SET_SCALAR_FP_WIDTH(s1, sew) \ + do { \ + dyn->vector_eew = vector_vsetvli(dyn, ninst, s1, (sew), VECTOR_LMUL1, \ + 1.0f / (float)(16 >> (sew))); \ + dyn->vector_sew = dyn->vector_eew; \ + } while (0) + +#define AVX_SCALAR_OP_PROLOG(SEW) \ + do { \ + q0 = VREG(vex.v); \ + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, (SEW)); \ + if (MODREG) { \ + ed = (nextop & 7) + (rex.b << 3); \ + q1 = VREG(ed); \ + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, (SEW)); \ + } else { \ + q1 = fpu_get_scratch(dyn); \ + SMREAD(); \ + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); \ + avx_set_vector_width(dyn, ninst, x1, (SEW), 1 << (SEW)); \ + VLE_V(q1, ed, (SEW), VECTOR_UNMASKED, VECTOR_NFIELD1); \ + } \ + GETGY_empty_vector(v0); \ + if (v0 != q0) { \ + if (v0 == q1) { \ + int _t = fpu_get_scratch(dyn); \ + avx_set_vector_width(dyn, ninst, x1, (SEW), 16); \ + VMV_V_V(_t, q1); \ + q1 = _t; \ + } \ + avx_set_vector_width(dyn, ninst, x1, (SEW), 16); \ + VMV_V_V(v0, q0); \ + } \ + SET_SCALAR_FP_WIDTH(x1, (SEW)); \ + } while (0) + +#define AVX_SCALAR_OP_STORE(SEW) \ + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, (SEW)) + #define SET_CACHE_VECTOR_WIDTH(S1) \ do { \ int sew = dyn->vector_sew; \ From db0615cbb0a5c80cab0ef9ace1467caed5ab358f Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 20 Oct 2026 02:50:45 +0800 Subject: [PATCH 058/156] [RV64_DYNAREC] Used LMUL1 scratch for byte shuffles --- src/dynarec/rv64/dynarec_rv64_0f_vector.c | 2 +- src/dynarec/rv64/dynarec_rv64_660f_vector.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_0f_vector.c index 7227510ee..a8fe89bf7 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_0f_vector.c @@ -1156,7 +1156,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETGX_vector(v0, 1, VECTOR_SEW32); GETEX_vector(v1, 0, 1, VECTOR_SEW32); u8 = F8; - q0 = fpu_get_scratch(dyn); + q0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL1); d0 = fpu_get_scratch(dyn); d1 = fpu_get_scratch(dyn); if (cpuext.xtheadvector) { // lack of vrgatherei16.vv diff --git a/src/dynarec/rv64/dynarec_rv64_660f_vector.c b/src/dynarec/rv64/dynarec_rv64_660f_vector.c index 0d356eff5..3c74c4abf 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_660f_vector.c @@ -1525,7 +1525,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); GETEX_vector(q1, 0, 1, VECTOR_SEW64); GETGX_empty_vector(q0); - v0 = fpu_get_scratch(dyn); + v0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL1); tmp64u0 = F8; if (cpuext.xtheadvector) { // lack of vrgatherei16.vv v1 = fpu_get_scratch(dyn); From ae3412c1bf9179b341996e18b656f11fd145f01e Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 20 Oct 2026 02:50:45 +0800 Subject: [PATCH 059/156] [RV64_DYNAREC] Deferred upper-zero and matched AVX load SEW --- src/dynarec/rv64/dynarec_rv64_functions.c | 3 +- src/dynarec/rv64/dynarec_rv64_helper.c | 36 +++++++++++++++-------- src/dynarec/rv64/dynarec_rv64_private.h | 1 + 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index bd986bc95..1024b28ca 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -63,6 +63,7 @@ int fpu_get_scratch_lmul(dynarec_rv64_t* dyn, int lmul) void fpu_reset_scratch(dynarec_rv64_t* dyn) { dyn->e.fpu_scratch = 0; + dyn->pending_zero_flushed = 0; } // Get a x87 double reg int fpu_get_reg_x87(dynarec_rv64_t* dyn, int t, int n) @@ -1170,7 +1171,7 @@ void updateUpperLiveness(dynarec_rv64_t* dyn) int j = inst->pred[p]; const instruction_rv64_t* pred = &dyn->insts[j]; merged_pending |= (pending_in[j] & (uint16_t)~pred->up32_write64) | pred->up32_skip; - merged_ymm |= (pend_ymm[j] & (uint16_t)~pred->ymm_upper_def) | (pred->ymm_zero & (uint16_t)~pred->ymm_upper_live); + merged_ymm |= (pend_ymm[j] & (uint16_t)~pred->ymm_upper_def) | (pred->ymm_zero & pred->ymm_upper_live); } if (inst->x64.barrier & BARRIER_FLOAT) merged_ymm = 0; if ((merged_pending != pending_in[i]) || (merged_ymm != pend_ymm[i])) { diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index b30770fb2..08fa8d84c 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -2925,6 +2925,11 @@ void avx_flush_pending_zero_vector(dynarec_rv64_t* dyn, int ninst, int s1, int n { if (!cpuext.vlen || cpuext.vlen < 32) return; + if (next) { + if (dyn->pending_zero_flushed) + return; + dyn->pending_zero_flushed = 1; + } for (int i = 0; i < 16; ++i) if ((dyn->e.ymm0 >> i) & 1) { SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 0); @@ -2955,13 +2960,24 @@ void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a sse_mark_used(dyn, ninst, a); if (width == 32 && cpuext.vlen >= 32) ymm_live_read(dyn, ninst, a); - avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 16); - int low = sse_get_reg_vector(dyn, ninst, s1, a, 0, VECTOR_SEW8); + if (dyn->e.ssecache[a].v != -1 && dyn->e.ssecache[a].vector && (width != 32 || dyn->e.ssecache[a].ymm)) { + int cache = dyn->e.ssecache[a].reg; + avx_set_vector_width(dyn, ninst, s1, sew, width); + if (cache != vreg) VMV_V_V(vreg, cache); + return; + } + int low; + if (width >= 16) { + avx_set_vector_width(dyn, ninst, s1, sew, width); + low = sse_get_reg_vector(dyn, ninst, s1, a, 0, sew); + } else { + avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 16); + low = sse_get_reg_vector(dyn, ninst, s1, a, 0, VECTOR_SEW8); + } if (width == 32 && !dyn->e.ssecache[a].ymm) { if (dyn->e.ssecache[a].ymm0) { - avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW32, 32); VXOR_VV(VMASK, VMASK, VMASK, VECTOR_UNMASKED); - VSLIDEUP_VI(low, VMASK, 4, VECTOR_UNMASKED); + VSLIDEUP_VI(low, VMASK, 16 >> sew, VECTOR_UNMASKED); } else { dyn->inst_sew = VECTOR_SEWNA; dyn->inst_vl = 0; // real vtype here is unknown, never elide vsetvli @@ -2974,29 +2990,23 @@ void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a } dyn->e.ssecache[a].ymm = 1; } - if (low != vreg) { - avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, width); + if (low != vreg) VMV_V_V(vreg, low); - } avx_set_vector_width(dyn, ninst, s1, sew, width); } void avx_store_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew) { sse_mark_used(dyn, ninst, a); - avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 16); int cache = sse_get_reg_empty_vector(dyn, ninst, s1, a); if (cache != vreg) { avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, width); VMV_V_V(cache, vreg); } if (cpuext.vlen >= 32) { - dyn->e.ssecache[a].ymm = 1; - dyn->e.extcache[EXTIDX(cache)].y = 1; + dyn->e.ssecache[a].ymm = (width == 32); + dyn->e.extcache[EXTIDX(cache)].y = (width == 32); if (width == 16) { - avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW32, 32); - VXOR_VV(VMASK, VMASK, VMASK, VECTOR_UNMASKED); - VSLIDEUP_VI(cache, VMASK, 4, VECTOR_UNMASKED); sse_set_pending_zero(dyn, a, 1); ymm_live_zero(dyn, ninst, a); } else { diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index cd724441d..5915eea54 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -211,6 +211,7 @@ typedef struct dynarec_rv64_s { int32_t forward_size; // size at the forward point int forward_ninst; // ninst at the forward point uint16_t ymm_zero; // bitmap of ymm to zero at purge + uint8_t pending_zero_flushed; uint8_t always_test; uint8_t abort; uint8_t vector_sew; // current sew status From d96343fbb1777458e4bc3adcd5a4b93c113fd245 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 21 Oct 2026 16:29:55 +0800 Subject: [PATCH 060/156] [RV64_DYNAREC] Added and optimized some SSE/AVX opcodes (#4581) * [RV64_DYNAREC] Fixed YMM upper-half pending-zero materialization on scalar path * [RV64_DYNAREC] Fixed deferred flags left behind on signal exit * [RV64_DYNAREC] Added and optimized some SSE/AVX opcodes --- src/dynarec/rv64/dynarec_rv64_660f_vector.c | 220 ++++++++++++ src/dynarec/rv64/dynarec_rv64_66f20f.c | 34 +- src/dynarec/rv64/dynarec_rv64_arch.c | 9 +- src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c | 52 +-- src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c | 8 +- .../rv64/dynarec_rv64_avx_66_0f38_vector.c | 225 +++++++++++- .../rv64/dynarec_rv64_avx_66_0f3a_vector.c | 282 +++++++-------- .../rv64/dynarec_rv64_avx_66_0f_vector.c | 322 +++++++++++++++--- .../rv64/dynarec_rv64_avx_f2_0f_vector.c | 87 ++++- .../rv64/dynarec_rv64_avx_f3_0f_vector.c | 35 +- src/dynarec/rv64/dynarec_rv64_f20f.c | 62 ++-- src/dynarec/rv64/dynarec_rv64_functions.c | 3 +- src/dynarec/rv64/dynarec_rv64_helper.c | 58 +++- src/dynarec/rv64/dynarec_rv64_helper.h | 124 +++++-- src/dynarec/rv64/dynarec_rv64_private.h | 4 + 15 files changed, 1224 insertions(+), 301 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_660f_vector.c b/src/dynarec/rv64/dynarec_rv64_660f_vector.c index 3c74c4abf..65eaf34e2 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_660f_vector.c @@ -38,6 +38,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i int64_t fixedaddress, gdoffset; uint32_t vtypei; int unscaled; + int u8s; MAYUSE(d0); MAYUSE(d1); MAYUSE(q0); @@ -46,6 +47,8 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i MAYUSE(eb1); MAYUSE(eb2); MAYUSE(j64); + MAYUSE(u8s); + static const int8_t round_round[] = { RD_RNE, RD_RDN, RD_RUP, RD_RTZ }; switch (opcode) { case 0x10: INST_NAME("MOVUPD Gx, Ex"); @@ -368,6 +371,43 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); VSUB_VV(q0, d0, d1, VECTOR_UNMASKED); break; + case 0x06: + INST_NAME("PHSUBD Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); + GETGX_vector(q0, 1, VECTOR_SEW32); + GETEX_vector(q1, 0, 0, VECTOR_SEW32); + v0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + d1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + VMV_V_V(v0, q0); + if (q1 & 1) VMV_V_V(d1, q1); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL2, 2); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); + VNSRL_WI(d0, v0, 0, VECTOR_UNMASKED); + ADDI(x4, xZR, 32); + VNSRL_WX(d1, v0, x4, VECTOR_UNMASKED); + VSUB_VV(q0, d0, d1, VECTOR_UNMASKED); + break; + case 0x07: + INST_NAME("PHSUBSW Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); + GETGX_vector(q0, 1, VECTOR_SEW16); + GETEX_vector(q1, 0, 0, VECTOR_SEW16); + v0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + d1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + VMV_V_V(v0, q0); + if (q1 & 1) VMV_V_V(d1, q1); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 2); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 8, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VNSRL_WI(d0, v0, 0, VECTOR_UNMASKED); + VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); + VSSUB_VV(q0, d0, d1, VECTOR_UNMASKED); + break; case 0x08 ... 0x0A: if (nextop == 0x08) { INST_NAME("PSIGNB Gx, Ex"); @@ -865,6 +905,14 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VXOR_VV(q0, q0, q0, VECTOR_UNMASKED); VMERGE_VIM(q0, q0, 0b11111); // implies vmask and widened it break; + case 0x38: + INST_NAME("PMINSB Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); + GETGX_vector(q0, 1, VECTOR_SEW8); + GETEX_vector(q1, 0, 0, VECTOR_SEW8); + VMIN_VV(q0, q1, q0, VECTOR_UNMASKED); + break; case 0x39: INST_NAME("PMINSD Gx, Ex"); nextop = F8; @@ -889,6 +937,14 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETGX_vector(q0, 1, VECTOR_SEW32); VMINU_VV(q0, q1, q0, VECTOR_UNMASKED); break; + case 0x3C: + INST_NAME("PMAXSB Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); + GETGX_vector(q0, 1, VECTOR_SEW8); + GETEX_vector(q1, 0, 0, VECTOR_SEW8); + VMAX_VV(q0, q1, q0, VECTOR_UNMASKED); + break; case 0x3D: INST_NAME("PMAXSD Gx, Ex"); nextop = F8; @@ -897,6 +953,22 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETEX_vector(q1, 0, 0, VECTOR_SEW32); VMAX_VV(q0, q1, q0, VECTOR_UNMASKED); break; + case 0x3E: + INST_NAME("PMAXUW Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); + GETEX_vector(q1, 0, 0, VECTOR_SEW16); + GETGX_vector(q0, 1, VECTOR_SEW16); + VMAXU_VV(q0, q1, q0, VECTOR_UNMASKED); + break; + case 0x3F: + INST_NAME("PMAXUD Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); + GETEX_vector(q1, 0, 0, VECTOR_SEW32); + GETGX_vector(q0, 1, VECTOR_SEW32); + VMAXU_VV(q0, q1, q0, VECTOR_UNMASKED); + break; case 0x40: INST_NAME("PMULLD Gx, Ex"); nextop = F8; @@ -905,6 +977,26 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETGX_vector(q0, 1, VECTOR_SEW32); VMUL_VV(q0, q1, q0, VECTOR_UNMASKED); break; + case 0x41: + INST_NAME("PHMINPOSUW Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); + GETEX_vector(q0, 0, 0, VECTOR_SEW16); + GETGX_empty_vector(v0); + q1 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch(dyn); + VMV_V_I(q2, -1); + VREDMINU_VS(q1, q0, q2, VECTOR_UNMASKED); + VMV_X_S(x4, q1); + ZEXTH(x4, x4); + VMSEQ_VX(VMASK, q0, x4, VECTOR_UNMASKED); + VFIRST_M(x5, VMASK, VECTOR_UNMASKED); + SLLI(x5, x5, 16); + OR(x4, x4, x5); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + VMV_S_X(v0, x4); + break; case 0xDB ... 0xDF: return 0; default: @@ -914,6 +1006,94 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0x3A: // these are some more SSSE3+ opcodes opcode = F8; switch (opcode) { + case 0x08: { + INST_NAME("ROUNDPS Gx, Ex, Ib"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); + GETEX_vector(q0, 0, 1, VECTOR_SEW32); + GETGX_empty_vector(v0); + u8 = F8; + q1 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch(dyn); + int r3 = fpu_get_scratch(dyn); + if (u8 & 4) { + u8s = sse_setround(dyn, ninst, x5, x6); + } else { + ADDI(x5, xZR, round_round[u8 & 3]); + FSRM(x6, x5); + } + VFCVT_X_F_V(q1, q0, VECTOR_UNMASKED); // qi + VFCVT_F_X_V(q2, q1, VECTOR_UNMASKED); // qf + MOV32w(x5, 0x80000000); + VAND_VX(r3, q0, x5, VECTOR_UNMASKED); + VMSEQ_VI(VMASK, q1, 0, VECTOR_UNMASKED); + VMERGE_VVM(q2, q2, r3); + MOV32w(x5, 0x00400000); + VOR_VX(r3, q0, x5, VECTOR_UNMASKED); + VMFEQ_VV(VMASK, q0, q0, VECTOR_UNMASKED); + VMERGE_VVM(q2, r3, q2); + d0 = fpu_get_scratch(dyn); + MOV32w(x5, 0x4f000000); + FMVWX(d0, x5); + VMFGE_VF(VMASK, q0, d0, VECTOR_UNMASKED); + VMERGE_VVM(q2, q2, q0); + d1 = fpu_get_scratch(dyn); + MOV32w(x5, 0xcf000000); + FMVWX(d1, x5); + VMFLE_VF(VMASK, q0, d1, VECTOR_UNMASKED); + VMERGE_VVM(q2, q2, q0); + if (u8 & 4) { + x87_restoreround(dyn, ninst, u8s); + } else { + FSRM(x5, x6); + } + VMV_V_V(v0, q2); + break; + } + case 0x09: { + INST_NAME("ROUNDPD Gx, Ex, Ib"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); + GETEX_vector(q0, 0, 1, VECTOR_SEW64); + GETGX_empty_vector(v0); + u8 = F8; + q1 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch(dyn); + int r3 = fpu_get_scratch(dyn); + if (u8 & 4) { + u8s = sse_setround(dyn, ninst, x5, x6); + } else { + ADDI(x5, xZR, round_round[u8 & 3]); + FSRM(x6, x5); + } + VFCVT_X_F_V(q1, q0, VECTOR_UNMASKED); // qi + VFCVT_F_X_V(q2, q1, VECTOR_UNMASKED); // qf + MOV64x(x5, 0x8000000000000000LL); + VAND_VX(r3, q0, x5, VECTOR_UNMASKED); + VMSEQ_VI(VMASK, q1, 0, VECTOR_UNMASKED); + VMERGE_VVM(q2, q2, r3); + MOV64x(x5, 0x0008000000000000LL); + VOR_VX(r3, q0, x5, VECTOR_UNMASKED); + VMFEQ_VV(VMASK, q0, q0, VECTOR_UNMASKED); + VMERGE_VVM(q2, r3, q2); + d0 = fpu_get_scratch(dyn); + MOV64x(x5, 0x43e0000000000000LL); + FMVDX(d0, x5); + VMFGE_VF(VMASK, q0, d0, VECTOR_UNMASKED); + VMERGE_VVM(q2, q2, q0); + d1 = fpu_get_scratch(dyn); + MOV64x(x5, 0xc3e0000000000000LL); + FMVDX(d1, x5); + VMFLE_VF(VMASK, q0, d1, VECTOR_UNMASKED); + VMERGE_VVM(q2, q2, q0); + if (u8 & 4) { + x87_restoreround(dyn, ninst, u8s); + } else { + FSRM(x5, x6); + } + VMV_V_V(v0, q2); + break; + } case 0x0E: INST_NAME("PBLENDW Gx, Ex, Ib"); nextop = F8; @@ -965,6 +1145,46 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i if (q0 != q1) VMV_V_V(q0, q1); } break; + case 0x42: + INST_NAME("MPSADBW Gx, Ex, Ib"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); + GETGX_vector(q0, 1, VECTOR_SEW8); + GETEX_vector(q1, 0, 1, VECTOR_SEW8); + u8 = F8; + { + int m3 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + int m4 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + int m5 = fpu_borrow_reg(dyn, ninst, x1, x2, 9); + int m6 = fpu_borrow_reg(dyn, ninst, x1, x2, 10); + int m7 = fpu_borrow_reg(dyn, ninst, x1, x2, 11); + int m8 = fpu_borrow_reg(dyn, ninst, x1, x2, 12); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VMV_V_V(m7, q0); + VMV_V_V(m8, q1); + VID_V(m5, VECTOR_UNMASKED); + VSRL_VI(m6, m5, 3, VECTOR_UNMASKED); + VAND_VI(m5, m5, 7, VECTOR_UNMASKED); + VADD_VV(m5, m5, m6, VECTOR_UNMASKED); + int off5 = ((u8 >> 2) & 1) * 4; + int off6 = (u8 & 3) * 4; + if (off5) VADD_VI(m5, m5, off5, VECTOR_UNMASKED); + if (off6) VADD_VI(m6, m6, off6, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(m3, m7, m5, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(m4, m8, m6, VECTOR_UNMASKED); + VMAXU_VV(m7, m3, m4, VECTOR_UNMASKED); + VMINU_VV(m4, m3, m4, VECTOR_UNMASKED); + VSUB_VV(m7, m7, m4, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 4); + VZEXT_VF2(m3, m7, VECTOR_UNMASKED); + VSLIDEDOWN_VI(m4, m3, 8, VECTOR_UNMASKED); + VADD_VV(m3, m3, m4, VECTOR_UNMASKED); + VSLIDEDOWN_VI(m4, m3, 16, VECTOR_UNMASKED); + VADD_VV(m3, m3, m4, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VMV_V_V(q0, m3); + } + break; case 0x16: nextop = F8; if (rex.w) { diff --git a/src/dynarec/rv64/dynarec_rv64_66f20f.c b/src/dynarec/rv64/dynarec_rv64_66f20f.c index c7745db4d..6772e94ba 100644 --- a/src/dynarec/rv64/dynarec_rv64_66f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_66f20f.c @@ -60,17 +60,29 @@ uintptr_t dynarec64_66F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in GETGD; GETEW(x1, 0); MV(x5, ed); - ZEROUP(gd); - MOV32w(x2, 0x82f63b78); - for (int j = 0; j < 2; ++j) { - SRLI(x6, x5, 8 * j); - ANDI(x6, x6, 0xFF); - XOR(gd, gd, x6); - for (int i = 0; i < 8; i++) { - SRLI((i & 1) ? gd : x4, (i & 1) ? x4 : gd, 1); - ANDI(x6, (i & 1) ? x4 : gd, 1); - BEQZ(x6, 4 + 4); - XOR((i & 1) ? gd : x4, (i & 1) ? gd : x4, x2); + if (cpuext.zbc) { + ZEROUP(gd); + XOR(x5, x5, gd); + SLLI(x5, x5, 48); + MOV64x(x2, 0x4869EC38DEA713F1ULL); + CLMUL(x5, x5, x2); + MOV64x(x2, 0x105EC76F1ULL); + CLMULH(x5, x5, x2); + SRLI(gd, gd, 16); + XOR(gd, x5, gd); + } else { + ZEROUP(gd); + MOV32w(x2, 0x82f63b78); + for (int j = 0; j < 2; ++j) { + SRLI(x6, x5, 8 * j); + ANDI(x6, x6, 0xFF); + XOR(gd, gd, x6); + for (int i = 0; i < 8; i++) { + SRLI((i & 1) ? gd : x4, (i & 1) ? x4 : gd, 1); + ANDI(x6, (i & 1) ? x4 : gd, 1); + BEQZ(x6, 4 + 4); + XOR((i & 1) ? gd : x4, (i & 1) ? gd : x4, x2); + } } } break; diff --git a/src/dynarec/rv64/dynarec_rv64_arch.c b/src/dynarec/rv64/dynarec_rv64_arch.c index b5a60bb04..391b10b19 100644 --- a/src/dynarec/rv64/dynarec_rv64_arch.c +++ b/src/dynarec/rv64/dynarec_rv64_arch.c @@ -26,7 +26,7 @@ typedef struct arch_flags_s { - uint8_t ignore:1; + uint8_t defered:1; // deferred flags are authoritative at this instruction } arch_flags_t; #define X87_ST_D 0 @@ -90,6 +90,11 @@ typedef struct arch_build_s static int arch_build(dynarec_rv64_t* dyn, int ninst, arch_build_t* arch) { memset(arch, 0, sizeof(arch_build_t)); + flagcache_t f = dyn->insts[ninst].f_entry; + if (f == status_set || f == status_unk) { + arch->flags = 1; + arch->flags_.defered = 1; + } // opcode can handle unaligned arch->unaligned = dyn->insts[ninst].unaligned; arch->rsp = dyn->insts[ninst].rsp_entry; @@ -357,6 +362,8 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) } SUPER() #undef GO + flags = arch->flags ? (arch_flags_t*)((uintptr_t)arch + sizeof(arch_arch_t)) : NULL; + if (!flags || !flags->defered) emu->df = d_none; uint16_t up32 = arch->up32; while (up32) { int r = __builtin_ctz(up32); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index 6f863f300..289841335 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -365,18 +365,19 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t BARRIER(BARRIER_FLOAT); if (vex.l) { INST_NAME("VZEROALL"); - for (int i = 0; i < (rex.is32bits ? 8 : 16); ++i) { - SD(xZR, xEmu, offsetof(x64emu_t, xmm[i]) + 0); - SD(xZR, xEmu, offsetof(x64emu_t, xmm[i]) + 8); - SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 0); - SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 8); - } } else { INST_NAME("VZEROUPPER"); - for (int i = 0; i < (rex.is32bits ? 8 : 16); ++i) { - SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 0); - SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 8); + } + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL4, 8); + v1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL4); + VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); + for (int off = 0; off < (rex.is32bits ? 8 : 16) * 16; off += 128) { + if (vex.l) { + ADDI(x4, xEmu, offsetof(x64emu_t, xmm) + off); + VSE8_V(v1, x4, VECTOR_UNMASKED, VECTOR_NFIELD1); } + ADDI(x4, xEmu, offsetof(x64emu_t, ymm) + off); + VSE8_V(v1, x4, VECTOR_UNMASKED, VECTOR_NFIELD1); } break; case 0xAE: @@ -501,26 +502,25 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t GETVY_vector(q0, VECTOR_SEW32); GETEY_vector(q1, 1, VECTOR_SEW32); u8 = F8; - selectors = 0; - for (int i = 0; i < (4 << vex.l); ++i) { - int lane = i & ~3; - int pos = i & 3; - int selector = lane + ((u8 >> (pos * 2)) & 3); - if (pos >= 2) selector |= 0x80; - selectors |= (uint64_t)selector << (i * 8); - } GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); - VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); - for (int i = 0; i < (4 << vex.l); ++i) { - int selector = selectors >> (i * 8); - MOV32w(x4, selector & 0x1f); - VRGATHER_VX_SAFE(q2, (selector & 0x80) ? q1 : q0, x4, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1 << i, x4, vex.l ? 2 : 1); - VMERGE_VVM(v1, v1, q2); - } - PUTGY_vector(v1, VECTOR_SEW32); + v2 = fpu_get_scratch(dyn); + MOV64x(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48)); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + VMV_V_X(q2, x4); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VID_V(VMASK, VECTOR_UNMASKED); + VMSGT_VI(VMASK, VMASK, 3, VECTOR_UNMASKED); + VOR_VI(q2, q2, 4, VECTOR_MASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); + VRGATHEREI16_VV(v1, q0, q2, VECTOR_UNMASKED); + VRGATHEREI16_VV(v2, q1, q2, VECTOR_UNMASKED); + VECTOR_LOAD_VMASK(vex.l ? 0xcc : 0x0c, x4, vex.l ? 2 : 1); + VMERGE_VVM(v0, v1, v2); + PUTGY_vector(v0, VECTOR_SEW32); break; default: DEFAULT_VECTOR; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c index 7eb30d766..0cbfb3ffc 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c @@ -2186,7 +2186,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDC: INST_NAME("VAESENC Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && cpuext.vlen >= 32 && !vex.l) { + if (cpuext.zvkned && cpuext.vlen >= 32) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); @@ -2258,7 +2258,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDD: INST_NAME("VAESENCLAST Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && cpuext.vlen >= 32 && !vex.l) { + if (cpuext.zvkned && cpuext.vlen >= 32) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); @@ -2365,7 +2365,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDE: INST_NAME("VAESDEC Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && cpuext.vlen >= 32 && !vex.l) { + if (cpuext.zvkned && cpuext.vlen >= 32) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); @@ -2444,7 +2444,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDF: INST_NAME("VAESDECLAST Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && cpuext.vlen >= 32 && !vex.l) { + if (cpuext.zvkned && cpuext.vlen >= 32) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c index 4bc8e5b9e..abd9303d5 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c @@ -26,7 +26,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint uint8_t opcode = F8; uint8_t nextop; - uint8_t gd, ed; + uint8_t gd, ed, vd, wback; uint8_t u8; int v0, v1, v2; int q0, q1, q2, q3, q4, q5; @@ -44,7 +44,6 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint switch (opcode) { case 0x00: INST_NAME("VPSHUFB Gx, Vx, Ex"); - BARRIER(BARRIER_FLOAT); nextop = F8; GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); v1 = fpu_get_scratch(dyn); @@ -63,6 +62,93 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VRGATHER_VV_SAFE(v0, q0, v2, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; + +#define GO(SEW, OP) \ + do { \ + int E_ = 16 >> (SEW); \ + int S_ = (vex.l ? 2 : 1) * E_; \ + q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); \ + q5 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); \ + q3 = fpu_get_scratch(dyn); \ + q4 = fpu_get_scratch(dyn); \ + vector_vsetvli(dyn, ninst, x1, (SEW), VECTOR_LMUL1, S_ / E_); \ + VMV_V_V(q2, q0); \ + if (q1 & 1) VMV_V_V(q5, q1); \ + vector_vsetvli(dyn, ninst, x1, (SEW), VECTOR_LMUL2, 2 * S_ / E_); \ + VSLIDEUP_VI_SAFE(q2, (q1 & 1) ? q5 : q1, S_, VECTOR_UNMASKED); \ + vector_vsetvli(dyn, ninst, x1, (SEW), VECTOR_LMUL1, S_ / E_); \ + VNSRL_WI(q3, q2, 0, VECTOR_UNMASKED); \ + if ((SEW) == VECTOR_SEW16) { \ + VNSRL_WI(q4, q2, 16, VECTOR_UNMASKED); \ + } else { \ + ADDI(x4, xZR, 32); \ + VNSRL_WX(q4, q2, x4, VECTOR_UNMASKED); \ + } \ + if (vex.l) { \ + OP(q3, q3, q4, VECTOR_UNMASKED); \ + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 2); \ + MOV64x(x4, 0x0003000100020000ULL); \ + VMV_S_X(q4, x4); \ + VRGATHEREI16_VV(v0, q3, q4, VECTOR_UNMASKED); \ + } else { \ + OP(v0, q3, q4, VECTOR_UNMASKED); \ + } \ + PUTGY_vector(v0, (SEW)); \ + } while (0) + + case 0x01: + INST_NAME("VPHADDW Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW16, 0); + GO(VECTOR_SEW16, VADD_VV); + break; + case 0x02: + INST_NAME("VPHADDD Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW32, 0); + GO(VECTOR_SEW32, VADD_VV); + break; + case 0x03: + INST_NAME("VPHADDSW Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW16, 0); + GO(VECTOR_SEW16, VSADD_VV); + break; + case 0x04: + INST_NAME("VPMADDUBSW Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); + q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + q3 = fpu_get_scratch(dyn); + q4 = fpu_get_scratch(dyn); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16 << vex.l); + VWMULSU_VV(q2, q1, q0, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, vex.l ? 2 : 1); + VNSRL_WI(q3, q2, 0, VECTOR_UNMASKED); + VNSRL_WI(q4, q2, 16, VECTOR_UNMASKED); + VSADD_VV(v0, q3, q4, VECTOR_UNMASKED); + PUTGY_vector(v0, VECTOR_SEW16); + break; + case 0x05: + INST_NAME("VPHSUBW Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW16, 0); + GO(VECTOR_SEW16, VSUB_VV); + break; + case 0x06: + INST_NAME("VPHSUBD Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW32, 0); + GO(VECTOR_SEW32, VSUB_VV); + break; + case 0x07: + INST_NAME("VPHSUBSW Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW16, 0); + GO(VECTOR_SEW16, VSSUB_VV); + break; +#undef GO + case 0x08: INST_NAME("VPSIGNB Gx, Vx, Ex"); nextop = F8; @@ -167,6 +253,31 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint SET_FLAGS_EQZ(x4, F_CF, x5); } break; + case 0x17: + INST_NAME("VPTEST Gx, Ex"); + nextop = F8; + SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); + GETGY_vector(q0, VECTOR_SEW32); + GETEY_vector(q1, 0, VECTOR_SEW32); + v0 = fpu_get_scratch(dyn); + CLEAR_FLAGS(); + SET_DFNONE(); + IFX (X_ZF) { + VAND_VV(v0, q0, q1, VECTOR_UNMASKED); + VMSNE_VX(VMASK, v0, xZR, VECTOR_UNMASKED); + VMV_X_S(x4, VMASK); + ANDI(x4, x4, (1 << (4 << vex.l)) - 1); + SET_FLAGS_EQZ(x4, F_ZF, x5); + } + IFX (X_CF) { + VXOR_VI(v0, q0, 0x1f, VECTOR_UNMASKED); + VAND_VV(v0, v0, q1, VECTOR_UNMASKED); + VMSNE_VX(VMASK, v0, xZR, VECTOR_UNMASKED); + VMV_X_S(x4, VMASK); + ANDI(x4, x4, (1 << (4 << vex.l)) - 1); + SET_FLAGS_EQZ(x4, F_CF, x5); + } + break; case 0x16: if (!vex.l) return 0; INST_NAME("VPERMPS Gx, Vx, Ex"); @@ -1146,9 +1257,85 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint PUTGY_vector(v0, sew); break; case 0xDC: + if (!cpuext.zvkned) { + BARRIER(BARRIER_FLOAT); + return 0; + } + INST_NAME("VAESENC Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + if (v0 != q0) { + if (v0 == q1) { + q2 = fpu_get_scratch(dyn); + VMV_V_V(q2, q1); + q1 = q2; + } + VMV_V_V(v0, q0); + } + VAESEM_VV(v0, q1); + PUTGY_vector(v0, VECTOR_SEW32); + break; case 0xDD: - BARRIER(BARRIER_FLOAT); - return 0; + if (!cpuext.zvkned) { + BARRIER(BARRIER_FLOAT); + return 0; + } + INST_NAME("VAESENCLAST Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + if (v0 != q0) { + if (v0 == q1) { + q2 = fpu_get_scratch(dyn); + VMV_V_V(q2, q1); + q1 = q2; + } + VMV_V_V(v0, q0); + } + VAESEF_VV(v0, q1); + PUTGY_vector(v0, VECTOR_SEW32); + break; + case 0xDE: + if (!cpuext.zvkned) { + BARRIER(BARRIER_FLOAT); + return 0; + } + INST_NAME("VAESDEC Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + if (v0 == q1) { + q2 = fpu_get_scratch(dyn); + VMV_V_V(q2, q1); + q1 = q2; + } + if (v0 != q0) VMV_V_V(v0, q0); + v1 = fpu_get_scratch(dyn); + VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); + VAESDF_VV(v0, v1); + MOV32w(x4, 0x63636363); + VMV_V_X(v1, x4); + VAESDM_VV(v1, v0); + VXOR_VV(v0, v1, q1, VECTOR_UNMASKED); + PUTGY_vector(v0, VECTOR_SEW32); + break; + case 0xDF: + if (!cpuext.zvkned) { + BARRIER(BARRIER_FLOAT); + return 0; + } + INST_NAME("VAESDECLAST Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + if (v0 != q0) { + if (v0 == q1) { + q2 = fpu_get_scratch(dyn); + VMV_V_V(q2, q1); + q1 = q2; + } + VMV_V_V(v0, q0); + } + VAESDF_VV(v0, q1); + PUTGY_vector(v0, VECTOR_SEW32); + break; case 0x13: if (!cpuext.zvfh) { BARRIER(BARRIER_FLOAT); @@ -1519,6 +1706,36 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VMERGE_VVM(v0, q2, v0); PUTGY_vector(v0, sew); break; + case 0xF7: + INST_NAME("SHLX Gd, Ed, Vd"); + nextop = F8; + GETGDd; + GETED(0); + GETVD; + SLLxw(gd, ed, vd); + break; + case 0x41: + if (vex.l || cpuext.xtheadvector) return 0; + INST_NAME("VPHMINPOSUW Gx, Ex"); + nextop = F8; + GETEY_vector(q0, 0, VECTOR_SEW16); + GETGY_empty_vector(v0); + q1 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch(dyn); + VMV_V_I(q2, -1); + VREDMINU_VS(q1, q0, q2, VECTOR_UNMASKED); + VMV_X_S(x4, q1); + ZEXTH(x4, x4); + VMSEQ_VX(VMASK, q0, x4, VECTOR_UNMASKED); + VFIRST_M(x5, VMASK, VECTOR_UNMASKED); + SLLI(x5, x5, 16); + OR(x4, x4, x5); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 0.25f); + VMV_S_X(v0, x4); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + break; default: DEFAULT_VECTOR; } diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c index 133bf5200..8b40a4dbd 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c @@ -93,16 +93,16 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETGY_empty_vector(v0); u8 = F8; VEC_SRC_KEEP(q0, v0); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); q1 = fpu_get_scratch(dyn); - for (int i = 0; i < (4 << vex.l); ++i) { - int lane = i & ~3; - int selector = lane + ((u8 >> ((i & 3) * 2)) & 3); - MOV32w(x4, selector); - VRGATHER_VX(q1, q0, x4, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1 << i, x4, vex.l ? 2 : 1); - VMERGE_VVM(v0, v0, q1); - } + MOV64x(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48)); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + VMV_V_X(q1, x4); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VID_V(VMASK, VECTOR_UNMASKED); + VMSGT_VI(VMASK, VMASK, 3, VECTOR_UNMASKED); + VOR_VI(q1, q1, 4, VECTOR_MASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); + VRGATHEREI16_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x05: @@ -112,64 +112,46 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETGY_empty_vector(v0); u8 = F8; VEC_SRC_KEEP(q0, v0); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); q1 = fpu_get_scratch(dyn); - for (int i = 0; i < (2 << vex.l); ++i) { - int lane = i & ~1; - int selector = lane + ((u8 >> i) & 1); - MOV32w(x4, selector); - VRGATHER_VX(q1, q0, x4, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1 << i, x4, vex.l ? 2 : 1); - VMERGE_VVM(v0, v0, q1); - } + MOV64x(x4, (uint64_t)(u8 & 1) | ((uint64_t)((u8 >> 1) & 1) << 16) | ((uint64_t)(((u8 >> 2) & 1) + 2) << 32) | ((uint64_t)(((u8 >> 3) & 1) + 2) << 48)); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + VMV_S_X(q1, x4); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); + VRGATHEREI16_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x06: if (!vex.l) return 0; INST_NAME("VPERM2F128 Gx, Vx, Ex, Ib"); nextop = F8; - GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW8, 1); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW64, 1); u8 = F8; - q2 = fpu_get_scratch(dyn); - q3 = fpu_get_scratch(dyn); - if (q0 == v0) { - q4 = fpu_get_scratch(dyn); - VMV_V_V(q4, q0); - q0 = q4; - } - if (q1 == v0) { - q4 = fpu_get_scratch(dyn); - VMV_V_V(q4, q1); - q1 = q4; - } - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - for (int i = 0; i < 2; ++i) { - int control = i ? (u8 >> 4) : u8; - int source = (control >> 1) & 1; - int index = control & 1; - int zero = control & 8; + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VMV_V_V(v0, q0); + for (int j = 0; j < 2; ++j) { + int control = j ? (u8 >> 4) & 3 : u8 & 3; + int zero = j ? (u8 & 0x80) : (u8 & 0x08); + int mask = j ? 0xc : 0x3; if (zero) { - VXOR_VV(q2, q2, q2, VECTOR_UNMASKED); - } else if (source) { - if (index) - VSLIDEDOWN_VI(q2, q1, 16, VECTOR_UNMASKED); - else - VMV_V_V(q2, q1); - } else { - if (index) - VSLIDEDOWN_VI(q2, q0, 16, VECTOR_UNMASKED); - else - VMV_V_V(q2, q0); - } - if (i) { - VMV_V_V(q3, q1); - VSLIDEUP_VI_SAFE(q3, q2, 16, VECTOR_UNMASKED); - q2 = q3; + VECTOR_LOAD_VMASK(mask, x4, 1); + VXOR_VV(v0, v0, v0, VECTOR_MASKED); + } else if (control != j) { + int src = (control & 2) ? q1 : q0; + VECTOR_LOAD_VMASK(mask, x4, 1); + if (((j == 0) && ((control & 1) == 0)) || ((j == 1) && ((control & 1) == 1))) { + VMERGE_VVM(v0, v0, src); + } else { + q2 = fpu_get_scratch(dyn); + if (j) + VSLIDEUP_VI(q2, src, 2, VECTOR_UNMASKED); + else + VSLIDEDOWN_VI(q2, src, 2, VECTOR_UNMASKED); + VMERGE_VVM(v0, v0, q2); + } } - VECTOR_LOAD_VMASK(i ? 0xffff0000 : 0xffff, x4, 2); - VMERGE_VVM(v0, v0, q2); } - PUTGY_vector(v0, VECTOR_SEW8); + PUTGY_vector(v0, VECTOR_SEW64); break; case 0x0E: INST_NAME("VPBLENDW Gx, Vx, Ex, Ib"); @@ -184,44 +166,28 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (!vex.l) return 0; INST_NAME("VINSERTF128 Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector(q0, VECTOR_SEW64); q1 = fpu_get_scratch(dyn); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); - avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, VECTOR_SEW8); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, VECTOR_SEW64); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 1); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); - VLE8_V(q1, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + VLE64_V(q1, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); } u8 = F8; - if (!(u8 & 1)) - v1 = fpu_get_scratch(dyn); - gd = ((nextop & 0x38) >> 3) + (rex.r << 3); - if (q0 == VREG(gd)) { - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 32); - q2 = fpu_get_scratch(dyn); - VMV_V_V(q2, q0); - q0 = q2; - } - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); - sse_forget_reg_vector(dyn, ninst, x1, gd); - sse_set_pending_zero(dyn, gd, 0); - ADDI(x1, xEmu, offsetof(x64emu_t, xmm[gd])); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 2); + GETGY_empty_vector(v0); + VMV_V_V(v0, q0); if (u8 & 1) { - VSE8_V(q0, x1, VECTOR_UNMASKED, VECTOR_NFIELD1); - ADDI(x1, xEmu, offsetof(x64emu_t, ymm[gd])); - VSE8_V(q1, x1, VECTOR_UNMASKED, VECTOR_NFIELD1); + VSLIDEUP_VI_SAFE(v0, q1, 2, VECTOR_UNMASKED); } else { - VSE8_V(q1, x1, VECTOR_UNMASKED, VECTOR_NFIELD1); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 32); - VSLIDEDOWN_VI(v1, q0, 16, VECTOR_UNMASKED); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); - ADDI(x1, xEmu, offsetof(x64emu_t, ymm[gd])); - VSE8_V(v1, x1, VECTOR_UNMASKED, VECTOR_NFIELD1); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + VMV_V_V(v0, q1); } - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 32); + PUTGY_vector(v0, VECTOR_SEW64); break; case 0x19: if (!vex.l) return 0; @@ -376,48 +342,34 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (!vex.l) return 0; INST_NAME("VPERM2I128 Gx, Vx, Ex, Ib"); nextop = F8; - GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW8, 1); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW64, 1); u8 = F8; - q2 = fpu_get_scratch(dyn); - q3 = fpu_get_scratch(dyn); - if (q0 == v0) { - q4 = fpu_get_scratch(dyn); - VMV_V_V(q4, q0); - q0 = q4; - } - if (q1 == v0) { - q4 = fpu_get_scratch(dyn); - VMV_V_V(q4, q1); - q1 = q4; - } - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - for (int i = 0; i < 2; ++i) { - int control = i ? (u8 >> 4) : u8; - int source = (control >> 1) & 1; - int index = control & 1; - int zero = control & 8; + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VMV_V_V(v0, q0); + for (int j = 0; j < 2; ++j) { + int control = j ? (u8 >> 4) & 3 : u8 & 3; + int zero = j ? (u8 & 0x80) : (u8 & 0x08); + int mask = j ? 0xc : 0x3; if (zero) { - VXOR_VV(q2, q2, q2, VECTOR_UNMASKED); - } else if (source) { - if (index) - VSLIDEDOWN_VI(q2, q1, 16, VECTOR_UNMASKED); - else - VMV_V_V(q2, q1); - } else { - if (index) - VSLIDEDOWN_VI(q2, q0, 16, VECTOR_UNMASKED); - else - VMV_V_V(q2, q0); - } - if (i) { - VMV_V_V(q3, q1); - VSLIDEUP_VI_SAFE(q3, q2, 16, VECTOR_UNMASKED); - q2 = q3; + VECTOR_LOAD_VMASK(mask, x4, 1); + VXOR_VV(v0, v0, v0, VECTOR_MASKED); + } else if (control != j) { + int src = (control & 2) ? q1 : q0; + VECTOR_LOAD_VMASK(mask, x4, 1); + if (((j == 0) && ((control & 1) == 0)) || ((j == 1) && ((control & 1) == 1))) { + VMERGE_VVM(v0, v0, src); + } else { + q2 = fpu_get_scratch(dyn); + if (j) + VSLIDEUP_VI(q2, src, 2, VECTOR_UNMASKED); + else + VSLIDEDOWN_VI(q2, src, 2, VECTOR_UNMASKED); + VMERGE_VVM(v0, v0, q2); + } } - VECTOR_LOAD_VMASK(i ? 0xffff0000 : 0xffff, x4, 2); - VMERGE_VVM(v0, v0, q2); } - PUTGY_vector(v0, VECTOR_SEW8); + PUTGY_vector(v0, VECTOR_SEW64); break; case 0x08: INST_NAME("VROUNDPS Gx, Ex, Ib"); @@ -831,24 +783,31 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETGY_empty_vector(v0); u8 = F8; q2 = fpu_get_scratch(dyn); + VMV_V_V(q2, q0); if (MODREG) { - VSLIDEDOWN_VI(q2, q1, (u8 >> 6) & 3, VECTOR_UNMASKED); - VMV_X_S(x5, q2); + q3 = fpu_get_scratch(dyn); + int count_s = (u8 >> 6) & 3; + int count_d = (u8 >> 4) & 3; + if (count_s > count_d) { + VSLIDEDOWN_VI(q3, q1, count_s - count_d, VECTOR_UNMASKED); + } else if (count_s < count_d) { + VSLIDEUP_VI_SAFE(q3, q1, count_d - count_s, VECTOR_UNMASKED); + } else { + q3 = q1; + } } else { + q3 = fpu_get_scratch(dyn); LWU(x5, ed, fixedaddress); + VMV_V_X(q3, x5); } + VECTOR_LOAD_VMASK(1 << ((u8 >> 4) & 3), x4, 1); + VMERGE_VVM(q2, q2, q3); // zero out the dwords selected by imm8[3:0] - VECTOR_LOAD_VMASK(u8 & 0xf, x4, 1); - q3 = fpu_get_scratch(dyn); - q4 = fpu_get_scratch(dyn); - VXOR_VV(q3, q3, q3, VECTOR_UNMASKED); - VMERGE_VVM(q4, q0, q3); - if (!(u8 & (1 << ((u8 >> 4) & 3)))) { - VECTOR_LOAD_VMASK(1 << ((u8 >> 4) & 3), x4, 1); - VMV_V_X(q3, x5); - VMERGE_VVM(q4, q4, q3); + if (u8 & 0xf) { + VECTOR_LOAD_VMASK(u8 & 0xf, x4, 1); + VXOR_VV(q2, q2, q2, VECTOR_MASKED); } - PUTGY_vector(q4, VECTOR_SEW32); + PUTGY_vector(q2, VECTOR_SEW32); break; case 0x40: { INST_NAME("VDPPS Gx, Vx, Ex, Ib"); @@ -886,6 +845,20 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint PUTGY_vector(q3, VECTOR_SEW32); break; } + case 0x4A: + INST_NAME("VBLENDVPS Gx, Vx, Ex, Vx2"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16 << vex.l, VECTOR_SEW32); + GETEY_vector(q1, 1, VECTOR_SEW32); + u8 = F8; + q2 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q2, (u8 >> 4) & 0xf, 16 << vex.l, VECTOR_SEW32); + GETGY_empty_vector(v0); + VMSLT_VX(VMASK, q2, xZR, VECTOR_UNMASKED); + VMERGE_VVM(v0, q0, q1); + PUTGY_vector(v0, VECTOR_SEW32); + break; case 0x4C: if (rex.w) return 0; INST_NAME("VPBLENDVB Gx, Vx, Ex, Vx2"); @@ -915,6 +888,49 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VMERGE_VVM(v0, q0, q1); PUTGY_vector(v0, VECTOR_SEW64); break; + case 0x0D: + INST_NAME("VBLENDPD Gx, Vx, Ex, Ib"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW64, 1); + u8 = F8; + VECTOR_LOAD_VMASK(vex.l ? (u8 & 0xf) : (u8 & 0x3), x4, vex.l ? 2 : 1); + VMERGE_VVM(v0, q0, q1); + PUTGY_vector(v0, VECTOR_SEW64); + break; + case 0x0F: + INST_NAME("VPALIGNR Gx, Vx, Ex, Ib"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW8, 1); + u8 = F8; + if (u8 > 31) { + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + } else { + q2 = fpu_get_scratch(dyn); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 4); + VXOR_VV(q2, q2, q2, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VMV_V_V(q2, q1); + VSLIDEUP_VI_SAFE(q2, q0, 16, VECTOR_UNMASKED); + if (vex.l) { + q3 = fpu_get_scratch(dyn); + q4 = fpu_get_scratch(dyn); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 4); + VXOR_VV(q3, q3, q3, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VMV_V_V(q3, q0); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 1); + VSLIDEDOWN_VI(q3, q1, 16, VECTOR_UNMASKED); + VSLIDEDOWN_VI(q4, q3, u8, VECTOR_UNMASKED); + } + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 1); + VSLIDEDOWN_VI(v0, q2, u8, VECTOR_UNMASKED); + if (vex.l) { + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VSLIDEUP_VI_SAFE(v0, q4, 16, VECTOR_UNMASKED); + } + } + PUTGY_vector(v0, VECTOR_SEW8); + break; default: DEFAULT_VECTOR; } diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index 0efa99b37..f70e51f4d 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -29,7 +29,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt uint8_t gd, ed; uint8_t wback; int v0, v1, v2; - int q0, q1, q2, d0, d1; + int q0, q1, q2, q3, q4, q5, d0, d1; uint64_t selectors; int64_t fixedaddress; rex_t rex = vex.rex; @@ -325,18 +325,20 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt nextop = F8; GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); q2 = fpu_get_scratch(dyn); - v1 = fpu_get_scratch(dyn); - v2 = fpu_get_scratch(dyn); - VID_V(q2, VECTOR_UNMASKED); - MOV32w(x4, 16); - VAND_VX(v1, q2, x4, VECTOR_UNMASKED); - VAND_VI(q2, q2, 15, VECTOR_UNMASKED); - VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); - VADD_VV(q2, q2, v1, VECTOR_UNMASKED); - VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(0xaaaaaaaa, x4, vex.l ? 2 : 1); - VMERGE_VVM(v0, v1, v2); + q3 = fpu_get_scratch(dyn); + q4 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + { + int w2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, vex.l ? 2 : 1); + VMV_V_I(VMASK, 0b0101); + VCOMPRESS_VM(q2, q0, VMASK); + VCOMPRESS_VM(q3, q1, VMASK); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, vex.l ? 2 : 1); + VWADDU_VX(q4, q2, xZR, VECTOR_UNMASKED); + VWADDU_VX(w2, q3, xZR, VECTOR_UNMASKED); + VSLIDE1UP_VX(q2, w2, xZR, VECTOR_UNMASKED); + VOR_VV(v0, q2, q4, VECTOR_UNMASKED); + } PUTGY_vector(v0, VECTOR_SEW8); break; case 0x61: @@ -376,16 +378,34 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt PUTGY_vector(v0, VECTOR_SEW32); break; case 0x63: - if (vex.l) return 0; INST_NAME("VPACKSSWB Gx, Vx, Ex"); nextop = F8; GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); - VMV_V_V(q2, q0); - VSLIDEUP_VI_SAFE(q2, q1, 8, VECTOR_UNMASKED); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); - VNCLIP_WI(v0, q2, 0, VECTOR_UNMASKED); + if (vex.l) { + q3 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + q4 = fpu_get_scratch(dyn); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); + VMV_V_V(q2, q0); + if (q1 & 1) { + VMV_V_V(q3, q1); + q1 = q3; + } + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 4); + VSLIDEUP_VI_SAFE(q2, q1, 16, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 32); + VNCLIP_WI(q4, q2, 0, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 2); + MOV64x(x4, 0x0003000100020000ULL); + VMV_S_X(q3, x4); + VRGATHEREI16_VV(v0, q4, q3, VECTOR_UNMASKED); + } else { + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); + VMV_V_V(q2, q0); + VSLIDEUP_VI_SAFE(q2, q1, 8, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); + VNCLIP_WI(v0, q2, 0, VECTOR_UNMASKED); + } PUTGY_vector(v0, VECTOR_SEW8); break; case 0x68: @@ -393,19 +413,20 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt nextop = F8; GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); q2 = fpu_get_scratch(dyn); - v1 = fpu_get_scratch(dyn); - v2 = fpu_get_scratch(dyn); - VID_V(q2, VECTOR_UNMASKED); - MOV32w(x4, 16); - VAND_VX(v1, q2, x4, VECTOR_UNMASKED); - VAND_VI(q2, q2, 15, VECTOR_UNMASKED); - VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); - VADD_VI(q2, q2, 8, VECTOR_UNMASKED); - VADD_VV(q2, q2, v1, VECTOR_UNMASKED); - VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(0xaaaaaaaa, x4, vex.l ? 2 : 1); - VMERGE_VVM(v0, v1, v2); + q3 = fpu_get_scratch(dyn); + q4 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + { + int w2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, vex.l ? 2 : 1); + VMV_V_I(VMASK, 0b1010); + VCOMPRESS_VM(q2, q0, VMASK); + VCOMPRESS_VM(q3, q1, VMASK); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, vex.l ? 2 : 1); + VWADDU_VX(q4, q2, xZR, VECTOR_UNMASKED); + VWADDU_VX(w2, q3, xZR, VECTOR_UNMASKED); + VSLIDE1UP_VX(q2, w2, xZR, VECTOR_UNMASKED); + VOR_VV(v0, q2, q4, VECTOR_UNMASKED); + } PUTGY_vector(v0, VECTOR_SEW8); break; case 0x69: @@ -447,31 +468,64 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt PUTGY_vector(v0, VECTOR_SEW32); break; case 0x6B: - if (vex.l) return 0; INST_NAME("VPACKSSDW Gx, Vx, Ex"); nextop = F8; GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 32); - VMV_V_V(q2, q0); - VSLIDEUP_VI_SAFE(q2, q1, 4, VECTOR_UNMASKED); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16); - VNCLIP_WI(v0, q2, 0, VECTOR_UNMASKED); + if (vex.l) { + q3 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + q4 = fpu_get_scratch(dyn); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 32); + VMV_V_V(q2, q0); + if (q1 & 1) { + VMV_V_V(q3, q1); + q1 = q3; + } + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL2, 4); + VSLIDEUP_VI_SAFE(q2, q1, 8, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); + VNCLIP_WI(q4, q2, 0, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 2); + MOV64x(x4, 0x0003000100020000ULL); + VMV_S_X(q3, x4); + VRGATHEREI16_VV(v0, q4, q3, VECTOR_UNMASKED); + } else { + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 32); + VMV_V_V(q2, q0); + VSLIDEUP_VI_SAFE(q2, q1, 4, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16); + VNCLIP_WI(v0, q2, 0, VECTOR_UNMASKED); + } PUTGY_vector(v0, VECTOR_SEW16); break; case 0x67: - if (vex.l) return 0; INST_NAME("VPACKUSWB Gx, Vx, Ex"); nextop = F8; GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); - VMAX_VX(q2, q0, xZR, VECTOR_UNMASKED); - v1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); - VMAX_VX(v1, q1, xZR, VECTOR_UNMASKED); - VSLIDEUP_VI_SAFE(q2, v1, 8, VECTOR_UNMASKED); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); - VNCLIPU_WI(v0, q2, 0, VECTOR_UNMASKED); + if (vex.l) { + q3 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + q4 = fpu_get_scratch(dyn); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); + VMAX_VX(q2, q0, xZR, VECTOR_UNMASKED); + VMAX_VX(q3, q1, xZR, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 4); + VSLIDEUP_VI_SAFE(q2, q3, 16, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 32); + VNCLIPU_WI(q4, q2, 0, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 2); + MOV64x(x4, 0x0003000100020000ULL); + VMV_S_X(q3, x4); + VRGATHEREI16_VV(v0, q4, q3, VECTOR_UNMASKED); + } else { + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); + VMAX_VX(q2, q0, xZR, VECTOR_UNMASKED); + v1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + VMAX_VX(v1, q1, xZR, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q2, v1, 8, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); + VNCLIPU_WI(v0, q2, 0, VECTOR_UNMASKED); + } PUTGY_vector(v0, VECTOR_SEW8); break; case 0x6C: @@ -845,6 +899,32 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VAND_VX(v0, v0, x5, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; + case 0xE1: + INST_NAME("VPSRAW Gx, Vx, Ex"); + nextop = F8; + GETVY_vector(q0, VECTOR_SEW16); + GETEY128_vector(q1, 0, VECTOR_SEW64); + GETGY_empty_vector(v0); + VMV_X_S(x4, q1); + ADDI(x5, xZR, 15); + MINU(x4, x4, x5); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW16); + VSRA_VX(v0, q0, x4, VECTOR_UNMASKED); + PUTGY_vector(v0, VECTOR_SEW16); + break; + case 0xE2: + INST_NAME("VPSRAD Gx, Vx, Ex"); + nextop = F8; + GETVY_vector(q0, VECTOR_SEW32); + GETEY128_vector(q1, 0, VECTOR_SEW64); + GETGY_empty_vector(v0); + VMV_X_S(x4, q1); + ADDI(x5, xZR, 31); + MINU(x4, x4, x5); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); + VSRA_VX(v0, q0, x4, VECTOR_UNMASKED); + PUTGY_vector(v0, VECTOR_SEW32); + break; case 0xD6: if (vex.l) return 0; INST_NAME("VMOVQ Ex, Gx"); @@ -1109,6 +1189,44 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VADD_VV(v0, d0, d1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; + case 0xF6: + INST_NAME("VPSADBW Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); + q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + v1 = fpu_get_scratch(dyn); + v2 = fpu_get_scratch(dyn); + d0 = q2 + 1; // second register of the LMUL2 group, used at VLEN=256 + if (vex.l && cpuext.vlen > 32) d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16 << vex.l); + VMINU_VV(v1, q0, q1, VECTOR_UNMASKED); + VMAXU_VV(v2, q0, q1, VECTOR_UNMASKED); + VSUB_VV(v1, v2, v1, VECTOR_UNMASKED); + VWADDU_VX(q2, v1, xZR, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, vex.l ? 4 : 2); + if (vex.l && cpuext.vlen > 32) VSLIDEDOWN_VI(d0, q2, 16, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 2); + ADDI(x4, xZR, 0xFF); + VMV_S_X(VMASK, x4); + VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); + VREDSUM_VS(v1, q2, v1, VECTOR_MASKED); + VSLIDEUP_VI_SAFE(v0, v1, 0, VECTOR_UNMASKED); + VMNAND_MM(VMASK, VMASK, VMASK); + VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); + VREDSUM_VS(v1, q2, v1, VECTOR_MASKED); + VSLIDEUP_VI_SAFE(v0, v1, 4, VECTOR_UNMASKED); + if (vex.l) { + VMNAND_MM(VMASK, VMASK, VMASK); + VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); + VREDSUM_VS(v1, d0, v1, VECTOR_MASKED); + VSLIDEUP_VI_SAFE(v0, v1, 8, VECTOR_UNMASKED); + VMNAND_MM(VMASK, VMASK, VMASK); + VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); + VREDSUM_VS(v1, d0, v1, VECTOR_MASKED); + VSLIDEUP_VI_SAFE(v0, v1, 12, VECTOR_UNMASKED); + } + PUTGY_vector(v0, VECTOR_SEW16); + break; case 0xF8: INST_NAME("VPSUBB Gx, Vx, Ex"); nextop = F8; @@ -1252,6 +1370,118 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VMERGE_VVM(v0, q2, v2); PUTGY_vector(v0, VECTOR_SEW64); break; + case 0xC2: + INST_NAME("VCMPPD Gx, Vx, Ex, Ib"); + nextop = F8; + GETVY_vector(q0, VECTOR_SEW64); + GETEY_vector(q1, 1, VECTOR_SEW64); + u8 = F8; + GETGY_empty_vector(v0); + q2 = fpu_get_scratch(dyn); + d0 = fpu_get_scratch(dyn); + switch (u8 & 0xf) { + case 0x0: VMFEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; + case 0x1: VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; + case 0x2: VMFLE_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; + case 0x3: + AVX_CMP_ORDERED_MASK(); + VMNAND_MM(VMASK, q2, q2); + break; + case 0x4: + VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); + VMNAND_MM(VMASK, d0, d0); + break; + case 0x5: + VMFLT_VV(d0, q0, q1, VECTOR_UNMASKED); + VMNAND_MM(VMASK, d0, d0); + break; + case 0x6: + VMFLE_VV(d0, q0, q1, VECTOR_UNMASKED); + VMNAND_MM(VMASK, d0, d0); + break; + case 0x7: + AVX_CMP_ORDERED_MASK(); + VMAND_MM(VMASK, q2, q2); + break; + case 0x8: + AVX_CMP_ORDERED_MASK(); + VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); + VMNAND_MM(VMASK, q2, q2); + VMOR_MM(VMASK, VMASK, d0); + break; + case 0x9: + VMFLE_VV(d0, q1, q0, VECTOR_UNMASKED); + VMNAND_MM(VMASK, d0, d0); + break; + case 0xa: + VMFLT_VV(d0, q1, q0, VECTOR_UNMASKED); + VMNAND_MM(VMASK, d0, d0); + break; + case 0xb: VMXOR_MM(VMASK, q2, q2); break; + case 0xc: + AVX_CMP_ORDERED_MASK(); + VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); + VMNAND_MM(VMASK, d0, d0); + VMAND_MM(VMASK, VMASK, q2); + break; + case 0xd: VMFLE_VV(VMASK, q1, q0, VECTOR_UNMASKED); break; + case 0xe: VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); break; + case 0xf: VMXNOR_MM(VMASK, q2, q2); break; + } + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + VMERGE_VIM(v0, v0, 0x1f); + PUTGY_vector(v0, VECTOR_SEW64); + break; + case 0xE6: + if (!BOX64ENV(dynarec_fastround)) return 0; + INST_NAME("VCVTTPD2DQ Gx, Ex"); + nextop = F8; + GETEY_vector(q0, 0, VECTOR_SEW64); + GETGY_empty_vector(v0); + d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + q2 = fpu_get_scratch(dyn); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); + VMV_V_V(d0, q0); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, vex.l ? 1 : 0.5f); + VFNCVT_RTZ_X_F_W(q2, d0, VECTOR_UNMASKED); + VMV_V_V(v0, q2); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + break; + case 0x7C: + case 0x7D: + if (!BOX64ENV(dynarec_fastnan)) return 0; + if (opcode == 0x7C) { + INST_NAME("VHADDPD Gx, Vx, Ex"); + } else { + INST_NAME("VHSUBPD Gx, Vx, Ex"); + } + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); + q2 = fpu_get_scratch(dyn); + q3 = fpu_get_scratch(dyn); + q4 = fpu_get_scratch(dyn); + q5 = fpu_get_scratch(dyn); + VSLIDEDOWN_VI(q2, q0, 1, VECTOR_UNMASKED); + if (opcode == 0x7C) + VFADD_VV(q2, q0, q2, VECTOR_UNMASKED); + else + VFSUB_VV(q2, q0, q2, VECTOR_UNMASKED); + VSLIDEDOWN_VI(q3, q1, 1, VECTOR_UNMASKED); + if (opcode == 0x7C) + VFADD_VV(q3, q1, q3, VECTOR_UNMASKED); + else + VFSUB_VV(q3, q1, q3, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VID_V(q4, VECTOR_UNMASKED); + VAND_VI(q4, q4, -2, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); + VRGATHEREI16_VV(q5, q3, q4, VECTOR_UNMASKED); + VECTOR_LOAD_VMASK(vex.l ? 0x0a : 0x02, x4, vex.l ? 2 : 1); + VMERGE_VVM(v0, q2, q5); + PUTGY_vector(v0, VECTOR_SEW64); + break; default: DEFAULT_VECTOR; } diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c index 1ec3b4fc3..71f4c84f6 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c @@ -28,7 +28,7 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt uint8_t nextop, u8; uint8_t gd, ed; int v0, v1, v2; - int q0, q1, q2, d0, d1; + int q0, q1, q2, q3, q4, q5, q6, d0, d1; int64_t fixedaddress; int64_t j64; rex_t rex = vex.rex; @@ -245,19 +245,27 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt GETEY_vector(q1, 1, VECTOR_SEW16); GETGY_empty_vector(v0); u8 = F8; - SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW16); q0 = fpu_get_scratch(dyn); q2 = fpu_get_scratch(dyn); - d0 = fpu_get_scratch(dyn); - VID_V(q0, VECTOR_UNMASKED); - VMV_V_V(q2, q0); - for (int k = 0; k < 4; ++k) { - VECTOR_LOAD_VMASK(vex.l ? ((1 << k) | (1 << (8 + k))) : (1 << k), x4, vex.l ? 2 : 1); - int delta = (int8_t)((u8 >> (k * 2)) & 3) - k; - if (delta) VADD_VI(d0, q0, delta, VECTOR_UNMASKED); - VMERGE_VVM(q2, q2, delta ? d0 : q0); + MOV64x(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48)); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + VMV_V_X(q0, x4); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VID_V(q2, VECTOR_UNMASKED); + VID_V(VMASK, VECTOR_UNMASKED); + VMSGT_VI(VMASK, VMASK, 3, VECTOR_UNMASKED); + VMERGE_VVM(q0, q0, q2); + if (vex.l) { + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q0); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 2); + VSLIDEUP_VI_SAFE(q0, q3, 8, VECTOR_UNMASKED); + VID_V(VMASK, VECTOR_UNMASKED); + VMSGT_VI(VMASK, VMASK, 7, VECTOR_UNMASKED); + VOR_VI(q0, q0, 8, VECTOR_MASKED); } - VRGATHER_VV_SAFE(v0, q1, q2, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16 << vex.l); + VRGATHER_VV_SAFE(v0, q1, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0x12: @@ -288,6 +296,63 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VMV_V_V(v0, v1); PUTGY_vector(v0, VECTOR_SEW8); break; + case 0xC2: + INST_NAME("VCMPSD Gx, Vx, Ex, Ib"); + nextop = F8; + AVX_SCALAR_CMP(VECTOR_SEW64); + break; + case 0xD0: + if (!BOX64ENV(dynarec_fastnan)) return 0; + INST_NAME("VADDSUBPS Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + q2 = fpu_get_scratch(dyn); + VID_V(q2, VECTOR_UNMASKED); + VAND_VI(q2, q2, 1, VECTOR_UNMASKED); + VMSEQ_VX(VMASK, q2, xZR, VECTOR_UNMASKED); + VFSUB_VV(v0, q0, q1, VECTOR_MASKED); + VXOR_VI(VMASK, VMASK, 0x1f, VECTOR_UNMASKED); + VFADD_VV(v0, q0, q1, VECTOR_MASKED); + PUTGY_vector(v0, VECTOR_SEW32); + break; + case 0x7C: + case 0x7D: + if (!BOX64ENV(dynarec_fastnan)) return 0; + if (opcode == 0x7C) { + INST_NAME("VHADDPS Gx, Vx, Ex"); + } else { + INST_NAME("VHSUBPS Gx, Vx, Ex"); + } + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + q2 = fpu_get_scratch(dyn); + q3 = fpu_get_scratch(dyn); + q4 = fpu_get_scratch(dyn); + q5 = fpu_get_scratch(dyn); + q6 = fpu_get_scratch(dyn); + VSLIDEDOWN_VI(q2, q0, 1, VECTOR_UNMASKED); + if (opcode == 0x7C) + VFADD_VV(q2, q0, q2, VECTOR_UNMASKED); + else + VFSUB_VV(q2, q0, q2, VECTOR_UNMASKED); + VSLIDEDOWN_VI(q3, q1, 1, VECTOR_UNMASKED); + if (opcode == 0x7C) + VFADD_VV(q3, q1, q3, VECTOR_UNMASKED); + else + VFSUB_VV(q3, q1, q3, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VID_V(q4, VECTOR_UNMASKED); + VAND_VI(q5, q4, 1, VECTOR_UNMASKED); + VSLL_VI(q5, q5, 1, VECTOR_UNMASKED); + VAND_VI(q4, q4, 4, VECTOR_UNMASKED); + VOR_VV(q4, q4, q5, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); + VRGATHEREI16_VV(q5, q2, q4, VECTOR_UNMASKED); + VRGATHEREI16_VV(q6, q3, q4, VECTOR_UNMASKED); + VECTOR_LOAD_VMASK(vex.l ? 0xcc : 0x0c, x4, vex.l ? 2 : 1); + VMERGE_VVM(v0, q5, q6); + PUTGY_vector(v0, VECTOR_SEW32); + break; default: DEFAULT_VECTOR; } diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c index 8d4cd0031..f52cf68f1 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c @@ -28,7 +28,7 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt uint8_t nextop, u8; uint8_t gd, ed; int v0, v1, v2; - int q0, q1, q2, d0, d1; + int q0, q1, q2, q3, d0, d1; int64_t fixedaddress; int64_t j64; rex_t rex = vex.rex; @@ -340,19 +340,27 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt GETEY_vector(q1, 1, VECTOR_SEW16); GETGY_empty_vector(v0); u8 = F8; - SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW16); q0 = fpu_get_scratch(dyn); q2 = fpu_get_scratch(dyn); - d0 = fpu_get_scratch(dyn); - VID_V(q0, VECTOR_UNMASKED); - VMV_V_V(q2, q0); - for (int k = 0; k < 4; ++k) { - VECTOR_LOAD_VMASK(vex.l ? ((1 << (4 + k)) | (1 << (12 + k))) : (1 << (4 + k)), x4, vex.l ? 2 : 1); - int delta = (int8_t)((u8 >> (k * 2)) & 3) - k; - if (delta) VADD_VI(d0, q0, delta, VECTOR_UNMASKED); - VMERGE_VVM(q2, q2, delta ? d0 : q0); + MOV64x(x4, (uint64_t)(4 + (u8 & 3)) | ((uint64_t)(4 + ((u8 >> 2) & 3)) << 16) | ((uint64_t)(4 + ((u8 >> 4) & 3)) << 32) | ((uint64_t)(4 + ((u8 >> 6) & 3)) << 48)); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + VMV_V_X(q0, x4); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VID_V(q2, VECTOR_UNMASKED); + VID_V(VMASK, VECTOR_UNMASKED); + VMSGT_VI(VMASK, VMASK, 3, VECTOR_UNMASKED); + VMERGE_VVM(q0, q2, q0); + if (vex.l) { + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q0); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 2); + VSLIDEUP_VI_SAFE(q0, q3, 8, VECTOR_UNMASKED); + VID_V(VMASK, VECTOR_UNMASKED); + VMSGT_VI(VMASK, VMASK, 7, VECTOR_UNMASKED); + VOR_VI(q0, q0, 8, VECTOR_MASKED); } - VRGATHER_VV_SAFE(v0, q1, q2, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16 << vex.l); + VRGATHER_VV_SAFE(v0, q1, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xE6: @@ -375,6 +383,11 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VMV_V_V(v0, d0); PUTGY_vector(v0, VECTOR_SEW64); break; + case 0xC2: + INST_NAME("VCMPSS Gx, Vx, Ex, Ib"); + nextop = F8; + AVX_SCALAR_CMP(VECTOR_SEW32); + break; default: DEFAULT_VECTOR; } diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c index 0b5011d79..ede569caf 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f.c @@ -154,14 +154,26 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETEB(x1, 0); GETGD; MV(x5, ed); - if (NEED_ZEROUP32(gd)) ZEROUP_RESULT(gd); - XOR(gd, gd, x5); - MOV32w(x2, 0x82f63b78); - for (int i = 0; i < 8; i++) { - SRLI((i & 1) ? gd : x4, (i & 1) ? x4 : gd, 1); - ANDI(x6, (i & 1) ? x4 : gd, 1); - BEQZ(x6, 4 + 4); - XOR((i & 1) ? gd : x4, (i & 1) ? gd : x4, x2); + if (cpuext.zbc) { + ZEROUP(gd); + XOR(x5, x5, gd); + SLLI(x5, x5, 56); + MOV64x(x2, 0x4869EC38DEA713F1ULL); + CLMUL(x5, x5, x2); + MOV64x(x2, 0x105EC76F1ULL); + CLMULH(x5, x5, x2); + SRLI(gd, gd, 8); + XOR(gd, x5, gd); + } else { + if (NEED_ZEROUP32(gd)) ZEROUP_RESULT(gd); + XOR(gd, gd, x5); + MOV32w(x2, 0x82f63b78); + for (int i = 0; i < 8; i++) { + SRLI((i & 1) ? gd : x4, (i & 1) ? x4 : gd, 1); + ANDI(x6, (i & 1) ? x4 : gd, 1); + BEQZ(x6, 4 + 4); + XOR((i & 1) ? gd : x4, (i & 1) ? gd : x4, x2); + } } break; case 0xF1: // CRC32 Gd, Ed @@ -171,17 +183,29 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETGD; GETED(0); MV(x5, ed); - if (NEED_ZEROUP32(gd)) ZEROUP_RESULT(gd); - MOV32w(x2, 0x82f63b78); - for (int j = 0; j < 4 * (rex.w + 1); ++j) { - SRLI(x3, x5, 8 * j); - ANDI(x3, x3, 0xFF); - XOR(gd, gd, x3); - for (int i = 0; i < 8; i++) { - SRLI((i & 1) ? gd : x4, (i & 1) ? x4 : gd, 1); - ANDI(x6, (i & 1) ? x4 : gd, 1); - BEQZ(x6, 4 + 4); - XOR((i & 1) ? gd : x4, (i & 1) ? gd : x4, x2); + if (cpuext.zbc) { + if (!rex.w) ZEROUP(x5); + ZEROUP(gd); + XOR(x5, x5, gd); + if (!rex.w) SLLI(x5, x5, 32); + MOV64x(x2, 0x4869EC38DEA713F1ULL); + CLMUL(x5, x5, x2); + MOV64x(x2, 0x105EC76F1ULL); + CLMULH(x5, x5, x2); + MV(gd, x5); + } else { + if (NEED_ZEROUP32(gd)) ZEROUP_RESULT(gd); + MOV32w(x2, 0x82f63b78); + for (int j = 0; j < 4 * (rex.w + 1); ++j) { + SRLI(x3, x5, 8 * j); + ANDI(x3, x3, 0xFF); + XOR(gd, gd, x3); + for (int i = 0; i < 8; i++) { + SRLI((i & 1) ? gd : x4, (i & 1) ? x4 : gd, 1); + ANDI(x6, (i & 1) ? x4 : gd, 1); + BEQZ(x6, 4 + 4); + XOR((i & 1) ? gd : x4, (i & 1) ? gd : x4, x2); + } } } break; diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index 1024b28ca..f2924f4d2 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -1171,7 +1171,8 @@ void updateUpperLiveness(dynarec_rv64_t* dyn) int j = inst->pred[p]; const instruction_rv64_t* pred = &dyn->insts[j]; merged_pending |= (pending_in[j] & (uint16_t)~pred->up32_write64) | pred->up32_skip; - merged_ymm |= (pend_ymm[j] & (uint16_t)~pred->ymm_upper_def) | (pred->ymm_zero & pred->ymm_upper_live); + uint16_t ymm_def = pred->ymm_pending_materialized ? UINT16_MAX : pred->ymm_upper_def; + merged_ymm |= (pend_ymm[j] & (uint16_t)~ymm_def) | (pred->ymm_zero & pred->ymm_upper_live); } if (inst->x64.barrier & BARRIER_FLOAT) merged_ymm = 0; if ((merged_pending != pending_in[i]) || (merged_ymm != pend_ymm[i])) { diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 08fa8d84c..abcc06dcd 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -1779,6 +1779,8 @@ void sse_forget_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a) int sse_get_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int forwrite, int sew) { sse_mark_used(dyn, ninst, a); + if (ninst >= 0 && ninst < dyn->size) + dyn->insts[ninst].vec_read |= 1u << a; if (dyn->e.ssecache[a].v != -1) { if (dyn->e.ssecache[a].vector == 0) { // it's in the fpu, forget it first... @@ -1916,7 +1918,8 @@ static void sse_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1) MESSAGE(LOG_DUMP, "\tPurge %sSSE Cache ------\n", next ? "locally " : ""); ++old; } - if (dyn->e.ssecache[i].vector) { + if (next && (dyn->purge_dead_vector & (1u << i))) { + } else if (dyn->e.ssecache[i].vector) { vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); flushed8 = 1; if (dyn->e.ssecache[i].write) { @@ -1940,6 +1943,7 @@ static void sse_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1) if (flushed8) vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); + dyn->purge_dead_vector = 0; avx_flush_pending_zero_vector(dyn, ninst, s1, next); if (old != -1) { MESSAGE(LOG_DUMP, "\t------ Purge SSE Cache\n"); @@ -2496,25 +2500,56 @@ static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, i cache->extcache[i].v = 0; } +static uint16_t vectorDeadAtTarget(dynarec_rv64_t* dyn, int i2, int ninst) +{ + if (i2 <= 0 || i2 >= ninst) + return 0; + for (int i = i2; i < ninst; ++i) { + if (!dyn->insts[i].x64.has_next || dyn->insts[i].x64.has_callret) + return 0; + if (dyn->insts[i].x64.jmp) { + int t = dyn->insts[i].x64.jmp_insts; + if (t > i2 && t <= ninst) + return 0; + } + } + uint16_t live = 0, dead = 0, seen = 0; + for (int i = i2; i <= ninst; ++i) { + uint16_t r = dyn->insts[i].vec_read & (uint16_t)~seen; + live |= r; + seen |= r; + uint16_t w = dyn->insts[i].vec_write_full & (uint16_t)~seen; + dead |= w; + seen |= w; + uint16_t u = (uint16_t)dyn->insts[i].vec_used & (uint16_t)~seen; + live |= u; + seen |= u; + } + return dead; +} + static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3) { int i2 = dyn->insts[ninst].x64.jmp_insts; if (i2 < 0) return; + uint16_t dead = vectorDeadAtTarget(dyn, i2, ninst); MESSAGE(LOG_DUMP, "\tCache Transform ---- ninst=%d -> %d\n", ninst, i2); - avx_sync_upper_vector(dyn, ninst, s1, 1); if ((!i2) || (dyn->insts[i2].x64.barrier & BARRIER_FLOAT)) { if (dyn->e.stack_next) { + dyn->purge_dead_vector = dead; fpu_purgecache(dyn, ninst, 1, s1, s2, s3); MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); return; } for (int i = 0; i < 24; ++i) if (dyn->e.extcache[i].v) { // there is something at ninst for i + dyn->purge_dead_vector = dead; fpu_purgecache(dyn, ninst, 1, s1, s2, s3); MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); return; } + avx_sync_upper_vector(dyn, ninst, s1, 1); MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); return; } @@ -2527,11 +2562,13 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in if (cache_i2.extcache[i].v) purge = 0; if (purge) { + dyn->purge_dead_vector = dead; fpu_purgecache(dyn, ninst, 1, s1, s2, s3); MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); return; } } + avx_sync_upper_vector(dyn, ninst, s1, 1); int stack_cnt = dyn->e.stack_next; int s3_top = 0xffff; extcache_t cache = dyn->e; @@ -2943,6 +2980,9 @@ void avx_sync_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next) { if (!cpuext.vlen || cpuext.vlen < 32) return; + #if STEP == 0 + if (!next) dyn->insts[ninst].ymm_pending_materialized = 1; + #endif for (int i = 0; i < 16; ++i) if (dyn->e.ssecache[i].v != -1 && dyn->e.ssecache[i].vector) avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, next, 0); @@ -2979,14 +3019,16 @@ void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a VXOR_VV(VMASK, VMASK, VMASK, VECTOR_UNMASKED); VSLIDEUP_VI(low, VMASK, 16 >> sew, VECTOR_UNMASKED); } else { + int sp = dyn->e.fpu_scratch; + int hi = fpu_get_scratch(dyn); dyn->inst_sew = VECTOR_SEWNA; dyn->inst_vl = 0; // real vtype here is unknown, never elide vsetvli + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a])); + VLE8_V(hi, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); - VECTOR_LOAD_VMASK(0xffff0000, s1, 2); - dyn->inst_vl = 0; // the mask load changed the real vl - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); - ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a]) - 16); - VLE8_V(low, s1, VECTOR_MASKED, VECTOR_NFIELD1); + VSLIDEUP_VI(low, hi, 16, VECTOR_UNMASKED); + dyn->e.fpu_scratch = sp; } dyn->e.ssecache[a].ymm = 1; } @@ -2998,6 +3040,8 @@ void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a void avx_store_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew) { sse_mark_used(dyn, ninst, a); + if (ninst >= 0 && ninst < dyn->size) + dyn->insts[ninst].vec_write_full |= 1u << a; int cache = sse_get_reg_empty_vector(dyn, ninst, s1, a); if (cache != vreg) { avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, width); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index b746ec6a3..3310968ea 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1656,38 +1656,108 @@ dyn->vector_sew = dyn->vector_eew; \ } while (0) -#define AVX_SCALAR_OP_PROLOG(SEW) \ - do { \ - q0 = VREG(vex.v); \ - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, (SEW)); \ - if (MODREG) { \ - ed = (nextop & 7) + (rex.b << 3); \ - q1 = VREG(ed); \ - avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, (SEW)); \ - } else { \ - q1 = fpu_get_scratch(dyn); \ - SMREAD(); \ - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); \ - avx_set_vector_width(dyn, ninst, x1, (SEW), 1 << (SEW)); \ - VLE_V(q1, ed, (SEW), VECTOR_UNMASKED, VECTOR_NFIELD1); \ - } \ - GETGY_empty_vector(v0); \ - if (v0 != q0) { \ - if (v0 == q1) { \ - int _t = fpu_get_scratch(dyn); \ - avx_set_vector_width(dyn, ninst, x1, (SEW), 16); \ - VMV_V_V(_t, q1); \ - q1 = _t; \ - } \ - avx_set_vector_width(dyn, ninst, x1, (SEW), 16); \ - VMV_V_V(v0, q0); \ - } \ - SET_SCALAR_FP_WIDTH(x1, (SEW)); \ +#define AVX_SCALAR_OP_PROLOG_D(SEW, D) \ + do { \ + q0 = VREG(vex.v); \ + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, (SEW)); \ + if (MODREG) { \ + ed = (nextop & 7) + (rex.b << 3); \ + q1 = VREG(ed); \ + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, (SEW)); \ + } else { \ + q1 = fpu_get_scratch(dyn); \ + SMREAD(); \ + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, (D)); \ + avx_set_vector_width(dyn, ninst, x1, (SEW), 1 << (SEW)); \ + VLE_V(q1, ed, (SEW), VECTOR_UNMASKED, VECTOR_NFIELD1); \ + } \ + GETGY_empty_vector(v0); \ + if (v0 != q0) { \ + if (v0 == q1) { \ + int _t = fpu_get_scratch(dyn); \ + avx_set_vector_width(dyn, ninst, x1, (SEW), 16); \ + VMV_V_V(_t, q1); \ + q1 = _t; \ + } \ + avx_set_vector_width(dyn, ninst, x1, (SEW), 16); \ + VMV_V_V(v0, q0); \ + } \ + SET_SCALAR_FP_WIDTH(x1, (SEW)); \ } while (0) +#define AVX_SCALAR_OP_PROLOG(SEW) AVX_SCALAR_OP_PROLOG_D(SEW, 0) + #define AVX_SCALAR_OP_STORE(SEW) \ avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, (SEW)) +#define AVX_CMP_ORDERED_MASK() \ + do { \ + VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); \ + VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); \ + VMAND_MM(q2, q2, d0); \ + } while (0) + +#define AVX_SCALAR_CMP(SEW) \ + do { \ + AVX_SCALAR_OP_PROLOG_D(SEW, 1); \ + u8 = F8; \ + q2 = fpu_get_scratch(dyn); \ + d0 = fpu_get_scratch(dyn); \ + switch (u8 & 0xf) { \ + case 0x0: VMFEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; \ + case 0x1: VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; \ + case 0x2: VMFLE_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; \ + case 0x3: \ + AVX_CMP_ORDERED_MASK(); \ + VMNAND_MM(VMASK, q2, q2); \ + break; \ + case 0x4: \ + VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); \ + VMNAND_MM(VMASK, d0, d0); \ + break; \ + case 0x5: \ + VMFLT_VV(d0, q0, q1, VECTOR_UNMASKED); \ + VMNAND_MM(VMASK, d0, d0); \ + break; \ + case 0x6: \ + VMFLE_VV(d0, q0, q1, VECTOR_UNMASKED); \ + VMNAND_MM(VMASK, d0, d0); \ + break; \ + case 0x7: \ + AVX_CMP_ORDERED_MASK(); \ + VMAND_MM(VMASK, q2, q2); \ + break; \ + case 0x8: \ + AVX_CMP_ORDERED_MASK(); \ + VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); \ + VMNAND_MM(VMASK, q2, q2); \ + VMOR_MM(VMASK, VMASK, d0); \ + break; \ + case 0x9: \ + VMFLE_VV(d0, q1, q0, VECTOR_UNMASKED); \ + VMNAND_MM(VMASK, d0, d0); \ + break; \ + case 0xa: \ + VMFLT_VV(d0, q1, q0, VECTOR_UNMASKED); \ + VMNAND_MM(VMASK, d0, d0); \ + break; \ + case 0xb: VMXOR_MM(VMASK, q2, q2); break; \ + case 0xc: \ + AVX_CMP_ORDERED_MASK(); \ + VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); \ + VMNAND_MM(VMASK, d0, d0); \ + VMAND_MM(VMASK, VMASK, q2); \ + break; \ + case 0xd: VMFLE_VV(VMASK, q1, q0, VECTOR_UNMASKED); break; \ + case 0xe: VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); break; \ + case 0xf: VMXNOR_MM(VMASK, q2, q2); break; \ + } \ + VXOR_VV(q2, q2, q2, VECTOR_UNMASKED); \ + VMERGE_VIM(q2, q2, 0x1f); \ + VMV_V_V(v0, q2); \ + AVX_SCALAR_OP_STORE(SEW); \ + } while (0) + #define SET_CACHE_VECTOR_WIDTH(S1) \ do { \ int sew = dyn->vector_sew; \ diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index 5915eea54..8940e78e1 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -164,6 +164,8 @@ typedef struct instruction_rv64_s { uint16_t up32_skip; // bitmask of GPRs where the implicit zero-up after a 32-bit write can be skipped uint16_t up32_pending; // bitmask of GPRs whose upper 32 bits are stale at entry to this instruction uint32_t vec_used; // bitmask of XMM/YMM registers touched by this instruction + uint16_t vec_read; // bitmask of XMM/YMM registers read by this instruction + uint16_t vec_write_full; // bitmask of XMM/YMM registers fully (both halves) written by this instruction uint32_t preload_xmmymm; // registers to preload at this instruction int preload_from; // last instruction of the region that uses them uint16_t ymm_upper_use; // bitmask of YMM upper halves read by this instruction @@ -171,6 +173,7 @@ typedef struct instruction_rv64_s { uint16_t ymm_upper_live; // bitmask of YMM upper halves live after this instruction uint16_t ymm_zero; // bitmask of YMM upper halves deferred-zeroed by this instruction uint16_t ymm_pending; // bitmask of pending YMM upper-half zeros on entry to this instruction + uint8_t ymm_pending_materialized; // pending YMM upper-half zeros are materialized before this instruction runs } instruction_rv64_t; typedef struct dynarec_rv64_s { @@ -217,6 +220,7 @@ typedef struct dynarec_rv64_s { uint8_t vector_sew; // current sew status uint8_t vector_eew; // current effective sew status, should only be used after SET_ELEMENT_WIDTH uint8_t inst_sew; // sew inside current instruction, for vsetvli elimination + uint16_t purge_dead_vector; // SIMD regs whose value is dead at the purge target (skip write-back) uint8_t inst_vl; // vl inside current instruction, for vsetvli elimination uint8_t inst_vlmul; // vlmul inside current instruction uint8_t is_file_mapped; // if the memory is a mapped file (probably binary, not a memory) From a111fcafeee03a930cbbd895184329a1ee4f08de Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Wed, 21 Oct 2026 17:25:44 +0800 Subject: [PATCH 061/156] [RV64_DYNAREC] Fix vector register aliasing --- src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c index abd9303d5..07a033061 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c @@ -1390,6 +1390,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q2, v0); if (MODREG) { q1 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); @@ -1551,6 +1552,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q2, v0); if (MODREG) { q1 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); @@ -1578,6 +1580,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q2, v0); if (MODREG) { q1 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); From 8851be9278e71b3bd608465836a34c2826ba7abb Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Thu, 22 Oct 2026 10:33:55 +0200 Subject: [PATCH 062/156] [WOWBOX64] Fixed GetEnvironnementVariableA (for #4585) --- wine/common/wrt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wine/common/wrt.c b/wine/common/wrt.c index a302c98ce..cb03ff1c0 100644 --- a/wine/common/wrt.c +++ b/wine/common/wrt.c @@ -93,6 +93,7 @@ DWORD WINAPI GetEnvironmentVariableA(LPCSTR name, LPSTR value, DWORD size) else { ret = 0; if (len) RtlUnicodeToMultiByteN(value, size, &ret, valueW, len * sizeof(WCHAR)); + if (ret < size) value[ret] = 0; } RtlFreeUnicodeString(&nameU); From fbba162d7c37135f51f645f554a48ca031b44ea5 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Thu, 22 Oct 2026 10:55:32 +0200 Subject: [PATCH 063/156] [RCFILE] Optimise steam profile --- system/box64.box64rc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/box64.box64rc b/system/box64.box64rc index 0b6f3c15e..f5f66889f 100644 --- a/system/box64.box64rc +++ b/system/box64.box64rc @@ -378,7 +378,7 @@ BOX64_NOGTK=1 [steam] BOX64_EMULATED_LIBS=libudev.so.0 BOX64_DYNAREC_BIGBLOCK=3 -BOX64_DYNAREC_STRONGMEM=2 +#BOX64_DYNAREC_STRONGMEM=2 #seems useless now BOX64_NOGTK=1 # this is for the 64bits version of the client [steamwebhelper] @@ -391,7 +391,7 @@ BOX64_DYNAREC_SAFEFLAGS=0 BOX64_ARCH=la64 BOX64_EMULATED_LIBS=libudev.so.0 BOX64_DYNAREC_BIGBLOCK=3 -BOX64_DYNAREC_STRONGMEM=2 +#BOX64_DYNAREC_STRONGMEM=2 BOX64_STEAM_VULKAN=1 BOX64_NOGTK=1 @@ -410,7 +410,7 @@ BOX64_SHAEXT=0 BOX64_PCLMULQDQ=0 BOX64_EMULATED_LIBS=libudev.so.0 BOX64_DYNAREC_BIGBLOCK=3 -BOX64_DYNAREC_STRONGMEM=2 +#BOX64_DYNAREC_STRONGMEM=2 BOX64_STEAM_VULKAN=1 BOX64_NOGTK=1 From 082ecb92b100a2242bd7aacbf882cb5a783f9578 Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Wed, 21 Oct 2026 18:47:03 +0800 Subject: [PATCH 064/156] [RV64_DYNAREC] Use bseti for single-bit 64-bit constants Mov64x(0x800000000000) Before: ``` ADDIW reg, zero, 1 SLLI reg, reg, 47 ``` After ``` BSETI reg, zero, 47 ``` --- src/dynarec/rv64/dynarec_rv64_helper.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index abcc06dcd..763a092f0 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -2804,6 +2804,12 @@ void rv64_move32(dynarec_rv64_t* dyn, int ninst, int reg, int32_t val, int zerou void rv64_move64(dynarec_rv64_t* dyn, int ninst, int reg, int64_t val) { + uint64_t uval = (uint64_t)val; + if (cpuext.zbs && uval && !(uval & (uval - 1))) { + BSETI_(reg, xZR, TrailingZeros64(uval)); + return; + } + if (((val << 32) >> 32) == val) { // 32bits value rv64_move32(dyn, ninst, reg, val, 0); From f267770d75a4d863045f80083a02bd199277b821 Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Wed, 21 Oct 2026 19:22:58 +0800 Subject: [PATCH 065/156] [RV64_DYNAREC] Optimize contiguous-1-bit cases MOV64x(x2, 0x7fffffffffffffff); Before: ``` ADDIW x2, zero, 1 SLLI x2, x2, 63 ADDI x2, x2, -1 ``` After: ``` ADDI x2, zero, -1 SRLI x2, x2, 1 ``` --- src/dynarec/rv64/dynarec_rv64_helper.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 763a092f0..d7672554b 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -2815,6 +2815,11 @@ void rv64_move64(dynarec_rv64_t* dyn, int ninst, int reg, int64_t val) rv64_move32(dyn, ninst, reg, val, 0); return; } + if (!(uval & (uval + 1))) { + ADDI(reg, xZR, -1); + SRLI(reg, reg, 64 - TrailingZeros64(~uval)); + return; + } int64_t lo12 = (val << 52) >> 52; int64_t hi52 = (val + 0x800) >> 12; From 39aae76ddf3c515393bab5b2dd58ce676386501f Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 22 Oct 2026 20:05:52 +0800 Subject: [PATCH 066/156] [RV64_DYNAREC] Optimized some AVX opcodes (#4586) --- src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c | 18 ++- .../rv64/dynarec_rv64_avx_66_0f38_vector.c | 123 ++++++++++++------ .../rv64/dynarec_rv64_avx_66_0f_vector.c | 18 ++- .../rv64/dynarec_rv64_avx_f3_0f_vector.c | 18 ++- 4 files changed, 126 insertions(+), 51 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index 289841335..7d026b95a 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -43,10 +43,20 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x10: INST_NAME("VMOVUPS Gx, Ex"); nextop = F8; - GETEY_vector(v1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); - VMV_V_V(v0, v1); - PUTGY_vector(v0, VECTOR_SEW8); + if (!MODREG) { + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, 0); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16 << vex.l); + VLE8_V(v0, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16 << vex.l, VECTOR_SEW8); + } else { + GETEY_vector(v1, 0, VECTOR_SEW8); + GETGY_empty_vector(v0); + VMV_V_V(v0, v1); + PUTGY_vector(v0, VECTOR_SEW8); + } break; case 0x11: INST_NAME("VMOVUPS Ex, Gx"); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c index 07a033061..dbcb260d9 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c @@ -1389,8 +1389,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q2); GETGY_empty_vector(v0); - VEC_SRC_KEEP(q2, v0); if (MODREG) { q1 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); @@ -1404,12 +1405,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VMV_V_V(v0, q1); - VFSGNJN_VV(v0, v0, v0, VECTOR_UNMASKED); // v0 = -Ex + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q1); + VFNMSAC_VV(q4, q0, q3, VECTOR_UNMASKED); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1, x4, 1); - VFMACC_VV(v0, q0, q2, VECTOR_MASKED); // v0[0] = Vx*Gx - Ex - VFSGNJN_VV(v0, v0, v0, VECTOR_UNMASKED); // v0[0] = -(Vx*Gx) + Ex - VMERGE_VVM(v0, q2, v0); + VMERGE_VVM(v0, q3, q4); PUTGY_vector(v0, sew); break; case 0xB9: @@ -1419,8 +1420,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q2); GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { q1 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); @@ -1434,8 +1436,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q3); + VFMACC_VV(q4, q0, q1, VECTOR_UNMASKED); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1, x4, 1); - VFMACC_VV(v0, q0, q1, VECTOR_MASKED); // v0[0] = Vx*Ex + Gx + VMERGE_VVM(v0, q3, q4); PUTGY_vector(v0, sew); break; case 0x99: @@ -1445,8 +1451,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q2); GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { q1 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); @@ -1460,8 +1467,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q0); + VFMACC_VV(q4, q3, q1, VECTOR_UNMASKED); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1, x4, 1); - VFMADD_VV(v0, q0, q1, VECTOR_MASKED); + VMERGE_VVM(v0, q3, q4); PUTGY_vector(v0, sew); break; case 0x9B: @@ -1471,8 +1482,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q2); GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { q1 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); @@ -1486,8 +1498,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q0); + VFMSAC_VV(q4, q3, q1, VECTOR_UNMASKED); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1, x4, 1); - VFMSUB_VV(v0, q0, q1, VECTOR_MASKED); + VMERGE_VVM(v0, q3, q4); PUTGY_vector(v0, sew); break; case 0x9D: @@ -1497,8 +1513,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q2); GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { q1 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); @@ -1512,9 +1529,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q0); + VFNMSAC_VV(q4, q3, q1, VECTOR_UNMASKED); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1, x4, 1); - VFNMSUB_VV(v0, q0, q1, VECTOR_MASKED); - VMERGE_VVM(v0, q2, v0); + VMERGE_VVM(v0, q3, q4); PUTGY_vector(v0, sew); break; case 0x9F: @@ -1524,8 +1544,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q2); GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { q1 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); @@ -1539,9 +1560,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q0); + VFNMACC_VV(q4, q3, q1, VECTOR_UNMASKED); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1, x4, 1); - VFNMADD_VV(v0, q0, q1, VECTOR_MASKED); - VMERGE_VVM(v0, q2, v0); + VMERGE_VVM(v0, q3, q4); PUTGY_vector(v0, sew); break; case 0xA9: @@ -1551,8 +1575,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q2); GETGY_empty_vector(v0); - VEC_SRC_KEEP(q2, v0); if (MODREG) { q1 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); @@ -1566,10 +1591,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VMV_V_V(v0, q1); + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q1); + VFMACC_VV(q4, q0, q3, VECTOR_UNMASKED); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1, x4, 1); - VFMACC_VV(v0, q0, q2, VECTOR_MASKED); - VMERGE_VVM(v0, q2, v0); + VMERGE_VVM(v0, q3, q4); PUTGY_vector(v0, sew); break; case 0xAB: @@ -1579,8 +1606,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q2); GETGY_empty_vector(v0); - VEC_SRC_KEEP(q2, v0); if (MODREG) { q1 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); @@ -1594,11 +1622,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VMV_V_V(v0, q1); - VFSGNJN_VV(v0, v0, v0, VECTOR_UNMASKED); + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q1); + VFMSAC_VV(q4, q0, q3, VECTOR_UNMASKED); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1, x4, 1); - VFMACC_VV(v0, q0, q2, VECTOR_MASKED); - VMERGE_VVM(v0, q2, v0); + VMERGE_VVM(v0, q3, q4); PUTGY_vector(v0, sew); break; case 0xAF: @@ -1608,6 +1637,8 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q2); GETGY_empty_vector(v0); if (MODREG) { q1 = fpu_get_scratch(dyn); @@ -1622,10 +1653,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VMV_V_V(v0, q2); + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q1); + VFNMACC_VV(q4, q0, q3, VECTOR_UNMASKED); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1, x4, 1); - VFNMADD_VV(v0, q1, q0, VECTOR_MASKED); - VMERGE_VVM(v0, q2, v0); + VMERGE_VVM(v0, q3, q4); PUTGY_vector(v0, sew); break; case 0xBB: @@ -1635,8 +1668,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q2); GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { q1 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); @@ -1650,9 +1684,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q3); + VFMSAC_VV(q4, q0, q1, VECTOR_UNMASKED); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1, x4, 1); - VFSGNJN_VV(v0, v0, v0, VECTOR_MASKED); - VFMACC_VV(v0, q0, q1, VECTOR_MASKED); + VMERGE_VVM(v0, q3, q4); PUTGY_vector(v0, sew); break; case 0xBD: @@ -1662,8 +1699,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q2); GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { q1 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); @@ -1677,9 +1715,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VFSGNJN_VV(q0, q0, q0, VECTOR_UNMASKED); + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q3); + VFNMSAC_VV(q4, q0, q1, VECTOR_UNMASKED); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1, x4, 1); - VFMACC_VV(v0, q0, q1, VECTOR_MASKED); + VMERGE_VVM(v0, q3, q4); PUTGY_vector(v0, sew); break; case 0xBF: @@ -1689,8 +1730,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q2); GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { q1 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); @@ -1704,9 +1746,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q3); + VFNMACC_VV(q4, q0, q1, VECTOR_UNMASKED); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1, x4, 1); - VFNMACC_VV(v0, q0, q1, VECTOR_MASKED); - VMERGE_VVM(v0, q2, v0); + VMERGE_VVM(v0, q3, q4); PUTGY_vector(v0, sew); break; case 0xF7: diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index f70e51f4d..17d54ca60 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -796,10 +796,20 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x6F: INST_NAME("VMOVDQA Gx, Ex"); nextop = F8; - GETEY_vector(v1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); - VMV_V_V(v0, v1); - PUTGY_vector(v0, VECTOR_SEW8); + if (!MODREG) { + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, 0); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16 << vex.l); + VLE8_V(v0, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16 << vex.l, VECTOR_SEW8); + } else { + GETEY_vector(v1, 0, VECTOR_SEW8); + GETGY_empty_vector(v0); + VMV_V_V(v0, v1); + PUTGY_vector(v0, VECTOR_SEW8); + } break; case 0x74: INST_NAME("VPCMPEQB Gx, Vx, Ex"); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c index f52cf68f1..c343fef44 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c @@ -177,10 +177,20 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x6F: INST_NAME("VMOVDQU Gx, Ex"); nextop = F8; - GETEY_vector(v1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); - VMV_V_V(v0, v1); - PUTGY_vector(v0, VECTOR_SEW8); + if (!MODREG) { + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, 0); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16 << vex.l); + VLE8_V(v0, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16 << vex.l, VECTOR_SEW8); + } else { + GETEY_vector(v1, 0, VECTOR_SEW8); + GETGY_empty_vector(v0); + VMV_V_V(v0, v1); + PUTGY_vector(v0, VECTOR_SEW8); + } break; case 0x7F: INST_NAME("VMOVDQU Ex, Gx"); From 0b0a31c53c04b0fbea9e0432c78bc78df95862bc Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Fri, 23 Oct 2026 14:15:23 +0800 Subject: [PATCH 067/156] [RV64_DYNAREC] Avoid redundant vsetvli when loading vector masks (#4583) 1. Trim mask immediates to the active vector element count to avoid setting unused bits. 2. Reuse the vector configuration when its element width can hold all active mask bits. --- src/dynarec/rv64/dynarec_rv64_helper.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index d7672554b..f594c771a 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -3355,11 +3355,22 @@ void vector_loadmask(dynarec_rv64_t* dyn, int ninst, int vreg, uint64_t imm, int abort(); } else { uint8_t sv_sew, sv_vlmul, sv_vl; + if (sew > VECTOR_SEW64) + sew = VECTOR_SEW8; + int count = (int)((16 >> sew) * multiple); + if (count > 32) + count = 32; + imm &= (1ULL << count) - 1; vector_save_vtype(dyn, &sv_sew, &sv_vlmul, &sv_vl); - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW64, VECTOR_LMUL1, 1); + int need_wrap = (sv_sew > VECTOR_SEW64 || sv_vlmul != VECTOR_LMUL1 || !sv_vl); + if ((sv_sew == VECTOR_SEW8 && count > 8) || (sv_sew == VECTOR_SEW16 && count > 16)) + need_wrap |= 1; + if (need_wrap) + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW64, VECTOR_LMUL1, 1); MOV64x(s1, imm); VMV_S_X(vreg, s1); - vector_restore_vtype(dyn, ninst, s1, sv_sew, sv_vlmul, sv_vl); + if (need_wrap) + vector_restore_vtype(dyn, ninst, s1, sv_sew, sv_vlmul, sv_vl); } #endif } From 827f0ee54e54087baab2ed1e33ebc38998700589 Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Wed, 21 Oct 2026 18:29:53 +0800 Subject: [PATCH 068/156] [RV64_DYNAREC] Optimitize VSHUFPS and VPERMILPS 128-bit case --- src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c | 14 +++++++++----- src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c | 14 +++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index 7d026b95a..d65d42f1d 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -520,11 +520,15 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t v2 = fpu_get_scratch(dyn); MOV64x(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48)); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); - VMV_V_X(q2, x4); - vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); - VID_V(VMASK, VECTOR_UNMASKED); - VMSGT_VI(VMASK, VMASK, 3, VECTOR_UNMASKED); - VOR_VI(q2, q2, 4, VECTOR_MASKED); + if (vex.l) { + VMV_V_X(q2, x4); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VID_V(VMASK, VECTOR_UNMASKED); + VMSGT_VI(VMASK, VMASK, 3, VECTOR_UNMASKED); + VOR_VI(q2, q2, 4, VECTOR_MASKED); + } else { + VMV_S_X(q2, x4); + } avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VRGATHEREI16_VV(v1, q0, q2, VECTOR_UNMASKED); VRGATHEREI16_VV(v2, q1, q2, VECTOR_UNMASKED); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c index 8b40a4dbd..8e86aef4e 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c @@ -96,11 +96,15 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q1 = fpu_get_scratch(dyn); MOV64x(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48)); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); - VMV_V_X(q1, x4); - vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); - VID_V(VMASK, VECTOR_UNMASKED); - VMSGT_VI(VMASK, VMASK, 3, VECTOR_UNMASKED); - VOR_VI(q1, q1, 4, VECTOR_MASKED); + if (vex.l) { + VMV_V_X(q1, x4); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VID_V(VMASK, VECTOR_UNMASKED); + VMSGT_VI(VMASK, VMASK, 3, VECTOR_UNMASKED); + VOR_VI(q1, q1, 4, VECTOR_MASKED); + } else { + VMV_S_X(q1, x4); + } avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VRGATHEREI16_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); From 5735c8b7c86844ed19ef515d60311f43ed073e7e Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Fri, 23 Oct 2026 21:56:21 +0800 Subject: [PATCH 069/156] [RV64_DYNAREC] Optimize some opcodes by removing redundant some vsetvli (#4588) When VLMUL, TU, and MU remain unchanged: For `vmv.s.x`, if SEW stays unchanged, the vector configuration does not need to change. For `vmv.v.v`, if the width stays unchanged, the vector configuration does not need to change. --- src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c | 10 ++++------ src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c | 1 - src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c | 2 -- src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c | 5 ++--- src/dynarec/rv64/dynarec_rv64_helper.c | 2 +- 5 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index d65d42f1d..bbfd07128 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -88,9 +88,8 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t INST_NAME("VMOVLPS Gx, Vx, Ex"); SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); - if (fixedaddress) { ADDI(x4, ed, fixedaddress); ed = x4; fixedaddress = 0; } - vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 0.5); - VLE64_V(q1, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + LD(x4, ed, fixedaddress); + VMV_S_X(q1, x4); } GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); @@ -158,9 +157,8 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t INST_NAME("VMOVHPS Gx, Vx, Ex"); SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); - if (fixedaddress) { ADDI(x4, ed, fixedaddress); ed = x4; fixedaddress = 0; } - vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 0.5); - VLE64_V(q1, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + LD(x4, ed, fixedaddress); + VMV_S_X(q1, x4); } GETGY_empty_vector(v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c index dbcb260d9..597a4fd43 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c @@ -1780,7 +1780,6 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint OR(x4, x4, x5); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 0.25f); VMV_S_X(v0, x4); avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); break; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c index 8e86aef4e..c59073c94 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c @@ -118,9 +118,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VEC_SRC_KEEP(q0, v0); q1 = fpu_get_scratch(dyn); MOV64x(x4, (uint64_t)(u8 & 1) | ((uint64_t)((u8 >> 1) & 1) << 16) | ((uint64_t)(((u8 >> 2) & 1) + 2) << 32) | ((uint64_t)(((u8 >> 3) & 1) + 2) << 48)); - vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); VMV_S_X(q1, x4); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VRGATHEREI16_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index 17d54ca60..cddf06fad 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -132,9 +132,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); - if (fixedaddress) { ADDI(x4, ed, fixedaddress); ed = x4; fixedaddress = 0; } - vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 0.5); - VLE64_V(q1, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + LD(x4, ed, fixedaddress); + VMV_S_X(q1, x4); } GETGY_empty_vector(v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index f594c771a..12d300cb1 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -3055,7 +3055,7 @@ void avx_store_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int dyn->insts[ninst].vec_write_full |= 1u << a; int cache = sse_get_reg_empty_vector(dyn, ninst, s1, a); if (cache != vreg) { - avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, width); + avx_set_vector_width(dyn, ninst, s1, sew, width); VMV_V_V(cache, vreg); } if (cpuext.vlen >= 32) { From 420eda69ff51ab5d5a7cbc3dee2e70433be3411d Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Fri, 23 Oct 2026 21:56:40 +0800 Subject: [PATCH 070/156] [RV64_DYNAREC] Fix VPERM2I128 vector mask multiple (#4589) VPERM2I128 only operates on 256-bit vectors, so the vector mask multiple parameter should be 2. --- src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c index c59073c94..7335d4cdc 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c @@ -136,11 +136,11 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint int zero = j ? (u8 & 0x80) : (u8 & 0x08); int mask = j ? 0xc : 0x3; if (zero) { - VECTOR_LOAD_VMASK(mask, x4, 1); + VECTOR_LOAD_VMASK(mask, x4, 2); VXOR_VV(v0, v0, v0, VECTOR_MASKED); } else if (control != j) { int src = (control & 2) ? q1 : q0; - VECTOR_LOAD_VMASK(mask, x4, 1); + VECTOR_LOAD_VMASK(mask, x4, 2); if (((j == 0) && ((control & 1) == 0)) || ((j == 1) && ((control & 1) == 1))) { VMERGE_VVM(v0, v0, src); } else { @@ -354,11 +354,11 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint int zero = j ? (u8 & 0x80) : (u8 & 0x08); int mask = j ? 0xc : 0x3; if (zero) { - VECTOR_LOAD_VMASK(mask, x4, 1); + VECTOR_LOAD_VMASK(mask, x4, 2); VXOR_VV(v0, v0, v0, VECTOR_MASKED); } else if (control != j) { int src = (control & 2) ? q1 : q0; - VECTOR_LOAD_VMASK(mask, x4, 1); + VECTOR_LOAD_VMASK(mask, x4, 2); if (((j == 0) && ((control & 1) == 0)) || ((j == 1) && ((control & 1) == 1))) { VMERGE_VVM(v0, v0, src); } else { From a46ad9dfe9db4c5c70c86ac9b4e9b5b737049cc9 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 26 Oct 2026 03:57:34 +0800 Subject: [PATCH 071/156] [RV64_DYNAREC] Reworked move immediate (#4591) * [RV64_DYNAREC] Reworked move immediate * Use -O2 for test37 --- .github/workflows/release.yml | 2 +- CMakeLists.txt | 1 + src/dynarec/rv64/dynarec_rv64_00_2.c | 9 +- src/dynarec/rv64/dynarec_rv64_00_3.c | 9 +- src/dynarec/rv64/dynarec_rv64_0f.c | 7 +- src/dynarec/rv64/dynarec_rv64_0f_vector.c | 4 +- src/dynarec/rv64/dynarec_rv64_66.c | 4 +- src/dynarec/rv64/dynarec_rv64_660f.c | 12 +- src/dynarec/rv64/dynarec_rv64_660f38.c | 32 +- src/dynarec/rv64/dynarec_rv64_660f_vector.c | 2 +- src/dynarec/rv64/dynarec_rv64_66f20f.c | 2 +- src/dynarec/rv64/dynarec_rv64_avx_0f.c | 4 +- src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c | 6 +- src/dynarec/rv64/dynarec_rv64_avx_66_0f.c | 27 +- src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c | 18 +- src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c | 6 +- .../rv64/dynarec_rv64_avx_66_0f3a_vector.c | 5 +- .../rv64/dynarec_rv64_avx_66_0f_vector.c | 7 +- src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c | 6 +- .../rv64/dynarec_rv64_avx_f2_0f_vector.c | 4 +- src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c | 4 +- .../rv64/dynarec_rv64_avx_f3_0f_vector.c | 2 +- src/dynarec/rv64/dynarec_rv64_d9.c | 2 +- src/dynarec/rv64/dynarec_rv64_f20f.c | 8 +- src/dynarec/rv64/dynarec_rv64_f20f_vector.c | 4 +- src/dynarec/rv64/dynarec_rv64_f30f.c | 46 +- src/dynarec/rv64/dynarec_rv64_f30f_vector.c | 6 +- src/dynarec/rv64/dynarec_rv64_helper.c | 112 ++- src/dynarec/rv64/dynarec_rv64_helper.h | 34 +- src/dynarec/rv64/rv64_emitter.h | 41 +- src/dynarec/rv64/rv64_mov_imm.c | 746 ++++++++++++++++++ src/dynarec/rv64/rv64_mov_imm.h | 74 ++ tests/CMakeLists.txt | 1 + tests/ref37.txt | 5 + tests/test37 | Bin 0 -> 29640 bytes tests/test37.c | 277 +++++++ 36 files changed, 1322 insertions(+), 207 deletions(-) create mode 100644 src/dynarec/rv64/rv64_mov_imm.c create mode 100644 src/dynarec/rv64/rv64_mov_imm.h create mode 100644 tests/ref37.txt create mode 100755 tests/test37 create mode 100644 tests/test37.c diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 41e2a78e3..782950a42 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -261,7 +261,7 @@ jobs: echo "BOX64_COMPILER=loongarch64-linux-gnu-gcc" >> $GITHUB_ENV sudo apt-get -y install git cmake make python3 libzydis-dev elif [[ ${{ matrix.platform }} == 'PPC64LE' ]]; then - echo BOX64_PLATFORM_MARCRO="-DPPC64LE=ON" >> $GITHUB_ENV + echo BOX64_PLATFORM_MARCRO="-DPPC64LE=ON -DBAD_SIGNAL=ON" >> $GITHUB_ENV echo "BOX64_COMPILER=powerpc64le-linux-gnu-gcc" >> $GITHUB_ENV sudo apt-get -y install git gcc-powerpc64le-linux-gnu cmake make python3 libzydis-dev else diff --git a/CMakeLists.txt b/CMakeLists.txt index 4098f33e2..68e5075b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1103,6 +1103,7 @@ if(RV64_DYNAREC) "${BOX64_ROOT}/src/dynarec/rv64/rv64_printer.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_jmpnext.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_consts.c" + "${BOX64_ROOT}/src/dynarec/rv64/rv64_mov_imm.c" "${BOX64_ROOT}/src/dynarec/rv64/updateflags_rv64.c" ) set(DYNAREC_ASM diff --git a/src/dynarec/rv64/dynarec_rv64_00_2.c b/src/dynarec/rv64/dynarec_rv64_00_2.c index e11d57a1d..6423ff20f 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_2.c +++ b/src/dynarec/rv64/dynarec_rv64_00_2.c @@ -1267,18 +1267,15 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xBF: INST_NAME("MOV Reg, Id"); gd = TO_NAT((opcode & 7) + (rex.b << 3)); - SCRATCH_USAGE(0); MARKREGd(gd); if (rex.w) { u64 = F64; - MOV64x(gd, u64); + MOV64xss(gd, u64, x1, x2); } else { + SCRATCH_USAGE(0); u32 = F32; MOV32w(gd, u32); - if ((int32_t)u32 >= 0) - UP32_ZERO(gd); - else if (NEED_ZEROUP(gd)) - ZEROUP_RESULT(gd); + UP32_ZERO(gd); } break; default: diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 741a2fcba..7838e908f 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -402,8 +402,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (eb2) { // load a mask to x3 (ffffffffffff00ff) - LUI(x3, 0xffff0); - ORI(x3, x3, 0xff); + MOV64x(x3, 0xFFFFFFFFFFFF00FF); // apply mask AND(eb1, eb1, x3); if (u8) { @@ -1532,7 +1531,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int OR(xFlags, xFlags, x3); } } - LUI(x2, 0xffff0); + MOV64x(x2, 0xFFFFFFFFFFFF0000); AND(xRAX, xRAX, x2); ZEXTH(x1, x1); OR(xRAX, xRAX, x1); @@ -1561,7 +1560,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int OR(xFlags, xFlags, x3); } } - LUI(x2, 0xffff0); + MOV64x(x2, 0xFFFFFFFFFFFF0000); AND(xRAX, xRAX, x2); ZEXTH(x1, x1); OR(xRAX, xRAX, x1); @@ -1589,7 +1588,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } DIVUW(x3, x2, ed); REMUW(x4, x2, ed); - LUI(x5, 0xffff0); + MOV64x(x5, 0xFFFFFFFFFFFF0000); AND(xRAX, xRAX, x5); ANDI(x3, x3, 0xff); OR(xRAX, xRAX, x3); diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index 178b30f16..623060334 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -1252,7 +1252,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni s0 = fpu_get_scratch(dyn); s1 = fpu_get_scratch(dyn); // 1.0f v0 = fpu_get_scratch(dyn); // 0.0f - LUI(x3, 0x3f800); + MOV32w(x3, 0x3F800000); FMVWX(s1, x3); // 1.0f if (!BOX64ENV(dynarec_fastnan)) { FCVTSW(v0, xZR, RD_DYN); @@ -1293,7 +1293,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETEX(x2, 0, 12); d0 = fpu_get_scratch(dyn); d1 = fpu_get_scratch(dyn); - LUI(x3, 0x3f800); + MOV32w(x3, 0x3F800000); FMVWX(d0, x3); // 1.0f if (!BOX64ENV(dynarec_fastnan)) MOV32w(x6, 0x00400000); @@ -2120,8 +2120,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni eb1 = TO_NAT(ed & 3); \ } \ if (eb2) { \ - LUI(tmp1, 0xffff0); \ - ORI(tmp1, tmp1, 0xff); \ + MOV64x(tmp1, 0xFFFFFFFFFFFF00FF); \ AND(eb1, eb1, tmp1); \ SLLI(tmp3, tmp3, 8); \ } else { \ diff --git a/src/dynarec/rv64/dynarec_rv64_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_0f_vector.c index a8fe89bf7..39a997215 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_0f_vector.c @@ -552,7 +552,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETEX_vector(v0, 0, 0, VECTOR_SEW32); GETGX_empty_vector(v1); v2 = fpu_get_scratch(dyn); - LUI(x4, 0x3f800); + MOV32w(x4, 0x3F800000); VMV_V_X(v2, x4); // 1.0f broadcast VFSQRT_V(v1, v0, VECTOR_UNMASKED); VFDIV_VV(v1, v2, v1, VECTOR_UNMASKED); // 1.0/sqrt(x) @@ -565,7 +565,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETEX_vector(v0, 0, 0, VECTOR_SEW32); GETGX_empty_vector(v1); v2 = fpu_get_scratch(dyn); - LUI(x4, 0x3f800); + MOV32w(x4, 0x3F800000); VMV_V_X(v2, x4); // 1.0f broadcast VFDIV_VV(v1, v2, v0, VECTOR_UNMASKED); // 1.0/x break; diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index 37251b07b..ee735d404 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -687,7 +687,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni BNEZ_MARK(x3); ANDI(x3, ed, 0b10); - LUI(x5, 0xffff0); + MOV64x(x5, 0xFFFFFFFFFFFF0000); ZEXTH(x6, gd); BNEZ_MARK3(x3); @@ -850,7 +850,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); POP1_16(x1); FLAGS_ADJUST_FROM11(x1, x1, x2); - LUI(x2, 0xffff0); + MOV64x(x2, 0xFFFFFFFFFFFF0000); AND(xFlags, xFlags, x2); OR(xFlags, xFlags, x1); MOV32w(x1, 0x3F7FF7); diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index 60007c7de..0edaa94ca 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -304,7 +304,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ed = x4; \ } \ B##NO(x1, 4 + 3 * 4); \ - LUI(x3, 0xffff0); \ + MOV64x(x3, 0xFFFFFFFFFFFF0000); \ AND(gd, gd, x3); \ OR(gd, gd, ed); @@ -466,7 +466,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SRLI(x3, x3, 29); MOV32w(x5, 0x007fffff); AND(x3, x3, x5); - LUI(x5, 0x7fc00); + MOV32w(x5, 0x7FC00000); OR(x3, x3, x5); OR(x3, x3, x4); FMVWX(d0, x3); @@ -490,7 +490,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FCVTLS(x3, d0, RD_DYN); SEXT_W(x5, x3); BEQ(x5, x3, 8); - LUI(x3, 0x80000); // INT32_MIN + MOV64x(x3, (int64_t)INT32_MIN); SW(x3, gback, gdoffset + 4 * i); } x87_restoreround(dyn, ninst, u8); @@ -1580,7 +1580,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int addr = geted(dyn, addr, ninst, nextop, &ed, x2, x4, &fixedaddress, rex, NULL, 1, 0); LBU(x1, ed, fixedaddress); } - LUI(x5, 0xffff0); + MOV64x(x5, 0xFFFFFFFFFFFF0000); AND(gd, gd, x5); OR(gd, gd, x1); break; @@ -1842,7 +1842,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int addr = geted(dyn, addr, ninst, nextop, &ed, x2, x4, &fixedaddress, rex, NULL, 1, 0); LB(x1, ed, fixedaddress); } - LUI(x5, 0xffff0); + MOV64x(x5, 0xFFFFFFFFFFFF0000); AND(gd, gd, x5); ANDN(x1, x1, x5, x5); OR(gd, gd, x1); @@ -2104,7 +2104,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETGDd; LD(x1, wback, fixedaddress + 8); // high part LD(x2, wback, fixedaddress + 0); // low part, also destroyed wback(x2) - MOV64x(x5, 0x8080808080808080); + MOV64xs(x5, 0x8080808080808080, x3); MOV64x(x6, 0x0002040810204081); AND(x2, x2, x5); MUL(x2, x2, x6); diff --git a/src/dynarec/rv64/dynarec_rv64_660f38.c b/src/dynarec/rv64/dynarec_rv64_660f38.c index 5e5edbcb3..b0830d564 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f38.c +++ b/src/dynarec/rv64/dynarec_rv64_660f38.c @@ -144,9 +144,8 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, INST_NAME("PHADDSW Gx, Ex"); nextop = F8; GETGX(); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); for (int i = 0; i < 4; ++i) { // tmp32s = GX->sw[i*2+0]+GX->sw[i*2+1]; // GX->sw[i] = sat(tmp32s); @@ -178,9 +177,8 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, nextop = F8; GETGX(); GETEX(x2, 0, 15); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); for (int i = 0; i < 8; ++i) { LBU(x3, gback, gdoffset + i * 2); LB(x4, wback, fixedaddress + i * 2); @@ -255,9 +253,8 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, INST_NAME("PHSUBSW Gx, Ex"); nextop = F8; GETGX(); - LUI(x6, 0xFFFF8); - LUI(x7, 0x8); - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); for (int i = 0; i < 4; ++i) { LH(x3, gback, gdoffset + 2 * (i * 2 + 0)); LH(x4, gback, gdoffset + 2 * (i * 2 + 1)); @@ -536,8 +533,7 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, nextop = F8; GETGX(); GETEX(x2, 0, 12); - LUI(x5, 0x10); // 65536 - ADDIW(x5, x5, -1); + MOV32w(x5, 0xFFFF); for (int i = 0; i < 4; ++i) { LW(x3, gback, gdoffset + i * 4); SATUw(x3, x5); @@ -968,7 +964,7 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, SRLI(x1, x1, 8); OR(x1, x1, x2); } - LUI(x2, 0xffff0); + MOV64x(x2, 0xFFFFFFFFFFFF0000); AND(gd, gd, x2); OR(gd, gd, x1); break; @@ -1081,16 +1077,16 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, // i = 0 FLD(d0, wback, fixedaddress); FEQD(x4, d0, d0); - BNEZ(x4, BOX64ENV(dynarec_fastnan) ? 8 : (7 * 4)); + BNEZ_MARK3(x4); if (!BOX64ENV(dynarec_fastnan)) { // sNaN -> qNaN, d0 |= (0x1 << 51) FMVXD(x3, d0); - ADDI(x4, xZR, 1); - SLLI(x4, x4, 51); + MOV64x(x4, 1ULL << 51); OR(x3, x3, x4); FMVDX(d0, x3); } B_MARK_nocond; + MARK3; // d0 is not nan FABSD(v1, d0); FLTD(x4, v1, d1); @@ -1118,16 +1114,16 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, // i = 1 FLD(d0, wback, fixedaddress + 8); FEQD(x4, d0, d0); - BNEZ(x4, BOX64ENV(dynarec_fastnan) ? 8 : (7 * 4)); + BNEZ_MARK4(x4); if (!BOX64ENV(dynarec_fastnan)) { // sNaN -> qNaN, d0 |= (0x1 << 51) FMVXD(x3, d0); - ADDI(x4, xZR, 1); - SLLI(x4, x4, 51); + MOV64x(x4, 1ULL << 51); OR(x3, x3, x4); FMVDX(d0, x3); } B_MARK2_nocond; + MARK4; // d0 is not nan FABSD(v1, d0); diff --git a/src/dynarec/rv64/dynarec_rv64_660f_vector.c b/src/dynarec/rv64/dynarec_rv64_660f_vector.c index 65eaf34e2..889509c69 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_660f_vector.c @@ -1778,7 +1778,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i } } else { tmp64u0 = ((tmp64u0 >> 6) << 48) | (((tmp64u0 >> 4) & 3) << 32) | (((tmp64u0 >> 2) & 3) << 16) | (tmp64u0 & 3); - VECTOR_SPLAT_IMM(v0, tmp64u0, x4); + VECTOR_SPLAT_IMM_S(v0, tmp64u0, x4, x3); SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); if (q0 == q1) { v1 = fpu_get_scratch(dyn); diff --git a/src/dynarec/rv64/dynarec_rv64_66f20f.c b/src/dynarec/rv64/dynarec_rv64_66f20f.c index 6772e94ba..c6bb88bfd 100644 --- a/src/dynarec/rv64/dynarec_rv64_66f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_66f20f.c @@ -64,7 +64,7 @@ uintptr_t dynarec64_66F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in ZEROUP(gd); XOR(x5, x5, gd); SLLI(x5, x5, 48); - MOV64x(x2, 0x4869EC38DEA713F1ULL); + MOV64xs(x2, 0x4869EC38DEA713F1ULL, x3); CLMUL(x5, x5, x2); MOV64x(x2, 0x105EC76F1ULL); CLMULH(x5, x5, x2); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_0f.c index c744fbbea..af99f8d10 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f.c @@ -389,7 +389,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in s0 = fpu_get_scratch(dyn); s1 = fpu_get_scratch(dyn); // 1.0f v0 = fpu_get_scratch(dyn); // 0.0f - LUI(x3, 0x3f800); + MOV32w(x3, 0x3F800000); FMVWX(s1, x3); // 1.0f if (!BOX64ENV(dynarec_fastnan)) { FMVWX(v0, xZR); @@ -462,7 +462,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in GETGY(); d0 = fpu_get_scratch(dyn); d1 = fpu_get_scratch(dyn); - LUI(x3, 0x3f800); + MOV32w(x3, 0x3F800000); FMVWX(d0, x3); // 1.0f if (!BOX64ENV(dynarec_fastnan)) MOV32w(x6, 0x00400000); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index bbfd07128..835e1491f 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -239,7 +239,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t GETEY_vector(v1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); v2 = fpu_get_scratch(dyn); - LUI(x4, 0x3f800); + MOV32w(x4, 0x3F800000); VMV_V_X(v2, x4); VFSQRT_V(v0, v1, VECTOR_UNMASKED); VFDIV_VV(v0, v2, v0, VECTOR_UNMASKED); @@ -252,7 +252,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t GETEY_vector(v1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); v2 = fpu_get_scratch(dyn); - LUI(x4, 0x3f800); + MOV32w(x4, 0x3F800000); VMV_V_X(v2, x4); VFDIV_VV(v0, v2, v1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -516,7 +516,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); - MOV64x(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48)); + MOV64xs(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48), x3); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); if (vex.l) { VMV_V_X(q2, x4); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c index d0fa8a6b1..bb02b898b 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c @@ -602,7 +602,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETGX(); d0 = fpu_get_scratch(dyn); u8 = sse_setround(dyn, ninst, x6, x4); - if (!BOX64ENV(dynarec_fastnan)) LUI(x7, 0x7fc00); + if (!BOX64ENV(dynarec_fastnan)) MOV32w(x7, 0x7FC00000); for (int i = 0; i < 2; ++i) { FLD(d0, wback, fixedaddress + i * 8); if (!BOX64ENV(dynarec_fastnan)) { @@ -663,7 +663,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FCVTLS(x3, d0, RD_DYN); SEXT_W(x5, x3); BEQ(x5, x3, 8); - LUI(x3, 0x80000); // INT32_MIN + MOV64x(x3, (int64_t)INT32_MIN); // INT32_MIN SW(x3, gback, gdoffset + 4 * i); } if (vex.l) { @@ -673,7 +673,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FCVTLS(x3, d0, RD_DYN); SEXT_W(x5, x3); BEQ(x5, x3, 8); - LUI(x3, 0x80000); // INT32_MIN + MOV64x(x3, (int64_t)INT32_MIN); // INT32_MIN SW(x3, gback, gyoffset + 4 * i); } } else @@ -1184,9 +1184,8 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETGY(); GETVX(); GETVY(); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); if (gd == ed) { ADDI(x5, xEmu, offsetof(x64emu_t, scratch)); LD(x3, wback, fixedaddress + 0); @@ -2537,7 +2536,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, nextop = F8; GETEX(x2, 0, vex.l ? 28 : 12); GETGD; - MOV64x(x5, 0x8080808080808080); + MOV64xs(x5, 0x8080808080808080, x3); MOV64x(x6, 0x0002040810204081); LD(x1, wback, fixedaddress + 0); AND(x1, x1, x5); @@ -3061,9 +3060,8 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETGY(); GETVX(); GETVY(); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); for (int i = 0; i < 8; ++i) { LH(x3, vback, vxoffset + i * 2); LH(x4, wback, fixedaddress + i * 2); @@ -3180,9 +3178,8 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETGY(); GETVX(); GETVY(); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); for (int i = 0; i < 8; ++i) { LH(x3, vback, vxoffset + i * 2); LH(x4, wback, fixedaddress + i * 2); @@ -3661,7 +3658,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, LWU(x5, xEmu, offsetof(x64emu_t, mxcsr)); ORI(x5, x5, 1); SW(x5, xEmu, offsetof(x64emu_t, mxcsr)); - LUI(x3, 0x80000); + MOV64x(x3, (int64_t)INT32_MIN); SW(x3, gback, gdoffset + 4 * i); } if (vex.l) { @@ -3674,7 +3671,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, LWU(x5, xEmu, offsetof(x64emu_t, mxcsr)); ORI(x5, x5, 1); SW(x5, xEmu, offsetof(x64emu_t, mxcsr)); - LUI(x3, 0x80000); + MOV64x(x3, (int64_t)INT32_MIN); SW(x3, gback, gdoffset + 8 + 4 * i); } } else { diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c index 0cbfb3ffc..490e9ab16 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c @@ -111,9 +111,8 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETVX(); GETGY(); GETVY(); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); if (gd == ed) { ADDI(x5, xEmu, offsetof(x64emu_t, scratch)); LD(x3, wback, fixedaddress + 0); @@ -260,9 +259,8 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETVX(); GETGY(); GETVY(); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); for (int i = 0; i < 8; ++i) { LBU(x3, vback, vxoffset + i * 2); LB(x4, wback, fixedaddress + i * 2); @@ -302,9 +300,8 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETVX(); GETGY(); GETVY(); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); if (gd == ed) { ADDI(x5, xEmu, offsetof(x64emu_t, scratch)); LD(x3, wback, fixedaddress + 0); @@ -1226,8 +1223,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETEX(x2, 0, vex.l ? 28 : 12); GETGX(); GETGY(); - LUI(x5, 0x10); // 65536 - ADDIW(x5, x5, -1); + MOV32w(x5, 0xFFFF); if (MODREG && ed == vex.v) { for (int i = 0; i < 4; ++i) { LW(x3, vback, vxoffset + i * 4); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c index 0bbbcf117..561a79446 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c @@ -354,15 +354,15 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i MARK; FLD(d0, x1, 0); FEQD(x4, d0, d0); - BNEZ(x4, BOX64ENV(dynarec_fastnan) ? 8 : (7 * 4)); + BNEZ_MARK3(x4); if (!BOX64ENV(dynarec_fastnan)) { FMVXD(x3, d0); - ADDI(x4, xZR, 1); - SLLI(x4, x4, 51); + MOV64x(x4, 1ULL << 51); OR(x3, x3, x4); FMVDX(d0, x3); } B_MARK2_nocond; + MARK3; FABSD(v1, d0); FLTD(x4, v1, d1); BNEZ(x4, 8); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c index 7335d4cdc..e86d6710a 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c @@ -66,7 +66,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint iota |= ((uint64_t)((u8 >> 4) & 3)) << 32; iota |= ((uint64_t)((u8 >> 6) & 3)) << 48; vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, vex.l ? 2 : 1); - VECTOR_SPLAT_IMM(q2, iota, x4); + VECTOR_SPLAT_IMM_S(q2, iota, x4, x3); } if (v0 == q0 || v0 == q2) { VRGATHEREI16_VV(q1, q0, q2, VECTOR_UNMASKED); @@ -94,7 +94,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint u8 = F8; VEC_SRC_KEEP(q0, v0); q1 = fpu_get_scratch(dyn); - MOV64x(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48)); + MOV64xs(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48), x3); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); if (vex.l) { VMV_V_X(q1, x4); @@ -118,6 +118,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VEC_SRC_KEEP(q0, v0); q1 = fpu_get_scratch(dyn); MOV64x(x4, (uint64_t)(u8 & 1) | ((uint64_t)((u8 >> 1) & 1) << 16) | ((uint64_t)(((u8 >> 2) & 1) + 2) << 32) | ((uint64_t)(((u8 >> 3) & 1) + 2) << 48)); + MOV64xs(x4, (uint64_t)(u8 & 1) | ((uint64_t)((u8 >> 1) & 1) << 16) | ((uint64_t)(((u8 >> 2) & 1) + 2) << 32) | ((uint64_t)(((u8 >> 3) & 1) + 2) << 48), x3); VMV_S_X(q1, x4); VRGATHEREI16_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index cddf06fad..7fc6f54f3 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -579,10 +579,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt uint32_t sel_lo = (u8 & 3) | (((u8 >> 2) & 3) << 16); uint32_t sel_hi = ((u8 >> 4) & 3) | (((u8 >> 6) & 3) << 16); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); - MOV32w(x4, sel_hi); - SLLI(x4, x4, 32); - MOV32w(x5, sel_lo); - OR(x4, x4, x5); // x4 = lane0 selector (64-bit,4 halfword indices) + MOV64x(x4, ((uint64_t)sel_hi << 32) | sel_lo); if (vex.l) { int s = fpu_get_scratch(dyn); MOV64x(x5, 0x0004000400040004LL); @@ -1370,7 +1367,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt selectors = 0; for (int i = 0; i < (2 << vex.l); ++i) selectors |= (uint64_t)((i >> 1) * 2 + ((u8 >> i) & 1)) << (i * 16); - MOV64x(x4, selectors); + MOV64xs(x4, selectors, x3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); VMV_V_X(v1, x4); VRGATHEREI16_VV(q2, q0, v1, VECTOR_UNMASKED); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c index a3a5e0bc7..73c9b2052 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c @@ -404,7 +404,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, SRLI(x4, x4, 29); MOV32w(x5, 0x007fffff); AND(x4, x4, x5); - LUI(x5, 0x7fc00); + MOV32w(x5, 0x7FC00000); OR(x4, x4, x5); OR(x4, x4, x6); FMVWX(v0, x4); @@ -932,7 +932,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FCVTLD(x3, d0, RD_DYN); SEXT_W(x5, x3); BEQ(x5, x3, 8); - LUI(x3, 0x80000); + MOV64x(x3, (int64_t)INT32_MIN); SW(x3, gback, gdoffset + 4 * i); } if (vex.l) { @@ -942,7 +942,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FCVTLD(x3, d0, RD_DYN); SEXT_W(x5, x3); BEQ(x5, x3, 8); - LUI(x3, 0x80000); + MOV64x(x3, (int64_t)INT32_MIN); SW(x3, gback, gdoffset + 8 + 4 * i); } } else { diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c index 71f4c84f6..2be87c489 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c @@ -162,7 +162,7 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt SRLI(x4, x4, 29); MOV32w(x5, 0x007fffff); AND(x4, x4, x5); - LUI(x5, 0x7fc00); + MOV32w(x5, 0x7FC00000); OR(x4, x4, x5); OR(x4, x4, x6); FMVWX(d1, x4); @@ -247,7 +247,7 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt u8 = F8; q0 = fpu_get_scratch(dyn); q2 = fpu_get_scratch(dyn); - MOV64x(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48)); + MOV64xs(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48), x3); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); VMV_V_X(q0, x4); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c index 649cc950d..ed249ceb5 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c @@ -377,7 +377,7 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FRFLAGS(x5); ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQZ(x5, 4 + 4); - LUI(x3, 0x80000000 >> 12); + MOV64x(x3, (int64_t)INT32_MIN); } SW(x3, gback, gdoffset + i * 4); } @@ -393,7 +393,7 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FRFLAGS(x5); ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQZ(x5, 4 + 4); - LUI(x3, 0x80000000 >> 12); + MOV64x(x3, (int64_t)INT32_MIN); } SW(x3, gback, gyoffset + i * 4); } diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c index c343fef44..9131269b2 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c @@ -352,7 +352,7 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt u8 = F8; q0 = fpu_get_scratch(dyn); q2 = fpu_get_scratch(dyn); - MOV64x(x4, (uint64_t)(4 + (u8 & 3)) | ((uint64_t)(4 + ((u8 >> 2) & 3)) << 16) | ((uint64_t)(4 + ((u8 >> 4) & 3)) << 32) | ((uint64_t)(4 + ((u8 >> 6) & 3)) << 48)); + MOV64xs(x4, (uint64_t)(4 + (u8 & 3)) | ((uint64_t)(4 + ((u8 >> 2) & 3)) << 16) | ((uint64_t)(4 + ((u8 >> 4) & 3)) << 32) | ((uint64_t)(4 + ((u8 >> 6) & 3)) << 48), x3); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); VMV_V_X(q0, x4); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); diff --git a/src/dynarec/rv64/dynarec_rv64_d9.c b/src/dynarec/rv64/dynarec_rv64_d9.c index c7dc92735..7b92d866f 100644 --- a/src/dynarec/rv64/dynarec_rv64_d9.c +++ b/src/dynarec/rv64/dynarec_rv64_d9.c @@ -148,7 +148,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni if (i2 >= 0) { LHU(x3, xEmu, offsetof(x64emu_t, fpu_tags)); if (i2 > 0) { - LUI(x5, 0xffff0); + MOV64x(x5, 0xFFFFFFFFFFFF0000); OR(x3, x3, x5); SRLI(x3, x3, i2 * 2); } diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c index ede569caf..264ea4db9 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f.c @@ -158,7 +158,7 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ZEROUP(gd); XOR(x5, x5, gd); SLLI(x5, x5, 56); - MOV64x(x2, 0x4869EC38DEA713F1ULL); + MOV64xs(x2, 0x4869EC38DEA713F1ULL, x3); CLMUL(x5, x5, x2); MOV64x(x2, 0x105EC76F1ULL); CLMULH(x5, x5, x2); @@ -188,7 +188,7 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ZEROUP(gd); XOR(x5, x5, gd); if (!rex.w) SLLI(x5, x5, 32); - MOV64x(x2, 0x4869EC38DEA713F1ULL); + MOV64xs(x2, 0x4869EC38DEA713F1ULL, x3); CLMUL(x5, x5, x2); MOV64x(x2, 0x105EC76F1ULL); CLMULH(x5, x5, x2); @@ -323,7 +323,7 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SRLI(x4, x4, 29); MOV32w(x5, 0x007fffff); AND(x4, x4, x5); - LUI(x5, 0x7fc00); + MOV32w(x5, 0x7FC00000); OR(x4, x4, x5); OR(x4, x4, x6); FMVWX(v0, x4); @@ -773,7 +773,7 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FCVTLD(x3, d0, RD_DYN); SEXT_W(x5, x3); BEQ(x5, x3, 8); - LUI(x3, 0x80000); // INT32_MIN + MOV64x(x3, (int64_t)INT32_MIN); // INT32_MIN SW(x3, gback, gdoffset + 4 * i); } x87_restoreround(dyn, ninst, u8); diff --git a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c index e67a744af..06e4f69f2 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c @@ -435,10 +435,10 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i d1 = fpu_get_scratch(dyn); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); tmp64u0 = 0x0007000600050004ULL; - MOV64x(x5, tmp64u0); + MOV64xs(x5, tmp64u0, x3); VMV_S_X(d1, x5); tmp64u0 = ((((uint64_t)u8 >> 6) & 3) << 48) | ((((uint64_t)u8 >> 4) & 3) << 32) | (((u8 >> 2) & 3) << 16) | (u8 & 3); - MOV64x(x5, tmp64u0); + MOV64xs(x5, tmp64u0, x3); VSLIDE1UP_VX_SAFE(d0, d1, x5, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); if (v0 == v1) { diff --git a/src/dynarec/rv64/dynarec_rv64_f30f.c b/src/dynarec/rv64/dynarec_rv64_f30f.c index ef87cefe4..e6307bde0 100644 --- a/src/dynarec/rv64/dynarec_rv64_f30f.c +++ b/src/dynarec/rv64/dynarec_rv64_f30f.c @@ -223,7 +223,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FEQS(x5, v1, v1); BNEZ_MARK(x5); BNEZ_MARK2(x4); - LUI(x5, 0x00400); + MOV32w(x5, 0x400000); OR(x3, x3, x5); FMVWX(v1, x3); B_MARK_nocond; @@ -239,7 +239,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETGXSS_empty(v1); q0 = fpu_get_scratch(dyn); // 1.0f d0 = fpu_get_scratch(dyn); // 0.0f - LUI(x3, 0x3F800); // 1.0f + MOV32w(x3, 0x3F800000); FMVWX(q0, x3); if (!BOX64ENV(dynarec_fastnan)) { MOV32w(x6, 0x00400000); @@ -273,7 +273,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETEXSS(v0, 0); GETGXSS_empty(v1); q0 = fpu_get_scratch(dyn); - LUI(x3, 0x3F800); // 1.0f + MOV32w(x3, 0x3F800000); FMVWX(q0, x3); if (!BOX64ENV(dynarec_fastnan)) { MOV32w(x6, 0x00400000); @@ -628,22 +628,14 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int CPOPxw(gd, ed); } else { if (rex.w) { - // x7 = 0x5555555555555555 - LUI(x7, 0x55555); - ADDIW(x7, x7, 0x555); - SLLI(x6, x7, 32); - ADD(x7, x7, x6); + MOV64xs(x7, 0x5555555555555555ULL, x6); // v = v - ((v >> 1) & x7) SRLI(x5, ed, 1); AND(x5, x5, x7); SUB(x5, ed, x5); - // x3 = 0x3333333333333333 - LUI(x3, 0x33333); - ADDIW(x3, x3, 0x333); - SLLI(x6, x3, 32); - ADD(x3, x3, x6); + MOV64xs(x3, 0x3333333333333333ULL, x6); // v = (v & x3) + ((v >> 2) & x3); SRLI(x7, x5, 2); @@ -651,39 +643,27 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int AND(x5, x5, x3); ADD(x5, x5, x7); - // x3 = 0x0F0F0F0F0F0F0F0F - LUI(x3, 0xF0F1); - ADDIW(x3, x3, 0xF0F); - SLLI(x6, x3, 32); - ADD(x3, x3, x6); + MOV64xs(x3, 0x0F0F0F0F0F0F0F0FULL, x6); // v = (v + (v >> 4) & x3) SRLI(x7, x5, 4); ADD(x5, x5, x7); AND(x5, x5, x3); - // x3 = 0x0101010101010101 - LUI(x3, 0x1010); - ADDIW(x3, x3, 0x101); - SLLI(x6, x3, 32); - ADD(x3, x3, x6); + MOV64xs(x3, 0x0101010101010101ULL, x6); // count = (v * x3) >> 56 MUL(gd, x5, x3); SRLI(gd, gd, 56); } else { - // x7 = 0x55555555uLL - LUI(x7, 0x55555); - ADDIW(x7, x7, 0x555); + MOV32w(x7, 0x55555555); // v = v - ((v >> 1) & x7) SRLI(x5, ed, 1); AND(x5, x5, x7); SUB(x5, ed, x5); - // x3 = 0x33333333uLL - LUI(x3, 0x33333); - ADDIW(x3, x3, 0x333); + MOV32w(x3, 0x33333333); // v = (v & x3) + ((v >> 2) & x3); SRLI(x7, x5, 2); @@ -691,18 +671,14 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int AND(x5, x5, x3); ADD(x5, x5, x7); - // x3 = 0x0F0F0F0FuLL - LUI(x3, 0xF0F1); - ADDIW(x3, x3, 0xF0F); + MOV32w(x3, 0x0F0F0F0F); // v = (v + (v >> 4) & x3) SRLI(x7, x5, 4); ADD(x5, x5, x7); AND(x5, x5, x3); - // x3 = 01010101uLL - LUI(x3, 0x1010); - ADDIW(x3, x3, 0x101); + MOV32w(x3, 0x01010101); // count = (v * x3) >> 24 MULW(gd, x5, x3); diff --git a/src/dynarec/rv64/dynarec_rv64_f30f_vector.c b/src/dynarec/rv64/dynarec_rv64_f30f_vector.c index c8c320633..38386b38b 100644 --- a/src/dynarec/rv64/dynarec_rv64_f30f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f30f_vector.c @@ -251,7 +251,7 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - LUI(x4, 0x3f800); + MOV32w(x4, 0x3F800000); FMVWX(v1, x4); // 1.0f SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); VFSQRT_V(v0, v1, VECTOR_UNMASKED); @@ -273,7 +273,7 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - LUI(x4, 0x3f800); + MOV32w(x4, 0x3F800000); FMVWX(v1, x4); // 1.0f VECTOR_LOAD_VMASK(0b0001, x4, 1); VFRDIV_VF(v0, v1, v1, VECTOR_MASKED); @@ -491,7 +491,7 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); tmp64u0 = ((((uint64_t)u8 >> 6) & 3) << 48) | ((((uint64_t)u8 >> 4) & 3) << 32) | (((u8 >> 2) & 3) << 16) | (u8 & 3); tmp64u0 += 0x0004000400040004ULL; - MOV64x(x5, tmp64u0); + MOV64xs(x5, tmp64u0, x3); VMV_S_X(d1, x5); tmp64u0 = 0x0003000200010000ULL; MOV64x(x5, tmp64u0); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 12d300cb1..a01de6ab2 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -25,6 +25,23 @@ #include "dynarec_rv64_private.h" #include "dynarec_rv64_functions.h" #include "../dynarec_helper.h" +#include "rv64_mov_imm.h" + +typedef struct rv64_mov_dynctx_s { + dynarec_rv64_t* dyn; + int ninst; +} rv64_mov_dynctx_t; + +static void rv64_mov_emit_word(void* p, uint32_t insn) +{ + rv64_mov_dynctx_t* c = (rv64_mov_dynctx_t*)p; + dynarec_rv64_t* dyn = c->dyn; + int ninst = c->ninst; + MAYUSE(dyn); + MAYUSE(ninst); + MAYUSE(insn); + EMIT(insn); +} /* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, uint8_t scratch, int64_t* fixaddress, rex_t rex, int* l, int i12, int delta) @@ -918,7 +935,7 @@ void x87_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1, int s2, in if (a > 0) { SLLI(s1, s1, a * 2); } else { - LUI(s3, 0xffff0); + MOV64x(s3, 0xFFFFFFFFFFFF0000); OR(s1, s1, s3); SRLI(s1, s1, -a * 2); } @@ -2781,55 +2798,72 @@ void CacheTransform(dynarec_rv64_t* dyn, int ninst, int cacheupd, int s1, int s2 } -void rv64_move32(dynarec_rv64_t* dyn, int ninst, int reg, int32_t val, int zeroup) +void rv64_move32(dynarec_rv64_t* dyn, int ninst, int reg, int32_t val) { - // Depending on val, the following insts are emitted. - // val == 0 -> ADDI - // lo12 != 0 && hi20 == 0 -> ADDI - // lo12 == 0 && hi20 != 0 -> LUI - // else -> LUI+ADDI - int32_t hi20 = (val + 0x800) >> 12 & 0xfffff; - int32_t lo12 = val & 0xfff; +#if STEP == 1 + (void)dyn; + (void)ninst; + (void)reg; + (void)val; + return; +#endif +#if STEP == 0 + (void)ninst; + (void)reg; + (void)val; + for (int i = 0; i < RV64_MOV_MAXOPS; ++i) + EMIT(0); + return; +#endif + rv64_mov_seq_t seq; + rv64_mov_dynctx_t ec = { dyn, ninst }; - int src = xZR; - if (hi20) { - LUI(reg, hi20); - src = reg; + if (rv64_mov_cache_get((uint64_t)(uint32_t)val, 0, 1, &seq)) { + rv64_mov_emit_seq(reg, -1, -1, &seq, rv64_mov_emit_word, &ec); + return; } - if (lo12 || !hi20) ADDIW(reg, src, lo12); - if (zeroup && (val & 0x80000000)) { - ZEROUP(reg); + + rv64_movctx_t ctx = { { cpuext.zba, cpuext.zbs, cpuext.zbb }, RV64_MOV_BUDGET }; + if (rv64_mov_seq32(&ctx, (uint32_t)val, 0, &seq)) { + rv64_mov_cache_put((uint64_t)(uint32_t)val, 0, 1, &seq); + rv64_mov_emit_seq(reg, -1, -1, &seq, rv64_mov_emit_word, &ec); } } -void rv64_move64(dynarec_rv64_t* dyn, int ninst, int reg, int64_t val) +void rv64_move64(dynarec_rv64_t* dyn, int ninst, int reg, int64_t val, int s1, int s2) { - uint64_t uval = (uint64_t)val; - if (cpuext.zbs && uval && !(uval & (uval - 1))) { - BSETI_(reg, xZR, TrailingZeros64(uval)); - return; - } +#if STEP == 1 + (void)dyn; + (void)ninst; + (void)reg; + (void)val; + (void)s1; + (void)s2; + return; +#endif +#if STEP == 0 + (void)ninst; + (void)reg; + (void)val; + (void)s1; + (void)s2; + for (int i = 0; i < RV64_MOV_MAXOPS; ++i) + EMIT(0); + return; +#endif + rv64_mov_seq_t seq; + rv64_mov_dynctx_t ec = { dyn, ninst }; + int nscratch = (s1 >= 0) + (s2 >= 0); - if (((val << 32) >> 32) == val) { - // 32bits value - rv64_move32(dyn, ninst, reg, val, 0); + if (rv64_mov_cache_get((uint64_t)val, nscratch, 0, &seq)) { + rv64_mov_emit_seq(reg, s1, s2, &seq, rv64_mov_emit_word, &ec); return; } - if (!(uval & (uval + 1))) { - ADDI(reg, xZR, -1); - SRLI(reg, reg, 64 - TrailingZeros64(~uval)); - return; - } - - int64_t lo12 = (val << 52) >> 52; - int64_t hi52 = (val + 0x800) >> 12; - int shift = 12 + TrailingZeros64((uint64_t)hi52); - hi52 = ((hi52 >> (shift - 12)) << shift) >> shift; - rv64_move64(dyn, ninst, reg, hi52); - SLLI(reg, reg, shift); - if (lo12) { - ADDI(reg, reg, lo12); + rv64_movctx_t ctx = { { cpuext.zba, cpuext.zbs, cpuext.zbb }, RV64_MOV_BUDGET }; + if (rv64_mov_seq64(&ctx, (uint64_t)val, 0, nscratch, &seq)) { + rv64_mov_cache_put((uint64_t)val, nscratch, 0, &seq); + rv64_mov_emit_seq(reg, s1, s2, &seq, rv64_mov_emit_word, &ec); } } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 3310968ea..d1317ebc2 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -979,6 +979,8 @@ #define GETMARK2 GETMARKi(1) #define MARK3 MARKi(2) #define GETMARK3 GETMARKi(2) +#define MARK4 MARKi(3) +#define GETMARK4 GETMARKi(3) #define MARKFi(i) dyn->insts[ninst].markf[i] = dyn->native_size #define GETMARKFi(i) dyn->insts[ninst].markf[i] @@ -1054,6 +1056,12 @@ #define BEQZ_MARK2(reg) BEQ_MARK2(reg, xZR) // Branch to MARK3 if reg1==0 (use j64) #define BEQZ_MARK3(reg) BEQ_MARK3(reg, xZR) +// Branch to MARK4 if reg1!=reg2 (use j64) +#define BNE_MARK4(reg1, reg2) Bxx_gen(NE, MARK4, reg1, reg2) +// Branch to MARK4 if reg1!=0 (use j64) +#define BNEZ_MARK4(reg) BNE_MARK4(reg, xZR) +// Branch to MARK4 instruction unconditionnal (use j64) +#define B_MARK4_nocond Bxx_gen(__, MARK4, 0, 0) // Branch to MARK3 instruction unconditionnal (use j64) #define B_MARK3_nocond Bxx_gen(__, MARK3, 0, 0) // Branch to MARKLOCK if reg1!=reg2 (use j64) @@ -1250,7 +1258,7 @@ SLLI(xs, xs, 41); \ SRLI(xs, xs, 41); \ OR(xs, xs, xt); \ - LUI(xt, 0x7fc00); \ + MOV32w(xt, 0x7FC00000); \ OR(xs, xs, xt); \ FMVWX(d, xs) #endif @@ -1400,8 +1408,7 @@ // Adjust the xFlags bit 5 -> bit 11, src and dst can be the same (and can be xFlags, but not s1) #define FLAGS_ADJUST_TO11(dst, src, s1) \ - LUI(s1, 0xFFFFF); \ - ADDIW(s1, s1, 0x7DF); \ + MOV64x(s1, 0xFFFFFFFFFFFFF7DF); \ AND(s1, src, s1); \ ANDI(dst, src, 1 << 5); \ SLLI(dst, dst, 11 - 5); \ @@ -2184,8 +2191,8 @@ int sse_setround(dynarec_rv64_t* dyn, int ninst, int s1, int s2); void CacheTransform(dynarec_rv64_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3); -void rv64_move64(dynarec_rv64_t* dyn, int ninst, int reg, int64_t val); -void rv64_move32(dynarec_rv64_t* dyn, int ninst, int reg, int32_t val, int zeroup); +void rv64_move64(dynarec_rv64_t* dyn, int ninst, int reg, int64_t val, int s1, int s2); +void rv64_move32(dynarec_rv64_t* dyn, int ninst, int reg, int32_t val); int vector_vsetvli(dynarec_rv64_t* dyn, int ninst, int s1, int sew, int vlmul, float multiple); void vector_loadmask(dynarec_rv64_t* dyn, int ninst, int vreg, uint64_t imm, int s1, float multiple); @@ -2526,11 +2533,10 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt SLLI(s1, s2, 8); \ J(20); /* end */ \ /* undefined/NaN */ \ - LUI(s1, 4); \ - ADDI(s1, s1, 0b010100000000); \ + MOV32w(s1, 0x4500); \ J(8); /* end */ \ /* equal */ \ - LUI(s1, 4); \ + MOV32w(s1, 0x4000); \ /* end */ \ OR(s3, s3, s1); \ SH(s3, xEmu, offsetof(x64emu_t, sw)); @@ -2672,6 +2678,18 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt } \ } while (0) +#define VECTOR_SPLAT_IMM_S(vreg, imm, s1, s2) \ + do { \ + if (imm == 0) { \ + VXOR_VV(vreg, vreg, vreg, VECTOR_UNMASKED); \ + } else if ((imm & 0xf) == imm) { \ + VMV_V_I(vreg, imm); \ + } else { \ + MOV64xs(s1, imm, s2); \ + VMV_V_X(vreg, s1); \ + } \ + } while (0) + #define VECTOR_LOAD_VMASK(mask, s1, multiple) \ vector_loadmask(dyn, ninst, VMASK, mask, s1, multiple) diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index 1992318f0..a44b46091 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -11,8 +11,10 @@ #define SPLIT12(A) ((A) & 0xfff) // MOV64x/MOV32w is quite complex, so use a function for this -#define MOV64x(A, B) rv64_move64(dyn, ninst, A, B) -#define MOV32w(A, B) rv64_move32(dyn, ninst, A, B, 1) +#define MOV64x(A, B) rv64_move64(dyn, ninst, A, B, -1, -1) +#define MOV64xs(A, B, S1) rv64_move64(dyn, ninst, A, B, S1, -1) +#define MOV64xss(A, B, S1, S2) rv64_move64(dyn, ninst, A, B, S1, S2) +#define MOV32w(A, B) rv64_move32(dyn, ninst, A, (int32_t)(B)) #define MOV64xw(A, B) \ do { \ if (rex.w) { \ @@ -1201,14 +1203,14 @@ } // Insert low 16bits in rs to low 16bits of rd -#define INSH(rd, rs, s1, s2, init_s1, zexth_rs) \ - if (init_s1) LUI(s1, 0xffff0); \ - AND(rd, rd, s1); \ - if (zexth_rs) { \ - ZEXTH(s2, rs); \ - OR(rd, rd, s2); \ - } else { \ - OR(rd, rd, rs); \ +#define INSH(rd, rs, s1, s2, init_s1, zexth_rs) \ + if (init_s1) MOV64x(s1, 0xFFFFFFFFFFFF0000); \ + AND(rd, rd, s1); \ + if (zexth_rs) { \ + ZEXTH(s2, rs); \ + OR(rd, rd, s2); \ + } else { \ + OR(rd, rd, rs); \ } // Insert low 16bits in rs to low 16bits of rd @@ -1291,7 +1293,7 @@ OR(s1, s1, s3); \ OR(s1, s1, s4); \ SLLIW(s3, rs, 8); \ - LUI(s2, 0xff0); \ + MOV32w(s2, 0xFF0000); \ AND(s3, s3, s2); \ OR(rd, s1, s3); \ } \ @@ -1327,15 +1329,14 @@ // Single-bit Set (Immediate) #define BSETI_(rd, rs1, imm) EMIT(R_type(0b0010100, imm, rs1, 0b001, rd, 0b0010011)) // Single-bit Set (Immediate), with fallback (s0 is used as a scratch register) -#define BSETI(rd, rs1, imm, s0) \ - do { \ - if (cpuext.zbs) \ - BSETI_(rd, rs1, imm); \ - else { \ - ADDI(s0, xZR, 1); \ - SLLI(s0, s0, (imm)); \ - OR(rd, rs1, s0); \ - } \ +#define BSETI(rd, rs1, imm, s0) \ + do { \ + if (cpuext.zbs) \ + BSETI_(rd, rs1, imm); \ + else { \ + MOV64x(s0, 1ULL << (imm)); \ + OR(rd, rs1, s0); \ + } \ } while (0) // Single-bit Extract (Register) diff --git a/src/dynarec/rv64/rv64_mov_imm.c b/src/dynarec/rv64/rv64_mov_imm.c new file mode 100644 index 000000000..0b0ca101a --- /dev/null +++ b/src/dynarec/rv64/rv64_mov_imm.c @@ -0,0 +1,746 @@ +// SPDX-License-Identifier: MIT + +/* + * 1. rv64_mov_seq64() and rv64_mov_seq32() + * + * These two functions try a number of standard tricks and keep the best result. + * "Best" means the fewest instructions; if two results use the same number of instructions, + * the one with the shorter dependency chain wins, because it has less latency. + * + * Some of the tricks are: + * - single ADDI for values that fit in 12 signed bits + * - LUI + ADDIW for ordinary 32-bit values + * - BSETI when only one or a few bits are set + * - building -1 and shifting it for simple masks + * - shifting the value, building the shifted value and shifting it back + * - splitting the value into a low half and a high half, building each half and joining them with a shift and an ADD + * - optional Zba / Zbs / Zbb instructions (SH1ADD, BCLRI, RORI, SLLIUW, ...) when the CPU has those extensions + * + * Some tricks build the value in pieces: + * they ask for a sequence for a sub-value and then add the instruction that joins the pieces together. + * The expensive recursive candidates stop at RV64_MOV_MAXDEPTH (currently 2), RV64_MOV_BUDGET caps the total work, + * and rv64_mov_min_ops64() skips branches that cannot improve the best result. + * + * 2. rv64_mov_emit_seq() + * + * This is the emitter, it turns the list that step 1 returns into real RISC-V instructions, + * using the destination register and the scratch registers that the caller provided. + * + * 3. rv64_mov_cache_get() and rv64_mov_cache_put() + * + * A small per-thread cache table remembers up to 1024 answers. + * An entry is identified by the value, the number of scratch registers used and whether this is a 32-bit or a 64-bit move. + * Very long sequences (more than 8 steps) are not cached. + */ +#include +#include + +#include "rv64_mov_imm.h" +#include "rv64_emitter.h" + +static int rv64_mov_ctz64(uint64_t x) { return x ? __builtin_ctzll(x) : 64; } +static int rv64_mov_clz64(uint64_t x) { return x ? __builtin_clzll(x) : 64; } +static int rv64_mov_popcnt64(uint64_t x) { return __builtin_popcountll(x); } + +static int32_t rv64_mov_sext12(uint32_t x) { return (int32_t)(((x & 0xfffu) ^ 0x800u) - 0x800u); } + +static int rv64_mov_fits12(uint64_t v) +{ + int64_t s = (int64_t)v; + return s >= -2048 && s <= 2047; +} + +static int rv64_mov_fits32(uint64_t v) +{ + int64_t s = (int64_t)v; + return s >= -0x80000000LL && s <= 0x7fffffffLL; +} + +static int rv64_mov_min_ops64(const rv64_movctx_t* ctx, uint64_t v) +{ + if (rv64_mov_fits12(v)) return 1; + if (ctx->caps.zbs && v && !(v & (v - 1))) return 1; + if (rv64_mov_fits32(v) && !(v & 0xfff)) return 1; + if (v && !(v & (v + 1))) return 2; + if (ctx->caps.zbs) { + int c = rv64_mov_popcnt64(v); + if (c && c <= 4) return c; + int z = rv64_mov_popcnt64(~v); + if (z && z <= 3) return 1 + z; + } + if (rv64_mov_fits32(v)) return 2; + int t = rv64_mov_ctz64(v); + if (v && t > 0 && (v >> t) == (~UINT64_C(0) >> t)) return 2; + if (v && t >= 12 && (v >> t) < 0x100000 && (ctx->caps.zba || (v >> t) < 0x80000)) return 2; + return 3; +} + +static void rv64_mov_seq_zero(rv64_mov_seq_t* p) +{ + p->n = 0; + p->depth = 0; + p->overflow = 0; +} + +static void rv64_mov_seq_copy(rv64_mov_seq_t* dst, const rv64_mov_seq_t* src) +{ + dst->n = src->n; + dst->depth = src->depth; + dst->overflow = src->overflow; + memcpy(dst->op, src->op, src->n * sizeof(rv64_movop_t)); +} + +static void rv64_mov_seq_add(rv64_mov_seq_t* p, uint8_t op, uint8_t rd, uint8_t rs, uint8_t rs2, int32_t imm, int depth) +{ + if (p->n >= RV64_MOV_MAXOPS) { + p->overflow = 1; + return; + } + p->op[p->n].op = op; + p->op[p->n].rd = rd; + p->op[p->n].rs = rs; + p->op[p->n].rs2 = rs2; + p->op[p->n].imm = imm; + p->n++; + if (depth > p->depth) p->depth = (uint8_t)depth; +} + +static void rv64_mov_seq_rename(rv64_mov_seq_t* p, uint8_t from, uint8_t to) +{ + int i; + for (i = 0; i < p->n; ++i) { + if (p->op[i].rd == from) p->op[i].rd = to; + if (p->op[i].rs == from) p->op[i].rs = to; + if (p->op[i].rs2 == from) p->op[i].rs2 = to; + } +} + +static void rv64_mov_seq_concat(rv64_mov_seq_t* dst, const rv64_mov_seq_t* src) +{ + int i; + int base = dst->depth; + if (dst->overflow || src->overflow) { + dst->overflow = 1; + return; + } + for (i = 0; i < src->n; ++i) { + if (dst->n >= RV64_MOV_MAXOPS) { + dst->overflow = 1; + return; + } + dst->op[dst->n] = src->op[i]; + dst->n++; + } + if (src->depth > base) base = src->depth; + dst->depth = (uint8_t)base; +} + +typedef struct rv64_movbest_s { + int cost; + int depth; + rv64_mov_seq_t seq; +} rv64_movbest_t; + +static void rv64_mov_best_try(rv64_movbest_t* best, const rv64_mov_seq_t* p) +{ + if (!p->n || p->n > RV64_MOV_MAXOPS || p->overflow) return; + if (p->n < best->cost || (p->n == best->cost && p->depth < best->depth)) { + best->cost = p->n; + best->depth = p->depth; + rv64_mov_seq_copy(&best->seq, p); + } +} + +static void rv64_mov_best_try1(rv64_movbest_t* best, const rv64_mov_seq_t* sub, + uint8_t op, uint8_t rd, uint8_t rs, int32_t imm) +{ + rv64_mov_seq_t p; + if (!sub->n || sub->n + 1 > RV64_MOV_MAXOPS || sub->overflow) return; + rv64_mov_seq_copy(&p, sub); + rv64_mov_seq_add(&p, op, rd, rs, 0, imm, sub->depth + 1); + rv64_mov_best_try(best, &p); +} + + +static int rv64_mov_seq_high(rv64_movctx_t* ctx, uint64_t hi, int sh, int depth, int nscratch, rv64_mov_seq_t* out) +{ + rv64_mov_seq_t sub; + rv64_movbest_t best; + best.cost = 99; + best.depth = 99; + best.seq.n = 0; + best.seq.depth = 0; + best.seq.overflow = 0; + + if (rv64_mov_seq64(ctx, hi, depth, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_SLLI, RV64_MOV_DST, 0, sh); + + if (hi < 0x100000000ULL && (hi & 0x80000000ULL) && sh >= 32) { + if (rv64_mov_seq64(ctx, (uint64_t)(int64_t)(int32_t)hi, depth, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_SLLI, RV64_MOV_DST, 0, sh); + } + + if (hi && hi < 0x100000ULL && sh >= 12) { + rv64_mov_seq_t p; + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_LUI, RV64_MOV_DST, 0, 0, (int32_t)hi, 1); + if (hi < 0x80000ULL) { + if (sh > 12) rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_DST, 0, 0, sh - 12, 2); + rv64_mov_best_try(&best, &p); + } else if (ctx->caps.zba && sh > 12) { + rv64_mov_seq_add(&p, RV64_MOV_SLLIUW, RV64_MOV_DST, 0, 0, sh - 12, 2); + rv64_mov_best_try(&best, &p); + } + } + + if (!best.cost) return 0; + rv64_mov_seq_copy(out, &best.seq); + return out->n; +} + +int rv64_mov_seq64(rv64_movctx_t* ctx, uint64_t v, int depth, int nscratch, rv64_mov_seq_t* out) +{ + rv64_movbest_t best; + best.cost = 99; + best.depth = 99; + best.seq.n = 0; + best.seq.depth = 0; + best.seq.overflow = 0; + rv64_mov_seq_t p, sub; + int64_t sv = (int64_t)v; + int t, n; + + if (rv64_mov_fits12(v)) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, (int32_t)sv, 1); + rv64_mov_best_try(&best, &p); + } + + if (rv64_mov_fits32(v) && !rv64_mov_fits12(v)) { + uint32_t vv = (uint32_t)v; + int32_t hi20 = (int32_t)(((uint64_t)vv + 0x800) >> 12) & 0xfffff; + int32_t lo12 = rv64_mov_sext12(vv); + rv64_mov_seq_zero(&p); + if (!lo12) { + rv64_mov_seq_add(&p, RV64_MOV_LUI, RV64_MOV_DST, 0, 0, hi20, 1); + } else if (!hi20) { + rv64_mov_seq_add(&p, RV64_MOV_ADDIW, RV64_MOV_DST, 0, 0, lo12, 1); + } else { + rv64_mov_seq_add(&p, RV64_MOV_LUI, RV64_MOV_DST, 0, 0, hi20, 1); + rv64_mov_seq_add(&p, RV64_MOV_ADDIW, RV64_MOV_DST, 0, 0, lo12, 2); + } + rv64_mov_best_try(&best, &p); + } + + if (ctx->caps.zbs && v && !(v & (v - 1))) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_BSETI, RV64_MOV_DST, 0, 0, rv64_mov_ctz64(v), 1); + rv64_mov_best_try(&best, &p); + } + + if (ctx->caps.zbs && v && rv64_mov_popcnt64(v) <= 4) { + uint64_t z = v; + int c = 0; + rv64_mov_seq_zero(&p); + while (z) { + rv64_mov_seq_add(&p, RV64_MOV_BSETI, RV64_MOV_DST, 0, 0, rv64_mov_ctz64(z), ++c); + z &= z - 1; + } + rv64_mov_best_try(&best, &p); + } + + if (v && !(v & (v + 1))) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, -1, 1); + rv64_mov_seq_add(&p, RV64_MOV_SRLI, RV64_MOV_DST, 0, 0, rv64_mov_clz64(v), 2); + rv64_mov_best_try(&best, &p); + } + + t = rv64_mov_ctz64(v); + if (v && t > 0 && t < 64 && (v >> t) == (~UINT64_C(0) >> t)) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, -1, 1); + rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_DST, 0, 0, t, 2); + rv64_mov_best_try(&best, &p); + } + + if (ctx->caps.zbs && v != ~UINT64_C(0)) { + int k = rv64_mov_ctz64(~v); + if ((v | (UINT64_C(1) << k)) == ~UINT64_C(0) && !rv64_mov_fits12(v)) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, -1, 1); + rv64_mov_seq_add(&p, RV64_MOV_BCLRI, RV64_MOV_DST, 0, 0, k, 2); + rv64_mov_best_try(&best, &p); + } + } + + if (ctx->caps.zbs && best.cost > 2) { + uint64_t zeros = ~v; + n = rv64_mov_popcnt64(zeros); + if (n > 0 && n <= 3) { + uint64_t z = zeros; + int c = 1; + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, -1, 1); + while (z) { + rv64_mov_seq_add(&p, RV64_MOV_BCLRI, RV64_MOV_DST, 0, 0, rv64_mov_ctz64(z), ++c); + z &= z - 1; + } + rv64_mov_best_try(&best, &p); + } + } + + if (ctx->caps.zbs && best.cost > 1) { + uint32_t low12 = (uint32_t)v & 0xfff; + int32_t cand[2]; + int ncand = 0; + if (v & 0x7ff) cand[ncand++] = (int32_t)(v & 0x7ff); + if (low12) { + int32_t a = rv64_mov_sext12(low12); + if (a >= 0 || (((uint64_t)v - (uint64_t)(int64_t)a) & 0x7ffff000ULL)) + cand[ncand++] = a; + } + for (int i = 0; i < ncand; ++i) { + int32_t a = cand[i]; + uint64_t w = v - (uint64_t)(int64_t)a; + uint64_t lui_part, rest, z; + int c = 0; + if (w & 0xfff) continue; + lui_part = w & 0x7ffff000ULL; + rest = w & ~0x7ffff000ULL; + if (a < 0 && !lui_part) continue; + if (rv64_mov_popcnt64(rest) > 4) continue; + rv64_mov_seq_zero(&p); + if (lui_part) { + rv64_mov_seq_add(&p, RV64_MOV_LUI, RV64_MOV_DST, 0, 0, (int32_t)(lui_part >> 12), ++c); + } + if (a) { + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, a, ++c); + } + z = rest; + while (z) { + rv64_mov_seq_add(&p, RV64_MOV_BSETI, RV64_MOV_DST, 0, 0, rv64_mov_ctz64(z), ++c); + z &= z - 1; + } + if (c) rv64_mov_best_try(&best, &p); + } + } + + { + uint32_t low12 = (uint32_t)v & 0xfff; + if (low12) { + int32_t a = rv64_mov_sext12(low12); + uint64_t w = v - (uint64_t)(int64_t)a; + if (w && w != v && rv64_mov_min_ops64(ctx, w) + 1 <= best.cost + && rv64_mov_seq64(ctx, w, depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_ADDI, RV64_MOV_DST, 0, a); + } + } + + t = rv64_mov_ctz64(v); + if (v && t >= 12 && t < 64) { + uint64_t hi = v >> t; + uint64_t his = (uint64_t)(sv >> t); + if (rv64_mov_min_ops64(ctx, hi) + 1 <= best.cost + && rv64_mov_seq64(ctx, hi, depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_SLLI, RV64_MOV_DST, 0, t); + if (his != hi && rv64_mov_min_ops64(ctx, his) + 1 <= best.cost + && rv64_mov_seq64(ctx, his, depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_SLLI, RV64_MOV_DST, 0, t); + if (ctx->caps.zba && t < 32 && hi < 0x100000000ULL && (hi & 0x80000000ULL)) { + if (rv64_mov_min_ops64(ctx, (uint64_t)(int64_t)(int32_t)hi) + 1 <= best.cost + && rv64_mov_seq64(ctx, (uint64_t)(int64_t)(int32_t)hi, depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_SLLIUW, RV64_MOV_DST, 0, t); + } + } + + if (depth < RV64_MOV_MAXDEPTH && best.cost > 2 && ctx->budget > 0 && rv64_mov_min_ops64(ctx, v) < best.cost) { + ctx->budget--; + uint32_t low12 = (uint32_t)v & 0xfff; + + { + int lz = rv64_mov_clz64(v); + for (int s = 1; s <= lz; ++s) { + uint64_t w = v << s; + int32_t sw = (int32_t)(uint32_t)w; + if ((uint64_t)(int64_t)sw != w || (w & 0xfff)) continue; + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_LUI, RV64_MOV_DST, 0, 0, (int32_t)((w >> 12) & 0xfffff), 1); + rv64_mov_seq_add(&p, RV64_MOV_SRLI, RV64_MOV_DST, 0, 0, s, 2); + rv64_mov_best_try(&best, &p); + } + } + + if (sv < 0 && rv64_mov_min_ops64(ctx, ~v) + 1 <= best.cost) { + if (rv64_mov_seq64(ctx, ~v, depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_XORI, RV64_MOV_DST, 0, -1); + } + + if (low12 >= 0x800) { + uint64_t w = v ^ (uint64_t)(int64_t)rv64_mov_sext12(low12); + if (w != v && rv64_mov_min_ops64(ctx, w) + 1 <= best.cost && rv64_mov_seq64(ctx, w, depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_XORI, RV64_MOV_DST, 0, + rv64_mov_sext12(low12)); + } + + if (ctx->caps.zbs) { + uint64_t hi_zeros = ~v & 0xffffffff80000000ULL; + n = rv64_mov_popcnt64(hi_zeros); + if (n > 0 && n <= 3) { + uint64_t nval = v | 0xffffffff80000000ULL; + if (nval != v && rv64_mov_min_ops64(ctx, nval) + n <= best.cost && rv64_mov_seq64(ctx, nval, depth + 1, nscratch, &sub)) { + uint64_t z = hi_zeros; + rv64_mov_seq_copy(&p, &sub); + int c = sub.depth; + while (z) { + rv64_mov_seq_add(&p, RV64_MOV_BCLRI, RV64_MOV_DST, 0, 0, rv64_mov_ctz64(z), ++c); + z &= z - 1; + } + rv64_mov_best_try(&best, &p); + } + } + } + + if (ctx->caps.zba) { + static const int mk[3] = { 9, 5, 3 }; + static const uint8_t mop[3] = { RV64_MOV_SH3ADD, RV64_MOV_SH2ADD, RV64_MOV_SH1ADD }; + for (int i = 0; i < 3; ++i) { + if (v % mk[i] == 0 && rv64_mov_min_ops64(ctx, v / mk[i]) + 1 <= best.cost && rv64_mov_seq64(ctx, v / mk[i], depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, mop[i], RV64_MOV_DST, RV64_MOV_DST, 0); + } + } + + for (int sh = 12; sh < 64; ++sh) { + uint64_t mask = (UINT64_C(1) << sh) - 1; + uint64_t low = v & mask; + int64_t lo = (int64_t)low; + uint64_t w, hi, his; + if (low >> (sh - 1)) lo = (int64_t)(low - (UINT64_C(1) << sh)); + if (lo < -2048 || lo > 2047) continue; + w = v - (uint64_t)lo; + hi = w >> sh; + his = (uint64_t)((int64_t)w >> sh); + int ov = 1 + !!lo; + if (rv64_mov_min_ops64(ctx, hi) + ov <= best.cost && rv64_mov_seq64(ctx, hi, depth + 1, nscratch, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_DST, 0, 0, sh, sub.depth + 1); + if (lo) rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, (int32_t)lo, sub.depth + 2); + rv64_mov_best_try(&best, &p); + } + if (his != hi && rv64_mov_min_ops64(ctx, his) + ov <= best.cost && rv64_mov_seq64(ctx, his, depth + 1, nscratch, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_DST, 0, 0, sh, sub.depth + 1); + if (lo) rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, (int32_t)lo, sub.depth + 2); + rv64_mov_best_try(&best, &p); + } + if (ctx->caps.zba && sh < 32 && hi < 0x100000000ULL && (hi & 0x80000000ULL)) { + if (rv64_mov_min_ops64(ctx, (uint64_t)(int64_t)(int32_t)hi) + ov <= best.cost && rv64_mov_seq64(ctx, (uint64_t)(int64_t)(int32_t)hi, depth + 1, nscratch, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_add(&p, RV64_MOV_SLLIUW, RV64_MOV_DST, 0, 0, sh, sub.depth + 1); + if (lo) rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, (int32_t)lo, sub.depth + 2); + rv64_mov_best_try(&best, &p); + } + } + } + + if (nscratch && v > 0xffffffffULL) { + uint32_t lo = (uint32_t)v; + uint64_t hi = v >> 32; + + if (lo == hi) { + if (rv64_mov_seq32(ctx, lo, depth + 1, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_rename(&p, RV64_MOV_DST, RV64_MOV_S1); + rv64_mov_seq_add(&p, RV64_MOV_SLLI2, RV64_MOV_DST, RV64_MOV_S1, 0, 32, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_DST, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + if ((lo & 0x80000000u) && rv64_mov_seq32(ctx, ~lo & 0xffffffffu, depth + 1, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_rename(&p, RV64_MOV_DST, RV64_MOV_S1); + rv64_mov_seq_add(&p, RV64_MOV_SLLI2, RV64_MOV_DST, RV64_MOV_S1, 0, 32, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_DST, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_XORI, RV64_MOV_DST, 0, 0, -1, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + } else { + if (rv64_mov_seq32(ctx, lo, depth + 1, &sub)) { + rv64_mov_seq_t lo_seq, hi_seq; + rv64_mov_seq_copy(&lo_seq, &sub); + if (rv64_mov_seq_high(ctx, hi, 32, depth + 1, 0, &hi_seq)) { + rv64_mov_seq_rename(&lo_seq, RV64_MOV_DST, RV64_MOV_S1); + p = lo_seq; + rv64_mov_seq_concat(&p, &hi_seq); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_DST, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + } + if (hi == (uint64_t)(uint32_t)(lo - 1) && (lo & 0x80000000u)) { + if (rv64_mov_seq64(ctx, (uint64_t)(int64_t)(int32_t)lo, depth + 1, 0, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_rename(&p, RV64_MOV_DST, RV64_MOV_S1); + rv64_mov_seq_add(&p, RV64_MOV_SLLI2, RV64_MOV_DST, RV64_MOV_S1, 0, 32, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_DST, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + } + if (!(lo & 0x80000000u)) { + uint32_t dlt = (uint32_t)hi - lo; + if (hi == (uint64_t)(uint32_t)~lo) { + if (rv64_mov_seq32(ctx, lo, depth + 1, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_rename(&p, RV64_MOV_DST, RV64_MOV_S1); + rv64_mov_seq_add(&p, RV64_MOV_XORI2, RV64_MOV_S2, RV64_MOV_S1, 0, -1, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_S2, 0, 0, 32, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_S2, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + } + if (nscratch >= 2 && dlt > 0 && dlt <= 2047) { + if (rv64_mov_seq32(ctx, lo, depth + 1, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_rename(&p, RV64_MOV_DST, RV64_MOV_S1); + rv64_mov_seq_add(&p, RV64_MOV_ADDI2, RV64_MOV_S2, RV64_MOV_S1, 0, (int32_t)dlt, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_S2, 0, 0, 32, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_S2, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + } + if (nscratch >= 2 && ctx->caps.zba) { + static const int mk[3] = { 3, 5, 9 }; + static const uint8_t mop[3] = { RV64_MOV_SH1ADD, RV64_MOV_SH2ADD, RV64_MOV_SH3ADD }; + for (int i = 0; i < 3; ++i) { + if (hi != (uint64_t)(uint32_t)(lo * mk[i])) continue; + if (rv64_mov_seq32(ctx, lo, depth + 1, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_rename(&p, RV64_MOV_DST, RV64_MOV_S1); + rv64_mov_seq_add(&p, mop[i], RV64_MOV_S2, RV64_MOV_S1, 0, 0, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_S2, 0, 0, 32, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_S2, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + } + } + } + + for (int sh = 33; sh <= 40; ++sh) { + uint64_t mask = (UINT64_C(1) << sh) - 1; + uint64_t lv = v & mask; + uint64_t hv = v >> sh; + if (!lv || !hv) continue; + if (!rv64_mov_seq64(ctx, lv, depth + 1, 0, &sub)) continue; + { + rv64_mov_seq_t lo_seq, hi_seq; + rv64_mov_seq_copy(&lo_seq, &sub); + if (!rv64_mov_seq_high(ctx, hv, sh, depth + 1, 0, &hi_seq)) continue; + rv64_mov_seq_rename(&lo_seq, RV64_MOV_DST, RV64_MOV_S1); + p = lo_seq; + rv64_mov_seq_concat(&p, &hi_seq); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_DST, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + } + } + } + + if (ctx->caps.zbb) { + uint64_t notv = ~v; + if (notv) { + int lo_z = rv64_mov_ctz64(notv); + int hi_z = rv64_mov_clz64(notv); + if (lo_z > 0 && rv64_mov_popcnt64(notv) == 64 - lo_z - hi_z) { + uint64_t rot = (v >> lo_z) | (v << (64 - lo_z)); + if (rv64_mov_seq64(ctx, rot, depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_RORI, RV64_MOV_DST, 0, 64 - lo_z); + } + } + } + } + + if (!best.cost) return 0; + rv64_mov_seq_copy(out, &best.seq); + return out->n; +} + +int rv64_mov_seq32(rv64_movctx_t* ctx, uint32_t v, int depth, rv64_mov_seq_t* out) +{ + rv64_movbest_t best; + best.cost = 99; + best.depth = 99; + best.seq.n = 0; + best.seq.depth = 0; + best.seq.overflow = 0; + rv64_mov_seq_t p, sub; + int t; + + if (!v || rv64_mov_fits12(v)) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, (int32_t)v, 1); + rv64_mov_best_try(&best, &p); + } + + if (ctx->caps.zbs && v && !(v & (v - 1))) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_BSETI, RV64_MOV_DST, 0, 0, rv64_mov_ctz64(v), 1); + rv64_mov_best_try(&best, &p); + } + + if (v && !(v & (v + 1))) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, -1, 1); + rv64_mov_seq_add(&p, RV64_MOV_SRLI, RV64_MOV_DST, 0, 0, rv64_mov_clz64(v), 2); + rv64_mov_best_try(&best, &p); + } + + if (!(v & 0x80000000u) && !rv64_mov_fits12(v)) { + int32_t hi20 = (int32_t)(((uint64_t)v + 0x800) >> 12) & 0xfffff; + int32_t lo12 = rv64_mov_sext12(v); + rv64_mov_seq_zero(&p); + if (!lo12) { + rv64_mov_seq_add(&p, RV64_MOV_LUI, RV64_MOV_DST, 0, 0, hi20, 1); + } else { + rv64_mov_seq_add(&p, RV64_MOV_LUI, RV64_MOV_DST, 0, 0, hi20, 1); + rv64_mov_seq_add(&p, RV64_MOV_ADDIW, RV64_MOV_DST, 0, 0, lo12, 2); + } + rv64_mov_best_try(&best, &p); + } + + if (depth < RV64_MOV_MAXDEPTH && (v & 0x80000000u) && ctx->budget > 0) { + ctx->budget--; + uint32_t w = v & 0x7fffffff; + + if (ctx->caps.zbs) { + if (!w) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_BSETI, RV64_MOV_DST, 0, 0, 31, 1); + rv64_mov_best_try(&best, &p); + } else if (rv64_mov_seq32(ctx, w, depth + 1, &sub)) { + rv64_mov_best_try1(&best, &sub, RV64_MOV_BSETI, RV64_MOV_DST, 0, 31); + } + } + if (rv64_mov_seq64(ctx, (uint64_t)(int64_t)(int32_t)v, depth + 1, 0, &sub)) { + if (ctx->caps.zba) + rv64_mov_best_try1(&best, &sub, RV64_MOV_ZEXTW, RV64_MOV_DST, 0, 0); + { + rv64_mov_seq_t q; + rv64_mov_seq_copy(&q, &sub); + rv64_mov_seq_add(&q, RV64_MOV_SLLI, RV64_MOV_DST, 0, 0, 32, sub.depth + 1); + rv64_mov_seq_add(&q, RV64_MOV_SRLI, RV64_MOV_DST, 0, 0, 32, sub.depth + 2); + rv64_mov_best_try(&best, &q); + } + } + } + + t = rv64_mov_ctz64(v); + if (depth < RV64_MOV_MAXDEPTH && v && t >= 12 && t <= 31 && ctx->budget > 0) { + ctx->budget--; + if (rv64_mov_seq32(ctx, v >> t, depth + 1, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_SLLI, RV64_MOV_DST, 0, t); + } + + if (depth < RV64_MOV_MAXDEPTH && best.cost > 2 && ctx->budget > 0) { + ctx->budget--; + for (int sh = 12; sh < 32; ++sh) { + uint32_t low = v & ((UINT32_C(1) << sh) - 1); + int32_t lo; + uint32_t hi; + if (low >> (sh - 1)) + lo = (int32_t)(low - (UINT32_C(1) << sh)); + else + lo = (int32_t)low; + if (lo < -2048 || lo > 2047) continue; + hi = (v - (uint32_t)lo) >> sh; + if (!rv64_mov_seq32(ctx, hi, depth + 1, &sub)) continue; + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_DST, 0, 0, sh, sub.depth + 1); + if (lo) rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, lo, sub.depth + 2); + rv64_mov_best_try(&best, &p); + } + } + + if (!best.cost) return 0; + rv64_mov_seq_copy(out, &best.seq); + return out->n; +} + +#define EMIT(A) emit_fn(emit_ctx, (uint32_t)(A)) + +void rv64_mov_emit_seq(int reg, int s1, int s2, const rv64_mov_seq_t* seq, rv64_mov_emit_fn emit_fn, void* emit_ctx) +{ + int vreg[3] = { reg, s1, s2 }; + uint8_t init = 0; + + for (int i = 0; i < seq->n; ++i) { + const rv64_movop_t* o = &seq->op[i]; + int rd = vreg[o->rd]; + int rs = vreg[o->rs]; + int first = !(init & (1 << o->rd)); + init |= (uint8_t)(1 << o->rd); + + switch (o->op) { + case RV64_MOV_ADDI: ADDI(rd, first ? xZR : rd, o->imm); break; + case RV64_MOV_ADDIW: ADDIW(rd, first ? xZR : rd, o->imm); break; + case RV64_MOV_LUI: LUI(rd, o->imm); break; + case RV64_MOV_SLLI: SLLI(rd, rd, o->imm); break; + case RV64_MOV_SRLI: SRLI(rd, rd, o->imm); break; + case RV64_MOV_SLLIUW: SLLIUW(rd, rd, o->imm); break; + case RV64_MOV_BSETI: BSETI_(rd, first ? xZR : rd, o->imm); break; + case RV64_MOV_BCLRI: BCLI(rd, first ? xZR : rd, o->imm); break; + case RV64_MOV_XORI: XORI(rd, rd, o->imm); break; + case RV64_MOV_ZEXTW: ZEXTW(rd, rd); break; + case RV64_MOV_RORI: RORI(rd, rd, o->imm); break; + case RV64_MOV_ADD: ADD(rd, rs, vreg[o->rs2]); break; + case RV64_MOV_SLLI2: SLLI(rd, rs, o->imm); break; + case RV64_MOV_SH1ADD: SH1ADD(rd, rs, rs); break; + case RV64_MOV_SH2ADD: SH2ADD(rd, rs, rs); break; + case RV64_MOV_SH3ADD: SH3ADD(rd, rs, rs); break; + case RV64_MOV_ADDI2: ADDI(rd, rs, o->imm); break; + case RV64_MOV_XORI2: XORI(rd, rs, o->imm); break; + default: break; + } + } +} + +#define RV64_MOV_CACHE_SIZE 1024 + +typedef struct rv64_mov_cache_s { + uint64_t v; + uint32_t key; + uint8_t n; + uint8_t used; + uint8_t pad[2]; + rv64_movop_t op[8]; +} rv64_mov_cache_t; + +static __thread rv64_mov_cache_t rv64_mov_cache[RV64_MOV_CACHE_SIZE]; + +static unsigned rv64_mov_cache_slot(uint64_t v, uint32_t key) +{ + uint64_t h = (v + ((uint64_t)key << 56)) * UINT64_C(0x9E3779B97F4A7C15); + return (unsigned)(h >> 54) & (RV64_MOV_CACHE_SIZE - 1); +} + +int rv64_mov_cache_get(uint64_t v, int nscratch, int is32, rv64_mov_seq_t* out) +{ + uint32_t key = (uint32_t)nscratch | ((uint32_t)is32 << 8); + rv64_mov_cache_t* e = &rv64_mov_cache[rv64_mov_cache_slot(v, key)]; + if (!e->used || e->v != v || e->key != key) return 0; + out->n = e->n; + out->depth = 0; + out->overflow = 0; + memcpy(out->op, e->op, (size_t)e->n * sizeof(rv64_movop_t)); + return 1; +} + +void rv64_mov_cache_put(uint64_t v, int nscratch, int is32, const rv64_mov_seq_t* seq) +{ + uint32_t key = (uint32_t)nscratch | ((uint32_t)is32 << 8); + rv64_mov_cache_t* e; + if (!seq->n || seq->n > 8) return; + e = &rv64_mov_cache[rv64_mov_cache_slot(v, key)]; + e->v = v; + e->key = key; + e->n = seq->n; + e->used = 1; + memcpy(e->op, seq->op, (size_t)seq->n * sizeof(rv64_movop_t)); +} diff --git a/src/dynarec/rv64/rv64_mov_imm.h b/src/dynarec/rv64/rv64_mov_imm.h new file mode 100644 index 000000000..6680fb139 --- /dev/null +++ b/src/dynarec/rv64/rv64_mov_imm.h @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT +#ifndef __RV64_MOV_IMM_H__ +#define __RV64_MOV_IMM_H__ + +#include + +#define RV64_MOV_MAXOPS 16 +#ifndef RV64_MOV_MAXDEPTH +#define RV64_MOV_MAXDEPTH 2 +#endif +#ifndef RV64_MOV_BUDGET +#define RV64_MOV_BUDGET 4096 +#endif + +enum rv64_movop_e { + RV64_MOV_ADDI, + RV64_MOV_ADDIW, + RV64_MOV_LUI, + RV64_MOV_SLLI, + RV64_MOV_SRLI, + RV64_MOV_SLLIUW, + RV64_MOV_BSETI, + RV64_MOV_BCLRI, + RV64_MOV_XORI, + RV64_MOV_ZEXTW, + RV64_MOV_RORI, + RV64_MOV_ADD, + RV64_MOV_SLLI2, + RV64_MOV_SH1ADD, + RV64_MOV_SH2ADD, + RV64_MOV_SH3ADD, + RV64_MOV_ADDI2, + RV64_MOV_XORI2, +}; + +#define RV64_MOV_DST 0 +#define RV64_MOV_S1 1 +#define RV64_MOV_S2 2 + +typedef struct rv64_movop_s { + uint8_t op; + uint8_t rd; + uint8_t rs; + uint8_t rs2; + int32_t imm; +} rv64_movop_t; + +typedef struct rv64_mov_seq_s { + uint8_t n; + uint8_t depth; + uint8_t overflow; + rv64_movop_t op[RV64_MOV_MAXOPS]; +} rv64_mov_seq_t; + +typedef struct rv64_movcaps_s { + uint8_t zba; + uint8_t zbs; + uint8_t zbb; +} rv64_movcaps_t; + +typedef struct rv64_movctx_s { + rv64_movcaps_t caps; + int budget; +} rv64_movctx_t; + +typedef void (*rv64_mov_emit_fn)(void* ctx, uint32_t insn); + +int rv64_mov_seq64(rv64_movctx_t* ctx, uint64_t v, int depth, int nscratch, rv64_mov_seq_t* out); +int rv64_mov_seq32(rv64_movctx_t* ctx, uint32_t v, int depth, rv64_mov_seq_t* out); +void rv64_mov_emit_seq(int reg, int s1, int s2, const rv64_mov_seq_t* seq, rv64_mov_emit_fn emit_fn, void* emit_ctx); +int rv64_mov_cache_get(uint64_t v, int nscratch, int is32, rv64_mov_seq_t* out); +void rv64_mov_cache_put(uint64_t v, int nscratch, int is32, const rv64_mov_seq_t* seq); + +#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 79b32b07f..7d523cfd2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -82,6 +82,7 @@ box64_add_test(Boundary 33 DISABLED_ON_ANDROID) box64_add_test(mmx 34) box64_add_test(xsave_xrstor 35 DISABLED_ON_ANDROID) box64_add_test(mxcsr_rounding_interpreter 36 ENV "BOX64_DYNAREC=0;BOX64_AVX=2" DISABLED_ON_ANDROID) +box64_add_test(move_imm 37 ARGS2 quick DISABLED_ON_ANDROID) if(BOX32) box64_add_test(bootSyscall_32bits 01 32BIT) diff --git a/tests/ref37.txt b/tests/ref37.txt new file mode 100644 index 000000000..48d8cfd38 --- /dev/null +++ b/tests/ref37.txt @@ -0,0 +1,5 @@ +mov r64, imm64: 69154 values ok +mov r32, imm32: 83538 values ok +mov r64, imm32: 83538 values ok +mov qword [rdi+disp], imm32: 66154 values ok +move immediate: PASS diff --git a/tests/test37 b/tests/test37 new file mode 100755 index 0000000000000000000000000000000000000000..1feae4e7073194a6f73c824b5271ced526f2378f GIT binary patch literal 29640 zcmeHwdw5jUx%XPLFSB!`OKWw$-@Eo&Gdm-kr_XuL zpR7E4uk~KnyWaJ#wbx#I&(4;4f%z`ZnMxYFf)V5$Vq+>L;dqNIAgg3ESr*Qd*hFRm z)&mwxd{c_l|^lIxao-BM2FXUQNWl`DUe zPw1E_^`+)zB!r~$RJmp;mzr1GVoc>!2c@O&MH~Mo^(~fibz^Nksky30<*L4GAxD1s zdz0$sC9=K?^}}PbA5<>g%Su~Y)=ZyP+S*v$+S1;&v3TRm>BZBhl|(v9rU( zsjC+)V^DL5aH>09-8QWB5iMWRiT}3CUw!M5Z+&+1mD8(djEv=H{_7ss?}>-(CK=+P zMEazO0;X~{4&o91;9CjrBAf@uE1_SuReaj3h7HjMqzQm>2ViVq#s%;X0q?b02AnB= z&ZnpC0{Es2;Ew|D#gUpQPS2;m@B(=9$NBg#y#PLV0sL#gdvT3FC?a?N}u%>V*#6lZeqO7gHwY8%G zRK#5a$%Lc9w)&QK7Kt`O69^3(>w`@#?e(oKH-%W!hHy(X1Y)?Mt&_F2)ps%yr1+f9 zt`7L;UKN~DGPPt{qMR&EO%|t=T*iX_+L|D$2(4|2L_^`)nyXqn+C#PVYg$97bZuKl zyR;@~v!0icVpKy+>d0NlT^JWsvda{+L<=KV<1$*^2GiWY^sY zZ;gFN!d=6N-^IQMn39@L6aF4*GCKIpain^W-Z65pAE|CYpWOu^qF z@m3`hN!6?16Ia@J8mr_7l}nhgz|%aW(!CD6xPD5)UI(7qrqVtKUipG(k2&z@$VA%jz{^XppdE7HGZNg4 z9e3a}9r%mIiypY>fr}ov=z)tKxafhu-vfX0jQXpu=Z}`J*LbCrG2f0uQCIwguje`I zS)n9;*%F}R<7;vDjILzF-%OO#@5JNrrkw(&g~aJ!C1G0VoIa9-X@PV4-;*#cFit<1 zglS=M`a4OO78IwqC1F~uoDL^pT3DQ3lYrynC&0QU&**91zw*5wkSyk<_rRbTNJ#p^2vxbCvH(S2G%Q{GK9t3;N@tVTV{afEZ^W~r8{;kIb&9#`o z0r*3AbsX9Ai_wb$_p7R{@B9w^;O{vyS|Hx_Z+$oaRbqPXHQa2?D}SMCKa|D~jD;QL z@q^^^r*Y_kSbmZ3dE**1iNOAYU&Z6Tn6VVFujgFcv%M5jf!_S0XBe|sAXZy6ssE?o zS=5*LUnCKTy&Q-IioE{V(f-}QFX)^0CE&^2pgcpjc0S0j0^o~1TeIUM&-MqY+%vm~dA8ppiZ>To%yZWvABcAyu}*k)bQ5~V zZ#>&KP@$Jp_M*b_Ljjb%fnHd;(;uroitbpCT z=jVS(_K+`@15PWzf90<@-1UhMN@(mH{RSEMrjNhj8QpC+;)t*3dCPbBoh)DZ3194p z@9+n1U-=PV?1b;|sX+pF^*LX~S6#3BVjuhXX{X$=|4t67V%I_Pldf0M4FOc_kNvv* zh4OgSL5eS_ClGrh5c|3B)%SgUx3IHl{?=o(|FF{+bNLM1XQA(oSiXv5T_3~DG+)nQ z?(aG5^KFe+V(@kyK1eX`ycos9oMapzqv}@t($t+@linqGXU{dz^FwNxz`hFD0H0g`|moN4PM!N1l{85IFf7%wdaYE-$JkiVvR+X|L`9&%HzPa z00T;K5P41PHM)-bV`mRyx`w)W%zw!_f5nM_=jtQAia&d{Un^>vT?C22rI0B9)rT|S zbo&Z5Z^!4J9W(%&s$-LIEKWaGnR#n$W0o)Ga~&8&4e2?;ef)T!;z(q!zc=%hzS*x+ z`>J}r;-2jxNTTHGdLri2i1PrhW~8g&Sf%SwQ>@N?tTGMi(rpdlrzy;-`CFeSYmd2} z#q5i@`l#jKdYDzBp%rn@4!Q!-Ok7YCdneF~mLopl5I81)X{+z%qB4KO#|!%OvE;5v zHL))+P#Y#v(^DGZkeCX-97hLenZ~d|3 z^LE6eS+V1RhQn33&IdfzhiZB=f8+1b|Hx}94o6=?+}tNb&*g3SNpIj#x z*oY!AL-gP9XKK6=0b8JVMA3(RVjUFo@dLC!a*XYVSB+zpZg|x?9mJJT(%lDWUq!ke zMD6rkahZhmzOB``mQr-|9D}2ek)wSTaHwa;TY?8(^!3`Y-RQg24)(5vzOB#sh%@$P za-uoC?sKXU$Rnp`2-&QM#$!IEz3`_I445hA+>G^K|Fht;C-#R>>aR|K_n~C3>%=;> zN3BdDdof+~z(o&S^uR?A{Et0A&uSVv8bjXBj*eDuXk&AI7ajvOrnC7~{=mFywzz8P zQg&lkOT#+*DU*CoH9m5=cYJGWmv?=AYgZ`Z?O2!2+B(*Uye(~Qp~jZ_XbAL(z9NPRIFrrmg($opSo}3b<=Wl zrqr&#_uyM!J$>-2pPza9k>67Nss&W0W~zf=T*4`Bk_nonZ$B1-&qHRoHme%4 zw2g55qj-EH^5&1@@x915BHxePIunmap=c)ZNyv}?DIQ-9{Ql44@e{}?(K>+=ziA2M z8*}*ZOt-ZYyo9HR+^Zpjl@HdpZY=v^sduET@mzlA@n_rvduFme>%C!+%diKof?6RutN#KSQq~~T^z6|Drs&{c% z@W~Dxh57%j-sbTuc`| zaM1%7J#f(j7d>#%0~bAT(F6Z$9+2;$srSy*duHukyM}McT)j7j<(f$JZX6}rvlB@! zO4Ykw`-a(QdjFA4bo#KMN!H>xs9D4LhsZJKKxhT>} zNmn;eA4|M?7pp+RgJrHVb>Gx^rHxUm&XbaX*4LEizJQW+7dtBv3cp_(qU@e29hGK_ zF;)L42`fH4lMw9#yFlTdM8M5bA8t_;T}a~5n1JU?I(FLytn85L|JO409(St3GTGmi zGG8q7)iUptdAH1W%6zZPACq~i-oF>NDs9d)zxZ)%?YwdP>Z`80+&gL6ny&U}m$!T> z-X$$7p57(EDVwKED=C{+QhtdfumEK3j<&lYNA{|?Q37o>Jr_U{Hzmk-N?6?R2+F|I zj68ZZlnZ4=3!!-=(FuHBjTb49VYy#HF@sxs5qTLdcRyvi`wf9K9|UA};-pU)T23gJ zQAVh5qO4z%-->L!Zs2uXWlZQ~)n(0*jMqw{WSjLyA(`>^@FCIRb$TT+edj;8? zg?l#rpN13b1Z&7ok-3kM7&jjR*KjJED{(T0<*lZ2Ca}ivye(7?qih!B)liwnqd6=; zLgfysaCknw`a1k8LeR~z`;DPg`NVs`c+x7jcEBw<-IY#tQ!|);98A;Geuko@j|0;T zQO?n?0e+?^7wGgTvqF@;`ZM6UT$Cs2Ga)rgl*{x*Xwhs@o~e%kevT+t>Vr{Xr6~LK zzW`q)%8T{;P@XHwb$STp>LI(qxmx!^&;0!Fqui_)pkAM_vs0f4ykC@~dM|8Pkg*$5 z8}(A)YjVkwZv6{LE%MAqc^j~dU1RM7rbpia{%bw-eEBy0+bA#3`Vpu*^~Z4j=FlU+ z->a_zensI+DDTxt!%AVpKK(y|S(QdT^q5W$-h$~KShZjOG0v-nJ%{vpsBMk)3aHO9 z^Piz8&0RPg^hxOuvo6gZ@iPGKe*)c2=-eYflQntNH9+n{dBh`B`WcnJ2@P&~I4&4} zrx^2?`vvd}A%vUyaR@!wyM(6h%zLt_jHo*Y{fO?DNLeBD4DsMJ`BJw|5z2GSs{!WI z<7<}h1uM@l#o3il^Q0z1M`ziegIq9Z1vt~Rot0oka=(vLb`>av9&$jMc3UOkf&52+ z!z8l1Qs7uF1t57sG*M&O3sD|Eh&nD!TP>NgGvT)pgNQXvtCUD{J3t=Jc?GQQH*op} zy?qq0=-r2C_&)FGU;Dr)5&~ zSAk+s!62U&u%X|BKzg~Lts&Z3plyct1w--cRLy6utS%+Vyv>CASJ$nCp)g@32XM;R z>&hl*H=)U4%xgkLX1n$nVW>Vfv=67O3c>fb5*N&Nox(D4qEKf;{~y$3-!H8Dt5RZX zDs=B|B|tyxE?7Is2Nz6{_fA=a@IA_yqr zKPN;ZdquQ@W*h^@m`bcV>Tpe<#BT-52e|^bQ{nCb?vEqJa`3H`D-!-g;4*pI4@?Y; zY!H3`O%LK2M})#txk*-?FozA-8Q@NW;|&}+Tcn=x)FFHspTc=q~rT) z0YvY7WO3sos*V&<#C=SP{_VVq7A6#FPs*zyMNTHx9ipP~impwEGD;L~m4dvCmw`vC zoL|KGwR{HWOI+4i&g)!han6_XGN#=iWhj=H+cH|^l|@VoI|vb*pznHYi^;TJ2c=I@ z_7UY@9F!j_%3h-UyMuB_R+El*wX_LxnO6h9ziShO&8}~ub=PW@cxy|W?cmXHZ6_yF zyYyZ6l5W3)Ji$SBttS<(n=#GRIan4rSt6pA^h*3FWvzp!&B?PxsIew9ZIgp#mt-l2 zAx>j&ckukw!K3fmxy2-VHp8C#98AAjBA0Q~XMs6aHb^5eI&QjTb&)+Di_~E=3X1 z_?mGsJ2LZ@k~=Kw<~m##uINy>|KdANNofd!I9R^dIaJr06)P|co!sF3Lrs=7T34tx();P0f_J7 zaP0?>g?ZYbx%yuLT!um^0pAC39SVzaWYuAItB`s)<{P#mzdQ?5^d{glJ8^QY#VG>T z8;Sj40CN=k_rP9ae1s8>lfuS3R>v;g*L18BWPXeIJ)BnZ63Q4|3${VzXoMH&s zCqR9i*h%(z6pj)=vcEy$*Emr5-(dJARXIh_>ipAW>qxL==Hukb!0C@*{s4!twNJ6X z2KM>JUa*V$z5v5taESUcFnOop5cQ2lVI&SVjBNd`l2-+Esz?iLyUV~?LZW0hUAV3w zfb6bCVF?ZxG8y1Wxu@ZJ7noJ~58#ck%!R;b&c(@9fl~;~4LF3|znAR%3$Rxhbzm2E zN5K%rA?n+X!Zre^zI#!)8;5Q8he}=*l-+Y|yB`84UFL+I11LN}0O|P!3NPY7XZ;fX zKBp9AARO1^XPyBr^L?CL|B2IY!T1&qVRMGumT}QtL#>gCP!=|S1cncBh`PQ+;R^z& zu0gmscyQP@TT-5@g0gw3ZSz=gdT|InQ&1=)fb`5qp&AFJQJ13jAT|obFzOSdW;tlf za9|kSDG-|htj966qbthzw{usaEm$JNH>WkVvz@s|QS+l9Ka6A470|bk^wA>yt|7D@ zd>Z(taAeWq=qcr)WnjE_um`MSZS)H;yoe*`m}D5Z$lB*6Yiatw)cMOb){~)v2xSQD{kq?r4^G=7v5kUG!vJPCULc(xzoPhG>xKbLi&2vR80NK2GI^+ zotVuj_-&>-o2ir46_aLg*HsX=MK6u>y6RsFNxBnQBqV8?O7CQg#!K!+WyE1~FPdd@ zZv=Oh;HJp|+*L)AyQ(zFU3Iz5T@3l@f}5sma8Dm6xu=(Yn$SI6a{nHf$%30g0Nj%m z_vF%~-IFEvV0d|yxT&N0&RPS*_$V)3d@k=~+?zqSg={nfmunc6Ddep*kX^(0e!$iN z_ylFTRkIEOfig+6(SvZ-YRSPATh?{~dhJ`&(K!Uw5RoFsx?O<7>3+gyteI^y&e{l; zb{rly`*Ku42jhN(;$}?EE`yclxrRP57omhVslUayodrlY-ocyN*nC<48+(C$gvxMC@kR#{)vVDJntAzYH~UE zi{|BxL1RkMs{Bb%JOYKm!u&)Hw!R@VM4N|}@GA>dt4ZDLLef?MGg#r*4aQ8AKn~)$ zZrKhjTP6r~Bl1w^Y|J+!2ebh}l);w`CC#H96^`L{1GH(PQg4D}RE)`*SZJFvW+c2f z&~5k*LBa~#mxk@jaa0R7SqJg)*?Ae-=;5Q64IRX3**9Kx2WG?x=vR1UVjldMkzw~Y zSvD!z{n&~U_RCnf5~g6(On^@=)%g_}8Hk&t+&2cJ8Kj`tVSmQN!dtm)LCHY8@^NVb zjX)$vEE`%`aFftfCi+;^KC#d%!lb-};!C2?>uA9gCl~dG636!q6t6$eg|3`N!Gk${ zT5>>4Pk2!DV}=UH8N|Ac7usWGrjOCE!9*#d3QNb!ow~7QTEfUX?b&t=Vc#@~fVxzufd_8H?QcTLPSzOmfk5o1)F zk*VFZz!o^c^vEznY+qY#K*mfHpGY_~o zSybRibPhO8?G46_Y?Id!!muElu06VCr(tQoVh@Y*Y*DV0Ww-Vk9z&&TSIyR1wh78k zKu>KciE3fKEo!6*jd^)SjycH4oMYrIH*$PbNHe?gjG@e>b8cjq+C!)#2j(0!46XLK zk!60z@Mw$d7NkSeFax>^jcnzHHdq%Tx%>v8(n*EZx`47M2!^TUa=1WnHxswXZS)Yh z&dAp;LEA=vThk_U!$V>VZP=Wp?8#bg6+pO5LI@J9(bB9>^AnJnqiZlX5Vdk$V{=g#I%@{` zj(W>uWIkY|p||cZ(khM2S=3=b=NW0mW~p-2AlJlUMj@;tAE2s@58IRlM%FH4B=Cbw zZOH=ipaqnv6{7>7VwfKQR11dX#wg_ZQDMt7Tbf|UU{gE7J_Uj!lHinla?@@Q3bmt* z3&tn6JWRcvWe!8P)KRx2dnH7@lCK>`kEClih)5QlfZj_+!^jJC!paMD!WcVxyj16d zs1t#R(Uq(;U{`unRNDUa2)OzJdS`H9+kB^OGwr&vcwL?9M8vAyiK3HtQkdskyA6&3 zZx|7S&uKCYzwLajX&W(Zqwc(a3%QGHmqNYpqLmx1gLgoxrU)>AZ`B^YM<*#Iz3DQo`%b+dc>`r;`~YUytbZ3#`mbmUHA+V z4@R0h!qGKdP56w`H9>sqX8 zUVJcWe((Jf^ zK5vDV2ykg#H3~~>uURq=6rnQ`?FfgYTf(9GMq6incx?k)vnd*i*q_u22D@O;^l4C} zjEZb*MAc1ga1uUf1<^J}KY0jJeME44l?$G43^9QSt_^o|b&59Ft`$X5ac4Aaf4WP4 zge!tyA+*%v17C>_6U|Nfid-bW3MN_yHxaLJyWQ@?Jot?i108tL0` z-mA)I$hR-N#ck29_RyTQq4rR?r2$}lxS@HD{lPkK@mg>3HB-FBP4$sY?G4T0j`ohO zNO4#DhL-lm;wXLPD*~eUMpRQgnoi(Io0(MQCWPk2EWCOGi5h4NVRhohZYS z;+uZAL2amSyi6F)g6l;^!H%Y;NQnHe`Uc&$o?)+=zA%QbnUObyYiS6G;UdE7YoAbS zXbv^3gCB&yq!%}|G=_qW_0f6^r%)%JI@%#H6A{o}-$q|b!xz<<72qroK=zmlM#A_oTcTH~-@{$)LHn04;6$^i7BRRY((Z&d>huluIJJe^ z8ag-OJ8$@=8+{0_3!|8ckG_eK#_&BjBH2S4G0@Nz2BEd94LGVo1aq*fog%=V6=<>$ zaWfm=h-+!Tf|WLRw1rC7MH)I-X;&m%+S1<8+SM2;MJNQPPm>=qT-)ANx~3%>u~}MM z)|9SoX!try`BWwTcjzjOZt6s9oRtm$zOFv937(4LLwIY0m;<9NO)a6ul4hC;TRNto zAQVbOd$br{Y)?YeH4;Hm zim-P_H*5owsTMCf8_k#Lqx&uW`+V6Rz2DlA26#u>jx>R=)HR?;fDR=N4HNKybAr%N zD>c+A4Yhj)XsF$zG;p&GyF`?9rt`(R{x_4a)c3jfx%tY3NG4wi1}iK%^EEt~B!qgd zJ6OYWRnkF;n~x0C_>{@7)BDYSWDbqj+1$kcc!GZ+|==V^xfJI1+uwP-~>{bWU5yjbiBfoDpfd^Py=Li zW+{oW>4`TOD7q~5_Cj{Lw$N)=lZZMSOq@-%aiFt4a$X-lr}0(#Iqg}42lZ!-ZWBm~xWRab`))U1m8c`N;Ha|#aWqV7b5qiRQOa}X(W z?!rF3eiuJw;^}aFGZcJc0`ZA?w_6}&2$RjGdYGWI+c}2j?L1~?kdQep?wN(YjG2$o zkbTU2d?5aD^BLfo2sa8^9QMEvTC-^%5()iGQBvrGRlbGVja&BU3&SXf`?vu5_&?!k zg8pOIi!S1O(REbA=sc=z(}CTl->L(8Q-4PX5mi}lNVQXJ*sjCei+w^$a*FXo#$SuE z@;Boa404;s%+C^Bf8`*)t=&%((kJ@gkVzgpGxsGpCxT;Q0Hy>^x$traT=`?YU$;v? zGmaZ}=`-U?13K)H2bU&mnu^Go`X5~1)eTXq(JqNfmoeJ(rsNRFGo!4FVPxjr<-+1# z7+Gf!YEReT9p4rs_;(teGMm{L_O)@R*_ z<_cB9A*l?jh+&n@unLctEcJvrAC2eCQcsX`Tr>9!fX%%R(vztHIIYvQhZ$~5JvL^p zX#-(%@Arg|lSk{!f@YVc9v6?MiZx3;4i-9`u(@{;9u1>n2andN3F{J%eyL(upMcH1 zep|?a(>l`;e=h4)`9yBGU9ozet13>w=3W!e4@AWYoYu)jMTuv(vf>16?&Y=+vl2M1 z(}Iv`{Yh3_Kyjv9>Y=Qt*a@3^4+-rPMGscA&uhyHw z`j!W{zMsQoFY`ZeA#*!G0URpEE-ZAv~AUGjo_RKQYub-R)+^%L&6Q{YU%} zuK$$305LTlbf)R~`OJ7H!RFRK*Z!jEUuk#f%usJD5F4JP80swmf~~xPa30|QOw|4b z*Z;$Xw}l<3sd^8;lk5M?@ztpT=$HB1Tz{LN=K5zubE_rjjx={-mB|eCP9)Xs9?J~% zKBR)xWnX85^^u_8C!d+48G71K=2n;VyWL5xj;idKIsch1Q#$)3o=U|E8nLIdJLJ6V zl?=4NIv+p%e#OOdSi%%3M~|C0zN>v(B??GtQC@~J;kzpdo5Wv^GU0bt5;lpy5@o`# zt|TmDUUA0v)sYjvveHH<{WNKFHjL$@;BOH4T*k)O{ENu}NNaF#{E9`ri{&LGQVR}h zSF*PRnnjSE&kvg=|KcGwpE`F-e0K`|A0=M>&Pee;gaWl|Ql*WNX0pcxen{eXK{gey zsGvZ0CVq$`3H^e9aN>7HivL3PyHOFxujl_bPH`sl^R;)d;4fg^bCP^i8YK+QW9t6` zC~CRjFJ$U>MGAj4@aUDVC3;cpeE2Tly^rbZge_H69c=7sYuf}72ZW70>{B~ggTeVrs%qv1=PjxZ;vWW7FJDwuOfAiBwcqRqC(;+95^lzt zf}n*%t@R`zOP#GzRw67fL9qni0b-&M2{o{iXlNrq3T|+Bh~Ov*HOp{rZiF@k**fgF zwk1@Vq^MFT5C+z_wLr723th@EF!B8(?Dm#4hSqegg;;(2S`0-AwzM~qoK0G@CLCI? zApDb=kSfESsz_+WNfPd8pa(w*g_tF5*f~Z0kIJ+T!xWFTfSn5DI!xswBwl62>r8an z$GfWu`I%B)<+N^dCbiyDxalZ3?sgQIS&ZuLl-yB_-N_Qp&5mTRM!|NJS+t?+(OzkwjGe>i5_x{}?o9 zO7;JZAkuG}mAv{rv&y|vSlO@mR8H$p`mMBr)$gTMPU~VysrK7g#`;hopDKCv`)!ra zlm@H%Q`>)!l%FdVs^5dF{G`N_Jl*D|%0B=cRiX4JuG{kZP4Vqasr`RHh)#L0lvDX$ zr!dNroXCHeB7aCSs9fc68>UiCloN@kf~mmt`9MV4Ib7bsBuicPKmRbH(aWu98UcqPsu zzjv(7sB(3`rqrnTQSf^x(Eg1awu$>5^?$=s`4z14Pauo8`V;c%`wMl&Kq4tV8%n|o z|0M|2epSD^pIj~Fy-HB#sW83WO|h@!)qR!vKXPYDITDRuN~&HJ2R{bRS--l^>MRxP z;>|?6WS^D1%JU%XlxLNayUfnjJSVY<`W0LVVbZ1S_g31J0x7>yG0NPV0@HmX)i2o- zR3$Inn7|V+C6!N<@-{Yko+lM9PNGCf$tm>o3&?+0%Fm(=5JyUtr+4I2am0S&DqBch z$CQdxUW)Hj9PzHW+Lp*t9VHc{@~)8bss3xZ#uoTy%79byDqnj6`RA6}@_xmbQollP zkn)n8$g=499MYte`Af;!RK{+-fc$0h=~91+Knf^)r{*4|lXCBB8=7R;`2=LN7E*>!(MW=aVmMw&m|h5l8{q{|E2~LY4pk literal 0 HcmV?d00001 diff --git a/tests/test37.c b/tests/test37.c new file mode 100644 index 000000000..5689e2365 --- /dev/null +++ b/tests/test37.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: MIT +#include +#include +#include +#include +#include + +#define BLOCK_VALUES 2048 +#define N16 0x10000u +#define N24 0x1000000u +#define STEP24 31u +#define NRAND64 50000u +#define NRAND32 12500u +#define NPOW (64u * 9u) + +enum { + F_MOV64, + F_MOV32, + F_MOVSXD, + F_STORE32, + F_COUNT +}; + +static uint8_t* pool; +static size_t pool_used; +static size_t pool_size; +static uint64_t checked[F_COUNT]; +static uint64_t failures; + +static void* alloc_code(size_t bytes) +{ + void* p; + if (pool_used + bytes > pool_size) { + fprintf(stderr, "code pool exhausted\n"); + exit(1); + } + p = pool + pool_used; + pool_used += bytes; + return p; +} + +static size_t emit_mov64(uint8_t* p, uint64_t v, int32_t disp) +{ + p[0] = 0x48; + p[1] = 0xB8; + memcpy(p + 2, &v, 8); + p[10] = 0x48; + p[11] = 0x89; + p[12] = 0x87; + memcpy(p + 13, &disp, 4); + return 17; +} + +static size_t emit_mov32(uint8_t* p, uint32_t v, int32_t disp) +{ + p[0] = 0xB8; + memcpy(p + 1, &v, 4); + p[5] = 0x48; + p[6] = 0x89; + p[7] = 0x87; + memcpy(p + 8, &disp, 4); + return 12; +} + +static size_t emit_movsxd(uint8_t* p, int32_t v, int32_t disp) +{ + p[0] = 0x48; + p[1] = 0xC7; + p[2] = 0xC0; + memcpy(p + 3, &v, 4); + p[7] = 0x48; + p[8] = 0x89; + p[9] = 0x87; + memcpy(p + 10, &disp, 4); + return 14; +} + +static size_t emit_store32(uint8_t* p, int32_t v, int32_t disp) +{ + p[0] = 0x48; + p[1] = 0xC7; + p[2] = 0x87; + memcpy(p + 3, &disp, 4); + memcpy(p + 7, &v, 4); + return 11; +} + +static size_t emit_value(int form, uint8_t* p, uint64_t v, int32_t disp) +{ + switch (form) { + case F_MOV64: + return emit_mov64(p, v, disp); + case F_MOV32: + return emit_mov32(p, (uint32_t)v, disp); + case F_MOVSXD: + return emit_movsxd(p, (int32_t)v, disp); + default: + return emit_store32(p, (int32_t)v, disp); + } +} + +static uint64_t expected(int form, uint64_t v) +{ + switch (form) { + case F_MOV64: + return v; + case F_MOV32: + return (uint32_t)v; + default: + return (uint64_t)(int64_t)(int32_t)v; + } +} + +typedef void (*block_fn)(uint64_t*); + +static void run_values(int form, const uint64_t* values, size_t count) +{ + size_t nblocks = (count + BLOCK_VALUES - 1) / BLOCK_VALUES; + size_t i, b; + uint8_t* start; + uint8_t* p; + uint8_t** blocks; + + start = alloc_code(count * 17 + nblocks); + blocks = malloc(nblocks * sizeof(*blocks)); + if (!blocks) exit(1); + + p = start; + for (b = 0; b < nblocks; ++b) { + size_t base = b * BLOCK_VALUES; + size_t n = count - base; + if (n > BLOCK_VALUES) n = BLOCK_VALUES; + blocks[b] = p; + for (i = 0; i < n; ++i) + p += emit_value(form, p, values[base + i], (int32_t)(i * 8)); + *p++ = 0xC3; + } + __builtin___clear_cache((char*)start, (char*)p); + + for (b = 0; b < nblocks; ++b) { + size_t base = b * BLOCK_VALUES; + size_t n = count - base; + uint64_t out[BLOCK_VALUES]; + block_fn fn = (block_fn)blocks[b]; + if (n > BLOCK_VALUES) n = BLOCK_VALUES; + fn(out); + for (i = 0; i < n; ++i) { + uint64_t want = expected(form, values[base + i]); + checked[form]++; + if (out[i] != want) { + if (failures < 20) + printf("FAIL form=%d value=%016llx expected=%016llx got=%016llx\n", form, + (unsigned long long)values[base + i], (unsigned long long)want, + (unsigned long long)out[i]); + failures++; + } + } + } + + free(blocks); +} + +static uint64_t rng_state = 0x123456789abcdefULL; + +static uint64_t rng(void) +{ + rng_state ^= rng_state << 13; + rng_state ^= rng_state >> 7; + rng_state ^= rng_state << 17; + return rng_state; +} + +static const uint64_t special[] = { + 0, 1, 2, 3, 0x7F, 0x80, 0xFF, 0x100, 0x7FFF, 0x8000, 0xFFFF, 0x10000, + 0x7FFFFFFF, 0x80000000, 0xFFFFFFFF, 0x100000000, + 0x7FFFFFFFFFFFFFFF, 0x8000000000000000, 0xFFFFFFFFFFFFFFFF, + 0xFFFF0000FFFF0000, 0x0000FFFF0000FFFF, 0x00FF00FF00FF00FF, 0xFF00FF00FF00FF00, + 0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 0x3333333333333333, 0xCCCCCCCCCCCCCCCC, + 0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 0x0101010101010101, 0x8080808080808080, + 0x123456789ABCDEF0, 0xFEDCBA9876543210, 0xDEADBEEFCAFEBABE, + 0x00000000FFFFFFFF, 0xFFFFFFFF00000000, 0x0000000100000001, 0xFFFFFFFF00000001, + 0x7FFFFFFFFFFFFFFE, 0x8000000000000001, 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFEFFFFFFFF +}; + +static void print_group(int form) +{ + static const char* name[F_COUNT] = { + "mov r64, imm64", + "mov r32, imm32", + "mov r64, imm32", + "mov qword [rdi+disp], imm32" + }; + printf("%s: %llu values ok\n", name[form], (unsigned long long)checked[form]); +} + +int main(int argc, char** argv) +{ + int quick = argc > 1 && !strcmp(argv[1], "quick"); + uint64_t* v16; + uint64_t* v24; + uint64_t* r64; + uint64_t* r32; + uint64_t* kpow; + uint64_t step24 = quick ? 0x400 : STEP24; + size_t nrand64 = quick ? 2000 : NRAND64; + size_t nrand32 = quick ? 1000 : NRAND32; + size_t n24 = (N24 - 1) / step24 + 1; + uint64_t i, k; + int d; + + pool_size = 64u << 20; + pool = mmap(NULL, pool_size, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (pool == MAP_FAILED) { + perror("mmap"); + return 1; + } + + v16 = malloc(N16 * sizeof(uint64_t)); + v24 = malloc(n24 * sizeof(uint64_t)); + r64 = malloc(nrand64 * sizeof(uint64_t)); + r32 = malloc(nrand32 * sizeof(uint64_t)); + kpow = malloc(NPOW * sizeof(uint64_t)); + if (!v16 || !v24 || !r64 || !r32 || !kpow) { + perror("malloc"); + return 1; + } + + for (i = 0; i < N16; ++i) + v16[i] = i; + for (i = 0; i < n24; ++i) + v24[i] = i * step24; + for (i = 0; i < nrand64; ++i) + r64[i] = rng(); + for (i = 0; i < nrand32; ++i) + r32[i] = (uint32_t)rng(); + i = 0; + for (k = 0; k < 64; ++k) { + for (d = -0x1000; d <= 0x1000; d += 0x400) { + kpow[i] = (UINT64_C(1) << k) + (uint64_t)(int64_t)d; + ++i; + } + } + + run_values(F_MOV64, v16, N16); + run_values(F_MOV64, r64, nrand64); + run_values(F_MOV64, r32, nrand32); + run_values(F_MOV64, kpow, NPOW); + run_values(F_MOV64, special, sizeof(special) / sizeof(special[0])); + + run_values(F_MOV32, v16, N16); + run_values(F_MOV32, v24, n24); + run_values(F_MOV32, r32, nrand32); + run_values(F_MOV32, kpow, NPOW); + run_values(F_MOV32, special, sizeof(special) / sizeof(special[0])); + + run_values(F_MOVSXD, v16, N16); + run_values(F_MOVSXD, v24, n24); + run_values(F_MOVSXD, r32, nrand32); + run_values(F_MOVSXD, kpow, NPOW); + run_values(F_MOVSXD, special, sizeof(special) / sizeof(special[0])); + + run_values(F_STORE32, v16, N16); + run_values(F_STORE32, kpow, NPOW); + run_values(F_STORE32, special, sizeof(special) / sizeof(special[0])); + + for (d = 0; d < F_COUNT; ++d) + print_group(d); + printf("move immediate: %s\n", failures ? "FAILED" : "PASS"); + + free(v16); + free(v24); + free(r64); + free(r32); + free(kpow); + return failures ? 1 : 0; +} From 7fffe8dfb51baf4b7dcc9ee1c6bf6c8547ec7d7b Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 26 Oct 2026 15:04:30 +0800 Subject: [PATCH 072/156] [RV64_DYNAREC] Fixed CMPXCHG up32 handling (#4593) --- src/dynarec/rv64/dynarec_rv64_0f.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index 623060334..ab6229c92 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -2489,11 +2489,12 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("CMPXCHG Ed, Gd"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); nextop = F8; - GETGD; - MARKREGs(xRAX); + GETGDs; + MARKREGsd(xRAX); MVxw(x7, xRAX); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGsd(ed); MVxw(x1, ed); wback = 0; } else { From d04c270fa9e6efa6125c0f9ea08d1fafd05005cc Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 26 Oct 2026 15:05:14 +0800 Subject: [PATCH 073/156] [RV64_DYNAREC] Fixed dynarec dump buffer overflow (#4595) --- src/dynarec/rv64/dynarec_rv64_functions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index f2924f4d2..c8ddfd3bc 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -721,7 +721,7 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r } if (!dyn->need_dump && !BOX64ENV(dynarec_gdbjit) && !BOX64ENV(dynarec_perf_map)) return; - static char buf[4096]; + static char buf[65536]; int length = sprintf(buf, "barrier=%d state=%d/%s(%s->%s), set=%X/%X, use=%X, need=%X/%X, fuse=%d/%d, sm=%d(%d/%d), sew@entry=%d, sew@exit=%d", dyn->insts[ninst].x64.barrier, dyn->insts[ninst].x64.state_flags, From 1d2083fe59d4edf634e0cc74a895a98dcdc05e49 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 26 Oct 2026 15:06:40 +0800 Subject: [PATCH 074/156] [RV64][CMAKE] Disabled auto-vectorization (#4596) --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 68e5075b8..84ef537d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -265,8 +265,9 @@ elseif(LARCH64) set(ASMFLAGS -pipe -march=loongarch64) elseif(RV64) add_definitions(-DRV64) - set(CFLAGS -pipe -march=rv64gc) + set(CFLAGS -pipe -march=rv64gc -fno-tree-vectorize) set(ASMFLAGS -pipe -march=rv64gc) + add_compile_options(-fno-tree-vectorize) elseif(PPC64LE) add_definitions(-DPPC64LE) set(CFLAGS -pipe -mcpu=power9) From 1a49e470758276d49b2d09a78e199e12951c6dc3 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 26 Oct 2026 15:17:09 +0800 Subject: [PATCH 075/156] [RV64_DYNAREC] Fixed stale YMM upper in scalar AVX upper access (#4594) --- src/dynarec/rv64/dynarec_rv64_helper.h | 44 ++++++++++++++++++-------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index d1317ebc2..b6beb8d53 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -526,9 +526,15 @@ gback = xEmu; \ gdoffset = offsetof(x64emu_t, xmm[gd]) -#define GETGY() \ - gd = ((nextop & 0x38) >> 3) + (rex.r << 3); \ - /* TODO: forget */ \ +#define GETGY() \ + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); \ + if (dyn->e.ssecache[gd].v != -1 && dyn->e.ssecache[gd].vector) \ + avx_flush_upper_vector(dyn, ninst, x3, gd, dyn->e.ssecache[gd].reg, 0, 0); \ + if (dyn->e.ymm0 & (1 << gd)) { \ + SD(xZR, xEmu, offsetof(x64emu_t, ymm[gd]) + 0); \ + SD(xZR, xEmu, offsetof(x64emu_t, ymm[gd]) + 8); \ + sse_set_pending_zero(dyn, gd, 0); \ + } \ gyoffset = offsetof(x64emu_t, ymm[gd]) #define GETVX() \ @@ -536,8 +542,14 @@ vback = xEmu; \ vxoffset = offsetof(x64emu_t, xmm[vex.v]) -#define GETVY() \ - /* TODO: forget */ \ +#define GETVY() \ + if (dyn->e.ssecache[vex.v].v != -1 && dyn->e.ssecache[vex.v].vector) \ + avx_flush_upper_vector(dyn, ninst, x3, vex.v, dyn->e.ssecache[vex.v].reg, 0, 0); \ + if (dyn->e.ymm0 & (1 << vex.v)) { \ + SD(xZR, xEmu, offsetof(x64emu_t, ymm[vex.v]) + 0); \ + SD(xZR, xEmu, offsetof(x64emu_t, ymm[vex.v]) + 8); \ + sse_set_pending_zero(dyn, vex.v, 0); \ + } \ vyoffset = offsetof(x64emu_t, ymm[vex.v]); // Get Ex address in general register a, will purge SS or SD if it's reg and is loaded. May use x3. Use wback as load address! @@ -554,14 +566,20 @@ } -#define GETEY() \ - if (MODREG) { \ - ed = (nextop & 7) + (rex.b << 3); \ - /* TODO: forget */ \ - wback = xEmu; \ - fixedaddress = offsetof(x64emu_t, ymm[ed]); \ - } else { \ - fixedaddress += 16; \ +#define GETEY() \ + if (MODREG) { \ + ed = (nextop & 7) + (rex.b << 3); \ + if (dyn->e.ssecache[ed].v != -1 && dyn->e.ssecache[ed].vector) \ + avx_flush_upper_vector(dyn, ninst, x3, ed, dyn->e.ssecache[ed].reg, 0, 0); \ + if (dyn->e.ymm0 & (1 << ed)) { \ + SD(xZR, xEmu, offsetof(x64emu_t, ymm[ed]) + 0); \ + SD(xZR, xEmu, offsetof(x64emu_t, ymm[ed]) + 8); \ + sse_set_pending_zero(dyn, ed, 0); \ + } \ + wback = xEmu; \ + fixedaddress = offsetof(x64emu_t, ymm[ed]); \ + } else { \ + fixedaddress += 16; \ } From e8a2f7f9c95c8b04e237b7f2a2957a6bd2310600 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 26 Oct 2026 15:49:25 +0800 Subject: [PATCH 076/156] [RV64_DYNAREC] Skipped cache type sync when no vector reg is used (#4598) --- src/dynarec/rv64/dynarec_rv64_helper.c | 3 +++ src/dynarec/rv64/dynarec_rv64_pass0.h | 10 +++++----- src/dynarec/rv64/dynarec_rv64_pass1.h | 8 ++++---- src/dynarec/rv64/dynarec_rv64_pass2.h | 6 +++--- src/dynarec/rv64/dynarec_rv64_pass3.h | 2 +- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index a01de6ab2..81b4d0e16 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -1777,6 +1777,7 @@ void sse_forget_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a) { if (dyn->e.ssecache[a].v == -1) return; + sse_mark_used(dyn, ninst, a); if (dyn->e.ssecache[a].vector == 1) return sse_forget_reg_vector(dyn, ninst, s1, a); if (dyn->e.ssecache[a].single) @@ -3025,6 +3026,8 @@ void avx_sync_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next) { if (!cpuext.vlen || cpuext.vlen < 32) return; + if (ninst >= 0 && ninst < dyn->size) + dyn->insts[ninst].vec_used |= 0xffff; #if STEP == 0 if (!next) dyn->insts[ninst].ymm_pending_materialized = 1; #endif diff --git a/src/dynarec/rv64/dynarec_rv64_pass0.h b/src/dynarec/rv64/dynarec_rv64_pass0.h index 67ff9b1cb..113179934 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass0.h +++ b/src/dynarec/rv64/dynarec_rv64_pass0.h @@ -88,11 +88,11 @@ dyn->insts[ninst - 1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst - 1].x64.addr;\ AREFLAGSNEEDED() -#define INST_EPILOG \ - dyn->insts[ninst].f_exit = dyn->f; \ - sse_sync_all_cache_types(&dyn->e); \ - dyn->insts[ninst].e = dyn->e; \ - dyn->insts[ninst].vector_sew_exit = dyn->vector_sew; \ +#define INST_EPILOG \ + dyn->insts[ninst].f_exit = dyn->f; \ + if (dyn->insts[ninst].vec_used) sse_sync_all_cache_types(&dyn->e); \ + dyn->insts[ninst].e = dyn->e; \ + dyn->insts[ninst].vector_sew_exit = dyn->vector_sew; \ dyn->insts[ninst].x64.has_next = (ok > 0) ? 1 : 0; #define INST_NAME(name) #define DEFAULT \ diff --git a/src/dynarec/rv64/dynarec_rv64_pass1.h b/src/dynarec/rv64/dynarec_rv64_pass1.h index f04e48530..546c26880 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass1.h +++ b/src/dynarec/rv64/dynarec_rv64_pass1.h @@ -20,10 +20,10 @@ dyn->e.barrier = 0; \ AREFLAGSNEEDED() -#define INST_EPILOG \ - sse_sync_all_cache_types(&dyn->e); \ - dyn->insts[ninst].e = dyn->e; \ - dyn->insts[ninst].f_exit = dyn->f; \ +#define INST_EPILOG \ + if (dyn->insts[ninst].vec_used) sse_sync_all_cache_types(&dyn->e); \ + dyn->insts[ninst].e = dyn->e; \ + dyn->insts[ninst].f_exit = dyn->f; \ dyn->insts[ninst].vector_sew_exit = dyn->vector_sew; #define INST_NAME(name) diff --git a/src/dynarec/rv64/dynarec_rv64_pass2.h b/src/dynarec/rv64/dynarec_rv64_pass2.h index 933f3581f..e6582104e 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass2.h +++ b/src/dynarec/rv64/dynarec_rv64_pass2.h @@ -29,9 +29,9 @@ dyn->insts[ninst].ymm0_pass2 = dyn->ymm_zero; \ } \ AREFLAGSNEEDED() -#define INST_EPILOG \ - dyn->insts[ninst].epilog = dyn->native_size; \ - sse_sync_all_cache_types(&dyn->e); \ +#define INST_EPILOG \ + dyn->insts[ninst].epilog = dyn->native_size; \ + if (dyn->insts[ninst].vec_used) sse_sync_all_cache_types(&dyn->e); \ dyn->vector_sew = dyn->insts[ninst].vector_sew_exit; #define INST_NAME(name) #define TABLE64(A, V) \ diff --git a/src/dynarec/rv64/dynarec_rv64_pass3.h b/src/dynarec/rv64/dynarec_rv64_pass3.h index 7dd58213a..f2dcadaa9 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass3.h +++ b/src/dynarec/rv64/dynarec_rv64_pass3.h @@ -30,7 +30,7 @@ addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst - 1].x64.size, dyn->insts[ninst - 1].size / 4); \ dyn->insts[ninst].ymm0_pass3 = dyn->ymm_zero; \ } \ - sse_sync_all_cache_types(&dyn->e); \ + if (ninst && dyn->insts[ninst - 1].vec_used) sse_sync_all_cache_types(&dyn->e); \ AREFLAGSNEEDED() #define INST_EPILOG \ dyn->vector_sew = dyn->insts[ninst].vector_sew_exit; From 3c563ba603fde5a3d0808a9f496163bfac3b1c55 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 26 Oct 2026 15:50:37 +0800 Subject: [PATCH 077/156] [RV64_DYNAREC] Added fast path to extcacheUnwind (#4599) --- src/dynarec/rv64/dynarec_rv64_functions.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index c8ddfd3bc..70790aa5d 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -427,6 +427,19 @@ int sewNeedsTransform(dynarec_rv64_t* dyn, int ninst) 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) + if (cache->olds[i].changed || cache->olds[i].purged) { + dirty = 1; + break; + } + if (!dirty) { + cache->barrier = 0; + cache->fpu_scratch = 0; + return; + } + } if (cache->swapped) { // unswap int a = -1; From a62e03fc7f39508749fe80d76f7dca3c3ad8bad0 Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Mon, 26 Oct 2026 15:51:35 +0800 Subject: [PATCH 078/156] [RV64_DYNAREC] Fix width error for VMOVSS (#4600) 1. The width of VMOVSS should be 16, which require clearing upper ymm 128 bits. If set it to 32, the upper 128 bits will not be cleared. 2. Remove unused q1 scratch allocation. --- src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c index 9131269b2..0989eade7 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c @@ -78,13 +78,11 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt avx_load_reg_vector(dyn, ninst, x1, q0, gd, 16, VECTOR_SEW32); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, VECTOR_SEW32); q2 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q2, vex.v, 16, VECTOR_SEW32); VFMV_F_S(d0 = fpu_get_scratch(dyn), q0); VFMV_S_F(q2, d0); - avx_store_reg_vector(dyn, ninst, x1, q2, ed, 32, VECTOR_SEW32); + avx_store_reg_vector(dyn, ninst, x1, q2, ed, 16, VECTOR_SEW32); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); VFMV_F_S(d0 = fpu_get_scratch(dyn), q0); From 49341072c87fe944367bfcf7210bcb62ba9a86b8 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 26 Oct 2026 15:52:56 +0800 Subject: [PATCH 079/156] [RV64_DYNAREC] Optimized a few AVX opcodes (#4601) --- src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c | 55 ++++++++++++++++--- .../rv64/dynarec_rv64_avx_66_0f38_vector.c | 8 +-- 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index 835e1491f..8cf9ba764 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -456,14 +456,16 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); d0 = fpu_get_scratch(dyn); - VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); - VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); - VMAND_MM(q2, q2, d0); switch (u8 & 0xf) { case 0x0: VMFEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; case 0x1: VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; case 0x2: VMFLE_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; - case 0x3: VMNAND_MM(VMASK, q2, q2); break; + case 0x3: + VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); + VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); + VMAND_MM(q2, q2, d0); + VMNAND_MM(VMASK, q2, q2); + break; case 0x4: VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); VMNAND_MM(VMASK, d0, d0); @@ -476,8 +478,16 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t VMFLE_VV(d0, q0, q1, VECTOR_UNMASKED); VMNAND_MM(VMASK, d0, d0); break; - case 0x7: VMAND_MM(VMASK, q2, q2); break; + case 0x7: + VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); + VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); + VMAND_MM(q2, q2, d0); + VMAND_MM(VMASK, q2, q2); + break; case 0x8: + VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); + VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); + VMAND_MM(q2, q2, d0); VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); VMNAND_MM(VMASK, q2, q2); VMOR_MM(VMASK, VMASK, d0); @@ -490,15 +500,28 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t VMFLT_VV(d0, q1, q0, VECTOR_UNMASKED); VMNAND_MM(VMASK, d0, d0); break; - case 0xb: VMXOR_MM(VMASK, q2, q2); break; + case 0xb: + VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); + VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); + VMAND_MM(q2, q2, d0); + VMXOR_MM(VMASK, q2, q2); + break; case 0xc: + VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); + VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); + VMAND_MM(q2, q2, d0); VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); VMNAND_MM(VMASK, d0, d0); VMAND_MM(VMASK, VMASK, q2); break; case 0xd: VMFLE_VV(VMASK, q1, q0, VECTOR_UNMASKED); break; case 0xe: VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); break; - case 0xf: VMXNOR_MM(VMASK, q2, q2); break; + case 0xf: + VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); + VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); + VMAND_MM(q2, q2, d0); + VMXNOR_MM(VMASK, q2, q2); + break; } VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -508,6 +531,24 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t INST_NAME("VSHUFPS Gx, Vx, Ex, Ib"); nextop = F8; GETVY_vector(q0, VECTOR_SEW32); + if (!vex.l && MODREG && ((nextop & 7) + (rex.b << 3)) == vex.v) { + u8 = F8; + MOV64x(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48)); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + q2 = fpu_get_scratch(dyn); + VMV_S_X(q2, x4); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16); + GETGY_empty_vector(v0); + if (v0 == q0) { + v2 = fpu_get_scratch(dyn); + VRGATHEREI16_VV(v2, q0, q2, VECTOR_UNMASKED); + v0 = v2; + } else { + VRGATHEREI16_VV(v0, q0, q2, VECTOR_UNMASKED); + } + PUTGY_vector(v0, VECTOR_SEW32); + break; + } GETEY_vector(q1, 1, VECTOR_SEW32); u8 = F8; GETGY_empty_vector(v0); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c index 597a4fd43..8357f11bd 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c @@ -1167,12 +1167,8 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); - GETGY_empty_vector(v0); - VEC_SRC_KEEP(q0, v0); - VEC_SRC_KEEP(q1, v0); - VMV_V_V(v0, q2); - VFMACC_VV(v0, q0, q1, VECTOR_UNMASKED); - PUTGY_vector(v0, sew); + VFMACC_VV(q2, q0, q1, VECTOR_UNMASKED); + PUTGY_vector(q2, sew); break; case 0xB6: INST_NAME("VFMADDSUB231PS/D Gx, Vx, Ex"); From be6e39cdeb88aaf02af444f378b2a12fdb39e3a7 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 26 Oct 2026 15:54:21 +0800 Subject: [PATCH 080/156] [RV64_DYNAREC] Added more AVX opcodes (#4602) --- src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c | 54 +++++++- .../rv64/dynarec_rv64_avx_66_0f_vector.c | 115 +++++++++++++++--- .../rv64/dynarec_rv64_avx_f2_0f_vector.c | 45 +++++++ .../rv64/dynarec_rv64_avx_f3_0f_vector.c | 78 +++++++++++- 4 files changed, 271 insertions(+), 21 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index 8cf9ba764..280e801a9 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -28,7 +28,8 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t uint8_t nextop, u8; uint8_t gd, ed; int v0, v1, v2; - int q0, q1, q2, d0; + int q0, q1, q2, d0, d1; + int j64; uint64_t selectors; int64_t fixedaddress; rex_t rex = vex.rex; @@ -38,6 +39,8 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t MAYUSE(q1); MAYUSE(q2); MAYUSE(d0); + MAYUSE(d1); + MAYUSE(j64); switch (opcode) { case 0x10: @@ -211,9 +214,54 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t SMWRITE2(); break; case 0x2E: - return 0; case 0x2F: - return 0; + if (opcode == 0x2F) { + INST_NAME("VCOMISS Gx, Ex"); + } else { + INST_NAME("VUCOMISS Gx, Ex"); + } + SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); + SET_DFNONE(); + nextop = F8; + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, gd, 16, VECTOR_SEW32); + d0 = fpu_get_scratch(dyn); + VFMV_F_S(d0, q0); + d1 = fpu_get_scratch(dyn); + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, VECTOR_SEW32); + VFMV_F_S(d1, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, 0); + FLW(d1, ed, fixedaddress); + } + CLEAR_FLAGS(); + IFX (X_ZF | X_PF | X_CF) { + FEQS(x3, d0, d0); + FEQS(x2, d1, d1); + AND(x2, x2, x3); + BNE_MARK(x2, xZR); + ORI(xFlags, xFlags, (1 << F_ZF) | (1 << F_PF) | (1 << F_CF)); + B_NEXT_nocond; + } + MARK; + IFX (X_CF) { + FLTS(x2, d0, d1); + BEQ_MARK2(x2, xZR); + ORI(xFlags, xFlags, 1 << F_CF); + B_NEXT_nocond; + } + MARK2; + IFX (X_ZF) { + FEQS(x2, d0, d1); + CBZ_NEXT(x2); + ORI(xFlags, xFlags, 1 << F_ZF); + } + break; case 0x50: INST_NAME("VMOVMSKPS Gd, Ex"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index 7fc6f54f3..b7d3e71b6 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -30,6 +30,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt uint8_t wback; int v0, v1, v2; int q0, q1, q2, q3, q4, q5, d0, d1; + int j64; uint64_t selectors; int64_t fixedaddress; rex_t rex = vex.rex; @@ -40,6 +41,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt MAYUSE(q2); MAYUSE(d0); MAYUSE(d1); + MAYUSE(j64); switch (opcode) { case 0x10: @@ -186,9 +188,54 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt SMWRITE2(); break; case 0x2E: - return 0; case 0x2F: - return 0; + if (opcode == 0x2F) { + INST_NAME("VCOMISD Gx, Ex"); + } else { + INST_NAME("VUCOMISD Gx, Ex"); + } + SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); + SET_DFNONE(); + nextop = F8; + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, gd, 16, VECTOR_SEW64); + d0 = fpu_get_scratch(dyn); + VFMV_F_S(d0, q0); + d1 = fpu_get_scratch(dyn); + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, VECTOR_SEW64); + VFMV_F_S(d1, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, 0); + FLD(d1, ed, fixedaddress); + } + CLEAR_FLAGS(); + IFX (X_ZF | X_PF | X_CF) { + FEQD(x3, d0, d0); + FEQD(x2, d1, d1); + AND(x2, x2, x3); + BNE_MARK(x2, xZR); + ORI(xFlags, xFlags, (1 << F_ZF) | (1 << F_PF) | (1 << F_CF)); + B_NEXT_nocond; + } + MARK; + IFX (X_CF) { + FLTD(x2, d0, d1); + BEQ_MARK2(x2, xZR); + ORI(xFlags, xFlags, 1 << F_CF); + B_NEXT_nocond; + } + MARK2; + IFX (X_ZF) { + FEQD(x2, d0, d1); + CBZ_NEXT(x2); + ORI(xFlags, xFlags, 1 << F_ZF); + } + break; case 0x50: INST_NAME("VMOVMSKPD Gd, Ex"); nextop = F8; @@ -528,25 +575,46 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt PUTGY_vector(v0, VECTOR_SEW8); break; case 0x6C: - if (vex.l) return 0; INST_NAME("VPUNPCKLQDQ Gx, Vx, Ex"); nextop = F8; GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW64); - VMV_V_V(v0, q0); - VSLIDEUP_VI_SAFE(v0, q1, 1, VECTOR_UNMASKED); + if (vex.l) { + q2 = fpu_get_scratch(dyn); + VID_V(q2, VECTOR_UNMASKED); + VAND_VI(q2, q2, 1, VECTOR_UNMASKED); + VMSNE_VX(VMASK, q2, xZR, VECTOR_UNMASKED); + VMV_V_V(v0, q0); + VSLIDEUP_VI(v0, q1, 1, VECTOR_MASKED); + } else { + VMV_V_V(v0, q0); + VSLIDEUP_VI_SAFE(v0, q1, 1, VECTOR_UNMASKED); + } PUTGY_vector(v0, VECTOR_SEW64); break; case 0x6D: - if (vex.l) return 0; INST_NAME("VPUNPCKHQDQ Gx, Vx, Ex"); nextop = F8; - GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); - q2 = fpu_get_scratch(dyn); - v1 = fpu_get_scratch(dyn); - VSLIDEDOWN_VI(q2, q0, 1, VECTOR_UNMASKED); - VSLIDEDOWN_VI(v1, q1, 1, VECTOR_UNMASKED); - VSLIDEUP_VI_SAFE(q2, v1, 1, VECTOR_UNMASKED); - VMV_V_V(v0, q2); + if (vex.l) { + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW64); + q2 = fpu_get_scratch(dyn); + v1 = fpu_get_scratch(dyn); + v2 = fpu_get_scratch(dyn); + VID_V(q2, VECTOR_UNMASKED); + VAND_VI(q2, q2, 1, VECTOR_UNMASKED); + VMSNE_VX(VMASK, q2, xZR, VECTOR_UNMASKED); + VSLIDEDOWN_VI(v1, q0, 1, VECTOR_UNMASKED); + VSLIDEDOWN_VI(v2, q1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI(v1, v2, 1, VECTOR_MASKED); + VMV_V_V(v0, v1); + } else { + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); + q2 = fpu_get_scratch(dyn); + v1 = fpu_get_scratch(dyn); + VSLIDEDOWN_VI(q2, q0, 1, VECTOR_UNMASKED); + VSLIDEDOWN_VI(v1, q1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q2, v1, 1, VECTOR_UNMASKED); + VMV_V_V(v0, q2); + } PUTGY_vector(v0, VECTOR_SEW64); break; case 0x6E: @@ -849,7 +917,26 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt } break; case 0x7E: - return 0; + INST_NAME(rex.w ? "VMOVQ Ed, Gx" : "VMOVD Ed, Gx"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, ((nextop & 0x38) >> 3) + (rex.r << 3), 16, rex.w ? VECTOR_SEW64 : VECTOR_SEW32); + SET_AVX_VECTOR_WIDTH(x1, rex.w ? VECTOR_SEW64 : VECTOR_SEW32); + if (MODREG) { + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + VMV_X_S(ed, q0); + if (!rex.w) ZEROUP(ed); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); + VMV_X_S(x4, q0); + if (rex.w) + SD(x4, ed, fixedaddress); + else + SW(x4, ed, fixedaddress); + SMWRITE2(); + } + break; case 0xD0: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VADDSUBPD Gx, Vx, Ex"); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c index 2be87c489..53a54b418 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c @@ -239,6 +239,51 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt MOV32w(gd, 0x80000000); } break; + case 0x2D: + INST_NAME("VCVTSD2SI Gd, Ex"); + nextop = F8; + GETGDd; + d0 = fpu_get_scratch(dyn); + if (MODREG) { + q0 = VREG((nextop & 7) + (rex.b << 3)); + avx_load_reg_vector(dyn, ninst, x1, q0, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); + VFMV_F_S(d0, q0); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLD(d0, ed, fixedaddress); + } + if (!BOX64ENV(dynarec_fastround)) FSFLAGSI(0); + LW(x5, xEmu, offsetof(x64emu_t, mxcsr)); + SRLI(x5, x5, 13); + ANDI(x5, x5, 3); + BEQZ_MARK(x5); + ADDI(x6, xZR, 3); + BEQ_MARK2(x5, x6); + ADDI(x6, xZR, 2); + BEQ_MARK3(x5, x6); + FCVTLDxw(gd, d0, RD_RDN); + B_MARK4_nocond; + MARK; + FCVTLDxw(gd, d0, RD_RNE); + B_MARK4_nocond; + MARK2; + FCVTLDxw(gd, d0, RD_RTZ); + B_MARK4_nocond; + MARK3; + FCVTLDxw(gd, d0, RD_RUP); + MARK4; + if (!rex.w) ZEROUP(gd); + if (!BOX64ENV(dynarec_fastround)) { + FRFLAGS(x5); + ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); + CBZ_NEXT(x5); + if (rex.w) + MOV64x(gd, 0x8000000000000000LL); + else + MOV32w(gd, 0x80000000); + } + break; case 0x70: INST_NAME("VPSHUFLW Gx, Ex, Ib"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c index 0989eade7..c25557a6c 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c @@ -220,13 +220,38 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt LW(x4, ed, fixedaddress); ed = x4; } - u8 = sse_setround(dyn, ninst, x5, x6); + LW(x5, xEmu, offsetof(x64emu_t, mxcsr)); + SRLI(x5, x5, 13); + ANDI(x5, x5, 3); d0 = fpu_get_scratch(dyn); + BEQZ_MARK(x5); + ADDI(x6, xZR, 3); + BEQ_MARK2(x5, x6); + ADDI(x6, xZR, 2); + BEQ_MARK3(x5, x6); if (rex.w) - FCVTSL(d0, ed, RD_DYN); + FCVTSL(d0, ed, RD_RDN); else - FCVTSW(d0, ed, RD_DYN); - x87_restoreround(dyn, ninst, u8); + FCVTSW(d0, ed, RD_RDN); + B_MARK4_nocond; + MARK; + if (rex.w) + FCVTSL(d0, ed, RD_RNE); + else + FCVTSW(d0, ed, RD_RNE); + B_MARK4_nocond; + MARK2; + if (rex.w) + FCVTSL(d0, ed, RD_RTZ); + else + FCVTSW(d0, ed, RD_RTZ); + B_MARK4_nocond; + MARK3; + if (rex.w) + FCVTSL(d0, ed, RD_RUP); + else + FCVTSW(d0, ed, RD_RUP); + MARK4; GETGY_empty_vector(v0); if (v0 != q0) { avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16); @@ -263,6 +288,51 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt MOV32w(gd, 0x80000000); } break; + case 0x2D: + INST_NAME("VCVTSS2SI Gd, Ex"); + nextop = F8; + GETGDd; + d0 = fpu_get_scratch(dyn); + if (MODREG) { + q0 = VREG((nextop & 7) + (rex.b << 3)); + avx_load_reg_vector(dyn, ninst, x1, q0, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); + VFMV_F_S(d0, q0); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLW(d0, ed, fixedaddress); + } + if (!BOX64ENV(dynarec_fastround)) FSFLAGSI(0); + LW(x5, xEmu, offsetof(x64emu_t, mxcsr)); + SRLI(x5, x5, 13); + ANDI(x5, x5, 3); + BEQZ_MARK(x5); + ADDI(x6, xZR, 3); + BEQ_MARK2(x5, x6); + ADDI(x6, xZR, 2); + BEQ_MARK3(x5, x6); + FCVTSxw(gd, d0, RD_RDN); + B_MARK4_nocond; + MARK; + FCVTSxw(gd, d0, RD_RNE); + B_MARK4_nocond; + MARK2; + FCVTSxw(gd, d0, RD_RTZ); + B_MARK4_nocond; + MARK3; + FCVTSxw(gd, d0, RD_RUP); + MARK4; + if (!rex.w) ZEROUP(gd); + if (!BOX64ENV(dynarec_fastround)) { + FRFLAGS(x5); + ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); + CBZ_NEXT(x5); + if (rex.w) + MOV64x(gd, 0x8000000000000000LL); + else + MOV32w(gd, 0x80000000); + } + break; case 0x51: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VSQRTSS Gx, Vx, Ex"); From 319a1a8ad6e2483854586120269593564cd92cad Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 26 Oct 2026 15:55:04 +0800 Subject: [PATCH 081/156] [RV64_DYNAREC] Avoid duplicate YMM upper zeroing on SSE cache purge (#4603) --- src/dynarec/rv64/dynarec_rv64_helper.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 81b4d0e16..5cb90d80e 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -1927,6 +1927,7 @@ static void sse_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1) int old = -1; uint8_t sew, vlmul, vl; int flushed8 = 0; + uint32_t zeroed = 0; vector_save_vtype(dyn, &sew, &vlmul, &vl); dyn->inst_sew = VECTOR_SEWNA; dyn->inst_vl = 0; @@ -1944,6 +1945,7 @@ static void sse_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1) ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VSE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); } + if (dyn->e.ssecache[i].ymm0) zeroed |= 1u << i; avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, next, !next); } else if (dyn->e.ssecache[i].single) FSW(dyn->e.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i])); @@ -1962,6 +1964,7 @@ static void sse_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1) if (flushed8) vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); dyn->purge_dead_vector = 0; + dyn->e.ymm0 &= ~zeroed; avx_flush_pending_zero_vector(dyn, ninst, s1, next); if (old != -1) { MESSAGE(LOG_DUMP, "\t------ Purge SSE Cache\n"); From e9f705df0cd90d9e7488c4434f93d1a3418e9d36 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 26 Oct 2026 15:56:18 +0800 Subject: [PATCH 082/156] [RV64_DYNAREC] Avoid duplicate pending-zero upper stores (#4604) --- src/dynarec/rv64/dynarec_rv64_helper.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 5cb90d80e..822459267 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -3007,7 +3007,7 @@ void avx_flush_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int r } // materialize the deferred zeros of YMM registers that are not in the cache anymore -void avx_flush_pending_zero_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next) +static void avx_flush_pending_zero_mask(dynarec_rv64_t* dyn, int ninst, int s1, int next, uint16_t mask) { if (!cpuext.vlen || cpuext.vlen < 32) return; @@ -3017,7 +3017,7 @@ void avx_flush_pending_zero_vector(dynarec_rv64_t* dyn, int ninst, int s1, int n dyn->pending_zero_flushed = 1; } for (int i = 0; i < 16; ++i) - if ((dyn->e.ymm0 >> i) & 1) { + if ((mask >> i) & 1) { SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 0); SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 8); if (!next) sse_set_pending_zero(dyn, i, 0); @@ -3025,6 +3025,11 @@ void avx_flush_pending_zero_vector(dynarec_rv64_t* dyn, int ninst, int s1, int n dyn->inst_vl = 0; // force the next vsetvli to be emited } +void avx_flush_pending_zero_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next) +{ + avx_flush_pending_zero_mask(dyn, ninst, s1, next, dyn->e.ymm0); +} + void avx_sync_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next) { if (!cpuext.vlen || cpuext.vlen < 32) @@ -3034,10 +3039,14 @@ void avx_sync_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next) #if STEP == 0 if (!next) dyn->insts[ninst].ymm_pending_materialized = 1; #endif + uint16_t handled = 0; for (int i = 0; i < 16; ++i) - if (dyn->e.ssecache[i].v != -1 && dyn->e.ssecache[i].vector) + if (dyn->e.ssecache[i].v != -1 && dyn->e.ssecache[i].vector) { + if (dyn->e.ssecache[i].ymm0) + handled |= (uint16_t)(1 << i); avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, next, 0); - avx_flush_pending_zero_vector(dyn, ninst, s1, next); + } + avx_flush_pending_zero_mask(dyn, ninst, s1, next, dyn->e.ymm0 & ~handled); } void avx_set_vector_width(dynarec_rv64_t* dyn, int ninst, int s1, int sew, int width) From 61add52ed5baf9213761fb20cca1585315fb9273 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 26 Oct 2026 15:56:56 +0800 Subject: [PATCH 083/156] [RV64_DYNAREC] Use generic vector stores for XMM spills (#4605) --- src/dynarec/rv64/dynarec_rv64_helper.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 822459267..077b9ba6a 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -2456,14 +2456,9 @@ static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, i case EXT_CACHE_XMMW: case EXT_CACHE_YMMW: MESSAGE(LOG_DUMP, "\t - Unloading %s\n", getCacheName(t, n)); - { - uint8_t sew, vlmul, vl; - vector_save_vtype(dyn, &sew, &vlmul, &vl); - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); - ADDI(s1, xEmu, offsetof(x64emu_t, xmm[n])); - VSE8_V(reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); - vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); - } + SET_CACHE_VECTOR_WIDTH(s1); + ADDI(s1, xEmu, offsetof(x64emu_t, xmm[n])); + VSE_V(reg, s1, dyn->vector_eew, VECTOR_UNMASKED, VECTOR_NFIELD1); if (t == EXT_CACHE_YMMW) avx_flush_upper_vector(dyn, ninst, s1, n, reg, 1, 1); break; From 21c14f1c048e48e3467fbb0198d957756e79c1c2 Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Mon, 26 Oct 2026 22:04:23 +0800 Subject: [PATCH 084/156] [RV64_DYNAREC] Keep origin vtype for VPMOVSX and VPMOVZX opcodes (#4607) `GETEY_vector_w` already configures SEW and VL for the narrow source. Use `VEC_SRC_KEEP` instead of `VEC_SRC_SAFE` for VPMOVSX* and VPMOVZX* to remove reduant vsetvli when the source aliases the destination. --- .../rv64/dynarec_rv64_avx_66_0f38_vector.c | 24 +++++++++---------- .../rv64/dynarec_rv64_avx_66_0f_vector.c | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c index 8357f11bd..df7c49fb2 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c @@ -385,7 +385,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 8 << vex.l); GETGY_empty_vector(v0); - VEC_SRC_SAFE(q0, v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16 << vex.l); VSEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); @@ -395,7 +395,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 4 << vex.l); GETGY_empty_vector(v0); - VEC_SRC_SAFE(q0, v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VSEXT_VF4(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -405,7 +405,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 2 << vex.l); GETGY_empty_vector(v0); - VEC_SRC_SAFE(q0, v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VSEXT_VF8(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -415,7 +415,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW16, 8 << vex.l); GETGY_empty_vector(v0); - VEC_SRC_SAFE(q0, v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VSEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -425,7 +425,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW16, 4 << vex.l); GETGY_empty_vector(v0); - VEC_SRC_SAFE(q0, v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VSEXT_VF4(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -435,7 +435,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW32, 8 << vex.l); GETGY_empty_vector(v0); - VEC_SRC_SAFE(q0, v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VSEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -577,7 +577,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 8 << vex.l); GETGY_empty_vector(v0); - VEC_SRC_SAFE(q0, v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16 << vex.l); VZEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); @@ -587,7 +587,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 4 << vex.l); GETGY_empty_vector(v0); - VEC_SRC_SAFE(q0, v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VZEXT_VF4(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -597,7 +597,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 2 << vex.l); GETGY_empty_vector(v0); - VEC_SRC_SAFE(q0, v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VZEXT_VF8(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -607,7 +607,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW16, 8 << vex.l); GETGY_empty_vector(v0); - VEC_SRC_SAFE(q0, v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VZEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -617,7 +617,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW16, 4 << vex.l); GETGY_empty_vector(v0); - VEC_SRC_SAFE(q0, v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VZEXT_VF4(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -627,7 +627,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW32, 8 << vex.l); GETGY_empty_vector(v0); - VEC_SRC_SAFE(q0, v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VZEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index b7d3e71b6..b0f4e68c5 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -640,7 +640,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt nextop = F8; GETEY_vector(q1, 1, VECTOR_SEW32); GETGY_empty_vector(v0); - VEC_SRC_SAFE(q1, v0); + VEC_SRC_KEEP(q1, v0); u8 = F8; q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL1); { From 11effee660253961698bc195ef3f53ebaeee4191 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Mon, 26 Oct 2026 16:00:27 +0100 Subject: [PATCH 085/156] Arm64 lrcpc (#4608) * [ARM64_DYNAREC] Use LRCPC2, LRCPC3 (if available) and USCAT for strongmem and volatile metadata * [ARM64_DYNAREC][LRCPC] Do not use lrcpc if unscaled is not possible on the opcode * [ARM64_DYNAREC] FFixed an issue with JMP FAR /CALL FAR --- src/dynarec/arm64/arm64_emitter.h | 74 +++++++++---------- src/dynarec/arm64/dynarec_arm64_00.c | 47 ++++++++---- src/dynarec/arm64/dynarec_arm64_0f.c | 4 + src/dynarec/arm64/dynarec_arm64_66.c | 14 +++- src/dynarec/arm64/dynarec_arm64_arch.c | 62 +++++++++++++++- src/dynarec/arm64/dynarec_arm64_arch.h | 5 ++ src/dynarec/arm64/dynarec_arm64_avx_0f.c | 1 + src/dynarec/arm64/dynarec_arm64_avx_66_0f.c | 2 + src/dynarec/arm64/dynarec_arm64_avx_66_0f38.c | 1 + src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c | 1 + src/dynarec/arm64/dynarec_arm64_f30f.c | 3 +- src/dynarec/arm64/dynarec_arm64_functions.c | 8 +- src/dynarec/arm64/dynarec_arm64_helper.c | 6 +- src/dynarec/arm64/dynarec_arm64_helper.h | 3 + src/dynarec/arm64/dynarec_arm64_pass0.h | 14 +++- src/dynarec/arm64/dynarec_arm64_pass1.h | 5 +- src/dynarec/arm64/dynarec_arm64_private.h | 1 + src/dynarec/dynarec_helper.h | 18 +++-- src/dynarec/dynarec_native_pass.c | 37 ++++++++-- src/libtools/sigtools.c | 7 ++ 20 files changed, 233 insertions(+), 80 deletions(-) diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h index 8558b5cfd..790b42efd 100644 --- a/src/dynarec/arm64/arm64_emitter.h +++ b/src/dynarec/arm64/arm64_emitter.h @@ -2373,51 +2373,51 @@ int convert_bitmask(uint64_t bitmask); // LRCPC extension #define LDAPR_gen(sz, Rn, Rt) ((sz)<<30 | 0b111<<27 | 1<<23 | 1<<21 | 0b11111<<16 | 1<<15 | 0b100<<12 | (Rn)<<5 | (Rt)) -#define LDAPRx(Rt, Rn) EMIT(LDAPR_gen(0b11, Rn, Rt)) -#define LDAPRw(Rt, Rn) EMIT(LDAPR_gen(0b10, Rn, Rt)) -#define LDAPRxw(Rt, Rn) EMIT(LDAPR_gen(0b10+rex.w, Rn, Rt)) -#define LDAPRz(Rt, Rn) EMIT(LDAPR_gen(rex.is32bits?0b10:0b11, Rn, Rt)) -#define LDAPRH(Rt, Rn) EMIT(LDAPR_gen(0b01, Rn, Rt)) -#define LDAPRB(Rt, Rn) EMIT(LDAPR_gen(0b00, Rn, Rt)) +#define LDAPRx(Rt, Rn) LEMIT(LDAPR_gen(0b11, Rn, Rt)) +#define LDAPRw(Rt, Rn) LEMIT(LDAPR_gen(0b10, Rn, Rt)) +#define LDAPRxw(Rt, Rn) LEMIT(LDAPR_gen(0b10+rex.w, Rn, Rt)) +#define LDAPRz(Rt, Rn) LEMIT(LDAPR_gen(rex.is32bits?0b10:0b11, Rn, Rt)) +#define LDAPRH(Rt, Rn) LEMIT(LDAPR_gen(0b01, Rn, Rt)) +#define LDAPRB(Rt, Rn) LEMIT(LDAPR_gen(0b00, Rn, Rt)) // LRCPC2 extension #define LRCPC2_gen(sz, opc, imm9, Rn, Rt) ((sz)<<30 | 0b011001<<24 | (opc)<<22 | ((imm9)&0b111111111)<<12 | (Rn)<<5 | (Rt)) -#define STLURx(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b11, 0b00, imm9, Rn, Rt)) -#define STLURw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b10, 0b00, imm9, Rn, Rt)) -#define STLURxw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b10+rex.w, 0b00, imm9, Rn, Rt)) -#define STLURz(Rt, Rn, imm9) EMIT(LRCPC2_gen(rex.is32bits?0b10:0b11, 0b00, imm9, Rn, Rt)) -#define STLURH(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, 0b00, imm9, Rn, Rt)) -#define STLURB(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, 0b00, imm9, Rn, Rt)) - -#define LDAPURx(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b11, 0b01, imm9, Rn, Rt)) -#define LDAPURw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b10, 0b01, imm9, Rn, Rt)) -#define LDAPURxw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b10+rex.w, 0b01, imm9, Rn, Rt)) -#define LDAPURz(Rt, Rn, imm9) EMIT(LRCPC2_gen(rex.is32bits?0b10:0b11, 0b01, imm9, Rn, Rt)) -#define LDAPURH(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, 0b01, imm9, Rn, Rt)) -#define LDAPURB(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, 0b01, imm9, Rn, Rt)) -#define LDAPURSW(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b10, 0b10, imm9, Rn, Rt)) -#define LDAPURSHw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, 0b11, imm9, Rn, Rt)) -#define LDAPURSHx(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, 0b10, imm9, Rn, Rt)) -#define LDAPURSHxw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b01, rex.w?0b10:0b11, imm9, Rn, Rt)) -#define LDAPURSBw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, 0b11, imm9, Rn, Rt)) -#define LDAPURSBx(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, 0b10, imm9, Rn, Rt)) -#define LDAPURSBxw(Rt, Rn, imm9) EMIT(LRCPC2_gen(0b00, rex.w?0b10:0b11, imm9, Rn, Rt)) +#define STLURx(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b11, 0b00, imm9, Rn, Rt)) +#define STLURw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b10, 0b00, imm9, Rn, Rt)) +#define STLURxw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b10+rex.w, 0b00, imm9, Rn, Rt)) +#define STLURz(Rt, Rn, imm9) LEMIT(LRCPC2_gen(rex.is32bits?0b10:0b11, 0b00, imm9, Rn, Rt)) +#define STLURH(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b01, 0b00, imm9, Rn, Rt)) +#define STLURB(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b00, 0b00, imm9, Rn, Rt)) + +#define LDAPURx(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b11, 0b01, imm9, Rn, Rt)) +#define LDAPURw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b10, 0b01, imm9, Rn, Rt)) +#define LDAPURxw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b10+rex.w, 0b01, imm9, Rn, Rt)) +#define LDAPURz(Rt, Rn, imm9) LEMIT(LRCPC2_gen(rex.is32bits?0b10:0b11, 0b01, imm9, Rn, Rt)) +#define LDAPURH(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b01, 0b01, imm9, Rn, Rt)) +#define LDAPURB(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b00, 0b01, imm9, Rn, Rt)) +#define LDAPURSW(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b10, 0b10, imm9, Rn, Rt)) +#define LDAPURSHw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b01, 0b11, imm9, Rn, Rt)) +#define LDAPURSHx(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b01, 0b10, imm9, Rn, Rt)) +#define LDAPURSHxw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b01, rex.w?0b10:0b11, imm9, Rn, Rt)) +#define LDAPURSBw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b00, 0b11, imm9, Rn, Rt)) +#define LDAPURSBx(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b00, 0b10, imm9, Rn, Rt)) +#define LDAPURSBxw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b00, rex.w?0b10:0b11, imm9, Rn, Rt)) #define NOLRCPC() dyn->insts[ninst].use_lrcpc=0 // LRCPC3 extension #define LRCPC3_gen(sz, opc, imm9, Rn, Rt) ((sz)<<30 | 0b011101<<24 | (opc)<<22 | ((imm9)&0b111111111)<<12 | 0b10<<10 | (Rn)<<5 | (Rt)) -#define VLDAPUR128(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b00, 0b11, imm9, Vn, Vt));} while(0) -#define VLDAPUR64(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b11, 0b01, imm9, Vn, Vt));} while(0) -#define VLDAPUR32(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b10, 0b01, imm9, Vn, Vt));} while(0) -#define VLDAPUR16(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b01, 0b01, imm9, Vn, Vt));} while(0) -#define VLDAPUR8(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b00, 0b01, imm9, Vn, Vt));} while(0) - -#define VSTLUR128(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b00, 0b10, imm9, Vn, Vt));} while(0) -#define VSTLUR64(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b11, 0b00, imm9, Vn, Vt));} while(0) -#define VSTLUR32(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b10, 0b00, imm9, Vn, Vt));} while(0) -#define VSTLUR16(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b01, 0b00, imm9, Vn, Vt));} while(0) -#define VSTLUR8(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else EMIT(LRCPC3_gen(0b00, 0b00, imm9, Vn, Vt));} while(0) +#define VLDAPUR128(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b00, 0b11, imm9, Vn, Vt));} while(0) +#define VLDAPUR64(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b11, 0b01, imm9, Vn, Vt));} while(0) +#define VLDAPUR32(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b10, 0b01, imm9, Vn, Vt));} while(0) +#define VLDAPUR16(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b01, 0b01, imm9, Vn, Vt));} while(0) +#define VLDAPUR8(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b00, 0b01, imm9, Vn, Vt));} while(0) + +#define VSTLUR128(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b00, 0b10, imm9, Vn, Vt));} while(0) +#define VSTLUR64(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b11, 0b00, imm9, Vn, Vt));} while(0) +#define VSTLUR32(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b10, 0b00, imm9, Vn, Vt));} while(0) +#define VSTLUR16(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b01, 0b00, imm9, Vn, Vt));} while(0) +#define VSTLUR8(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b00, 0b00, imm9, Vn, Vt));} while(0) #endif //__ARM64_EMITTER_H__ diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 67b861b93..bd9993be1 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -1604,16 +1604,14 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else { // mem <= reg IF_UNALIGNED(ip) { MESSAGE(LOG_DEBUG, "\tUnaligned path"); + NOLRCPC(); addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, &lock, 0, 0); if(gd==wback) { MOVx_REG(x2, wback); wback = x2; } for(int i=0; i<(1<<(2+rex.w)); ++i) { - if(dyn->insts[ninst].use_lrcpc) - STLURB(gd, wback, i); - else - STURB_I9(gd, wback, i); + STURB_I9(gd, wback, i); RORxw(gd, gd, 8); } // gd restored after that @@ -2034,6 +2032,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(rex.rep) { INST_NAME("REP MOVSB"); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); MOVw_REG(xRSI, xRSI); @@ -2095,8 +2094,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRSI, xRSI); } GETDIR(x3, 1); - LDRB_U12(x1, xRSI, 0); - STRB_U12(x1, xRDI, 0); + unscaled = 0; + LDB(x1, xRSI, 0); + STB(x1, xRDI, 0); ADDy_REG(xRSI, xRSI, x3); ADDy_REG(xRDI, xRDI, x3); } @@ -2107,6 +2107,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(rex.rep) { INST_NAME("REP MOVSD"); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); MOVw_REG(xRSI, xRSI); @@ -2131,8 +2132,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRSI, xRSI); } GETDIR(x3, rex.w?8:4); - LDRxw_U12(x1, xRSI, 0); - STRxw_U12(x1, xRDI, 0); + unscaled = 0; + LDxw(x1, xRSI, 0); + STxw(x1, xRDI, 0); ADDy_REG(xRSI, xRSI, x3); ADDy_REG(xRDI, xRDI, x3); } @@ -2150,6 +2152,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); SMREAD(); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); MOVw_REG(xRSI, xRSI); @@ -2183,8 +2186,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } GETDIR(x3, 1); SMREAD(); - LDRB_U12(x1, xRSI, 0); - LDRB_U12(x2, xRDI, 0); + unscaled = 0; + LDB(x1, xRSI, 0); + LDB(x2, xRDI, 0); ADDy_REG(xRSI, xRSI, x3); ADDy_REG(xRDI, xRDI, x3); emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5); @@ -2203,6 +2207,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); SMREAD(); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); MOVw_REG(xRSI, xRSI); @@ -2236,8 +2241,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } GETDIR(x3, rex.w?8:4); SMREAD(); - LDRxw_U12(x1, xRSI, 0); - LDRxw_U12(x2, xRDI, 0); + unscaled = 0; + LDxw(x1, xRSI, 0); + LDxw(x2, xRDI, 0); ADDy_REG(xRSI, xRSI, x3); ADDy_REG(xRDI, xRDI, x3); emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5); @@ -2262,6 +2268,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(rex.rep) { INST_NAME("REP STOSB"); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); } @@ -2313,7 +2320,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRDI, xRDI); } GETDIR(x3, 1); - STRB_U12(xRAX, xRDI, 0); + unscaled = 0; + STB(xRAX, xRDI, 0); ADDy_REG(xRDI, xRDI, x3); } SMWRITE(); @@ -2322,6 +2330,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(rex.rep) { INST_NAME("REP STOSD"); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); } @@ -2343,7 +2352,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRDI, xRDI); } GETDIR(x3, rex.w?8:4); - STRxw_U12(xRAX, xRDI, 0); + unscaled = 0; + STxw(xRAX, xRDI, 0); ADDy_REG(xRDI, xRDI, x3); } SMWRITE(); @@ -2354,6 +2364,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else { INST_NAME("LODSB"); } + NOLRCPC(); GETDIR(x1, 1); SMREAD(); if(rex.rep) { @@ -2377,6 +2388,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else { INST_NAME("LODSD"); } + NOLRCPC(); GETDIR(x1, rex.w?8:4); if(rex.rep) { CBZx_NEXT(xRCX); @@ -2393,6 +2405,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; case 0xAE: + NOLRCPC(); switch(rex.rep) { case 1: case 2: @@ -2441,6 +2454,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; case 0xAF: + NOLRCPC(); switch(rex.rep) { case 1: case 2: @@ -2906,6 +2920,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else { // mem <= i32 IF_UNALIGNED(ip) { MESSAGE(LOG_DEBUG, "\tUnaligned path"); + NOLRCPC(); addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, &lock, 0, 4); i64 = F32S; if(i64) { @@ -4716,7 +4731,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin STPx_S7_preindex(x4, xRIP, xSP, -16); } if (rex.w) PUSH2(x5, xRIP); else PUSH2_32(x5, xRIP); - STH(x3, xEmu, offsetof(x64emu_t, segs[_CS])); + STRH_U12(x3, xEmu, offsetof(x64emu_t, segs[_CS])); jump_to_next(dyn, 0, ed, ninst, rex.is32bits); CALLRET_RET(can_continue); if (BOX64DRENV(dynarec_callret) && !can_continue) { @@ -4752,7 +4767,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin LDxw(x1, wback, 0); ed = x1; LDH(x3, wback, rex.w?8:4); - STH(x3, xEmu, offsetof(x64emu_t, segs[_CS])); + STRH_U12(x3, xEmu, offsetof(x64emu_t, segs[_CS])); jump_to_next(dyn, 0, ed, ninst, rex.w?0:1); *need_epilog = 0; *ok = 0; diff --git a/src/dynarec/arm64/dynarec_arm64_0f.c b/src/dynarec/arm64/dynarec_arm64_0f.c index aed2b81fd..4468898ac 100644 --- a/src/dynarec/arm64/dynarec_arm64_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_0f.c @@ -298,6 +298,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else { IF_UNALIGNED(ip) { MESSAGE(LOG_DEBUG, "\tUnaligned path"); + NOLRCPC(); addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0); if(wback!=x1) { MOVx_REG(x1, wback); @@ -502,6 +503,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin UDF(0); } else { INST_NAME("MOVNTPS Ex,Gx"); + NOLRCPC(); GETG; v0 = sse_get_reg(dyn, ninst, x1, gd, 0); addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0); @@ -2594,6 +2596,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 0xC3: INST_NAME("MOVNTI Ed, Gd"); + NOLRCPC(); nextop=F8; GETGD; if(MODREG) { // reg <= reg @@ -2989,6 +2992,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0xE7: INST_NAME("MOVNTQ Em, Gm"); + NOLRCPC(); nextop = F8; gd = (nextop&0x38)>>3; if(MODREG) { diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c index c723bb623..a3bbce9c1 100644 --- a/src/dynarec/arm64/dynarec_arm64_66.c +++ b/src/dynarec/arm64/dynarec_arm64_66.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT #include #include #include @@ -884,6 +884,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(rex.rep) { INST_NAME("REP MOVSW"); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); MOVw_REG(xRSI, xRSI); @@ -908,8 +909,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRSI, xRSI); } GETDIR(x3, 2); - LDRH_U12(x1, xRSI, 0); - STRH_U12(x1, xRDI, 0); + unscaled = 0; + LDH(x1, xRSI, 0); + STH(x1, xRDI, 0); ADDy_REG(xRSI, xRSI, x3); ADDy_REG(xRDI, xRDI, x3); } @@ -928,6 +930,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else SETFLAGS(X_ALL, SF_SET_PENDING); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); MOVw_REG(xRSI, xRSI); @@ -981,6 +984,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(rex.rep) { INST_NAME("REP STOSW"); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); } @@ -1002,7 +1006,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRDI, xRDI); } GETDIR(x3, 2); - STRH_U12(xRAX, xRDI, 0); + unscaled = 0; + STH(xRAX, xRDI, 0); ADDy_REG(xRDI, xRDI, x3); } SMWRITE(); @@ -1051,6 +1056,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else SETFLAGS(X_ALL, SF_SET_PENDING); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); } diff --git a/src/dynarec/arm64/dynarec_arm64_arch.c b/src/dynarec/arm64/dynarec_arm64_arch.c index 35cdc07c6..792da2217 100644 --- a/src/dynarec/arm64/dynarec_arm64_arch.c +++ b/src/dynarec/arm64/dynarec_arm64_arch.c @@ -13,6 +13,11 @@ #include "dynarec_arm64_arch.h" #include "dynarec_arm64_functions.h" #include "dynarec_native.h" +#include "custommem.h" +#include "khash.h" + +KHASH_SET_INIT_INT64(lrcpc) +static kh_lrcpc_t *lrcpc = NULL; //order might be important, so define SUPER for the right one #define SUPER() \ @@ -68,6 +73,7 @@ typedef struct arch_arch_s SUPER() #undef GO uint16_t unaligned:1; + uint16_t lrcpc:1; uint16_t seq:10; // how many instruction on the same values } arch_arch_t; @@ -77,6 +83,7 @@ typedef struct arch_build_s SUPER() #undef GO uint8_t unaligned; + uint8_t lrcpc; #define GO(A) arch_##A##_t A##_; SUPER() #undef GO @@ -102,6 +109,8 @@ static int arch_build(dynarec_arm_t* dyn, int ninst, arch_build_t* arch, int noa } // opcode can handle unaligned arch->unaligned = dyn->insts[ninst].unaligned; + // opcode has lrcpc opcode in it + arch->lrcpc = dyn->insts[ninst].has_lrcpc; if(!noarch) { // got through all naoncache to gather regs assignments if(dyn->use_x87 || dyn->use_mmx || dyn->use_xmm || dyn->use_ymm) { @@ -163,7 +172,7 @@ static int arch_build(dynarec_arm_t* dyn, int ninst, arch_build_t* arch, int noa arch->x87_.delta = dyn->insts[ninst].n.x87stack; } } - return arch->flags + arch->x87 + arch->mmx + arch->sse + arch->ymm + arch->unaligned; + return arch->flags + arch->x87 + arch->mmx + arch->sse + arch->ymm + arch->unaligned + arch->lrcpc; } static int sizeof_arch(arch_arch_t* arch) @@ -218,6 +227,7 @@ static void build_next(arch_arch_t* arch, arch_build_t* build) SUPER() #undef GO arch->unaligned = build->unaligned; + arch->lrcpc = build->lrcpc; arch->seq = 0; void* p = ((void*)arch)+sizeof(arch_arch_t); #define GO(A) \ @@ -421,3 +431,53 @@ int arch_unaligned(dynablock_t* db, uintptr_t x64pc) } return arch->unaligned; } + +int arch_lrcpc(dynablock_t* db, uintptr_t x64pc) +{ + if(!db) + return 0; + if(!db->arch_size || !db->arch) + return 0; + int ninst = getX64AddressInst(db, x64pc); + if(ninst<0) { + return 0; + } + // look for state at ninst + arch_arch_t* arch = db->arch; + arch_arch_t* next = arch; + int i = -1; + while(iseq; + next = (arch_arch_t*)((uintptr_t)next + sizeof_arch(arch)); + } + return arch->lrcpc; +} + +void add_lrcpc_address(uintptr_t addr) +{ + if(!lrcpc) + lrcpc = kh_init(lrcpc); + khint_t k; + int ret; + k = kh_put(lrcpc, lrcpc, addr, &ret); // just add +} + +int is_addr_lrcpc(uintptr_t addr) +{ + if(!lrcpc) + return 0; + khint_t k = kh_get(lrcpc, lrcpc, addr); + return (k==kh_end(lrcpc))?0:1; +} + +int mark_db_lrcpc(dynablock_t* db, uintptr_t x64pc) +{ + add_lrcpc_address(x64pc); + if(db->to_delete) + return 2; // already marked + db->to_delete = 1; // mark block for deletion + MarkDynablock(db); // and mark it as dirty +if(BOX64ENV(showsegv)) printf_log(LOG_INFO, "Marked db %p as dirty, and address %p as avoid lrcpc\n", db, (void*)x64pc); + return 2; // marked, exit handling... +} diff --git a/src/dynarec/arm64/dynarec_arm64_arch.h b/src/dynarec/arm64/dynarec_arm64_arch.h index c4a63b212..ef8f366aa 100644 --- a/src/dynarec/arm64/dynarec_arm64_arch.h +++ b/src/dynarec/arm64/dynarec_arm64_arch.h @@ -22,4 +22,9 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) #endif // get if instruction can be regenerated for unaligned access int arch_unaligned(dynablock_t* db, uintptr_t x64pc); +// get if instruction has lrcpc so it can be regenerated without +int arch_lrcpc(dynablock_t* db, uintptr_t x64pc); +void add_lrcpc_address(uintptr_t addr); +int is_addr_lrcpc(uintptr_t addr); +int mark_db_lrcpc(dynablock_t* db, uintptr_t x64pc); #endif // __DYNAREC_ARM_ARCH_H__ diff --git a/src/dynarec/arm64/dynarec_arm64_avx_0f.c b/src/dynarec/arm64/dynarec_arm64_avx_0f.c index 97db6dacb..5cce52f5f 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_0f.c @@ -269,6 +269,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int UDF(0); } else { INST_NAME("VMOVNTPS Ex, Gx"); + NOLRCPC(); GETG; v0 = sse_get_reg(dyn, ninst, x1, gd, 0); if(vex.l) { diff --git a/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c b/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c index b68f8e833..0528125a4 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c @@ -244,6 +244,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, case 0x2B: INST_NAME("VMOVNTPD Ex,Gx"); + NOLRCPC(); nextop = F8; GETG; if(MODREG) { @@ -1784,6 +1785,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, break; case 0xE7: INST_NAME("VMOVNTDQ Ex,Gx"); + NOLRCPC(); nextop = F8; GETG; if(MODREG) { diff --git a/src/dynarec/arm64/dynarec_arm64_avx_66_0f38.c b/src/dynarec/arm64/dynarec_arm64_avx_66_0f38.c index c5b3d9484..5b80be2cd 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_66_0f38.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_66_0f38.c @@ -643,6 +643,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip break; case 0x2A: INST_NAME("VMOVNTDQA Gx, Ex"); + NOLRCPC(); nextop = F8; GETG; if(MODREG) { diff --git a/src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c b/src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c index 8454ea42c..12d7eacac 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c @@ -551,6 +551,7 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, } else { IF_UNALIGNED(ip) { MESSAGE(LOG_DEBUG, "\tUnaligned path"); + NOLRCPC(); addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0); for(int i=0; i<16; ++i) { VST1_8(v0, i, i?x1:wback); diff --git a/src/dynarec/arm64/dynarec_arm64_f30f.c b/src/dynarec/arm64/dynarec_arm64_f30f.c index 9ba5e34d1..549197aed 100644 --- a/src/dynarec/arm64/dynarec_arm64_f30f.c +++ b/src/dynarec/arm64/dynarec_arm64_f30f.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT #include #include #include @@ -591,6 +591,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n } else { IF_UNALIGNED(ip) { MESSAGE(LOG_DEBUG, "\tUnaligned path"); + NOLRCPC(); addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0); for(int i=0; i<16; ++i) { VST1_8(v0, i, i?x1:wback); diff --git a/src/dynarec/arm64/dynarec_arm64_functions.c b/src/dynarec/arm64/dynarec_arm64_functions.c index d8ec21222..c1dbe812f 100644 --- a/src/dynarec/arm64/dynarec_arm64_functions.c +++ b/src/dynarec/arm64/dynarec_arm64_functions.c @@ -768,7 +768,7 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r } static char buf[8192]; - int length = sprintf(buf, "barrier=%d state=%d/%s(%s->%s)/%c, set=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d/%d)", + int length = sprintf(buf, "barrier=%d state=%d/%s(%s->%s)/%c, set=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d/%d)%d", dyn->insts[ninst].x64.barrier, dyn->insts[ninst].x64.state_flags, df_status[dyn->f], @@ -780,7 +780,11 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r dyn->insts[ninst].x64.use_flags, dyn->insts[ninst].x64.need_before, dyn->insts[ninst].x64.need_after, - dyn->smwrite, dyn->insts[ninst].will_write, dyn->insts[ninst].last_write, dyn->insts[ninst].lock); + dyn->smwrite, dyn->insts[ninst].will_write, dyn->insts[ninst].last_write, dyn->insts[ninst].lock, + dyn->insts[ninst].x64.strongmem); + if(dyn->insts[ninst].use_lrcpc || dyn->insts[ninst].has_lrcpc) { + length += sprintf(buf + length, " LRCPC:%d/%d", dyn->insts[ninst].use_lrcpc, dyn->insts[ninst].has_lrcpc); + } if (dyn->insts[ninst].nat_flags_op) { if (dyn->insts[ninst].nat_flags_op == NAT_FLAG_OP_TOUCH && dyn->insts[ninst].before_nat_flags) length += sprintf(buf + length, " NF:%d/read:%x", dyn->insts[ninst].nat_flags_op, dyn->insts[ninst].before_nat_flags); diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index c719175c1..27c777185 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -35,7 +35,11 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u int lock = l?((l==LOCK_LOCK)?1:2):0; if(lock==2) *l = 0; - if(dyn->insts[ninst].use_lrcpc) { absmax = 0; mask=0;}// there is no "Scaled" version, only Unscaled + if(dyn->insts[ninst].use_lrcpc) { + if(!unscaled) { + NOLRCPC(); + } else { absmax = 0; mask=0;} + } // there is no "Scaled" version, only Unscaled if(rex.is32bits && rex.is67) return geted16(dyn, addr, ninst, nextop, ed, hint, fixaddress, unscaled, absmax, mask, rex, s); diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index f53500a12..e846f61f8 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -40,6 +40,9 @@ #ifndef FEMIT #define FEMIT(A) EMIT(A) #endif +#ifndef LEMIT +#define LEMIT(A) EMIT(A) +#endif #ifndef ENDPREFIX #define ENDPREFIX #endif diff --git a/src/dynarec/arm64/dynarec_arm64_pass0.h b/src/dynarec/arm64/dynarec_arm64_pass0.h index f10458958..812a9aae5 100644 --- a/src/dynarec/arm64/dynarec_arm64_pass0.h +++ b/src/dynarec/arm64/dynarec_arm64_pass0.h @@ -38,8 +38,9 @@ dyn->n.combined1 = dyn->n.combined2 = 0;\ dyn->n.swapped = 0; dyn->n.barrier = 0; \ dyn->insts[ninst].f_entry = dyn->f; \ - dyn->insts[ninst].x64.strongmem = ((box64_wine && VolatileRangesContains(ip)) ? 0 : BOX64DRENV(dynarec_strongmem)); \ - if(ninst) {dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr;} \ + dyn->insts[ninst].x64.strongmem = ((box64_wine && VolatileRangesContains(ip)) ? 0 : BOX64DRENV(dynarec_strongmem)); \ + if(dyn->insts[ninst].x64.strongmem && cpuext.lrcpc && cpuext.lrcpc2 && cpuext.uscat) dyn->insts[ninst].use_lrcpc = 1; \ + if(ninst) {dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr;} \ AREFLAGSNEEDED() #define INST_EPILOG \ @@ -47,7 +48,11 @@ dyn->insts[ninst].n = dyn->n; \ if(dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH && !dyn->insts[ninst].set_nat_flags) \ dyn->insts[ninst].nat_flags_op=NAT_FLAG_OP_UNUSABLE; \ - dyn->insts[ninst].x64.has_next = (ok>0)?1:0; + dyn->insts[ninst].x64.has_next = (ok>0)?1:0; \ + if(dyn->insts[ninst].use_lrcpc && (!dyn->insts[ninst].has_lrcpc || is_addr_lrcpc(ip))) \ + dyn->insts[ninst].use_lrcpc = 0; \ + if(dyn->insts[ninst].x64.strongmem && dyn->insts[ninst].use_lrcpc) dyn->insts[ninst].x64.strongmem = 0 + #define INST_NAME(name) #define DEFAULT \ --dyn->size; \ @@ -59,7 +64,8 @@ } -#define FEMIT(A) dyn->insts[ninst].nat_flags_op = dyn->insts[ninst].x64.set_flags?NAT_FLAG_OP_TOUCH:NAT_FLAG_OP_UNUSABLE +#define FEMIT(A) do {dyn->insts[ninst].nat_flags_op = dyn->insts[ninst].x64.set_flags?NAT_FLAG_OP_TOUCH:NAT_FLAG_OP_UNUSABLE; EMIT(A);} while(0) +#define LEMIT(A) do {dyn->insts[ninst].has_lrcpc = 1; EMIT(A);} while(0) #define IFNATIVE(A) if(mark_natflag(dyn, ninst, A, 0)) #define IFNATIVEN(A) if(mark_natflag(dyn, ninst, A, 0)) #define UFLAG_IF if(dyn->insts[ninst].x64.set_flags) diff --git a/src/dynarec/arm64/dynarec_arm64_pass1.h b/src/dynarec/arm64/dynarec_arm64_pass1.h index 8b468966e..6368d1b7d 100644 --- a/src/dynarec/arm64/dynarec_arm64_pass1.h +++ b/src/dynarec/arm64/dynarec_arm64_pass1.h @@ -3,6 +3,7 @@ #define FINI #define MESSAGE(A, ...) do {} while (0) #define EMIT(A) do {} while (0) +#define LEMIT(A) do {dyn->insts[ninst].has_lrcpc = 1; EMIT(A);} while(0) // do not update dyn->f for SETFLAGS(..., SF_SET_PENDING) because it will use either DF_NONE or DF_SET anyway (similar to SF_SET_NODF) #define SETFLAGS(A,B) \ @@ -20,7 +21,9 @@ #define INST_EPILOG \ dyn->insts[ninst].n = dyn->n; \ - dyn->insts[ninst].f_exit = dyn->f + dyn->insts[ninst].f_exit = dyn->f; \ + if(dyn->insts[ninst].use_lrcpc && (!dyn->insts[ninst].has_lrcpc || is_addr_lrcpc(ip))) \ + dyn->insts[ninst].use_lrcpc = 0 #define INST_NAME(name) diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h index 62d2d440d..040e96eb8 100644 --- a/src/dynarec/arm64/dynarec_arm64_private.h +++ b/src/dynarec/arm64/dynarec_arm64_private.h @@ -157,6 +157,7 @@ typedef struct instruction_arm64_s { unsigned fpu_used:1; // any xmm/ymm/x87/mmx reg used unsigned fpupurge:1; // this opcode will purge all fpu regs unsigned use_lrcpc:1;// use the various lrcpc opcode here instead of regular LD/ST + memory barrier + unsigned has_lrcpc:1;// set if the opcode has some lrcpc opcode in it flagcache_t f_exit; // flags status at end of instruction neoncache_t n; // neoncache at end of instruction (but before poping) flagcache_t f_entry; // flags status before the instruction begin diff --git a/src/dynarec/dynarec_helper.h b/src/dynarec/dynarec_helper.h index 96d9ec998..fd63918ce 100644 --- a/src/dynarec/dynarec_helper.h +++ b/src/dynarec/dynarec_helper.h @@ -42,13 +42,15 @@ #if STEP == 1 -#define SMWRITE() \ - do { \ - /* Mark that current sequence writes to guest memory. */ \ - /* This will be used in SMEND for last_write. */ \ - dyn->smwrite = 1; \ - /* Mark that current opcode writes to guest memory. */ \ - dyn->insts[ninst].will_write = 1; \ +#define SMWRITE() \ + do { \ + if(STRONGMEM_LEVEL()) { \ + /* Mark that current sequence writes to guest memory. */\ + /* This will be used in SMEND for last_write. */ \ + dyn->smwrite = 1; \ + /* Mark that current opcode writes to guest memory. */ \ + dyn->insts[ninst].will_write = 1; \ + } \ } while (0) #define SMWRITELOCK(lock) \ @@ -113,7 +115,7 @@ } \ } else { \ /* Mark that current sequence writes to guest memory. */ \ - dyn->smwrite = 1; \ + if(STRONGMEM_LEVEL()) dyn->smwrite = 1; \ } \ } \ } while (0) diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index d5ce776ca..99453ee29 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -238,10 +238,29 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int } else if (dyn->insts[ninst].will_write) { WILLWRITE(); } - + #endif int is_opcode_volatile = /*box64_wine &&*/ VolatileRangesContains(ip) && VolatileOpcodesHas(ip); - if (is_opcode_volatile && !dyn->insts[ninst].lock && dyn->insts[ninst].will_write) - DMB_ISHST(); + #if defined(ARM64) && STEP == 1 + if(is_opcode_volatile && cpuext.lrcpc && cpuext.lrcpc2 && cpuext.uscat) dyn->insts[ninst].use_lrcpc = 1; + #endif + #if STEP > 1 + #ifdef ARM64 + if (is_opcode_volatile && dyn->insts[ninst].use_lrcpc && dyn->insts[ninst].lock) + NOLRCPC(); + #endif + if (is_opcode_volatile && !dyn->insts[ninst].lock) { + #ifdef ARM64 + if(!dyn->insts[ninst].use_lrcpc) { + #endif + if(dyn->insts[ninst].will_write) + DMB_ISHST(); + #ifdef ARM64 + } else { + SMEND(); + } + #endif + } + #endif if (BOX64DRENV(dynarec_dump) && (!BOX64ENV(dynarec_dump_range_end) || (ip >= BOX64ENV(dynarec_dump_range_start) && ip < BOX64ENV(dynarec_dump_range_end)))) { dyn->need_dump = BOX64DRENV(dynarec_dump) == 3 && STEP != 3 ? 0 : BOX64DRENV(dynarec_dump); @@ -332,8 +351,16 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int #if STEP > 1 if (dyn->insts[ninst].lock) DMB_ISH(); - else if (is_opcode_volatile && dyn->insts[ninst].will_read) - DMB_ISHLD(); + else if (is_opcode_volatile) { + #ifdef ARM64 + if(!dyn->insts[ninst].use_lrcpc) { + #endif + if(dyn->insts[ninst].will_read) + DMB_ISHLD(); + #ifdef ARM64 + } + #endif + } #endif #if defined(ARM64) || defined(LA64) || defined(RV64) if(dyn->insts[ninst].x64.has_next && dyn->insts[ninst+1].preload_xmmymm) { diff --git a/src/libtools/sigtools.c b/src/libtools/sigtools.c index d46feeca8..c7a9cc63a 100644 --- a/src/libtools/sigtools.c +++ b/src/libtools/sigtools.c @@ -183,6 +183,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, size); + if(arch_lrcpc(db, x64pc)) mark_db_lrcpc(db, x64pc); // regen dynablock without this lrcpc opcode uint64_t value = (val==xZR)?0:p->uc_mcontext.regs[val]; if(size==8 && (((uintptr_t)addr)&3)==0) { for(int i=0; i<2; ++i) @@ -263,6 +264,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, 1<vregs[val]; if(scale>2 && (((uintptr_t)addr)&3)==0) { for(int i=0; i<(1<<(scale-2)); ++i) @@ -345,6 +347,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, 1<2 && (((uintptr_t)addr)&3)==0) { for(int i=0; i<(1<<(scale-2)); ++i) @@ -410,6 +413,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, size); + if(arch_lrcpc(db, x64pc)) mark_db_lrcpc(db, x64pc); uint64_t value = 0; if(size==8 && (((uintptr_t)addr)&3)==0) { for(int i=0; i<2; ++i) @@ -432,6 +436,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, size); + if(arch_lrcpc(db, x64pc)) mark_db_lrcpc(db, x64pc); int32_t value = 0; for(int i=0; iuc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, 2); + if(arch_lrcpc(db, x64pc)) mark_db_lrcpc(db, x64pc); uint16_t value = 0; for(int i=0; i<2; ++i) value |= ((uint16_t)addr[i]) << (i*8); @@ -466,6 +472,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, 2); + if(arch_lrcpc(db, x64pc)) mark_db_lrcpc(db, x64pc); int16_t value = 0; for(int i=0; i<2; ++i) value |= ((int16_t)addr[i]) << (i*8); From 74ee4280dbd3ea311808d7204e29ae5a6ff85517 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 26 Oct 2026 23:12:23 +0800 Subject: [PATCH 086/156] [DYNAREC] Added callret=3 and move in_used tracking to it (#4609) Also removed the leafcall optimization from LoongArch. --- configurator/model.py | 1 + docs/USAGE.md | 2 +- docs/USAGE_CN.md | 2 +- docs/box64.pod | 2 +- docs/gen/usage.json | 2 +- docs/gen/usage_cn.json | 2 +- src/dynarec/arm64/dynarec_arm64_helper.c | 6 +- src/dynarec/dynablock.c | 4 +- src/dynarec/dynarec_arch.h | 8 +- src/dynarec/dynarec_native.c | 371 ----------------------- src/dynarec/dynarec_native_pass.c | 77 +---- src/dynarec/dynarec_private.h | 11 - src/dynarec/la64/dynarec_la64_00_0.c | 7 - src/dynarec/la64/dynarec_la64_00_1.c | 7 - src/dynarec/la64/dynarec_la64_00_2.c | 4 - src/dynarec/la64/dynarec_la64_00_3.c | 78 +---- src/dynarec/la64/dynarec_la64_0f.c | 4 - src/dynarec/la64/dynarec_la64_helper.c | 9 +- src/dynarec/la64/dynarec_la64_helper.h | 31 -- src/dynarec/la64/dynarec_la64_pass0.h | 8 - src/dynarec/la64/dynarec_la64_pass2.h | 3 +- src/dynarec/la64/dynarec_la64_private.h | 5 - src/dynarec/rv64/dynarec_rv64_helper.c | 8 +- src/include/dynarec_native.h | 3 - src/tools/env.c | 1 + 25 files changed, 41 insertions(+), 615 deletions(-) diff --git a/configurator/model.py b/configurator/model.py index 2c92583da..cf6870740 100644 --- a/configurator/model.py +++ b/configurator/model.py @@ -103,6 +103,7 @@ class ValueState: ("BOX64_DYNAREC_BIGBLOCK", "0"), ("BOX64_DYNAREC_SAFEFLAGS", "2"), ("BOX64_DYNAREC_STRONGMEM", "2"), + ("BOX64_DYNAREC_CALLRET", "3"), ), "safe": ( ("BOX64_DYNAREC_BIGBLOCK", "0"), diff --git a/docs/USAGE.md b/docs/USAGE.md index 2b0f2932f..2bbd6ab62 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -80,7 +80,7 @@ Optimize CALL/RET opcodes. Available in WowBox64. * 0: Do not optimize CALL/RET, use jump table. * 1: Try to optimize CALL/RET, skipping the jump table when possible. * 2: Try to optimize CALL/RET, skipping the jump table when possible, adding code to handle return to dirty/modified block. Does not work on WowBox64. [Default] - * 3: Same as 2, with leaf call analysis that tries to duplicate leaf bodies into their callers. Only available for LoongArch for now. + * 3: Same as 2, but also track dynablock usage so blocks are not reclaimed while still in use. ### BOX64_DYNAREC_DF diff --git a/docs/USAGE_CN.md b/docs/USAGE_CN.md index f7ec7edd6..f93c8f083 100644 --- a/docs/USAGE_CN.md +++ b/docs/USAGE_CN.md @@ -80,7 +80,7 @@ BOX64_DYNAREC_CALLRET=1 * 0: 不优化 CALL/RET,使用跳转表。 * 1: 尝试优化 CALL/RET,在可能的情况下跳过跳转表。 * 2: 尝试优化 CALL/RET,在可能的情况下跳过跳转表,同时增加对返回到脏/已修改代码块的代码的处理。在 WowBox64 上不可用。 [默认值] - * 3: 在 2 的基础上,对叶子函数进行分析,并将符合条件的叶子函数体复制到调用方。目前仅支持龙架构。 + * 3: 在 2 的基础上,额外跟踪代码块的使用情况,避免回收仍在使用中的代码块。 ### BOX64_DYNAREC_DF diff --git a/docs/box64.pod b/docs/box64.pod index 83621c376..40fc9f3e9 100644 --- a/docs/box64.pod +++ b/docs/box64.pod @@ -175,7 +175,7 @@ Optimize CALL/RET opcodes. Available in WowBox64. * 0 : Do not optimize CALL/RET, use jump table. * 1 : Try to optimize CALL/RET, skipping the jump table when possible. * 2 : Try to optimize CALL/RET, skipping the jump table when possible, adding code to handle return to dirty/modified block. Does not work on WowBox64. [Default] - * 3 : Same as 2, with leaf call analysis that tries to duplicate leaf bodies into their callers. Only available for LoongArch for now. + * 3 : Same as 2, but also track dynablock usage so blocks are not reclaimed while still in use. =item B =I<0|1> diff --git a/docs/gen/usage.json b/docs/gen/usage.json index e259d3ef7..1d0f49e17 100644 --- a/docs/gen/usage.json +++ b/docs/gen/usage.json @@ -309,7 +309,7 @@ }, { "key": "3", - "description": "Same as 2, with leaf call analysis that tries to duplicate leaf bodies into their callers. Only available for LoongArch for now.", + "description": "Same as 2, but also track dynablock usage so blocks are not reclaimed while still in use.", "default": false } ] diff --git a/docs/gen/usage_cn.json b/docs/gen/usage_cn.json index 7292afb68..7833debcf 100644 --- a/docs/gen/usage_cn.json +++ b/docs/gen/usage_cn.json @@ -107,7 +107,7 @@ "0": "不优化 CALL/RET,使用跳转表。", "1": "尝试优化 CALL/RET,在可能的情况下跳过跳转表。", "2": "尝试优化 CALL/RET,在可能的情况下跳过跳转表,同时增加对返回到脏/已修改代码块的代码的处理。在 WowBox64 上不可用。", - "3": "在 2 的基础上,对叶子函数进行分析,并将符合条件的叶子函数体复制到调用方。目前仅支持龙架构。" + "3": "在 2 的基础上,额外跟踪代码块的使用情况,避免回收仍在使用中的代码块。" } }, "BOX64_DYNAREC_DF": { diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index 27c777185..ac4f39b8c 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -349,7 +349,7 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog); SMEND(); CHECK_DFNONE(0); - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); BR(x2); } @@ -425,7 +425,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32 if(reg!=x1) { MOVx_REG(x1, xRIP); } - if(BOX64DRENV(dynarec_callret) >= 2 && !dyn->insts[ninst].x64.has_callret) + if(BOX64DRENV(dynarec_callret) >= 3 && !dyn->insts[ninst].x64.has_callret) doLeaveBlock(dyn, ninst, x4, x5, x6); // #ifdef HAVE_TRACE // The BLR form is only for gdb backtraces, but it breaks the @@ -451,7 +451,7 @@ void ret_to_next(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex) // pop the actual return address for ARM stack LDPx_S7_postindex(xLR, x6, xSP, 16); SUBx_REG(x6, x6, xRIP); // is it the right address? - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x3); CBNZx(x6, 2*4); RET(xLR); diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c index d81e7f352..4f470b10f 100644 --- a/src/dynarec/dynablock.c +++ b/src/dynarec/dynablock.c @@ -325,8 +325,10 @@ int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size) void dynablock_leave_runtime(dynablock_t* db) { if(!db) return; - if(BOX64ENV(dynarec_callret) < 2) return; +#ifdef HAVE_IN_USED + if(BOX64ENV(dynarec_callret) < 3) return; __atomic_fetch_sub(&db->in_used, 1, __ATOMIC_ACQ_REL); +#endif } dynablock_t* CreateDBnoAlt(x64emu_t* emu, uintptr_t addr, int is32bits) diff --git a/src/dynarec/dynarec_arch.h b/src/dynarec/dynarec_arch.h index 729e24d39..8c55c93e6 100644 --- a/src/dynarec/dynarec_arch.h +++ b/src/dynarec/dynarec_arch.h @@ -8,6 +8,8 @@ #define dynarec_native_t dynarec_arm_t #define extcache_native_t neoncache_t +#define HAVE_IN_USED + #define ADDITIONNAL_DEFINITION() \ int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst); @@ -49,12 +51,12 @@ extern void arm64_next_invalid(); #define PRINT_OPCODE(C, A) arm64_print(C, A) #elif defined(LA64) -#define HAVE_LEAFCALL - #define instruction_native_t instruction_la64_t #define dynarec_native_t dynarec_la64_t #define extcache_native_t lsxcache_t +#define HAVE_IN_USED + #define ADDITIONNAL_DEFINITION() \ int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst); @@ -98,6 +100,8 @@ extern void la64_next_invalid(); #define dynarec_native_t dynarec_rv64_t #define extcache_native_t extcache_t +#define HAVE_IN_USED + #define ADDITIONNAL_DEFINITION() \ int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst); \ int sewNeedsTransform(dynarec_rv64_t* dyn, int ninst); diff --git a/src/dynarec/dynarec_native.c b/src/dynarec/dynarec_native.c index 3c80f848e..24c89af58 100644 --- a/src/dynarec/dynarec_native.c +++ b/src/dynarec/dynarec_native.c @@ -416,347 +416,6 @@ uintptr_t native_pass1(dynarec_native_t* dyn, uintptr_t addr, int alternate, int uintptr_t native_pass2(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits, int inst_max); uintptr_t native_pass3(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits, int inst_max); -#ifdef HAVE_LEAFCALL -#define LEAFCALL_MAX_INSTS 128 -#define LEAFCALL_MAX_BYTES 4096 -#define LEAFCALL_MAX_EMBEDDEDS 32 -#define LEAFCALL_MAX_TOTAL_INSTS 512 - -typedef struct leafcall_peek_s { - dynarec_native_t dyn; - instruction_native_t insts[LEAFCALL_MAX_INSTS + 2]; - int jmps[LEAFCALL_MAX_INSTS + 2]; - uintptr_t next[LEAFCALL_MAX_INSTS + 2]; -} leafcall_peek_t; - -typedef struct leafcall_analysis_s { - uintptr_t work[LEAFCALL_MAX_INSTS]; - uintptr_t decoded[LEAFCALL_MAX_INSTS]; - uint8_t decoded_len[LEAFCALL_MAX_INSTS]; - instruction_native_t* decoded_inst; - uintptr_t body_start; - uintptr_t body_end; - int work_size; - int decoded_size; - int saw_ret; - int reads_rsp; - int implicit_rsp; - int failed; -} leafcall_analysis_t; - -typedef struct leaf_embedded_s { - dynarec_native_t dyn; -} leaf_embedded_t; - -static leaf_embedded_t static_leaf_embeddeds[LEAFCALL_MAX_EMBEDDEDS]; -static instruction_native_t static_leafinsts[LEAFCALL_MAX_TOTAL_INSTS + LEAFCALL_MAX_EMBEDDEDS]; -static int static_leafjmps[LEAFCALL_MAX_TOTAL_INSTS]; -static int static_leafpreds[LEAFCALL_MAX_TOTAL_INSTS * 2]; -static instsize_t static_leaf_instsize[LEAFCALL_INSTSIZE_SCRATCH]; -static int static_leaf_embedded_count; -static int static_leafinst_count; -static int static_leafdecoded_count; -static int static_leafpred_count; - -static int leafcall_readable(uintptr_t addr, uintptr_t size) -{ - if (!size) - return 1; - uintptr_t end = addr + size - 1; - if (end < addr) - return 0; - uintptr_t cur = addr; - while (1) { - uint32_t prot = getProtection(cur); - if ((prot & (PROT_READ | PROT_EXEC)) != (PROT_READ | PROT_EXEC)) - return 0; - uintptr_t page_end = (cur & ~(box64_pagesize - 1)) + box64_pagesize - 1; - if (end <= page_end) - return 1; - cur = page_end + 1; - } -} - -static int leafcall_seen(const leafcall_analysis_t* scan, uintptr_t addr) -{ - for (int i = 0; i < scan->decoded_size; ++i) - if (scan->decoded[i] == addr) - return 1; - return 0; -} - -static int leafcall_queue_jump(leafcall_analysis_t* scan, uintptr_t addr, uintptr_t continuation) -{ - if (!addr || addr == continuation) - return 0; - if (addr < scan->body_start || addr >= scan->body_end) - return 0; - if (leafcall_seen(scan, addr)) - return 1; - for (int i = 0; i < scan->work_size; ++i) - if (scan->work[i] == addr) - return 1; - if (scan->work_size >= LEAFCALL_MAX_INSTS) - return 0; - scan->work[scan->work_size++] = addr; - return 1; -} - -static int leafcall_check_segment(leafcall_analysis_t* scan, uintptr_t entry, uintptr_t continuation, int is32bits) -{ - if (!leafcall_readable(entry, 1) || leafcall_seen(scan, entry)) - return leafcall_seen(scan, entry); - - leafcall_peek_t peek; - memset(&peek, 0, sizeof(peek)); - dynarec_native_t* dyn = &peek.dyn; - dyn->start = entry; - dyn->end = entry + LEAFCALL_MAX_BYTES; - if (dyn->end < entry) - return 0; - uintptr_t mapped = SizeFileMapped(entry); - if (mapped && mapped < LEAFCALL_MAX_BYTES) - dyn->end = entry + mapped; - dyn->cap = LEAFCALL_MAX_INSTS + 2; - dyn->insts = peek.insts; - dyn->jmp_cap = LEAFCALL_MAX_INSTS + 2; - dyn->jmps = peek.jmps; - dyn->next_cap = LEAFCALL_MAX_INSTS + 2; - dyn->next = peek.next; - dyn->env = GetCurEnvByAddr(entry); - dyn->is_file_mapped = IsAddrElfOrFileMapped(entry); - dyn->peeking_flags = 1; - - uintptr_t end = native_pass0(dyn, entry, 0, is32bits, LEAFCALL_MAX_INSTS); - if (dyn->size <= 0 || dyn->size > LEAFCALL_MAX_INSTS || end < entry) - return 0; - - for (int i = 0; i < dyn->size; ++i) { - instruction_x64_t* inst = &dyn->insts[i].x64; - uintptr_t ip = inst->addr; - uintptr_t next = (i + 1 < dyn->size) ? dyn->insts[i + 1].x64.addr : end; - if (ip == continuation || ip < scan->body_start || next > scan->body_end) - return 0; - if (leafcall_seen(scan, ip)) - continue; - if (scan->decoded_size >= LEAFCALL_MAX_INSTS) - return 0; - scan->decoded[scan->decoded_size] = ip; - scan->decoded_len[scan->decoded_size] = next - ip; - if (scan->decoded_inst) { - scan->decoded_inst[scan->decoded_size] = dyn->insts[i]; - scan->decoded_inst[scan->decoded_size].pred = NULL; - scan->decoded_inst[scan->decoded_size].pred_sz = 0; - } - ++scan->decoded_size; - - if (dyn->insts[i].host_call) - return 0; - - if (inst->leaf_kind == LEAF_KIND_CALL) - return 0; - - int implicit_rsp = (inst->leaf_rsp & LEAF_RSP_PUSHPOP) ? 1 : 0; - if (implicit_rsp) scan->implicit_rsp = 1; - - if (inst->leaf_kind == LEAF_KIND_RET) { - scan->saw_ret = 1; - continue; - } - - uint16_t sp_bits = (dyn->insts[i].up32_read | dyn->insts[i].up32_write64 | dyn->insts[i].up32_write32 | dyn->insts[i].up32_zero) & (1u << _SP); - if ((inst->leaf_rsp & LEAF_RSP_REF) || (!implicit_rsp && sp_bits)) - scan->reads_rsp = 1; - - if (!inst->has_next) { - if (!inst->jmp || inst->jmp_cond) - return 0; - if (!leafcall_queue_jump(scan, inst->jmp, continuation)) - return 0; - continue; - } - if (inst->jmp) { - if (!inst->jmp_cond || !leafcall_queue_jump(scan, inst->jmp, continuation)) - return 0; - } - } - return 1; -} - -static int leafcall_analyze_leaf(leafcall_analysis_t* scan, uintptr_t target, uintptr_t continuation, int is32bits, instruction_native_t* decoded_inst) -{ - memset(scan, 0, sizeof(*scan)); - scan->decoded_inst = decoded_inst; - scan->body_start = target; - scan->body_end = target + LEAFCALL_MAX_BYTES; - if (scan->body_end < target) - return 0; - uintptr_t mapped = SizeFileMapped(target); - if (mapped && mapped < LEAFCALL_MAX_BYTES) - scan->body_end = target + mapped; - scan->work[scan->work_size++] = target; - while (scan->work_size && !scan->failed) { - uintptr_t entry = scan->work[--scan->work_size]; - if (!leafcall_check_segment(scan, entry, continuation, is32bits)) - scan->failed = 1; - } - if (scan->failed || !scan->saw_ret || !scan->decoded_size) - return 0; - - for (int i = 1; i < scan->decoded_size; ++i) { - uintptr_t addr = scan->decoded[i]; - uint8_t len = scan->decoded_len[i]; - instruction_native_t inst; - if (decoded_inst) - inst = decoded_inst[i]; - int j = i; - while (j && scan->decoded[j - 1] > addr) { - scan->decoded[j] = scan->decoded[j - 1]; - scan->decoded_len[j] = scan->decoded_len[j - 1]; - if (decoded_inst) - decoded_inst[j] = decoded_inst[j - 1]; - --j; - } - scan->decoded[j] = addr; - scan->decoded_len[j] = len; - if (decoded_inst) - decoded_inst[j] = inst; - } - if (scan->decoded[0] != target) - return 0; - for (int i = 1; i < scan->decoded_size; ++i) - if (scan->decoded[i] < scan->decoded[i - 1] + scan->decoded_len[i - 1]) - return 0; - return 1; -} - -static int leaf_embedded_find(const instruction_native_t* insts, int size, uintptr_t addr) -{ - int low = 0; - int high = size - 1; - while (low <= high) { - int mid = (low + high) / 2; - if (insts[mid].x64.addr == addr) - return mid; - if (insts[mid].x64.addr < addr) - low = mid + 1; - else - high = mid - 1; - } - return -1; -} - -static int leaf_embedded_build(uintptr_t target, uintptr_t continuation, int is32bits, uint8_t* embedded_id) -{ - instruction_native_t decoded[LEAFCALL_MAX_INSTS + 2]; - leafcall_analysis_t scan; - if (!embedded_id || static_leaf_embedded_count >= LEAFCALL_MAX_EMBEDDEDS || BOX64ENV(dynarec_test) || BOX64ENV(dynarec_trace)) - return 0; -#ifdef HAVE_ALTJUMP - if (getAlternateJump((void*)target, is32bits)) - return 0; -#endif - if (!leafcall_analyze_leaf(&scan, target, continuation, is32bits, decoded)) - return 0; - if (static_leafdecoded_count + scan.decoded_size > LEAFCALL_MAX_TOTAL_INSTS || static_leafinst_count + scan.decoded_size + 1 > (int)(sizeof(static_leafinsts) / sizeof(static_leafinsts[0]))) - return 0; - - leaf_embedded_t* embedded = &static_leaf_embeddeds[static_leaf_embedded_count]; - memset(embedded, 0, sizeof(*embedded)); - dynarec_native_t* leaf = &embedded->dyn; - leaf->insts = &static_leafinsts[static_leafinst_count]; - memcpy(leaf->insts, decoded, scan.decoded_size * sizeof(decoded[0])); - memset(&leaf->insts[scan.decoded_size], 0, sizeof(leaf->insts[scan.decoded_size])); - leaf->size = scan.decoded_size; - leaf->cap = scan.decoded_size + 1; - leaf->start = target; - leaf->end = scan.decoded[scan.decoded_size - 1] + scan.decoded_len[scan.decoded_size - 1]; - leaf->isize = leaf->end - target; - leaf->env = GetCurEnvByAddr(target); - leaf->is_file_mapped = IsAddrElfOrFileMapped(target); - leaf->peeking_flags = 2; - leaf->inline_leaf = 1; - leaf->inline_is32bits = is32bits; - leaf->inline_rsp = scan.reads_rsp ? 0 : (scan.implicit_rsp ? (is32bits ? 4 : 8) : -(is32bits ? 4 : 8)); - leaf->instsize = static_leaf_instsize; - leaf->jmps = &static_leafjmps[static_leafdecoded_count]; - leaf->jmp_cap = scan.decoded_size; - - for (int i = 0; i < leaf->size; ++i) { - instruction_native_t* inst = &leaf->insts[i]; - inst->x64.size = scan.decoded_len[i]; - inst->x64.alive = 0; - inst->x64.jmp_insts = -1; - inst->pred = NULL; - inst->pred_sz = 0; - if (inst->x64.has_next) { - if (i + 1 >= leaf->size || inst->x64.addr + inst->x64.size != leaf->insts[i + 1].x64.addr) - return 0; - } - if (inst->x64.jmp) { - int target_inst = leaf_embedded_find(leaf->insts, leaf->size, inst->x64.jmp); - if (target_inst < 0) - return 0; - inst->x64.jmp_insts = target_inst; - inst->barrier_maybe = 0; - leaf->jmps[leaf->jmp_sz++] = i; - } - int isret = (inst->x64.leaf_kind == LEAF_KIND_RET); - if (isret) - inst->x64.need_after |= X_PEND; - } - leaf->insts[leaf->size].x64.addr = leaf->end; - - sizePredecessors(leaf); - int predecessor_count = 0; - for (int i = 0; i < leaf->size; ++i) - predecessor_count += leaf->insts[i].pred_sz; - if (static_leafpred_count + predecessor_count > (int)(sizeof(static_leafpreds) / sizeof(static_leafpreds[0]))) - return 0; - leaf->predecessor = &static_leafpreds[static_leafpred_count]; - fillPredecessors(leaf); - for (int i = 0; i < leaf->size; ++i) - if (!leaf->insts[i].x64.alive) - return 0; - - PREUPDATE_SPECIFICS(leaf); - int pos = leaf->size - 1; - while (pos >= 0) - pos = updateNeed(leaf, pos, 0); - updateUpperLiveness(leaf); - updateRspMerge(leaf, is32bits); - UPDATE_SPECIFICS(leaf); - - static_leafinst_count += leaf->size + 1; - static_leafdecoded_count += leaf->size; - static_leafpred_count += predecessor_count; - *embedded_id = ++static_leaf_embedded_count; - return 1; -} - -static void leaf_embedded_reset(dynarec_native_t* dyn) -{ - static_leaf_embedded_count = 0; - static_leafinst_count = 0; - static_leafdecoded_count = 0; - static_leafpred_count = 0; - memset(static_leaf_embeddeds, 0, sizeof(static_leaf_embeddeds)); - dyn->leaf_embeddeds = static_leaf_embeddeds; -} - -void* dynarec_get_leaf_embedded(void* owner, int ninst) -{ - dynarec_native_t* dyn = owner; - if (!dyn || !dyn->leaf_embeddeds || ninst < 0 || ninst >= dyn->size) - return NULL; - int embedded_id = dyn->insts[ninst].x64.leaf_embedded; - if (embedded_id <= 0 || embedded_id > static_leaf_embedded_count) - return NULL; - leaf_embedded_t* embeddeds = dyn->leaf_embeddeds; - return &embeddeds[embedded_id - 1].dyn; -} -#endif - #define PEEK_FLAGS_INSTS 16 typedef struct peek_flags_state_s { @@ -948,9 +607,6 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, helper.next_cap = MAX_INSTS; helper.table64 = NULL; helper.env = GetCurEnvByAddr(addr); - #ifdef HAVE_LEAFCALL - leaf_embedded_reset(&helper); - #endif if(prot&PROT_NEVERCLEAN) { helper.always_test = 1; } @@ -1031,33 +687,6 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, state = BUILD_ABORT_EMPTY; continue; } - #ifdef HAVE_LEAFCALL - if (BOX64DRENV(dynarec_callret) >= 3) { - for (int i = 0; i < helper.size; ++i) { - instruction_x64_t* inst = &helper.insts[i].x64; - if (inst->leaf_kind != LEAF_KIND_CALL) - continue; - uintptr_t target = inst->leaf_target; - uintptr_t continuation = inst->addr + inst->size; - uint8_t embedded_id = 0; - if (!target || !inst->has_next || i + 1 >= helper.size || helper.insts[i + 1].x64.addr != continuation || !leaf_embedded_build(target, continuation, is32bits, &embedded_id)) - inst->leaf_call = 0; - else - inst->leaf_embedded = embedded_id; - } - for (int i = 0; i < helper.size; ++i) - if (helper.insts[i].x64.leaf_call) - helper.insts[i].x64.barrier = BARRIER_FLOAT; - } else { - for (int i = 0; i < helper.size; ++i) { - helper.insts[i].x64.leaf_call = 0; - helper.insts[i].x64.leaf_embedded = 0; - helper.insts[i].x64.leaf_kind = LEAF_KIND_NONE; - helper.insts[i].x64.leaf_rsp = 0; - helper.insts[i].x64.leaf_target = 0; - } - } - #endif if(!is_inhotpage && !isprotectedDB(addr, 1)) { dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr); state = BUILD_ABORT_NULL; diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index 99453ee29..90c2917e5 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -119,11 +119,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int fpu_reset(dyn); ARCH_INIT(); int reset_n = -1; // -1 no reset; -2 reset to 0; else reset to the state of reset_n - #if defined(HAVE_LEAFCALL) - dyn->last_ip = (dyn->inline_leaf || alternate || (dyn->insts && dyn->insts[0].pred_sz)) ? 0 : ip; // RIP is always set at start of ordinary blocks unless there is a predecessor! - #else dyn->last_ip = (alternate || (dyn->insts && dyn->insts[0].pred_sz)) ? 0 : ip; // RIP is always set at start of block unless there is a predecessor! - #endif int stopblock = 2 + !dyn->is_file_mapped; // if block is in elf memory or file mapped memory, it can be extended with BOX64DRENV(dynarec_bigblock)==2, else it needs 3 // ok, go now INIT; @@ -131,10 +127,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int uintptr_t cur_page = ALIGN_DOWN(addr); #endif while(ok) { - #if STEP > 0 && defined(HAVE_LEAFCALL) - if (dyn->inline_leaf) - addr = dyn->insts[ninst].x64.addr; - #endif #if STEP == 0 int stop_for_guard = 0; if(cur_page != (ALIGN_DOWN(addr))) { @@ -169,7 +161,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int ip = addr; #ifdef ARM64 if(!ninst) { - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doEnterBlock(dyn, 0, x1, x2, x3); if(dyn->always_test) checkCRC(dyn, 0); @@ -179,7 +171,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int } #elif defined(LA64) if(!ninst) { - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doEnterBlock(dyn, 0, x1, x2, x3); if(dyn->always_test) checkCRC(dyn, 0); @@ -190,7 +182,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int } #elif defined(RV64) if(!ninst) { - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doEnterBlock(dyn, 0, x1, x2, x3); if (dyn->insts[0].preload_xmmymm) doPreload(dyn, 0); @@ -342,12 +334,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int return ip; INST_EPILOG; - #if STEP == 0 && defined(HAVE_LEAFCALL) - if (!dyn->peeking_flags && BOX64DRENV(dynarec_callret) >= 3 && dyn->insts[ninst].x64.leaf_kind == LEAF_KIND_CALL && dyn->insts[ninst].x64.leaf_target) { - dyn->insts[ninst].x64.leaf_call = 1; - } - #endif - #if STEP > 1 if (dyn->insts[ninst].lock) DMB_ISH(); @@ -580,60 +566,3 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d)\n", dyn->size); return addr; } - -#ifdef HAVE_LEAFCALL -void emit_inline_leaf(dynarec_native_t* parent, int parent_ninst) -{ - dynarec_native_t* leaf = dynarec_get_leaf_embedded(parent, parent_ninst); - if (!leaf) { - parent->abort = 1; - return; - } - - leaf->block = parent->block; - leaf->native_start = parent->native_start; - leaf->native_size = parent->native_size; - leaf->table64 = parent->table64; - leaf->table64size = parent->table64size; - leaf->table64cap = parent->table64cap; - leaf->tablestart = parent->tablestart; - leaf->jmp_next = parent->jmp_next; - leaf->dynablock = parent->dynablock; - leaf->callrets = parent->callrets; - leaf->callret_size = parent->callret_size; - leaf->need_dump = parent->need_dump; - leaf->need_reloc = parent->need_reloc; - leaf->relocs = parent->relocs; - leaf->reloc_size = parent->reloc_size; - leaf->inline_native_end = parent->insts[parent_ninst].mark[2]; - leaf->insts_size = 0; - leaf->abort = 0; - - size_t native_start = leaf->native_size; - native_pass(leaf, leaf->start, 0, leaf->inline_is32bits, leaf->size); - size_t native_delta = leaf->native_size - native_start; - - parent->block = leaf->block; - parent->native_size = leaf->native_size; - parent->table64size = leaf->table64size; - parent->callret_size = leaf->callret_size; - parent->reloc_size = leaf->reloc_size; - parent->abort |= leaf->abort; - - #if STEP == 1 - POSTUPDATE_SPECIFICS(leaf); - #elif STEP == 2 - parent->insts[parent_ninst].size += native_delta; - if (leaf->insts_size > LEAFCALL_INSTSIZE_SCRATCH) - parent->abort = 1; - #elif STEP == 3 - parent->insts[parent_ninst].size2 += native_delta; - for (int i = 0; i < leaf->size; ++i) { - if (!leaf->insts[i].x64.alive) - continue; - if (leaf->insts[i].size2 != leaf->insts[i].size) - parent->abort = 1; - } - #endif -} -#endif diff --git a/src/dynarec/dynarec_private.h b/src/dynarec/dynarec_private.h index bbd8e7350..86a44003c 100644 --- a/src/dynarec/dynarec_private.h +++ b/src/dynarec/dynarec_private.h @@ -36,12 +36,6 @@ #define NAT_FLAGS_FUSION 0 #define NAT_FLAGS_NOFUSION 1 -#define LEAF_KIND_NONE 0 -#define LEAF_KIND_CALL 1 -#define LEAF_KIND_RET 2 -#define LEAF_RSP_PUSHPOP 1 -#define LEAF_RSP_REF 2 - typedef struct instruction_x64_s { uintptr_t addr; //address of the instruction int32_t size; // size of the instruction @@ -50,7 +44,6 @@ typedef struct instruction_x64_s { uint8_t jmp_cond:1; // 1 of conditionnal jump uint8_t has_next:1; // does this opcode can continue to the next? uint8_t has_callret:1; // this instruction have an optimized call setup - uint8_t leaf_call:1; // direct call to a proven closed leaf body uint8_t alive:1; // this opcode gets executed (0 if dead code in that block) uint8_t self_loop:1; // this is a landing address for a self-loop (loop on itslef with no exit) uint8_t barrier; // next instruction is a jump point, so no optim allowed @@ -61,10 +54,6 @@ typedef struct instruction_x64_s { uint8_t gen_flags; // calculated uint8_t need_before;// calculated uint8_t need_after; // calculated - uint8_t leaf_embedded; - uint8_t leaf_kind; - uint8_t leaf_rsp; - uintptr_t leaf_target; uint8_t strongmem:3; // strongmem model at the opcode } instruction_x64_t; diff --git a/src/dynarec/la64/dynarec_la64_00_0.c b/src/dynarec/la64/dynarec_la64_00_0.c index 4bc033367..0ca58e983 100644 --- a/src/dynarec/la64/dynarec_la64_00_0.c +++ b/src/dynarec/la64/dynarec_la64_00_0.c @@ -105,7 +105,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int emit_add32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5, x6); break; case 0x06: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("PUSH ES"); LD_HU(x1, xEmu, offsetof(x64emu_t, segs[_ES])); @@ -126,7 +125,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0x07: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("POP ES"); SMREAD(); @@ -195,7 +193,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int emit_or32c(dyn, ninst, rex, xRAX, i64, x3, x4); break; case 0x0E: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("PUSH CS"); LD_HU(x1, xEmu, offsetof(x64emu_t, segs[_CS])); @@ -283,7 +280,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int emit_adc32(dyn, ninst, rex, xRAX, x1, x3, x4, x5, x6); break; case 0x16: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("PUSH SS"); LD_HU(x1, xEmu, offsetof(x64emu_t, segs[_SS])); @@ -304,7 +300,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0x17: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("POP SS"); SMREAD(); @@ -380,7 +375,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int emit_sbb32(dyn, ninst, rex, xRAX, x2, x3, x4, x5); break; case 0x1E: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("PUSH DS"); LD_HU(x1, xEmu, offsetof(x64emu_t, segs[_DS])); @@ -401,7 +395,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0x1F: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("POP DS"); SMREAD(); diff --git a/src/dynarec/la64/dynarec_la64_00_1.c b/src/dynarec/la64/dynarec_la64_00_1.c index 699718082..d1a562c3b 100644 --- a/src/dynarec/la64/dynarec_la64_00_1.c +++ b/src/dynarec/la64/dynarec_la64_00_1.c @@ -93,7 +93,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x56: case 0x57: INST_NAME("PUSH reg"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); SCRATCH_USAGE(0); gd = TO_NAT((opcode & 0x07) + (rex.b << 3)); MARKREGsz(gd); @@ -110,8 +109,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x5E: case 0x5F: INST_NAME("POP reg"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); - if (opcode == 0x5C) MARK_LEAF_RSP(LEAF_RSP_REF); SCRATCH_USAGE(0); SMREAD(); gd = TO_NAT((opcode & 0x07) + (rex.b << 3)); @@ -122,7 +119,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x60: if (rex.is32bits) { INST_NAME("PUSHAD"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); MV(x1, xRSP); PUSH1_32(xRAX); PUSH1_32(xRCX); @@ -150,7 +146,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x61: if (rex.is32bits) { INST_NAME("POPAD"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); SMREAD(); POP1_32(xRDI); POP1_32(xRSI); @@ -250,7 +245,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x68: INST_NAME("PUSH Id"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (!rex.is32bits) UP32_READ(xRSP); i64 = F32S; if (PK(0) == 0xC3) { @@ -320,7 +314,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x6A: INST_NAME("PUSH Ib"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (!rex.is32bits) UP32_READ(xRSP); i64 = F8S; if (!i64) { diff --git a/src/dynarec/la64/dynarec_la64_00_2.c b/src/dynarec/la64/dynarec_la64_00_2.c index bb1f1df6b..553470554 100644 --- a/src/dynarec/la64/dynarec_la64_00_2.c +++ b/src/dynarec/la64/dynarec_la64_00_2.c @@ -605,7 +605,6 @@ uintptr_t dynarec64_00_2(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int switch ((nextop >> 3) & 7) { case 0: INST_NAME("POP Ed"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); SMREAD(); MARKREGsdz(xRSP); if (MODREG) { @@ -679,7 +678,6 @@ uintptr_t dynarec64_00_2(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0x9A: - MARK_LEAF_CALL(); if (rex.is32bits) { DEFAULT; } else { @@ -716,7 +714,6 @@ uintptr_t dynarec64_00_2(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x9C: INST_NAME("PUSHF"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); READFLAGS(X_ALL); RESTORE_EFLAGS(x1); if (!rex.is32bits) UP32_READ(xRSP); @@ -724,7 +721,6 @@ uintptr_t dynarec64_00_2(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x9D: INST_NAME("POPF"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); if (!rex.is32bits) UP32_READ(xRSP); POP1z(xFlags); diff --git a/src/dynarec/la64/dynarec_la64_00_3.c b/src/dynarec/la64/dynarec_la64_00_3.c index 6e1bc44d3..caddad588 100644 --- a/src/dynarec/la64/dynarec_la64_00_3.c +++ b/src/dynarec/la64/dynarec_la64_00_3.c @@ -346,64 +346,32 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xC2: INST_NAME("RETN"); - MARK_LEAF_RET(); if (BOX64DRENV(dynarec_safeflags)) { READFLAGS(X_PEND); // lets play safe here too } BARRIER(BARRIER_FLOAT); u16 = F16; if (!rex.is32bits) UP32_READ(xRSP); - if (dyn->inline_leaf) { - if (dyn->inline_rsp >= 0) - ADDIz(xRSP, xRSP, rex.is32bits ? 4 : 8); - } else { - POP1z(xRIP); - } + POP1z(xRIP); if (u16 < 2048) ADDIz(xRSP, xRSP, u16); else { MOV32w(x1, u16); ADDz(xRSP, xRSP, x1); } - if (dyn->inline_leaf) { - SMEND(); - CHECK_DFNONE(0); - if (ninst + 1 < dyn->size) { - j64 = dyn->inline_native_end - dyn->native_size; - B(j64); - } - CLEARIP(); - } else { - ret_to_next(dyn, ip, ninst, rex); - } + ret_to_next(dyn, ip, ninst, rex); *need_epilog = 0; *ok = 0; break; case 0xC3: INST_NAME("RET"); - MARK_LEAF_RET(); if (BOX64DRENV(dynarec_safeflags)) { READFLAGS(X_PEND); // so instead, force the deferred flags, so it's not too slow, and flags are not lost } BARRIER(BARRIER_FLOAT); if (!rex.is32bits) UP32_READ(xRSP); - if (dyn->inline_leaf) { - if (dyn->inline_rsp >= 0) - ADDIz(xRSP, xRSP, rex.is32bits ? 4 : 8); - } else { - POP1z(xRIP); - } - if (dyn->inline_leaf) { - SMEND(); - CHECK_DFNONE(0); - if (ninst + 1 < dyn->size) { - j64 = dyn->inline_native_end - dyn->native_size; - B(j64); - } - CLEARIP(); - } else { - ret_to_next(dyn, ip, ninst, rex); - } + POP1z(xRIP); + ret_to_next(dyn, ip, ninst, rex); *need_epilog = 0; *ok = 0; break; @@ -517,7 +485,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xC8: INST_NAME("ENTER Iw,Ib"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); u16 = F16; u8 = (F8) & 0x1f; if (!rex.is32bits) { @@ -546,7 +513,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xC9: INST_NAME("LEAVE"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); MARKREGsz(xRBP); MVz(xRSP, xRBP); POP1z(xRBP); @@ -1323,7 +1289,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xE8: INST_NAME("CALL Id"); i32 = (rex.is32bits && rex.is66) ? F16S : F32S; - MARK_LEAF_CALL(); if (addr + i32 == 0) { #if STEP == 3 printf_log(LOG_INFO, "Warning, CALL to 0x0 at %p (%p)\n", (void*)addr, (void*)(addr - 1)); @@ -1431,32 +1396,12 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } // regular call BARRIER(BARRIER_FLOAT); - int leaf_call = dyn->insts[ninst].x64.leaf_call && - dyn->insts[ninst].x64.leaf_embedded && - BOX64DRENV(dynarec_callret) >= 3; - dynarec_la64_t* leaf_embedded = leaf_call ? dynarec_get_leaf_embedded(dyn, ninst) : NULL; - if (!leaf_embedded) - leaf_call = 0; - uintptr_t leaf_target = rex.is32bits ? (uint32_t)(addr + i32) : addr + i32; - MARK_LEAF_CALL_TARGET(leaf_target); - if (!leaf_call || !leaf_embedded->inline_rsp) { - if (dyn->need_reloc) { - TABLE64(x2, addr); - } else { - MOV64x(x2, addr); - } - PUSH1z(x2); - } else if (leaf_embedded->inline_rsp > 0) { - ADDIz(xRSP, xRSP, -leaf_embedded->inline_rsp); - } - if (leaf_call) { - SET_HASCALLRET(); - MESSAGE(LOG_DUMP, "Embedded leaf call:\n"); - emit_inline_leaf(dyn, ninst); - MARK3; - CLEARIP(); - break; + if (dyn->need_reloc) { + TABLE64(x2, addr); + } else { + MOV64x(x2, addr); } + PUSH1z(x2); int can_continue = (addr < (dyn->start + dyn->isize)); if (BOX64DRENV(dynarec_callret)) { SET_HASCALLRET(); @@ -1475,7 +1420,7 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int *ok = 0; *need_epilog = 0; } - j64 = leaf_target; + j64 = rex.is32bits ? (uint32_t)(addr + i32) : addr + i32; j64 = (uintptr_t)getAlternate((void*)j64); jump_to_next(dyn, j64, 0, ninst, rex.is32bits); CALLRET_RET(can_continue); @@ -2147,7 +2092,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 2: INST_NAME("CALL Ed"); - MARK_LEAF_CALL(); PASS2IF ((BOX64DRENV(dynarec_safeflags) > 1) || ((ninst && dyn->insts[ninst - 1].x64.set_flags) || ((ninst > 1) && dyn->insts[ninst - 2].x64.set_flags)), 1) { READFLAGS(X_PEND); // that's suspicious } else { @@ -2200,7 +2144,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int CLEARIP(); break; case 3: // CALL FAR Ed - MARK_LEAF_CALL(); if (MODREG) { DEFAULT; } else { @@ -2295,7 +2238,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 6: // Push Ed INST_NAME("PUSH Ed"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (!rex.is32bits) UP32_READ(xRSP); GETEDz(0); PUSH1z(ed); diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c index 93223c7e3..c10c0aa32 100644 --- a/src/dynarec/la64/dynarec_la64_0f.c +++ b/src/dynarec/la64/dynarec_la64_0f.c @@ -1669,13 +1669,11 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni #undef GO case 0xA0: INST_NAME("PUSH FS"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); LD_HU(x2, xEmu, offsetof(x64emu_t, segs[_FS])); PUSH1z(x2); break; case 0xA1: INST_NAME("POP FS"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); POP1z(x2); ST_H(x2, xEmu, offsetof(x64emu_t, segs[_FS])); CBZ_NEXT(x2); @@ -1754,13 +1752,11 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0xA8: INST_NAME("PUSH GS"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); LD_HU(x2, xEmu, offsetof(x64emu_t, segs[_GS])); PUSH1z(x2); break; case 0xA9: INST_NAME("POP GS"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); POP1z(x2); ST_H(x2, xEmu, offsetof(x64emu_t, segs[_GS])); CBZ_NEXT(x2); diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c index 73c2af5ff..65d1c2922 100644 --- a/src/dynarec/la64/dynarec_la64_helper.c +++ b/src/dynarec/la64/dynarec_la64_helper.c @@ -48,7 +48,6 @@ uintptr_t geted(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, if ((nextop & 7) == 4) { uint8_t sib = PK(0); - if ((sib & 7) == 4) MARK_LEAF_RSP(LEAF_RSP_REF); if (((sib & 7) != 5) || ((nextop & 0xC0) != 0)) UP32_READ(TO_NAT((sib & 7) + (rex.b << 3))); if ((((sib >> 3) & 7) + (rex.x << 3)) != 4) UP32_READ(TO_NAT(((sib >> 3) & 7) + (rex.x << 3))); } else if (((nextop & 7) != 5) || ((nextop & 0xC0) != 0)) { @@ -379,7 +378,7 @@ void jump_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog); SMEND(); CHECK_DFNONE(0); - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); BR(x2); } @@ -401,7 +400,7 @@ void jump_to_epilog_fast(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog_fast); SMEND(); CHECK_DFNONE(0); - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); BR(x2); } @@ -489,7 +488,7 @@ void jump_to_next(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 } CLEARIP(); SMEND(); - if (BOX64DRENV(dynarec_callret) >= 2 && !dyn->insts[ninst].x64.has_callret) + if (BOX64DRENV(dynarec_callret) >= 3 && !dyn->insts[ninst].x64.has_callret) doLeaveBlock(dyn, ninst, x4, x5, x6); // The JIRL(xRA, ...) form is only for gdb backtraces, but it breaks the // return-address-stack prediction on every block-to-block jump, which is @@ -514,7 +513,7 @@ void ret_to_next(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex) LD_D(xRA, xSP, 0); // native addr LD_D(x6, xSP, 8); // x86 addr ADDI_D(xSP, xSP, 16); // pop - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x7); BNE(x6, xRIP, 2 * 4); // is it the right address? BR(xRA); diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index cb26fd31b..511e30f8f 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -435,8 +435,6 @@ static inline int comis_fuse_inverted(int condition) #define MARKREGd(r) \ do { \ - if ((r) == xRSP) \ - MARK_LEAF_RSP(LEAF_RSP_REF); \ if (rex.w) \ UP32_WRITE64(r); \ else \ @@ -445,8 +443,6 @@ static inline int comis_fuse_inverted(int condition) #define MARKREGdz(r) \ do { \ - if ((r) == xRSP) \ - MARK_LEAF_RSP(LEAF_RSP_REF); \ if (!rex.is32bits) \ UP32_WRITE64(r); \ else \ @@ -455,15 +451,11 @@ static inline int comis_fuse_inverted(int condition) #define MARKREGs(r) \ do { \ - if ((r) == xRSP) \ - MARK_LEAF_RSP(LEAF_RSP_REF); \ if (rex.w) UP32_READ(r); \ } while (0) #define MARKREGsz(r) \ do { \ - if ((r) == xRSP) \ - MARK_LEAF_RSP(LEAF_RSP_REF); \ if (!rex.is32bits) UP32_READ(r); \ } while (0) @@ -1667,26 +1659,6 @@ static inline int comis_fuse_inverted(int condition) #ifndef SET_HASCALLRET #define SET_HASCALLRET() #endif -#ifndef MARK_LEAF_CALL -#define MARK_LEAF_CALL() \ - do { \ - } while (0) -#endif -#ifndef MARK_LEAF_CALL_TARGET -#define MARK_LEAF_CALL_TARGET(T) \ - do { \ - } while (0) -#endif -#ifndef MARK_LEAF_RET -#define MARK_LEAF_RET() \ - do { \ - } while (0) -#endif -#ifndef MARK_LEAF_RSP -#define MARK_LEAF_RSP(F) \ - do { \ - } while (0) -#endif #ifndef CALLRET_RET #define CALLRET_RET(A) do {if(BOX64DRENV(dynarec_callret)>1) {NOP();}} while(0) #endif @@ -1798,9 +1770,6 @@ static inline int comis_fuse_inverted(int condition) #define native_pass STEPNAME(native_pass) #define updateflags_pass STEPNAME(updateflags_pass) -#define emit_inline_leaf STEPNAME(emit_inline_leaf) -void emit_inline_leaf(dynarec_la64_t* dyn, int ninst); - #define dynarec64_00 STEPNAME(dynarec64_00) #define dynarec64_00_0 STEPNAME(dynarec64_00_0) #define dynarec64_00_1 STEPNAME(dynarec64_00_1) diff --git a/src/dynarec/la64/dynarec_la64_pass0.h b/src/dynarec/la64/dynarec_la64_pass0.h index 9c34c057f..e0e13e6d8 100644 --- a/src/dynarec/la64/dynarec_la64_pass0.h +++ b/src/dynarec/la64/dynarec_la64_pass0.h @@ -70,14 +70,6 @@ } else \ dyn->insts[ninst].barrier_maybe = 1 #define SET_HASCALLRET() dyn->insts[ninst].x64.has_callret = 1 -#define MARK_LEAF_CALL() dyn->insts[ninst].x64.leaf_kind = LEAF_KIND_CALL -#define MARK_LEAF_CALL_TARGET(T) \ - do { \ - dyn->insts[ninst].x64.leaf_kind = LEAF_KIND_CALL; \ - dyn->insts[ninst].x64.leaf_target = (uintptr_t)(T); \ - } while (0) -#define MARK_LEAF_RET() dyn->insts[ninst].x64.leaf_kind = LEAF_KIND_RET -#define MARK_LEAF_RSP(F) dyn->insts[ninst].x64.leaf_rsp |= (F) #define NEW_INST \ ++dyn->size; \ dyn->insts[ninst].x64.addr = ip; \ diff --git a/src/dynarec/la64/dynarec_la64_pass2.h b/src/dynarec/la64/dynarec_la64_pass2.h index 0223e2cbd..c5d4ebeb4 100644 --- a/src/dynarec/la64/dynarec_la64_pass2.h +++ b/src/dynarec/la64/dynarec_la64_pass2.h @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT #define INIT \ do { \ - if (!dyn->inline_leaf) \ - dyn->native_size = 0; \ + dyn->native_size = 0; \ } while (0) #define ENDPREFIX \ dyn->prefixsize = dyn->native_size; \ diff --git a/src/dynarec/la64/dynarec_la64_private.h b/src/dynarec/la64/dynarec_la64_private.h index c9721df92..933dec490 100644 --- a/src/dynarec/la64/dynarec_la64_private.h +++ b/src/dynarec/la64/dynarec_la64_private.h @@ -214,9 +214,6 @@ typedef struct dynarec_la64_s { size_t insts_size; // size of the instruction size array (calculated) int callret_size; // size of the array callret_t* callrets; // array of callret return, with NOP / UDF depending if the block is clean or dirty - void* leaf_embeddeds; - uintptr_t inline_native_end; - int16_t inline_rsp; uintptr_t forward; // address of the last end of code while testing forward uintptr_t forward_to; // address of the next jump to (to check if everything is ok) int32_t forward_size; // size at the forward point @@ -231,8 +228,6 @@ typedef struct dynarec_la64_s { uint8_t use_ymm:1; uint8_t no_scalar_renaming:1; uint8_t is_file_mapped:1; - uint8_t inline_leaf:1; - uint8_t inline_is32bits:1; void* gdbjit_block; uint32_t need_x87check; // x87 low precision check int x87round_active; // we are in the middle of x87_setround and x87_restoreround diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 077b9ba6a..66ae83167 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -407,7 +407,7 @@ void jump_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog); SMEND(); CHECK_DFNONE(0); - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); BR(x2); } @@ -429,7 +429,7 @@ void jump_to_epilog_fast(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog_fast); SMEND(); CHECK_DFNONE(0); - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); BR(x2); } @@ -539,7 +539,7 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 } CLEARIP(); SMEND(); - if (BOX64DRENV(dynarec_callret) >= 2 && !dyn->insts[ninst].x64.has_callret) + if (BOX64DRENV(dynarec_callret) >= 3 && !dyn->insts[ninst].x64.has_callret) doLeaveBlock(dyn, ninst, x4, x5, x6); // #ifdef HAVE_TRACE // The JALR(xRA, ...) form is only for gdb backtraces, but it breaks the @@ -564,7 +564,7 @@ void ret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex) LD(xRA, xSP, 0); // native addr LD(x6, xSP, 8); // x86 addr ADDI(xSP, xSP, 16); // pop - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x7); BNE(x6, xRIP, 2 * 4); // is it the right address? BR(xRA); diff --git a/src/include/dynarec_native.h b/src/include/dynarec_native.h index dcf9ca1f3..c7ff8f5dc 100644 --- a/src/include/dynarec_native.h +++ b/src/include/dynarec_native.h @@ -7,12 +7,9 @@ typedef struct x64emu_s x64emu_t; typedef struct instsize_s instsize_t; #define MAX_INSTS 32760 -#define LEAFCALL_INSTSIZE_SCRATCH 32768 void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size); -void* dynarec_get_leaf_embedded(void* owner, int ninst); - void CancelBlock64(int need_lock); dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, int noalt); diff --git a/src/tools/env.c b/src/tools/env.c index 37e3caa4f..38f74625c 100644 --- a/src/tools/env.c +++ b/src/tools/env.c @@ -238,6 +238,7 @@ static void applyCustomRules() SET_BOX64ENV_IF_EMPTY(dynarec_bigblock, 0); SET_BOX64ENV_IF_EMPTY(dynarec_safeflags, 2); SET_BOX64ENV_IF_EMPTY(dynarec_strongmem, 2); + SET_BOX64ENV_IF_EMPTY(dynarec_callret, 3); } else if (!strcasecmp(box64env.profile, "safe")) { SET_BOX64ENV_IF_EMPTY(dynarec_bigblock, 0); SET_BOX64ENV_IF_EMPTY(dynarec_safeflags, 2); From 4b7d2eaabe5888b6ab216a27434aa69699b30c94 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 27 Oct 2026 15:09:29 +0800 Subject: [PATCH 087/156] [RV64_DYNAREC] Remove redundant vsetvli from scalar AVX prolog (#4611) --- src/dynarec/rv64/dynarec_rv64_helper.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index b6beb8d53..be7cb399b 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1690,11 +1690,7 @@ q1 = VREG(ed); \ avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, (SEW)); \ } else { \ - q1 = fpu_get_scratch(dyn); \ - SMREAD(); \ - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, (D)); \ - avx_set_vector_width(dyn, ninst, x1, (SEW), 1 << (SEW)); \ - VLE_V(q1, ed, (SEW), VECTOR_UNMASKED, VECTOR_NFIELD1); \ + q1 = -1; \ } \ GETGY_empty_vector(v0); \ if (v0 != q0) { \ @@ -1707,6 +1703,13 @@ avx_set_vector_width(dyn, ninst, x1, (SEW), 16); \ VMV_V_V(v0, q0); \ } \ + if (!MODREG) { \ + q1 = fpu_get_scratch(dyn); \ + SMREAD(); \ + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, (D)); \ + avx_set_vector_width(dyn, ninst, x1, (SEW), 1 << (SEW)); \ + VLE_V(q1, ed, (SEW), VECTOR_UNMASKED, VECTOR_NFIELD1); \ + } \ SET_SCALAR_FP_WIDTH(x1, (SEW)); \ } while (0) From 63ed07ac8370f373a2349e387e5d7d19be5b0777 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 27 Oct 2026 15:10:18 +0800 Subject: [PATCH 088/156] [RV64_DYNAREC] Store VMOVSS directly from the vector register (#4612) --- src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c index c25557a6c..eb419a61a 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c @@ -74,7 +74,7 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt INST_NAME("VMOVSS Ex, [Vx,] Gx"); nextop = F8; gd = ((nextop & 0x38) >> 3) + (rex.r << 3); - q0 = fpu_get_scratch(dyn); + q0 = VREG(gd); avx_load_reg_vector(dyn, ninst, x1, q0, gd, 16, VECTOR_SEW32); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); @@ -85,8 +85,8 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt avx_store_reg_vector(dyn, ninst, x1, q2, ed, 16, VECTOR_SEW32); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - VFMV_F_S(d0 = fpu_get_scratch(dyn), q0); - FSW(d0, ed, fixedaddress); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VSE32_V(q0, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); SMWRITE2(); } break; From 11a20e37c8f5996dfcd3b1f247a9b273e56ad189 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 27 Oct 2026 15:26:44 +0800 Subject: [PATCH 089/156] [RV64_DYNAREC] Emit scalar AVX FMA with vl=1 (#4613) --- .../rv64/dynarec_rv64_avx_66_0f38_vector.c | 232 +++++++----------- 1 file changed, 92 insertions(+), 140 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c index df7c49fb2..46536dd07 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c @@ -1382,15 +1382,13 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFNMADD213Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - q3 = fpu_get_scratch(dyn); - VMV_V_V(q3, q2); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1403,25 +1401,22 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint } q4 = fpu_get_scratch(dyn); VMV_V_V(q4, q1); - VFNMSAC_VV(q4, q0, q3, VECTOR_UNMASKED); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1, x4, 1); - VMERGE_VVM(v0, q3, q4); - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFNMSAC_VV(q4, q0, q2, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0xB9: INST_NAME("VFMADD231Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - q3 = fpu_get_scratch(dyn); - VMV_V_V(q3, q2); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1432,27 +1427,21 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - q4 = fpu_get_scratch(dyn); - VMV_V_V(q4, q3); - VFMACC_VV(q4, q0, q1, VECTOR_UNMASKED); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1, x4, 1); - VMERGE_VVM(v0, q3, q4); - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFMACC_VV(q2, q0, q1, VECTOR_UNMASKED); + PUTGY_vector(q2, sew); break; case 0x99: INST_NAME("VFMADD132Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - q3 = fpu_get_scratch(dyn); - VMV_V_V(q3, q2); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1465,25 +1454,22 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint } q4 = fpu_get_scratch(dyn); VMV_V_V(q4, q0); - VFMACC_VV(q4, q3, q1, VECTOR_UNMASKED); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1, x4, 1); - VMERGE_VVM(v0, q3, q4); - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFMACC_VV(q4, q2, q1, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0x9B: INST_NAME("VFMSUB132Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - q3 = fpu_get_scratch(dyn); - VMV_V_V(q3, q2); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1496,25 +1482,22 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint } q4 = fpu_get_scratch(dyn); VMV_V_V(q4, q0); - VFMSAC_VV(q4, q3, q1, VECTOR_UNMASKED); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1, x4, 1); - VMERGE_VVM(v0, q3, q4); - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFMSAC_VV(q4, q2, q1, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0x9D: INST_NAME("VFNMADD132Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - q3 = fpu_get_scratch(dyn); - VMV_V_V(q3, q2); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1527,25 +1510,22 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint } q4 = fpu_get_scratch(dyn); VMV_V_V(q4, q0); - VFNMSAC_VV(q4, q3, q1, VECTOR_UNMASKED); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1, x4, 1); - VMERGE_VVM(v0, q3, q4); - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFNMSAC_VV(q4, q2, q1, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0x9F: INST_NAME("VFNMSUB132Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - q3 = fpu_get_scratch(dyn); - VMV_V_V(q3, q2); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1558,25 +1538,22 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint } q4 = fpu_get_scratch(dyn); VMV_V_V(q4, q0); - VFNMACC_VV(q4, q3, q1, VECTOR_UNMASKED); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1, x4, 1); - VMERGE_VVM(v0, q3, q4); - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFNMACC_VV(q4, q2, q1, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0xA9: INST_NAME("VFMADD213Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - q3 = fpu_get_scratch(dyn); - VMV_V_V(q3, q2); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1589,25 +1566,22 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint } q4 = fpu_get_scratch(dyn); VMV_V_V(q4, q1); - VFMACC_VV(q4, q0, q3, VECTOR_UNMASKED); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1, x4, 1); - VMERGE_VVM(v0, q3, q4); - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFMACC_VV(q4, q0, q2, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0xAB: INST_NAME("VFMSUB213Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - q3 = fpu_get_scratch(dyn); - VMV_V_V(q3, q2); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1620,25 +1594,22 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint } q4 = fpu_get_scratch(dyn); VMV_V_V(q4, q1); - VFMSAC_VV(q4, q0, q3, VECTOR_UNMASKED); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1, x4, 1); - VMERGE_VVM(v0, q3, q4); - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFMSAC_VV(q4, q0, q2, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0xAF: INST_NAME("VFNMSUB213Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - q3 = fpu_get_scratch(dyn); - VMV_V_V(q3, q2); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1651,25 +1622,22 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint } q4 = fpu_get_scratch(dyn); VMV_V_V(q4, q1); - VFNMACC_VV(q4, q0, q3, VECTOR_UNMASKED); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1, x4, 1); - VMERGE_VVM(v0, q3, q4); - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFNMACC_VV(q4, q0, q2, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0xBB: INST_NAME("VFMSUB231Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - q3 = fpu_get_scratch(dyn); - VMV_V_V(q3, q2); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1680,27 +1648,21 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - q4 = fpu_get_scratch(dyn); - VMV_V_V(q4, q3); - VFMSAC_VV(q4, q0, q1, VECTOR_UNMASKED); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1, x4, 1); - VMERGE_VVM(v0, q3, q4); - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFMSAC_VV(q2, q0, q1, VECTOR_UNMASKED); + PUTGY_vector(q2, sew); break; case 0xBD: INST_NAME("VFNMADD231Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - q3 = fpu_get_scratch(dyn); - VMV_V_V(q3, q2); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1711,27 +1673,21 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - q4 = fpu_get_scratch(dyn); - VMV_V_V(q4, q3); - VFNMSAC_VV(q4, q0, q1, VECTOR_UNMASKED); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1, x4, 1); - VMERGE_VVM(v0, q3, q4); - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFNMSAC_VV(q2, q0, q1, VECTOR_UNMASKED); + PUTGY_vector(q2, sew); break; case 0xBF: INST_NAME("VFNMSUB231Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - q3 = fpu_get_scratch(dyn); - VMV_V_V(q3, q2); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1742,13 +1698,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - q4 = fpu_get_scratch(dyn); - VMV_V_V(q4, q3); - VFNMACC_VV(q4, q0, q1, VECTOR_UNMASKED); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1, x4, 1); - VMERGE_VVM(v0, q3, q4); - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFNMACC_VV(q2, q0, q1, VECTOR_UNMASKED); + PUTGY_vector(q2, sew); break; case 0xF7: INST_NAME("SHLX Gd, Ed, Vd"); From 9cb238fd92131faf3ce30f08fd46a7838a6eca16 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 28 Oct 2026 17:05:46 +0800 Subject: [PATCH 090/156] [RV64_DYNAREC] Fixed missing read tracking in AVX register loads (#4614) --- src/dynarec/rv64/dynarec_rv64_helper.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 66ae83167..099dea4e2 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -3053,6 +3053,8 @@ void avx_set_vector_width(dynarec_rv64_t* dyn, int ninst, int s1, int sew, int w void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew) { sse_mark_used(dyn, ninst, a); + if (ninst >= 0 && ninst < dyn->size) + dyn->insts[ninst].vec_read |= 1u << a; if (width == 32 && cpuext.vlen >= 32) ymm_live_read(dyn, ninst, a); if (dyn->e.ssecache[a].v != -1 && dyn->e.ssecache[a].vector && (width != 32 || dyn->e.ssecache[a].ymm)) { From 13f5aea7d26e16248c1dcf145283a8c0aadca20a Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 28 Oct 2026 17:06:48 +0800 Subject: [PATCH 091/156] [RV64_DYNAREC] Fixed vtype tracking across cache transforms (#4615) --- src/dynarec/rv64/dynarec_rv64_helper.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 099dea4e2..f30187aee 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -2788,12 +2788,18 @@ static void sewTransform(dynarec_rv64_t* dyn, int ninst, int s1) void CacheTransform(dynarec_rv64_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3) { + uint8_t sew = dyn->inst_sew; + uint8_t vlmul = dyn->inst_vlmul; + uint8_t vl = dyn->inst_vl; if (cacheupd & 2) fpuCacheTransform(dyn, ninst, s1, s2, s3); if (cacheupd & 1) flagsCacheTransform(dyn, ninst, s1); if (cacheupd & 4) sewTransform(dyn, ninst, s1); + dyn->inst_sew = sew; + dyn->inst_vlmul = vlmul; + dyn->inst_vl = vl; } From 61bbb76bdc801bed3551b180ec57e3a3c66c4568 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 28 Oct 2026 17:10:29 +0800 Subject: [PATCH 092/156] [RV64_DYNAREC] Fixed displacement range for some opcodes (#4616) --- src/dynarec/rv64/dynarec_rv64_660f.c | 2 +- src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c | 2 +- src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index 0edaa94ca..87cb99f65 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -764,7 +764,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SB(x3, gback, gdoffset + 2 * i + 1); } } else { - GETEX(x2, 0, 7); + GETEX(x2, 0, 15); for (int i = 0; i < 8; ++i) { // GX->ub[2 * i + 1] = EX->ub[i + 8]; LBU(x3, wback, fixedaddress + i + 8); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c index 561a79446..d8799e5e9 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c @@ -946,7 +946,7 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0x42: INST_NAME("VMPSADBW Gx, Vx, Ex, Ib"); nextop = F8; - GETEX(x2, 1, vex.l ? 28 : 12); + GETEX(x2, 1, 22); GETVX(); GETVY(); GETGX(); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c index 73c9b2052..c43bd4768 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c @@ -586,7 +586,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0x7D: INST_NAME("VHSUBPS Gx, Vx, Ex"); nextop = F8; - GETEX(x2, 0, vex.l ? 24 : 8); + GETEX(x2, 0, vex.l ? 28 : 12); GETGX(); GETGY(); GETVX(); @@ -769,7 +769,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0x7C: INST_NAME("VHADDPS Gx, Vx, Ex"); nextop = F8; - GETEX(x2, 0, vex.l ? 24 : 8); + GETEX(x2, 0, vex.l ? 28 : 12); GETGX(); GETGY(); GETVX(); From c4eb274b9adadec4064f094ba2b3fa874628e891 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 28 Oct 2026 17:12:03 +0800 Subject: [PATCH 093/156] [RV64_DYNAREC] Fixed extcache initialization for preloaded registers (#4617) --- src/dynarec/rv64/dynarec_rv64_functions.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index 70790aa5d..88ec685c3 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -986,6 +986,8 @@ static void applyPreloadState(dynarec_rv64_t* dyn, int first, int first_use, int s->ymm = 0; s->ymm0 = (e->ymm0 >> reg) & 1; e->fpuused[EXTIDX(VREG(reg))] = 1; + e->extcache[EXTIDX(VREG(reg))].n = reg; + e->extcache[EXTIDX(VREG(reg))].y = 0; sse_sync_cache_type(e, reg); } } From 78217d33fec3e3a51821c42a2a6755091a95b848 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 28 Oct 2026 17:13:02 +0800 Subject: [PATCH 094/156] [RV64_DYNAREC] Reset vtype tracking at block start and reset (#4618) --- src/dynarec/rv64/dynarec_rv64_helper.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index be7cb399b..65a5d3812 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1605,10 +1605,16 @@ #define ARCH_INIT() \ SMSTART(); \ dyn->vector_sew = VECTOR_SEWNA; \ + dyn->inst_sew = VECTOR_SEWNA; \ + dyn->inst_vlmul = VECTOR_LMUL1; \ + dyn->inst_vl = 0; \ dyn->e.ymm0 = 0; -#define ARCH_RESET() \ - dyn->vector_sew = VECTOR_SEWNA; +#define ARCH_RESET() \ + dyn->vector_sew = VECTOR_SEWNA; \ + dyn->inst_sew = VECTOR_SEWNA; \ + dyn->inst_vlmul = VECTOR_LMUL1; \ + dyn->inst_vl = 0; #if STEP < 2 #define GETIP(A, scratch) From 4c6be6cb2353f5de267ecfd0f3efa32b9b497bf2 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 28 Oct 2026 17:28:16 +0800 Subject: [PATCH 095/156] [RV64_DYNAREC] Kept pending YMM zero mask on local purges (#4619) --- src/dynarec/rv64/dynarec_rv64_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index f30187aee..24fc15e5c 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -1964,7 +1964,7 @@ static void sse_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1) if (flushed8) vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); dyn->purge_dead_vector = 0; - dyn->e.ymm0 &= ~zeroed; + if (!next) dyn->e.ymm0 &= ~zeroed; avx_flush_pending_zero_vector(dyn, ninst, s1, next); if (old != -1) { MESSAGE(LOG_DUMP, "\t------ Purge SSE Cache\n"); From ec2f98e95a1768e54ab8c2067e3452744942c37c Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 28 Oct 2026 17:39:14 +0800 Subject: [PATCH 096/156] [RV64_DYNAREC] Fixed up32 handling in some opcodes (#4620) --- src/dynarec/rv64/dynarec_rv64_0f.c | 5 +++++ src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c | 1 + src/dynarec/rv64/dynarec_rv64_avx_f2_0f38.c | 1 + src/dynarec/rv64/dynarec_rv64_emit_shift.c | 4 ++-- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index ab6229c92..785616a60 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -2495,6 +2495,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); MARKREGsd(ed); + UP32_READ(ed); MVxw(x1, ed); wback = 0; } else { @@ -3013,6 +3014,10 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 1: if (rex.w) { INST_NAME("CMPXCHG16B Gq, Eq"); + MARKREGsd(xRAX); + MARKREGsd(xRDX); + MARKREGs(xRBX); + MARKREGs(xRCX); SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION); SET_DFNONE(); SMREAD(); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c index e86d6710a..a488ab6d2 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c @@ -746,6 +746,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, rex.w ? VECTOR_SEW64 : VECTOR_SEW32); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGs(ed); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 1); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f38.c index aad73d8fe..d455740ae 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f38.c @@ -98,6 +98,7 @@ uintptr_t dynarec64_AVX_F2_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETED(0); GETVD; if (rex.w) { + MARKREGs(xRDX); if ((gd == xRDX) || (gd == ed) || (gd == vd)) gb1 = x3; else diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c index ea3a1fb2f..14df60e87 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c @@ -1566,7 +1566,7 @@ void emit_rcl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s { int64_t j64; SET_DFNONE(); - UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); + UP32_WRITE32(s1); if (!rex.w) ZEROUP_RESULT(s1); IFX (X_OF) { ANDI(xFlags, xFlags, ~(1UL << F_OF2)); @@ -1614,7 +1614,7 @@ void emit_rcr32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s { int64_t j64; SET_DFNONE(); - UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); + UP32_WRITE32(s1); if (!rex.w) ZEROUP_RESULT(s1); IFX (X_OF) { ANDI(xFlags, xFlags, ~(1UL << F_OF2)); From 2da641175cc2525f98f14b71427b914312184173 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 28 Oct 2026 17:40:33 +0800 Subject: [PATCH 097/156] [RV64_DYNAREC] Fixed vtype restore skipped by epilog branches (#4621) --- src/dynarec/rv64/dynarec_rv64_avx.c | 12 ++++++------ src/dynarec/rv64/dynarec_rv64_functions.c | 1 + src/dynarec/rv64/dynarec_rv64_pass0.h | 1 + src/dynarec/rv64/dynarec_rv64_pass1.h | 1 + src/dynarec/rv64/dynarec_rv64_pass2.h | 4 ++++ src/dynarec/rv64/dynarec_rv64_pass3.h | 6 +++++- src/dynarec/rv64/dynarec_rv64_private.h | 1 + 7 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_avx.c b/src/dynarec/rv64/dynarec_rv64_avx.c index e34ef3f14..d2bbd7834 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx.c +++ b/src/dynarec/rv64/dynarec_rv64_avx.c @@ -56,7 +56,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n retaddr = dynarec64_AVX_0F_vector(dyn, addr, ip, ninst, vex, ok, need_epilog); if (retaddr) { if (dyn->vector_sew != VECTOR_SEWNA) - avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); + dyn->vtype_restore = dyn->vector_sew; } else { addr = vaddr; BARRIER(BARRIER_FLOAT); @@ -70,7 +70,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n retaddr = dynarec64_AVX_66_0F_vector(dyn, addr, ip, ninst, vex, ok, need_epilog); if (retaddr) { if (dyn->vector_sew != VECTOR_SEWNA) - avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); + dyn->vtype_restore = dyn->vector_sew; } else { addr = vaddr; BARRIER(BARRIER_FLOAT); @@ -84,7 +84,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n retaddr = dynarec64_AVX_F2_0F_vector(dyn, addr, ip, ninst, vex, ok, need_epilog); if (retaddr) { if (dyn->vector_sew != VECTOR_SEWNA) - avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); + dyn->vtype_restore = dyn->vector_sew; } else { addr = vaddr; BARRIER(BARRIER_FLOAT); @@ -98,7 +98,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n retaddr = dynarec64_AVX_F3_0F_vector(dyn, addr, ip, ninst, vex, ok, need_epilog); if (retaddr) { if (dyn->vector_sew != VECTOR_SEWNA) - avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); + dyn->vtype_restore = dyn->vector_sew; } else { addr = vaddr; BARRIER(BARRIER_FLOAT); @@ -112,7 +112,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n retaddr = dynarec64_AVX_66_0F38_vector(dyn, addr, ip, ninst, vex, ok, need_epilog); if (retaddr) { if (dyn->vector_sew != VECTOR_SEWNA) - avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); + dyn->vtype_restore = dyn->vector_sew; } else { addr = vaddr; BARRIER(BARRIER_FLOAT); @@ -135,7 +135,7 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n retaddr = dynarec64_AVX_66_0F3A_vector(dyn, addr, ip, ninst, vex, ok, need_epilog); if (retaddr) { if (dyn->vector_sew != VECTOR_SEWNA) - avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); + dyn->vtype_restore = dyn->vector_sew; } else { addr = vaddr; BARRIER(BARRIER_FLOAT); diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index 88ec685c3..d2c473d46 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -119,6 +119,7 @@ static void fpu_reset_reg_extcache(dynarec_rv64_t* dyn, extcache_t* e) e->extcache[i].v = 0; } dyn->vector_sew = VECTOR_SEWNA; + dyn->vtype_restore = VECTOR_SEWNA; } void fpu_reset_reg(dynarec_rv64_t* dyn) { diff --git a/src/dynarec/rv64/dynarec_rv64_pass0.h b/src/dynarec/rv64/dynarec_rv64_pass0.h index 113179934..cf493b341 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass0.h +++ b/src/dynarec/rv64/dynarec_rv64_pass0.h @@ -90,6 +90,7 @@ #define INST_EPILOG \ dyn->insts[ninst].f_exit = dyn->f; \ + dyn->vtype_restore = VECTOR_SEWNA; \ if (dyn->insts[ninst].vec_used) sse_sync_all_cache_types(&dyn->e); \ dyn->insts[ninst].e = dyn->e; \ dyn->insts[ninst].vector_sew_exit = dyn->vector_sew; \ diff --git a/src/dynarec/rv64/dynarec_rv64_pass1.h b/src/dynarec/rv64/dynarec_rv64_pass1.h index 546c26880..9505ea0a8 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass1.h +++ b/src/dynarec/rv64/dynarec_rv64_pass1.h @@ -21,6 +21,7 @@ AREFLAGSNEEDED() #define INST_EPILOG \ + dyn->vtype_restore = VECTOR_SEWNA; \ if (dyn->insts[ninst].vec_used) sse_sync_all_cache_types(&dyn->e); \ dyn->insts[ninst].e = dyn->e; \ dyn->insts[ninst].f_exit = dyn->f; \ diff --git a/src/dynarec/rv64/dynarec_rv64_pass2.h b/src/dynarec/rv64/dynarec_rv64_pass2.h index e6582104e..f344368ec 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass2.h +++ b/src/dynarec/rv64/dynarec_rv64_pass2.h @@ -31,6 +31,10 @@ AREFLAGSNEEDED() #define INST_EPILOG \ dyn->insts[ninst].epilog = dyn->native_size; \ + if (dyn->vtype_restore != VECTOR_SEWNA) { \ + avx_set_vector_width(dyn, ninst, x1, dyn->vtype_restore, 16); \ + dyn->vtype_restore = VECTOR_SEWNA; \ + } \ if (dyn->insts[ninst].vec_used) sse_sync_all_cache_types(&dyn->e); \ dyn->vector_sew = dyn->insts[ninst].vector_sew_exit; #define INST_NAME(name) diff --git a/src/dynarec/rv64/dynarec_rv64_pass3.h b/src/dynarec/rv64/dynarec_rv64_pass3.h index f2dcadaa9..0503a23f0 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass3.h +++ b/src/dynarec/rv64/dynarec_rv64_pass3.h @@ -32,7 +32,11 @@ } \ if (ninst && dyn->insts[ninst - 1].vec_used) sse_sync_all_cache_types(&dyn->e); \ AREFLAGSNEEDED() -#define INST_EPILOG \ +#define INST_EPILOG \ + if (dyn->vtype_restore != VECTOR_SEWNA) { \ + avx_set_vector_width(dyn, ninst, x1, dyn->vtype_restore, 16); \ + dyn->vtype_restore = VECTOR_SEWNA; \ + } \ dyn->vector_sew = dyn->insts[ninst].vector_sew_exit; #define INST_NAME(name) inst_name_pass3(dyn, ninst, name, rex) diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index 8940e78e1..f741e9fbf 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -223,6 +223,7 @@ typedef struct dynarec_rv64_s { uint16_t purge_dead_vector; // SIMD regs whose value is dead at the purge target (skip write-back) uint8_t inst_vl; // vl inside current instruction, for vsetvli elimination uint8_t inst_vlmul; // vlmul inside current instruction + uint8_t vtype_restore; uint8_t is_file_mapped; // if the memory is a mapped file (probably binary, not a memory) void* gdbjit_block; uint32_t need_x87check; // x87 low precision check From 3795fe40fb46abd05499e1bafe017036c16dcd7a Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Wed, 28 Oct 2026 18:37:24 +0800 Subject: [PATCH 098/156] [RV64_DYNAREC] Fix POPCNT/TZCNT/LZCNT with 66h and rex.w prefix (#4622) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For POPCNT/TZCNT/LZCNT, if both the 66H operand-size prefix and REX.W=1 are present, the effective operand width is 64 bits. The `dynarec64_F30F` routine handles translation of 64‑bit POPCNT. --- src/dynarec/rv64/dynarec_rv64_66f30f.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dynarec/rv64/dynarec_rv64_66f30f.c b/src/dynarec/rv64/dynarec_rv64_66f30f.c index b9be7b9b2..4c3264542 100644 --- a/src/dynarec/rv64/dynarec_rv64_66f30f.c +++ b/src/dynarec/rv64/dynarec_rv64_66f30f.c @@ -51,6 +51,7 @@ uintptr_t dynarec64_66F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in switch (opcode) { case 0xB8: + if (rex.w) return dynarec64_F30F(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); INST_NAME("POPCNT Gw, Ew"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); SET_DFNONE(); @@ -91,6 +92,7 @@ uintptr_t dynarec64_66F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in GWBACK; break; case 0xBC: + if (rex.w) return dynarec64_F30F(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); INST_NAME("TZCNT Gw, Ew"); if (!BOX64DRENV(dynarec_safeflags)) { SETFLAGS(X_CF | X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION); @@ -123,6 +125,7 @@ uintptr_t dynarec64_66F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in GWBACK; break; case 0xBD: + if (rex.w) return dynarec64_F30F(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); INST_NAME("LZCNT Gw, Ew"); if (!BOX64DRENV(dynarec_safeflags)) { SETFLAGS(X_CF | X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION); From ea513ac1250a0bd04648040429953644d511b657 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 28 Oct 2026 18:37:59 +0800 Subject: [PATCH 099/156] [RV64_DYNAREC] Cleared pending zero on materialized upper halves (#4623) --- src/dynarec/rv64/dynarec_rv64_helper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 24fc15e5c..adafeef2b 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -3094,6 +3094,7 @@ void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a dyn->e.fpu_scratch = sp; } dyn->e.ssecache[a].ymm = 1; + sse_set_pending_zero(dyn, a, 0); } if (low != vreg) VMV_V_V(vreg, low); From 30d5c77188fa9cf8bea7064d93ced554c3a34cde Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 28 Oct 2026 19:16:15 +0800 Subject: [PATCH 100/156] [RV64_DYNAREC] Keep live YMMs cached across merge points, skip dead write-backs (#4610) --- src/dynarec/dynarec_native_pass.c | 5 + src/dynarec/rv64/dynarec_rv64_functions.c | 54 +++++---- src/dynarec/rv64/dynarec_rv64_helper.c | 132 +++++++++++++++++++--- src/dynarec/rv64/dynarec_rv64_helper.h | 2 + src/dynarec/rv64/dynarec_rv64_private.h | 1 + 5 files changed, 158 insertions(+), 36 deletions(-) diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index 90c2917e5..bb479037e 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -373,6 +373,11 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int dyn->last_ip = 0; } } + #if defined(RV64) + if(dyn->insts[ninst].x64.has_next && dyn->insts[next].promote_ymm && !(dyn->insts[next].x64.barrier & BARRIER_FLOAT)) { + avx_promote_upper(dyn, ninst, x1, dyn->insts[next].promote_ymm); + } + #endif #endif #ifndef PROT_READ #define PROT_READ 1 diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index d2c473d46..b9931a6d3 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -1000,18 +1000,10 @@ void updatePreloads(dynarec_rv64_t* dyn) for (int first = 0; first < dyn->size; ++first) { if (dyn->insts[first].preload_xmmymm) continue; - if (first) { - if (dyn->insts[first].pred_sz <= 1) - continue; - int has_linear = 0; - for (int j = 0; j < dyn->insts[first].pred_sz; ++j) - if (dyn->insts[first].pred[j] == first - 1) - has_linear = 1; - if (!has_linear) - continue; - } else if (!dyn->insts[first].pred_sz) { + if (first) + break; + if (!dyn->insts[first].pred_sz) continue; - } int last = dyn->size + 1; for (int j = 0; j < dyn->insts[first].pred_sz; ++j) { int pred = dyn->insts[first].pred[j]; @@ -1084,22 +1076,43 @@ void updateUpperLiveness(dynarec_rv64_t* dyn) for (int i = 0; i < n; ++i) { instruction_rv64_t* inst = &dyn->insts[i]; + inst->promote_ymm = 0; if (!inst->x64.alive || inst->pred_sz < 2 || (inst->x64.barrier & BARRIER_FLOAT)) continue; const extcache_t* first = &dyn->insts[inst->pred[0]].e; - for (int p = 1; p < inst->pred_sz; ++p) { + uint16_t promote = 0; + int need_barrier = 0; + for (int p = 1; p < inst->pred_sz && !need_barrier; ++p) { const extcache_t* pe = &dyn->insts[inst->pred[p]].e; - int diff = (first->ymm0 != pe->ymm0); - for (int r = 0; r < 16 && !diff; ++r) - if (first->ssecache[r].v != -1 && pe->ssecache[r].v != -1 - && (first->ssecache[r].ymm != pe->ssecache[r].ymm - || first->ssecache[r].ymm0 != pe->ssecache[r].ymm0)) - diff = 1; - if (diff) { - inst->x64.barrier |= BARRIER_FLOAT; + uint16_t mask_diff = (uint16_t)(first->ymm0 ^ pe->ymm0); + uint16_t resolved = 0; + for (int r = 0; r < 16; ++r) { + const sse_cache_t* a = &first->ssecache[r]; + const sse_cache_t* b = &pe->ssecache[r]; + int a_cached = (a->v != -1 && a->vector); + int b_cached = (b->v != -1 && b->vector); + if (!a_cached || !b_cached) + continue; + if (a->ymm == b->ymm && a->ymm0 == b->ymm0) + continue; + int a_ok = a->ymm || (!a->ymm && a->ymm0); + int b_ok = b->ymm || (!b->ymm && b->ymm0); + if (a_ok && b_ok) { + if (!a->ymm) promote |= (uint16_t)(1u << r); + if (!b->ymm) promote |= (uint16_t)(1u << r); + resolved |= (uint16_t)(1u << r); + continue; + } + need_barrier = 1; break; } + if (mask_diff & (uint16_t)~resolved) + need_barrier = 1; } + if (need_barrier) + inst->x64.barrier |= BARRIER_FLOAT; + else + inst->promote_ymm = promote; } int sp = 0; @@ -1191,6 +1204,7 @@ void updateUpperLiveness(dynarec_rv64_t* dyn) merged_ymm |= (pend_ymm[j] & (uint16_t)~ymm_def) | (pred->ymm_zero & pred->ymm_upper_live); } if (inst->x64.barrier & BARRIER_FLOAT) merged_ymm = 0; + merged_ymm &= (uint16_t)~inst->promote_ymm; if ((merged_pending != pending_in[i]) || (merged_ymm != pend_ymm[i])) { pending_in[i] = merged_pending; pend_ymm[i] = merged_ymm; diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index adafeef2b..478b1e1eb 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -2455,6 +2455,10 @@ static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, i break; case EXT_CACHE_XMMW: case EXT_CACHE_YMMW: + if (dyn->purge_dead_vector & (1u << n)) { + MESSAGE(LOG_DUMP, "\t - Dropping dead %s\n", getCacheName(t, n)); + break; + } MESSAGE(LOG_DUMP, "\t - Unloading %s\n", getCacheName(t, n)); SET_CACHE_VECTOR_WIDTH(s1); ADDI(s1, xEmu, offsetof(x64emu_t, xmm[n])); @@ -2544,6 +2548,80 @@ static uint16_t vectorDeadAtTarget(dynarec_rv64_t* dyn, int i2, int ninst) return dead; } +static void avx_zero_upper(dynarec_rv64_t* dyn, int ninst, int s1, int reg) +{ + uint8_t sew0, vlmul0, vl0; + vector_save_vtype(dyn, &sew0, &vlmul0, &vl0); + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW32, VECTOR_LMUL1, 2); + VXOR_VV(VMASK, VMASK, VMASK, VECTOR_UNMASKED); + VSLIDEUP_VI(reg, VMASK, 4, VECTOR_UNMASKED); + vector_restore_vtype(dyn, ninst, s1, sew0, vlmul0, vl0); +} + +// materialize the deferred zeros of YMM registers that are not in the cache anymore +static void avx_flush_pending_zero_mask(dynarec_rv64_t* dyn, int ninst, int s1, int next, uint16_t mask) +{ + if (!cpuext.vlen || cpuext.vlen < 32) + return; + if (next) { + if (dyn->pending_zero_flushed) + return; + dyn->pending_zero_flushed = 1; + } + for (int i = 0; i < 16; ++i) + if ((mask >> i) & 1) { + SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 0); + SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 8); + if (!next) sse_set_pending_zero(dyn, i, 0); + } + dyn->inst_vl = 0; // force the next vsetvli to be emited +} + +static int find_sse_slot_in(const extcache_t* e, int n, int* is_ymm) +{ + for (int i = 0; i < 24; ++i) { + if (!e->extcache[i].v) + continue; + int t = e->extcache[i].t; + if ((t == EXT_CACHE_XMMR || t == EXT_CACHE_XMMW || t == EXT_CACHE_YMMR || t == EXT_CACHE_YMMW) + && e->extcache[i].n == n) { + if (is_ymm) + *is_ymm = (t == EXT_CACHE_YMMR || t == EXT_CACHE_YMMW); + return i; + } + } + return -1; +} + +static void avx_sync_upper_vector_target(dynarec_rv64_t* dyn, int ninst, int s1, int i2) +{ + if (!cpuext.vlen || cpuext.vlen < 32) + return; + if (ninst >= 0 && ninst < dyn->size) + dyn->insts[ninst].vec_used |= 0xffff; + const extcache_t* tgt = &dyn->insts[i2].e; + uint16_t handled = 0; + uint16_t dead = dyn->purge_dead_vector; + for (int i = 0; i < 16; ++i) { + sse_cache_t* c = &dyn->e.ssecache[i]; + if (c->v == -1 || !c->vector) + continue; + if (c->ymm0) + handled |= (uint16_t)(1 << i); + if (dead & (1u << i)) + continue; + int t_ymm = 0; + int t_slot = find_sse_slot_in(tgt, i, &t_ymm); + if (c->ymm && !c->ymm0 && t_slot >= 0 && t_ymm + && !((tgt->ymm0 >> i) & 1) && EXTREG(t_slot) == c->reg) + continue; + avx_flush_upper_vector(dyn, ninst, s1, i, c->reg, 1, 0); + } + avx_flush_pending_zero_mask(dyn, ninst, s1, 1, dyn->e.ymm0 & (uint16_t)~handled & (uint16_t)~dead); +} + static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3) { int i2 = dyn->insts[ninst].x64.jmp_insts; @@ -2584,7 +2662,8 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in return; } } - avx_sync_upper_vector(dyn, ninst, s1, 1); + dyn->purge_dead_vector = dead; + avx_sync_upper_vector_target(dyn, ninst, s1, i2); int stack_cnt = dyn->e.stack_next; int s3_top = 0xffff; extcache_t cache = dyn->e; @@ -2699,6 +2778,21 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in } } } + dyn->purge_dead_vector = 0; + uint16_t promote = dyn->insts[i2].promote_ymm; + if (promote) { + for (int r = 0; r < 16; ++r) { + if (!((promote >> r) & 1)) + continue; + const sse_cache_t* src = &dyn->e.ssecache[r]; + const sse_cache_t* dst = &cache_i2.ssecache[r]; + if (dst->v != -1 && dst->vector && dst->ymm + && src->v != -1 && src->vector && !src->ymm && src->ymm0) { + MESSAGE(LOG_DUMP, "\t - Promoting upper half of %s\n", getCacheName(EXT_CACHE_YMMW, r)); + avx_zero_upper(dyn, ninst, s1, dst->reg); + } + } + } if (stack_cnt != cache_i2.stack || dyn->e.x87stack != cache_i2.x87stack) { MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d / pending %d -> %d -\n", stack_cnt, cache_i2.stack, dyn->e.x87stack, cache_i2.x87stack); int a = dyn->e.x87stack - cache_i2.x87stack; @@ -3007,23 +3101,27 @@ void avx_flush_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int r vector_restore_vtype(dyn, ninst, s1, sew0, vlmul0, vl0); } -// materialize the deferred zeros of YMM registers that are not in the cache anymore -static void avx_flush_pending_zero_mask(dynarec_rv64_t* dyn, int ninst, int s1, int next, uint16_t mask) +void avx_promote_upper(dynarec_rv64_t* dyn, int ninst, int s1, uint16_t mask) { - if (!cpuext.vlen || cpuext.vlen < 32) - return; - if (next) { - if (dyn->pending_zero_flushed) - return; - dyn->pending_zero_flushed = 1; - } - for (int i = 0; i < 16; ++i) - if ((mask >> i) & 1) { - SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 0); - SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 8); - if (!next) sse_set_pending_zero(dyn, i, 0); + for (int r = 0; r < 16; ++r) { + if (!((mask >> r) & 1)) + continue; + sse_cache_t* c = &dyn->e.ssecache[r]; + if (c->v == -1 || !c->vector) { + sse_set_pending_zero(dyn, r, 0); + continue; } - dyn->inst_vl = 0; // force the next vsetvli to be emited + if (!c->ymm) { + if (c->ymm0) + avx_zero_upper(dyn, ninst, s1, c->reg); + else + loadUpperCache(dyn, ninst, s1, r, c->reg, 0); + c->ymm = 1; + } + c->write = 1; + sse_set_pending_zero(dyn, r, 0); + sse_sync_cache_type(&dyn->e, r); + } } void avx_flush_pending_zero_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next) @@ -3130,11 +3228,13 @@ void doPreload(dynarec_rv64_t* dyn, int ninst) uint32_t preload = dyn->insts[ninst].preload_xmmymm; if (!preload) return; + uint16_t saved_read = dyn->insts[ninst].vec_read; MESSAGE(LOG_INFO, "Preload XMM/YMM -------- %x\n", preload); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); for (int i = 0; i < 16; ++i) if (preload & (1u << i)) sse_get_reg_vector(dyn, ninst, x1, i, 0, VECTOR_SEW8); + dyn->insts[ninst].vec_read = saved_read; MESSAGE(LOG_INFO, "-------- Preload XMM/YMM\n"); } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 65a5d3812..7eef3e56e 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -2023,6 +2023,7 @@ #define avx_load_reg_vector STEPNAME(avx_load_reg_vector) #define avx_store_reg_vector STEPNAME(avx_store_reg_vector) #define avx_flush_upper_vector STEPNAME(avx_flush_upper_vector) +#define avx_promote_upper STEPNAME(avx_promote_upper) #define avx_sync_upper_vector STEPNAME(avx_sync_upper_vector) #define doPreload STEPNAME(doPreload) #define avx_flush_pending_zero_vector STEPNAME(avx_flush_pending_zero_vector) @@ -2291,6 +2292,7 @@ void sse_purge07cache(dynarec_rv64_t* dyn, int ninst, int s1); void sse_reflect_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a); void avx_flush_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int reg, int next, int dead); +void avx_promote_upper(dynarec_rv64_t* dyn, int ninst, int s1, uint16_t mask); void avx_sync_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next); void avx_flush_pending_zero_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next); void doPreload(dynarec_rv64_t* dyn, int ninst); diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index f741e9fbf..e5b178978 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -174,6 +174,7 @@ typedef struct instruction_rv64_s { uint16_t ymm_zero; // bitmask of YMM upper halves deferred-zeroed by this instruction uint16_t ymm_pending; // bitmask of pending YMM upper-half zeros on entry to this instruction uint8_t ymm_pending_materialized; // pending YMM upper-half zeros are materialized before this instruction runs + uint16_t promote_ymm; // per-instruction bitmask of registers to promote } instruction_rv64_t; typedef struct dynarec_rv64_s { From 4e8f73c27723328a39ddd362500a22bf52241cd8 Mon Sep 17 00:00:00 2001 From: Mark Zhuang Date: Thu, 29 Oct 2026 16:09:48 +0800 Subject: [PATCH 101/156] [DEBIAN] Fix changelog formatting (#4625) Before fix: dpkg-parsechangelog warned about malformed headings, unrecognized lines, and missing trailers. Build error on spacemit k3: bianbu:~/box64$ dpkg-buildpackage -b -uc -us -j8 dpkg-buildpackage: warning: debian/changelog(l3): badly formatted heading line LINE: This version adds a lot of refactor and speed improvements to the LoongArch backend, so more opcodes on the RISC-V backend, and many QoL new features! dpkg-buildpackage: warning: debian/changelog(l9): badly formatted heading line LINE: -- Sebastien Chevalier Mon, 2 Aug 2026 10:30:33 -0100 dpkg-buildpackage: warning: debian/changelog(l11): found start of entry where expected more change data or trailer LINE: box64 (0.4.2) unstable; urgency=low dpkg-buildpackage: warning: debian/changelog(l11): found end of file where expected more change data or trailer dpkg-buildpackage: info: source package box64 dpkg-buildpackage: info: source version 0.4.4 dpkg-buildpackage: info: source distribution unstable dpkg-buildpackage: info: source changed by dpkg-buildpackage: error: cannot parse maintainer email address "" from changelog entry After fix: Check: dpkg-parsechangelog --all -l debian/changelog -S Version Result: 0.4.4, no warnings --- debian/changelog | 400 +++++++++++++++++++++++------------------------ 1 file changed, 200 insertions(+), 200 deletions(-) diff --git a/debian/changelog b/debian/changelog index a3101c7b3..4e3406515 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,178 +1,178 @@ box64 (0.4.4) unstable; urgency=low -This version adds a lot of refactor and speed improvements to the LoongArch backend, so more opcodes on the RISC-V backend, and many QoL new features! - => A new box64-configurator is now present (a python app) to help managing custom RCFILE profiles. It is available in both english and chinese. - => DynaCache is now enabled by default. It will compress the files and use up to 2GB of disk space. - => You can use box64-configurator on the special `[*]` profile to change default values - => More improvements on emulation accuracy that help running more DRM'd games + * This version adds a lot of refactor and speed improvements to the LoongArch backend, so more opcodes on the RISC-V backend, and many QoL new features! + * => A new box64-configurator is now present (a python app) to help managing custom RCFILE profiles. It is available in both english and chinese. + * => DynaCache is now enabled by default. It will compress the files and use up to 2GB of disk space. + * => You can use box64-configurator on the special `[*]` profile to change default values + * => More improvements on emulation accuracy that help running more DRM'd games --- Sebastien Chevalier Mon, 2 Aug 2026 10:30:33 -0100 + -- Sebastien Chevalier Mon, 2 Aug 2026 10:30:33 -0100 box64 (0.4.2) unstable; urgency=low -This version add lots on unconnected new things, like a PPC64LE backend, Vulkan overlay support or more Dynarec finetunning. - => Vulkan x64 overlay support. That means using the linux version of Steam, Fossilize & GameOverlayUI will work. - => Many dynarec refactors, especialy on ARM64 & LA64 with fixes to speed regression introduced with the the last 2 releases and improved compatibility. - => Support for SteamRT3 & new Proton 11 - => New PCC64LE in the work. Not finished, but should be usable already (but the platform seems to use a 64k pagesize by default, so compatibility will suffer on this platformm). Note that main Box64 mainteners don't have access to relevent hardware, so support will be limited. + * This version add lots on unconnected new things, like a PPC64LE backend, Vulkan overlay support or more Dynarec finetunning. + * => Vulkan x64 overlay support. That means using the linux version of Steam, Fossilize & GameOverlayUI will work. + * => Many dynarec refactors, especialy on ARM64 & LA64 with fixes to speed regression introduced with the the last 2 releases and improved compatibility. + * => Support for SteamRT3 & new Proton 11 + * => New PCC64LE in the work. Not finished, but should be usable already (but the platform seems to use a 64k pagesize by default, so compatibility will suffer on this platformm). Note that main Box64 mainteners don't have access to relevent hardware, so support will be limited. --- Sebastien Chevalier Mon, 20 Apr 2026 10:30:33 -0100 + -- Sebastien Chevalier Mon, 20 Apr 2026 10:30:33 -0100 box64 (0.4.0) unstable; urgency=low -This version added many important refactors: the opcode prefix decoder for Dynarec, libGL and Vulkan, the FSGSBASE support, making segments handling easier and faster. - => Improved compatibility accross all architecture, allowing more DRM protected game to run - => the prefix refactor helped removed lots of redundant source file, simplifying maintenance - => BOX32 is getting more and more stable, even if still not 100% ok. But Steam is more stable than before, runs on all architecture. And some gameoverlay UI works, on OpenGL games. gameoverlay (and fossilize) support for Vulkan is planned for later. + * This version added many important refactors: the opcode prefix decoder for Dynarec, libGL and Vulkan, the FSGSBASE support, making segments handling easier and faster. + * => Improved compatibility accross all architecture, allowing more DRM protected game to run + * => the prefix refactor helped removed lots of redundant source file, simplifying maintenance + * => BOX32 is getting more and more stable, even if still not 100% ok. But Steam is more stable than before, runs on all architecture. And some gameoverlay UI works, on OpenGL games. gameoverlay (and fossilize) support for Vulkan is planned for later. --- Sebastien Chevalier Mon, 3 Jan 2026 10:30:33 -0100 + -- Sebastien Chevalier Mon, 3 Jan 2026 10:30:33 -0100 box64 (0.3.8) unstable; urgency=low -This version introduce DynaCache, a disk cache for the generated native code. It's not enabled by default for now (but it will use cache file if present by default). It can dramaticaly speedup the load of program (try with linux factorio for example). This version also improve in the volatile metadata handling. There is a massive compatiblity improvment for box32 and on all dynarec in general too. And few more function wrapping... + * This version introduce DynaCache, a disk cache for the generated native code. It's not enabled by default for now (but it will use cache file if present by default). It can dramaticaly speedup the load of program (try with linux factorio for example). This version also improve in the volatile metadata handling. There is a massive compatiblity improvment for box32 and on all dynarec in general too. And few more function wrapping... - => DynaCache for faster loading of program, and avoid runtime hicups - => Batter box32 compatibility (much less "Out of Memory" error) - => Unity3D games on Wayland are working now - => Volatile Metadata fully supported and handled, making games like Starfield to just work. - => More work on AVX support for RV64 & LA64. LA64 almost there, while RV64 has Scalar only support (no hardware vector support yet for AVX) + * => DynaCache for faster loading of program, and avoid runtime hicups + * => Batter box32 compatibility (much less "Out of Memory" error) + * => Unity3D games on Wayland are working now + * => Volatile Metadata fully supported and handled, making games like Starfield to just work. + * => More work on AVX support for RV64 & LA64. LA64 almost there, while RV64 has Scalar only support (no hardware vector support yet for AVX) --- Sebastien Chevalier Mon, 10 Oct 2025 10:30:33 -0100 + -- Sebastien Chevalier Mon, 10 Oct 2025 10:30:33 -0100 box64 (0.3.6) unstable; urgency=low -This version introduces wowbox64.dll for Hangover; the ability to use the Volatile Metadata of Windows executables for x64 wine; and some better x87/SSE/AVX handling + * This version introduces wowbox64.dll for Hangover; the ability to use the Volatile Metadata of Windows executables for x64 wine; and some better x87/SSE/AVX handling - => WowBox64 can be built directly from Box64 repo, and can be found in the CI artifacts also - => it also supports a subset of BOX64_XXXX settings, which can be set from command line or via a setting file ".box64rc" in the Wine prefix home - => Volatile Metadata, when present, allows only applying strong memory ordering when needed, as marked by the compiler, giving overall better performances - => The precision control bit of x87 is now handled, allowing some older games to run correctly - => More work has been done in the handling of precise NaN and Round handling in SSE & AVX opcodes + * => WowBox64 can be built directly from Box64 repo, and can be found in the CI artifacts also + * => it also supports a subset of BOX64_XXXX settings, which can be set from command line or via a setting file ".box64rc" in the Wine prefix home + * => Volatile Metadata, when present, allows only applying strong memory ordering when needed, as marked by the compiler, giving overall better performances + * => The precision control bit of x87 is now handled, allowing some older games to run correctly + * => More work has been done in the handling of precise NaN and Round handling in SSE & AVX opcodes --- Sebastien Chevalier Thu, 6 Jun 2025 10:30:33 -0100 + -- Sebastien Chevalier Thu, 6 Jun 2025 10:30:33 -0100 box64 (0.3.4) unstable; urgency=low -* This version is Faster and more compatible -* => The RV64 backend got faster and more stable, with lots of RVV 1.0 / xThreadVector support to emulate SSE/SSE2+ opcode (no AVX yet) -* => On ARM64, Box64 now support more DRM types than before. -* => BOX32 can run steam now. At least on ARM64 backend, it's still not working on RV64 and LA64 for now. -* Please check CHAGELOG.md for more details + * This version is Faster and more compatible + * => The RV64 backend got faster and more stable, with lots of RVV 1.0 / xThreadVector support to emulate SSE/SSE2+ opcode (no AVX yet) + * => On ARM64, Box64 now support more DRM types than before. + * => BOX32 can run steam now. At least on ARM64 backend, it's still not working on RV64 and LA64 for now. + * Please check CHAGELOG.md for more details --- Sebastien Chevalier Thu, 10 Mar 2025 10:30:33 -0100 + -- Sebastien Chevalier Thu, 10 Mar 2025 10:30:33 -0100 box64 (0.3.2) unstable; urgency=low -* Introduced Box32 to run 32bits apps on 64bits OS -* => Box32 is a build option for Box64, and is disabled by default -* => Optionnal binfmt integration available for Box32 -* => Wrapped some basics libs, including graphics and sounds so a few games already works -* => Work In Progress, many issues remain to be fixed, but some Linux games are playable -* Introduced Native Flags. Can be controled with BOX64_DYNAREC_NATIVEFLAGS, but enabled by default -* => Available on the 3 Dynarec backend, with different implementations -* => ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default -* +> Can lead to large speedup on certain cases -* Improved Strong Memory Model emulation, with better default options and a more efficiant emulation -* Dynarec: RV64: using RVV (and XThreadVector) to implement SSEx opcodes, with some massive speedup when used! -* Some bugfix and improvment in the Signal handler and internal memory tracking -* Improvment to TRAP signal generation and Handling -* Improved CPUID opcodes again, and the various virtual file in /proc that represent those data -* Improved some x87 operations, like long double handling and infinity comparisons... -* Dynarec: ARM64 fixes to a few opcodes -* Dynarec: RV64 fixes to many opcodes -* Dynarec: LA64 fixes to a few opcodes -* Dynarec: RV64 fixes and improvments on LOCK prefixes opcodes -* Dynarec: Many optimisation on some individual opcodes, an all 3 backends -* WRAPPING: More libs and functions wrapped. Some wrapping fixes too -* WREPPING: New wrapperhelper to help coding new wrapping & fixing/enhancing existing one -* ElfLoader: Improved object fetching -* New build profile for SD865 and ORYON -* Changed the installation folder of x86 libs to avoid conflict with linux distro -* Added a few syscalls -* Some more Vulkan extensions wrapped -* More work on build system, and github CI (generating WCP archive), with some fixes on the Android version (still not 100% operational) - --- Sebastien Chevalier Thu, 6 Dec 2024 10:30:33 -0100 + * Introduced Box32 to run 32bits apps on 64bits OS + * => Box32 is a build option for Box64, and is disabled by default + * => Optionnal binfmt integration available for Box32 + * => Wrapped some basics libs, including graphics and sounds so a few games already works + * => Work In Progress, many issues remain to be fixed, but some Linux games are playable + * Introduced Native Flags. Can be controled with BOX64_DYNAREC_NATIVEFLAGS, but enabled by default + * => Available on the 3 Dynarec backend, with different implementations + * => ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default + * +> Can lead to large speedup on certain cases + * Improved Strong Memory Model emulation, with better default options and a more efficiant emulation + * Dynarec: RV64: using RVV (and XThreadVector) to implement SSEx opcodes, with some massive speedup when used! + * Some bugfix and improvment in the Signal handler and internal memory tracking + * Improvment to TRAP signal generation and Handling + * Improved CPUID opcodes again, and the various virtual file in /proc that represent those data + * Improved some x87 operations, like long double handling and infinity comparisons... + * Dynarec: ARM64 fixes to a few opcodes + * Dynarec: RV64 fixes to many opcodes + * Dynarec: LA64 fixes to a few opcodes + * Dynarec: RV64 fixes and improvments on LOCK prefixes opcodes + * Dynarec: Many optimisation on some individual opcodes, an all 3 backends + * WRAPPING: More libs and functions wrapped. Some wrapping fixes too + * WREPPING: New wrapperhelper to help coding new wrapping & fixing/enhancing existing one + * ElfLoader: Improved object fetching + * New build profile for SD865 and ORYON + * Changed the installation folder of x86 libs to avoid conflict with linux distro + * Added a few syscalls + * Some more Vulkan extensions wrapped + * More work on build system, and github CI (generating WCP archive), with some fixes on the Android version (still not 100% operational) + + -- Sebastien Chevalier Thu, 6 Dec 2024 10:30:33 -0100 box64 (0.3.0) unstable; urgency=low -* AVX and AVX2 implemented, along with BMI1, BMI2, ADX, FMA, F16C and RDANDR extension! -* Introduced BOX64_AVX env. var. to enable/disable AVX extension: -* => BOX64_AVX=1 enable AVX, BMI1, F16C and VAES extension -* => BOX64_AVX=2 also enable AVX2, BMI2, FMA, ADX,VPCLMULQDQ and RDRAND -* Dynarec: Implemented most AVX/AVX2 and friends in ARM64 Dynarec (using only NEON, so available on all ARM64 CPU) -* => ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default -* Improved CPUID opcodes, adding a few leaf, fixing same. Returnning an Haswell type of CPU now (was Pentium IV before) -* Dynarec: Small optim in the emit_pf helper, on all 3 backends -* Dynarec: ARM64 some fixes to a few opcodes -* Dynarec: LA64 many new opcodes added, and fixes. -* Dynarec: RV64 some new opcodes added, many fixes. -* Dynarec: RV64 Adding some infrastructure to use RVV (if available) for SIMD emulation. -* Dynarec: Many small changes and fixes around handling of x87, registers and internal jump. -* WRAPPING: Added a workaround on SDL_GetThreadID to fix a race condition that was happening mostly on LA64 and broke many SDL games -* WRAPPING: More libs and functions wrapped. Some wrapping fixes too (including a nasty error on some rare libGL functions) -* WRAPPING: Wayland is now supported. Wine-wayland at least works now -* Dynarec: LA64 improved LOCK CMPXCHG handling, and better 16Byte LOCK handling too (fixes many Unity3D games) -* Dynarec: RV64 improved LOCK CMPXCHG handling -* COSIM: Many fixes and improvment, to make BOX64_DYNAREC_TEST more usable -* Detect when a Wine program use UnityPlayer.dll to atumaticaly use BOX64_DYNAREC_STRONGMEM=1 (unless it's already set), so more games just work -* ElfLoader: Added a new type of relocation - --- Sebastien Chevalier Thu, 9 Jul 2024 10:30:33 -0100 + * AVX and AVX2 implemented, along with BMI1, BMI2, ADX, FMA, F16C and RDANDR extension! + * Introduced BOX64_AVX env. var. to enable/disable AVX extension: + * => BOX64_AVX=1 enable AVX, BMI1, F16C and VAES extension + * => BOX64_AVX=2 also enable AVX2, BMI2, FMA, ADX,VPCLMULQDQ and RDRAND + * Dynarec: Implemented most AVX/AVX2 and friends in ARM64 Dynarec (using only NEON, so available on all ARM64 CPU) + * => ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default + * Improved CPUID opcodes, adding a few leaf, fixing same. Returnning an Haswell type of CPU now (was Pentium IV before) + * Dynarec: Small optim in the emit_pf helper, on all 3 backends + * Dynarec: ARM64 some fixes to a few opcodes + * Dynarec: LA64 many new opcodes added, and fixes. + * Dynarec: RV64 some new opcodes added, many fixes. + * Dynarec: RV64 Adding some infrastructure to use RVV (if available) for SIMD emulation. + * Dynarec: Many small changes and fixes around handling of x87, registers and internal jump. + * WRAPPING: Added a workaround on SDL_GetThreadID to fix a race condition that was happening mostly on LA64 and broke many SDL games + * WRAPPING: More libs and functions wrapped. Some wrapping fixes too (including a nasty error on some rare libGL functions) + * WRAPPING: Wayland is now supported. Wine-wayland at least works now + * Dynarec: LA64 improved LOCK CMPXCHG handling, and better 16Byte LOCK handling too (fixes many Unity3D games) + * Dynarec: RV64 improved LOCK CMPXCHG handling + * COSIM: Many fixes and improvment, to make BOX64_DYNAREC_TEST more usable + * Detect when a Wine program use UnityPlayer.dll to atumaticaly use BOX64_DYNAREC_STRONGMEM=1 (unless it's already set), so more games just work + * ElfLoader: Added a new type of relocation + + -- Sebastien Chevalier Thu, 9 Jul 2024 10:30:33 -0100 box64 (0.2.8) unstable; urgency=low -* Wrapping: More libs and function wrapping (gtk3, vulkan...) -* Reworked X11 Callback handling, for better stability -* Reworked exit and the load/unload of libs and symbol resolution -* Some more profiles in box64rc -* Better way to rename executable (including wine ones) so driver like mesa can apply the correct profile -* Reworked memory managment in the Dynarec, limiting amount of dynamic allocation -* Improved memory tracking and managment. Also introduce BOX64_MMAP32 to force 32bits compatible mmap for external libs (like mesa) -* => Allow Vulkan drvier on Wine/WOW64 games to allocate 32bits compatible memory, allowing dxvk on 32bits. -* Reworked memory managment in the Dynarec, limiting amount of dynamic allocation -* Lots of improvments in x87 handling (virtual stack, rounding, ffree, etc.) -* => should improve games stability -* Dynarec: ARM64 some opcodes optimisation, especialy shift and rotation ones -* Dynarec: RV64 lots of opcoded added. -* => Some games on linux now have a good speed. Game on Wine are still a bit slow, and dxvk still have issues -* Dynarec: Added Loogarch backend! Note that Loongarch are 16K pagesize platform by default. -* => Linux games are running, and with good speed, especialy on 3A6000 platforms. Games on Wine are not working yet due to 16k pagesize limitation -* Dynarec: Better handling of large block in the dynarec -* Dynarec: Lots of improvments and fixes to BOX86_DYNAREC_CALLRET optimisation. -* => It can be used on more software now, and combine with BOX64_DYNAREC_BOGBLOCKS 2 or 3 can gives some good speed boosts. - --- Sebastien Chevalier Thu, 31 May 2024 17:30:33 -0100 + * Wrapping: More libs and function wrapping (gtk3, vulkan...) + * Reworked X11 Callback handling, for better stability + * Reworked exit and the load/unload of libs and symbol resolution + * Some more profiles in box64rc + * Better way to rename executable (including wine ones) so driver like mesa can apply the correct profile + * Reworked memory managment in the Dynarec, limiting amount of dynamic allocation + * Improved memory tracking and managment. Also introduce BOX64_MMAP32 to force 32bits compatible mmap for external libs (like mesa) + * => Allow Vulkan drvier on Wine/WOW64 games to allocate 32bits compatible memory, allowing dxvk on 32bits. + * Reworked memory managment in the Dynarec, limiting amount of dynamic allocation + * Lots of improvments in x87 handling (virtual stack, rounding, ffree, etc.) + * => should improve games stability + * Dynarec: ARM64 some opcodes optimisation, especialy shift and rotation ones + * Dynarec: RV64 lots of opcoded added. + * => Some games on linux now have a good speed. Game on Wine are still a bit slow, and dxvk still have issues + * Dynarec: Added Loogarch backend! Note that Loongarch are 16K pagesize platform by default. + * => Linux games are running, and with good speed, especialy on 3A6000 platforms. Games on Wine are not working yet due to 16k pagesize limitation + * Dynarec: Better handling of large block in the dynarec + * Dynarec: Lots of improvments and fixes to BOX86_DYNAREC_CALLRET optimisation. + * => It can be used on more software now, and combine with BOX64_DYNAREC_BOGBLOCKS 2 or 3 can gives some good speed boosts. + + -- Sebastien Chevalier Thu, 31 May 2024 17:30:33 -0100 box64 (0.2.6) unstable; urgency=low - * X64Libs: Updated libstdc++ & libgcc_s - * X64Libs: Use x86_64 vrsion of libunwind (it's needed by wine) - * Dynarec: More opcodes on ARM64 & RV64 - * Dynarec: Fixed some flags propagation issues inside blocks - * Dynarec: Improved Strong Memory Model emulation, introducing a 3rd level - * Dynarec: ARM64: reworked shift and bit opcodes flags handling - * Dynarec: RV64: Many fixes, making Wow64 apps running - * Dynarec: ARM64: Added support for SSE4.2 (with CRC32 if supported by CPU) - * Dynarec: ARM64: Added support for SHA (with hardware support if CPU allows it) - * Dynarec: ARM64: The CALLRET optimisation has been improved and is now default - * CPU: Remoworked how INT, priviliged opcodes and teh Trace flags works - * CPU: Added full support for SSE4.2 - * CPU: Added full support for SHA extension - * ElfLoader: rework how elf memory is handled - * Emulation: Added some more syscalls - * Emulation: Better handling of Signal (also handling SIGMAX correctly) - * Emulation: Better support for POKEUSER/PEEKUSER (helps Windows Unity games) - * Wrapping: More libs and some fixes in function wrapping (gtk3, vulkan...) - * Wrapping: Removed faked libunwind wrapping - * Hardware: Added more profile, with support ADLink Ampere Altra, Qualcomm 8Gen3, and Pi5 machines - * OS: Added profile to build for Android and Termux. - * OS: New option to use mold for a high speed link - * => More hadware support, more functions wrapped for an improve compatibity - * => More CPU extension, with ARM64 hardware support when possible, and improved CALLRET optimisation for an improved speed of emulation - * => Some work also to reduce the memory footprint - --- Sebastien Chevalier Thu, 15 Dec 2023 17:30:33 -0100 + * X64Libs: Updated libstdc++ & libgcc_s + * X64Libs: Use x86_64 vrsion of libunwind (it's needed by wine) + * Dynarec: More opcodes on ARM64 & RV64 + * Dynarec: Fixed some flags propagation issues inside blocks + * Dynarec: Improved Strong Memory Model emulation, introducing a 3rd level + * Dynarec: ARM64: reworked shift and bit opcodes flags handling + * Dynarec: RV64: Many fixes, making Wow64 apps running + * Dynarec: ARM64: Added support for SSE4.2 (with CRC32 if supported by CPU) + * Dynarec: ARM64: Added support for SHA (with hardware support if CPU allows it) + * Dynarec: ARM64: The CALLRET optimisation has been improved and is now default + * CPU: Remoworked how INT, priviliged opcodes and teh Trace flags works + * CPU: Added full support for SSE4.2 + * CPU: Added full support for SHA extension + * ElfLoader: rework how elf memory is handled + * Emulation: Added some more syscalls + * Emulation: Better handling of Signal (also handling SIGMAX correctly) + * Emulation: Better support for POKEUSER/PEEKUSER (helps Windows Unity games) + * Wrapping: More libs and some fixes in function wrapping (gtk3, vulkan...) + * Wrapping: Removed faked libunwind wrapping + * Hardware: Added more profile, with support ADLink Ampere Altra, Qualcomm 8Gen3, and Pi5 machines + * OS: Added profile to build for Android and Termux. + * OS: New option to use mold for a high speed link + * => More hadware support, more functions wrapped for an improve compatibity + * => More CPU extension, with ARM64 hardware support when possible, and improved CALLRET optimisation for an improved speed of emulation + * => Some work also to reduce the memory footprint + + -- Sebastien Chevalier Thu, 15 Dec 2023 17:30:33 -0100 box64 (0.2.4) unstable; urgency=low @@ -199,74 +199,74 @@ box64 (0.2.4) unstable; urgency=low * => Dynarec now support RISC-V, large speedup on RISC-V 64, were games are now playable (like Stardew Valley on a Vision Five 2) * => Improved compatibility with more fixes in elf handling, more wrapped libs and functiond, more fixed opcodes and refined profile --- Sebastien Chevalier Thu, 10 Mar 2023 10:20:33 -0500 + -- Sebastien Chevalier Thu, 10 Mar 2023 10:20:33 -0500 box64 (0.2.2) unstable; urgency=low - * Added a hacked version for overridden malloc/free functions, enabling libcef (and derivative) to work. - * Added rcfile handling: box64 now read "/etc/box64.box64rc" and "~/.box64rc" and apply per process parameters - * Added BOX64_DYNAREC_CALLRET to optimized CALL/RET opcode using semi-direct native CALL/RET (get more than 10% speedup) - * Added BOX64_DYNAREC_FORWARD to allow bigger Dynarec block to be build (can get more then 30% of Speedup!) - * Improved memory protection tracking and signal handling, again - * Simplified mutex handling (faster, cleaner) - * Reduce memory used by the memory tracking (memory almost divide by 4 is some critical use case) - * Added d3dadaptor9 wrapping - * More wrapped libs (especially on the gtk familly) - * Improved/fixed some Syscall handling - * Refactored Strong Memory Model emulation (faster and more accurate) - * Added some more opcode to ARM64 Dynarec, and fixed some other - * Some fixes to flags handling in the Dynarec on some special cases - * Refactor library loading/unloading, with refcount. - * Some special cases fixes for dlopen (fixes deadcells, maybe others too) - * Improved mmap mapping, espcially with MAP_32BITS flag - * More wrapped functions and syscalls - * Lots of improvment in the Rounding of float & double (Dynarec and Interpreter), and proper handling of denormals when converting to/from 80 bits long double - * Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel) - * More support on the RV64 port - * More support to build under musl environment - --- Sebastien Chevalier Thu, 10 Mar 2023 10:20:33 -0500 + * Added a hacked version for overridden malloc/free functions, enabling libcef (and derivative) to work. + * Added rcfile handling: box64 now read "/etc/box64.box64rc" and "~/.box64rc" and apply per process parameters + * Added BOX64_DYNAREC_CALLRET to optimized CALL/RET opcode using semi-direct native CALL/RET (get more than 10% speedup) + * Added BOX64_DYNAREC_FORWARD to allow bigger Dynarec block to be build (can get more then 30% of Speedup!) + * Improved memory protection tracking and signal handling, again + * Simplified mutex handling (faster, cleaner) + * Reduce memory used by the memory tracking (memory almost divide by 4 is some critical use case) + * Added d3dadaptor9 wrapping + * More wrapped libs (especially on the gtk familly) + * Improved/fixed some Syscall handling + * Refactored Strong Memory Model emulation (faster and more accurate) + * Added some more opcode to ARM64 Dynarec, and fixed some other + * Some fixes to flags handling in the Dynarec on some special cases + * Refactor library loading/unloading, with refcount. + * Some special cases fixes for dlopen (fixes deadcells, maybe others too) + * Improved mmap mapping, espcially with MAP_32BITS flag + * More wrapped functions and syscalls + * Lots of improvment in the Rounding of float & double (Dynarec and Interpreter), and proper handling of denormals when converting to/from 80 bits long double + * Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel) + * More support on the RV64 port + * More support to build under musl environment + + -- Sebastien Chevalier Thu, 10 Mar 2023 10:20:33 -0500 box64 (0.2.0) unstable; urgency=low - * Wrapped more vulkan function, dxvk 2.0 now works - * Added support for overridden malloc/free functions - * Refactor Dynarec memory management, reducing memory footprint (from 20% to 40% of Dynarec size) - * Improved elf loader - * Improved dlsym handling with RTLD_NEXT - * Added BOX64_DYNAREC_SAFEFLAGS to allow finetuning Dynarec generated code handling of flags accross function calls and returns. - * Added BOX64_BASH to setup x86_64 bash binary, so shell script can be run in x86_64 world - * Added BOX64_ROLLING_LOG to have details log only on crash - * Work on alignment for some of pthread structures - * More wrapped libraries in the gtk family - * Some fixes on the Dynarec x87 code (fixing a bunch of games like ut2004 or Piczle Puzzle) - * Improved TLS Size handling (Unity3D games now works) - * More PageSize Compile options - * Improved execv family of function to have better box64 integration - * Added support for wrapped libfuse so AppImage works - * Adjusted the binfmt integration so AppImage are automaticaly picked - * Improved FAudio, SDL2, GL (and more) wrapping - * More wrapped libs, like libEGL.so, to helps emulated Qt4/5 libs to load - * Improved Signal Handling and memory protection traking - * Some signature fixes to some wrapped functions (in libc) - * Added more syscalls - * Added a lot of new opcodes to the ARM64 Dynarec - * docs: add instructions for Debian-based Linux by @ryanfortner in #306 - * Fix typos and arch type string by @archanox in #321 - * Fix grammar by @Jai-JAP in #326 - * Enable 64k page size by @martinmanyhats in #334 - * Align address when call mprotect by @wannacu in #336 - * Add wrapped functions needed for 'ls -l'. by @stiltr in #294 - * add 18.04 tegra X1 github actions by @theofficialgman in #345 - * change order of matrix (to preview better under checkmark dropdown by @theofficialgman in #346 - * Backport SDL_DYNAPI_entry wrapper from box86. by @JohnnyonFlame in #374 - * Add SW64 base support by @wannacu in #382 - * fix overzealous replace in wrappers pathnames by @NobodyNada in #415 - * Create X64WINE.md by @WheezyE in #423 - * src: asm: Rename lr & fp registers to their x-equivalents by @fredldotme in #426 - * Malloc override by @ptitSeb in #437 - * Remove dynablocklist by @ptitSeb in #438 - * Fix Pkgbuilds by @Jai-JAP in #452 + * Wrapped more vulkan function, dxvk 2.0 now works + * Added support for overridden malloc/free functions + * Refactor Dynarec memory management, reducing memory footprint (from 20% to 40% of Dynarec size) + * Improved elf loader + * Improved dlsym handling with RTLD_NEXT + * Added BOX64_DYNAREC_SAFEFLAGS to allow finetuning Dynarec generated code handling of flags accross function calls and returns. + * Added BOX64_BASH to setup x86_64 bash binary, so shell script can be run in x86_64 world + * Added BOX64_ROLLING_LOG to have details log only on crash + * Work on alignment for some of pthread structures + * More wrapped libraries in the gtk family + * Some fixes on the Dynarec x87 code (fixing a bunch of games like ut2004 or Piczle Puzzle) + * Improved TLS Size handling (Unity3D games now works) + * More PageSize Compile options + * Improved execv family of function to have better box64 integration + * Added support for wrapped libfuse so AppImage works + * Adjusted the binfmt integration so AppImage are automaticaly picked + * Improved FAudio, SDL2, GL (and more) wrapping + * More wrapped libs, like libEGL.so, to helps emulated Qt4/5 libs to load + * Improved Signal Handling and memory protection traking + * Some signature fixes to some wrapped functions (in libc) + * Added more syscalls + * Added a lot of new opcodes to the ARM64 Dynarec + * docs: add instructions for Debian-based Linux by @ryanfortner in #306 + * Fix typos and arch type string by @archanox in #321 + * Fix grammar by @Jai-JAP in #326 + * Enable 64k page size by @martinmanyhats in #334 + * Align address when call mprotect by @wannacu in #336 + * Add wrapped functions needed for 'ls -l'. by @stiltr in #294 + * add 18.04 tegra X1 github actions by @theofficialgman in #345 + * change order of matrix (to preview better under checkmark dropdown by @theofficialgman in #346 + * Backport SDL_DYNAPI_entry wrapper from box86. by @JohnnyonFlame in #374 + * Add SW64 base support by @wannacu in #382 + * fix overzealous replace in wrappers pathnames by @NobodyNada in #415 + * Create X64WINE.md by @WheezyE in #423 + * src: asm: Rename lr & fp registers to their x-equivalents by @fredldotme in #426 + * Malloc override by @ptitSeb in #437 + * Remove dynablocklist by @ptitSeb in #438 + * Fix Pkgbuilds by @Jai-JAP in #452 -- Sebastien Chevalier Thu, 17 Nov 2022 11:20:33 -0500 From 4df6988c9f02de9a2f9ad8c3cc1dd81f33a6cced Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 29 Oct 2026 21:19:55 +0800 Subject: [PATCH 102/156] [ARM64_DYNAREC] Fixed xmm value lost in a loop (#4627) ``` pcmpestrm xmm0, xmm14, 0x2 ``` In this opcode, `sse_get_reg_empty()` marked xmm0 old value as dead even when the same opcode had already read it, so loop merge points skipped storing it. And in the second iteration, the C helper of this opcode will have a stale value from memory. --- src/dynarec/arm64/dynarec_arm64_helper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index ac4f39b8c..adfebf0c7 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -1548,8 +1548,9 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a) dyn->n.xmm_used |= 1<n.ssecache[a].reg; } + if(!(dyn->n.xmm_used&(1<n.xmm_unneeded |= 1<n.xmm_used |= 1<n.xmm_unneeded |= 1<n.ssecache[a].reg = fpu_get_reg_xmm(dyn, NEON_CACHE_XMMW, a); dyn->n.ssecache[a].write = 1; // it will be write... return dyn->n.ssecache[a].reg; From 5055f947ebcb403e9396554a5f17a113b41ddbaa Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 29 Oct 2026 23:26:10 +0800 Subject: [PATCH 103/156] [ARM64_DYNAREC] Fixed wrong x87 NaN sign with memory operands (#4628) --- src/dynarec/arm64/dynarec_arm64_d8.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_d8.c b/src/dynarec/arm64/dynarec_arm64_d8.c index da414c771..c0a6abe3a 100644 --- a/src/dynarec/arm64/dynarec_arm64_d8.c +++ b/src/dynarec/arm64/dynarec_arm64_d8.c @@ -328,7 +328,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDS(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, v2, s5, s6); + X87_ARITH_NAN_END_S(v1, s0, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -339,7 +339,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDD(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, v2, s5, s6); + X87_ARITH_NAN_END_D(v1, s0, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -362,7 +362,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULS(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, v2, s5, s6); + X87_ARITH_NAN_END_S(v1, s0, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -373,7 +373,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULD(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, v2, s5, s6); + X87_ARITH_NAN_END_D(v1, s0, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -425,7 +425,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, v2, s5, s6); + X87_ARITH_NAN_END_S(v1, s0, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -436,7 +436,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, v2, s5, s6); + X87_ARITH_NAN_END_D(v1, s0, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -459,7 +459,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, s0, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, v2, s5, s6); + X87_ARITH_NAN_END_S(v1, s0, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -470,7 +470,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, s0, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, v2, s5, s6); + X87_ARITH_NAN_END_D(v1, s0, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -493,7 +493,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, v2, s5, s6); + X87_ARITH_NAN_END_S(v1, s0, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -504,7 +504,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, v2, s5, s6); + X87_ARITH_NAN_END_D(v1, s0, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -527,7 +527,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, s0, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, v2, s5, s6); + X87_ARITH_NAN_END_S(v1, s0, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -538,7 +538,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, s0, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, v2, s5, s6); + X87_ARITH_NAN_END_D(v1, s0, s5, s6); } } X87_CHECK_PRECISION(v1); From 07e9e5c34420b3116913b44e3f38a5c8f6f4e546 Mon Sep 17 00:00:00 2001 From: "Ari (Hamid) Zare" <12127420+hamidzr@users.noreply.github.com> Date: Thu, 29 Oct 2026 10:37:25 -0500 Subject: [PATCH 104/156] Fix typos in documentation (#4629) Signed-off-by: Hamid Zare <12127420+hamidzr@users.noreply.github.com> --- AGENTS.md | 2 +- README.md | 4 ++-- docs/BUNDLE-X86-LIBS.md | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 2a633ad04..ada114da9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,7 +20,7 @@ These use cases are **permitted** when making a contribution with the help of AI - Formatting code for consistency and readability (but do not overload code with comments) - Completing code segments based on established patterns - Drafting documentation for project components with which the contributor is already familiar - - Writting Wrappers Callback handling and/or wrappers structures conversion when needed + - Writing Wrappers Callback handling and/or wrappers structures conversion when needed AI-generated code that has undergone extensive human editing may be accepted, provided you (1) fully understand the AI's initial output, (2) can debug any issues independently (with or without further AI assistance), and (3) are prepared to discuss it directly with human reviewers. diff --git a/README.md b/README.md index 7e2417d14..6e219facb 100644 --- a/README.md +++ b/README.md @@ -58,14 +58,14 @@ Box64 requires 64-bit libraries on the host system, as it directly translates x8 1. Box32 is still experimental, but it's pretty stable now and can be used. 2. Some shell scripts (such as the GOG game installer) may rely on `uname -m` to determine the current architecture. Please run them as `box64 script.sh` to allow Box64 to take over. -Note that DynaCache is now enabled by default (with compression). This will creates files in `~/.cache/box64` to save generated code for executed binaries and libraries, so launch time can be greatly reduced on second run. The files are compressed and will take up to 2Gb by default. You can disable DynaCache writting, by switching it to a Read-only mode by creating (or modifying) `~/.box64rc` and writting there +Note that DynaCache is now enabled by default (with compression). This will creates files in `~/.cache/box64` to save generated code for executed binaries and libraries, so launch time can be greatly reduced on second run. The files are compressed and will take up to 2Gb by default. You can disable DynaCache writing, by switching it to a Read-only mode by creating (or modifying) `~/.box64rc` and writing there ```ini [*] BOX64_DYNACACHE=2 ``` -(or 0 to completly disabled it). Please refer to [Usage Documentation](docs/USAGE.md) for more details on how to configure Box64. +(or 0 to completely disabled it). Please refer to [Usage Documentation](docs/USAGE.md) for more details on how to configure Box64. --- diff --git a/docs/BUNDLE-X86-LIBS.md b/docs/BUNDLE-X86-LIBS.md index a6f91692d..cdacf8c46 100644 --- a/docs/BUNDLE-X86-LIBS.md +++ b/docs/BUNDLE-X86-LIBS.md @@ -78,13 +78,13 @@ Preference of operating system packages that provide a library: 2. DEBs from Debian 11 provide 5 years of updates. 3. EOPKG from Solus provide old variants of obscure 32-bit libraries. 4. XBPS from Void Linux provide updated variants of obscure 32-bit libraries. -5. Other (whereever a library is packaged) +5. Other (wherever a library is packaged) Some essential libraries will always be emulated and should be bundled. The full list can be found in the [in the core source code](https://github.com/ptitSeb/box64/blob/v0.4.0/src/core.c#L413). Some essential library files will never be emulated (only natively wrapped instead) and should not be bundled. This includes glibc, OpenGL, Vulkan, and X11/Xorg libraries. The full list can be found [in the library source code](https://github.com/ptitSeb/box64/blob/v0.4.0/src/librarian/library.c#L440). Other libraries with lots of dependencies, such as GTK, require all dependencies to be installed for emulation to work. This becomes dependency hell and should be avoided. -For finding package names that contian a specific library file, use the [pkgs.org website](https://pkgs.org/). Otherwise, use one of these package manager commands on a x86_64 Linux distribution: +For finding package names that contain a specific library file, use the [pkgs.org website](https://pkgs.org/). Otherwise, use one of these package manager commands on a x86_64 Linux distribution: - DEB - `apt-file ` - EOPKG From 25418aa1924ec2dcf535ab298e681f9f8fe2cec3 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Fri, 30 Oct 2026 15:05:12 +0800 Subject: [PATCH 105/156] [ARM64_DYNAREC] Fixed another xmm value lost in a loop (#4630) --- src/dynarec/arm64/dynarec_arm64_660f.c | 12 ++++++++++++ src/dynarec/arm64/dynarec_arm64_functions.c | 5 +++++ src/dynarec/arm64/dynarec_arm64_functions.h | 3 +++ 3 files changed, 20 insertions(+) diff --git a/src/dynarec/arm64/dynarec_arm64_660f.c b/src/dynarec/arm64/dynarec_arm64_660f.c index 2d09c4bf6..fcf0ef538 100644 --- a/src/dynarec/arm64/dynarec_arm64_660f.c +++ b/src/dynarec/arm64/dynarec_arm64_660f.c @@ -1324,6 +1324,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n ed = (nextop&7)+(rex.b<<3); if(ed>7) sse_reflect_reg(dyn, ninst, ed); + else + sse_mark_used(dyn, ninst, ed); ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed])); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1); @@ -1496,11 +1498,15 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n SETFLAGS(X_ALL, SF_SET_DF); if(gd>7) // no need to reflect cache as xmm0-xmm7 will be saved before the function call anyway sse_reflect_reg(dyn, ninst, gd); + else + sse_mark_used(dyn, ninst, gd); ADDx_U12(x3, xEmu, offsetof(x64emu_t, xmm[gd])); if(MODREG) { ed = (nextop&7)+(rex.b<<3); if(ed>7) sse_reflect_reg(dyn, ninst, ed); + else + sse_mark_used(dyn, ninst, ed); ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed])); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1); @@ -1540,6 +1546,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n ed = (nextop&7)+(rex.b<<3); if(ed>7) sse_reflect_reg(dyn, ninst, ed); + else + sse_mark_used(dyn, ninst, ed); ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed])); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1); @@ -1589,11 +1597,15 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n GETG; if(gd>7) sse_reflect_reg(dyn, ninst, gd); + else + sse_mark_used(dyn, ninst, gd); ADDx_U12(x2, xEmu, offsetof(x64emu_t, xmm[gd])); if(MODREG) { ed = (nextop&7)+(rex.b<<3); if(ed>7) sse_reflect_reg(dyn, ninst, ed); + else + sse_mark_used(dyn, ninst, ed); ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed])); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1); diff --git a/src/dynarec/arm64/dynarec_arm64_functions.c b/src/dynarec/arm64/dynarec_arm64_functions.c index c1dbe812f..398d8aa18 100644 --- a/src/dynarec/arm64/dynarec_arm64_functions.c +++ b/src/dynarec/arm64/dynarec_arm64_functions.c @@ -1514,6 +1514,11 @@ void updateYmm0s(dynarec_arm_t* dyn, int ninst, int max_ninst_reached) } +void sse_mark_used(dynarec_arm_t* dyn, int ninst, int a) +{ + dyn->n.xmm_used |= 1< Date: Fri, 30 Oct 2026 15:08:22 +0800 Subject: [PATCH 106/156] [INTERP] Fix some small errors (#4631) 1. sprintf `0x%x` need at least 11 bytes. 2. Fix RDPID opcode --- src/emu/x64runf30f.c | 27 ++++++++++++++------------- src/emu/x64tls.c | 2 +- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/emu/x64runf30f.c b/src/emu/x64runf30f.c index 3a99ebf63..cc678f853 100644 --- a/src/emu/x64runf30f.c +++ b/src/emu/x64runf30f.c @@ -552,19 +552,20 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) GX->ud[0]=(tmp8s)?0xffffffff:0; break; - case 0xC7: - CHECK_FLAGS(emu); - nextop = F8; - GETE8xw(0); - switch(tmp8u&7) { - case 6: /* RDPID Ed */ - ED->q[0] = helper_getcpu(emu); - SET_FLAG(F_CF); - break; - default: - return 0; - } - GX->ud[0]=(tmp8s)?0xffffffff:0; + case 0xC7: + nextop = F8; + tmp8u = nextop >> 3; + switch(tmp8u&7) { + case 7: /* RDPID Ed */ + if (!MODREG) { + return 0; + } + GETED(0); + ED->q[0] = helper_getcpu(emu); + break; + default: + return 0; + } break; case 0xD6: /* MOVQ2DQ Gx, Em */ diff --git a/src/emu/x64tls.c b/src/emu/x64tls.c index a427186eb..6ebe541b7 100644 --- a/src/emu/x64tls.c +++ b/src/emu/x64tls.c @@ -137,7 +137,7 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_32_t* td, int size) static const char* arch_prctl_param(int code) { - static char ret[10] = {0}; + static char ret[12] = {0}; switch (code) { case 0x1001: return "ARCH_SET_GS"; case 0x1002: return "ARCH_SET_FS"; From 5250c6e7a5a081d5d46c3df65f57d166724944c3 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Fri, 30 Oct 2026 15:15:12 +0800 Subject: [PATCH 107/156] [ARM64_DYNAREC] Fixed BOUND leaking a cleared deferred flags state (#4633) The BOUND handler emits a conditional CALL_S() and then continues. call_c() clears df and sets dyn->f to status_none, but only on the taken path. The fall-through kept a pending df while the codegen thought it was cleared, so the stale deferred op was re-applied later and corrupted the flags. Save and restore dyn->f around that call. --- src/dynarec/arm64/dynarec_arm64_00.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index bd9993be1..c3fa4fe26 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -37,6 +37,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin int32_t i32, tmp; int64_t i64, j64; uint8_t u8; + uint8_t f_save; uint8_t gb1, gb2, eb1, eb2; uint16_t u16; uint32_t u32; @@ -984,8 +985,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin B_NEXT_nocond; MARK; STORE_XEMU_CALL(xRIP); + f_save = dyn->f; CALL_S(const_native_br, -1); LOAD_XEMU_CALL(xRIP); + dyn->f = f_save; } else { INST_NAME("Illegal 62"); if(BOX64DRENV(dynarec_safeflags)>1) { From d318afe1b9e285b52e599093cef08f90dbb543de Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Fri, 30 Oct 2026 16:12:12 +0800 Subject: [PATCH 108/156] [INTERP] Added 16-bit LOCK BTR/BTC/BTS opcodes (#4634) --- src/emu/x64run66f0.c | 171 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) diff --git a/src/emu/x64run66f0.c b/src/emu/x64run66f0.c index 25d196be5..f39ec0cee 100644 --- a/src/emu/x64run66f0.c +++ b/src/emu/x64run66f0.c @@ -244,6 +244,177 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr) } break; + case 0xAB: /* BTS Ew,Gw */ + CHECK_FLAGS(emu); + nextop = F8; + if(MODREG) { + emu->error |= ERR_ILLEGAL; + return 0; + } + GETEW(0); + GETGW; + tmp16s = GW->sword[0]; + tmp8u = tmp16s & 15; + tmp16s >>= 4; + ED = (reg64_t*)((uintptr_t)ED + (tmp16s << 1)); + #if defined(DYNAREC) && !defined(TEST_INTERPRETER) + if ((uintptr_t)ED & 1) { + do { + tmp32u = native_lock_read_b(&(ED->byte[tmp8u >> 3])); + if (tmp32u & (1 << (tmp8u & 7))) { + SET_FLAG(F_CF); + tmp32s = 0; + } else { + tmp32u ^= (1 << (tmp8u & 7)); + tmp32s = native_lock_write_b(&(ED->byte[tmp8u >> 3]), tmp32u); + CLEAR_FLAG(F_CF); + } + } while (tmp32s); + } else { + do { + tmp32u = native_lock_read_h(ED); + if (tmp32u & (1 << tmp8u)) { + SET_FLAG(F_CF); + tmp32s = 0; + } else { + tmp32u ^= (1 << tmp8u); + tmp32s = native_lock_write_h(ED, tmp32u); + CLEAR_FLAG(F_CF); + } + } while (tmp32s); + } + #else + pthread_mutex_lock(&my_context->mutex_lock); + if (ED->word[0] & (1 << tmp8u)) { + SET_FLAG(F_CF); + } else { + ED->word[0] ^= (1 << tmp8u); + CLEAR_FLAG(F_CF); + } + pthread_mutex_unlock(&my_context->mutex_lock); + #endif + if (BOX64ENV(dynarec_test)) { + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_PF); + } + break; + + case 0xB3: /* BTR Ew,Gw */ + CHECK_FLAGS(emu); + nextop = F8; + if(MODREG) { + emu->error |= ERR_ILLEGAL; + return 0; + } + GETEW(0); + GETGW; + tmp16s = GW->sword[0]; + tmp8u = tmp16s & 15; + tmp16s >>= 4; + ED = (reg64_t*)((uintptr_t)ED + (tmp16s << 1)); + #if defined(DYNAREC) && !defined(TEST_INTERPRETER) + if ((uintptr_t)ED & 1) { + do { + tmp32u = native_lock_read_b(&(ED->byte[tmp8u >> 3])); + if (tmp32u & (1 << (tmp8u & 7))) { + SET_FLAG(F_CF); + tmp32u ^= (1 << (tmp8u & 7)); + tmp32s = native_lock_write_b(&(ED->byte[tmp8u >> 3]), tmp32u); + } else { + CLEAR_FLAG(F_CF); + tmp32s = 0; + } + } while (tmp32s); + } else { + do { + tmp32u = native_lock_read_h(ED); + if (tmp32u & (1 << tmp8u)) { + SET_FLAG(F_CF); + tmp32u ^= (1 << tmp8u); + tmp32s = native_lock_write_h(ED, tmp32u); + } else { + CLEAR_FLAG(F_CF); + tmp32s = 0; + } + } while (tmp32s); + } + #else + pthread_mutex_lock(&my_context->mutex_lock); + if (ED->word[0] & (1 << tmp8u)) { + SET_FLAG(F_CF); + ED->word[0] ^= (1 << tmp8u); + } else { + CLEAR_FLAG(F_CF); + } + pthread_mutex_unlock(&my_context->mutex_lock); + #endif + if (BOX64ENV(dynarec_test)) { + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_PF); + } + break; + + case 0xBB: /* BTC Ew,Gw */ + CHECK_FLAGS(emu); + nextop = F8; + if(MODREG) { + emu->error |= ERR_ILLEGAL; + return 0; + } + GETEW(0); + GETGW; + tmp16s = GW->sword[0]; + tmp8u = tmp16s & 15; + tmp16s >>= 4; + ED = (reg64_t*)((uintptr_t)ED + (tmp16s << 1)); + #if defined(DYNAREC) && !defined(TEST_INTERPRETER) + if ((uintptr_t)ED & 1) { + do { + tmp32u = native_lock_read_b(&(ED->byte[tmp8u >> 3])); + if (tmp32u & (1 << (tmp8u & 7))) { + SET_FLAG(F_CF); + tmp32s = 0; + } else { + CLEAR_FLAG(F_CF); + } + tmp32u ^= (1 << (tmp8u & 7)); + tmp32s = native_lock_write_b(&(ED->byte[tmp8u >> 3]), tmp32u); + } while (tmp32s); + } else { + do { + tmp32u = native_lock_read_h(ED); + if (tmp32u & (1 << tmp8u)) { + SET_FLAG(F_CF); + tmp32s = 0; + } else { + CLEAR_FLAG(F_CF); + } + tmp32u ^= (1 << tmp8u); + tmp32s = native_lock_write_h(ED, tmp32u); + } while (tmp32s); + } + #else + pthread_mutex_lock(&my_context->mutex_lock); + if (ED->word[0] & (1 << tmp8u)) { + SET_FLAG(F_CF); + } else { + CLEAR_FLAG(F_CF); + } + ED->word[0] ^= (1 << tmp8u); + pthread_mutex_unlock(&my_context->mutex_lock); + #endif + if (BOX64ENV(dynarec_test)) { + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_PF); + } + break; + case 0xC1: /* XADD Gw,Ew */ nextop = F8; if(MODREG) { From fb0b267f53fc0e0459963d3064f174daa0c8f362 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Fri, 30 Oct 2026 16:15:05 +0800 Subject: [PATCH 109/156] [ARM64_DYNAREC] Don't skip dirty preloaded regs on loopback (#4626) * [ARM64_DYNAREC] Don't skip dirty preloaded regs on loopback * [ARM64_DYNAREC] Added host_call and refined SSE preload handling --- src/dynarec/arm64/dynarec_arm64_functions.c | 7 ++++++- src/dynarec/arm64/dynarec_arm64_helper.c | 6 ++++++ src/dynarec/arm64/dynarec_arm64_pass0.h | 2 ++ src/dynarec/arm64/dynarec_arm64_private.h | 3 +++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/dynarec/arm64/dynarec_arm64_functions.c b/src/dynarec/arm64/dynarec_arm64_functions.c index 398d8aa18..c8151c060 100644 --- a/src/dynarec/arm64/dynarec_arm64_functions.c +++ b/src/dynarec/arm64/dynarec_arm64_functions.c @@ -1578,12 +1578,17 @@ void addSSEPreload(dynarec_arm_t* dyn, int ninst, int i2, uint32_t preload) if(i2 && !dyn->insts[i2-1].x64.has_next) // need a previous opcode to set the preload, unless it's the #0 return; // check if there is jump out or outside this loop + int has_host_call = 0; for(int i=i2; iinsts[i].x64.has_next || (dyn->insts[i].x64.barrier&BARRIER_FLOAT)) return; // for now, unneeded stop at first jump, so this should also stop there if(dyn->insts[i].x64.jmp/* && ((dyn->insts[i].x64.jmp_insts>ninst) || (dyn->insts[i].x64.jmp_instsinsts[i].host_call_clobber) + return; + if(dyn->insts[i].host_call) + has_host_call = 1; } uint16_t ymm_mask = 0; for(int i=0; i<16; ++i) { @@ -1622,9 +1627,9 @@ void addSSEPreload(dynarec_arm_t* dyn, int ninst, int i2, uint32_t preload) } } preload = (preload&0xffff) | (ymm_mask<<16); // update ymm_mask - //TODO: should check native calls too? 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.ymm_unneeded |= ymm_mask; } diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index adfebf0c7..e292d988f 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -548,6 +548,7 @@ void iret_to_next(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, int void call_c(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int reg, int ret, int saveflags, int savereg) { MAYUSE(fnc); + dyn->insts[ninst].host_call = 1; CHECK_DFNONE(1); #if STEP == 0 dyn->insts[ninst].nat_flags_op = NAT_FLAG_OP_UNUSABLE; @@ -607,6 +608,7 @@ void call_c(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int reg, int ret, void call_d(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int ret, int arg1, int arg2, int sav1, int sav2) { MAYUSE(fnc); + dyn->insts[ninst].host_call = 1; CHECK_DFNONE(1); #if STEP == 0 dyn->insts[ninst].nat_flags_op = NAT_FLAG_OP_UNUSABLE; @@ -653,6 +655,8 @@ void call_d(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int ret, int arg1 void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w) { MAYUSE(fnc); + dyn->insts[ninst].host_call = 1; + dyn->insts[ninst].host_call_clobber = 1; CHECK_DFNONE(1); #if STEP == 0 dyn->insts[ninst].nat_flags_op = NAT_FLAG_OP_UNUSABLE; @@ -2129,6 +2133,8 @@ static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int MESSAGE(LOG_DUMP, "\tFPU Cache Transform ---- ninst=%d -> %d\n", ninst, i2); uint32_t unneeded = dyn->insts[i2].n.xmm_unneeded | (dyn->insts[i2].n.ymm_unneeded<<16); if((!i2) || (dyn->insts[i2].x64.barrier&BARRIER_FLOAT)) { + if(dyn->insts[i2].preload_host_call) + unneeded &= ~dyn->insts[i2].preload_xmmymm; int need_purge = 0; if(dyn->n.stack_next) need_purge = 1; diff --git a/src/dynarec/arm64/dynarec_arm64_pass0.h b/src/dynarec/arm64/dynarec_arm64_pass0.h index 812a9aae5..2f194e72a 100644 --- a/src/dynarec/arm64/dynarec_arm64_pass0.h +++ b/src/dynarec/arm64/dynarec_arm64_pass0.h @@ -38,6 +38,8 @@ dyn->n.combined1 = dyn->n.combined2 = 0;\ dyn->n.swapped = 0; dyn->n.barrier = 0; \ dyn->insts[ninst].f_entry = dyn->f; \ + dyn->insts[ninst].host_call = 0; \ + dyn->insts[ninst].host_call_clobber = 0;\ dyn->insts[ninst].x64.strongmem = ((box64_wine && VolatileRangesContains(ip)) ? 0 : BOX64DRENV(dynarec_strongmem)); \ if(dyn->insts[ninst].x64.strongmem && cpuext.lrcpc && cpuext.lrcpc2 && cpuext.uscat) dyn->insts[ninst].use_lrcpc = 1; \ if(ninst) {dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr;} \ diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h index 040e96eb8..3df190d9a 100644 --- a/src/dynarec/arm64/dynarec_arm64_private.h +++ b/src/dynarec/arm64/dynarec_arm64_private.h @@ -156,6 +156,9 @@ typedef struct instruction_arm64_s { unsigned x87_used:1; // no fine tracking, just a global "any reg used" unsigned fpu_used:1; // any xmm/ymm/x87/mmx reg used unsigned fpupurge:1; // this opcode will purge all fpu regs + unsigned host_call:1; // this opcode performs a native call + unsigned host_call_clobber:1; // native call does not preserve cached xmm0-7 (call_n) + unsigned preload_host_call:1; // preload range contains a host call, needs write-back at merge unsigned use_lrcpc:1;// use the various lrcpc opcode here instead of regular LD/ST + memory barrier unsigned has_lrcpc:1;// set if the opcode has some lrcpc opcode in it flagcache_t f_exit; // flags status at end of instruction From 75cff5c5849867b568f981cd1416c884207c2d41 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Fri, 30 Oct 2026 16:26:41 +0800 Subject: [PATCH 110/156] [INTERP] Fixed unaligned LOCK BTS (#4635) --- src/emu/x64runf0.c | 82 +++++++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/src/emu/x64runf0.c b/src/emu/x64runf0.c index c17bf60ac..583cd0628 100644 --- a/src/emu/x64runf0.c +++ b/src/emu/x64runf0.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT #define _GNU_SOURCE #include #include @@ -79,7 +79,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) GETED(0); \ GETGD; \ if(F) {CHECK_FLAGS(emu); eflags=emu->eflags;} \ - if(((uintptr_t)ED)&(rex.w?7:3)) { \ + if(((uintptr_t)ED)&(rex.w?7:3)) { \ if(rex.w) { \ do { \ if(F) emu->eflags = eflags; \ @@ -178,35 +178,63 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) #else ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2))); #endif -#if defined(DYNAREC) && !defined(TEST_INTERPRETER) + #if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) { tmp8u&=63; - do { - tmp64u = native_lock_read_dd(ED); - if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) { + SET_FLAG(F_CF); + tmp32s = 0; + } else { + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + CLEAR_FLAG(F_CF); + } + } while(tmp32s); + } else { + do { + tmp64u = native_lock_read_dd(ED); + if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) { + SET_FLAG(F_CF); + tmp32s = 0; + } else { + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + CLEAR_FLAG(F_CF); + } + } while(tmp32s); + } else { + do { + tmp32u = native_lock_read_d(ED); + if(tmp32u & (1<mutex_lock); if(rex.w) { tmp8u&=63; @@ -226,7 +254,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) } } pthread_mutex_unlock(&my_context->mutex_lock); -#endif + #endif if(BOX64ENV(dynarec_test)) { CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); From 6c88bbda42931c408147ed2f2bc22cf9eb34b135 Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Sat, 31 Oct 2026 00:44:05 +0800 Subject: [PATCH 111/156] [RV64_DYNAREC] Keep live XMMs when reflecting cache (#4624) When BOX64_DYNAREC_TEST is enabled, `dead=1` will corrupt xmm register value. --- src/dynarec/rv64/dynarec_rv64_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 478b1e1eb..ccd99ca02 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -1983,7 +1983,7 @@ static void sse_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1) flushed8 = 1; ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VSE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); - avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, 0, 1); + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, 0, 0); } else if (dyn->e.ssecache[i].single) FSW(dyn->e.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i])); else From 8a7a148bdda279c92601fe13817b87e036f94ae3 Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Sat, 31 Oct 2026 00:45:33 +0800 Subject: [PATCH 112/156] [RV64_DYNAREC] Translate round mode for some int to float convert opcodes (#4636) Add sse_setround for CVTSI2SS/CVTDQ2PS/VCVTDQ2PS/CVTSI2SD opcodes. --- src/dynarec/rv64/dynarec_rv64_0f_vector.c | 2 ++ src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c | 2 ++ src/dynarec/rv64/dynarec_rv64_f20f.c | 6 ++++-- src/dynarec/rv64/dynarec_rv64_f20f_vector.c | 9 +++++++-- src/dynarec/rv64/dynarec_rv64_f30f_vector.c | 11 ++++++++--- 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_0f_vector.c index 39a997215..718e4e82e 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_0f_vector.c @@ -659,7 +659,9 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); GETEX_vector(q0, 0, 0, VECTOR_SEW32); GETGX_empty_vector(v0); + if (!BOX64ENV(dynarec_fastround)) u8 = sse_setround(dyn, ninst, x6, x4); VFCVT_F_X_V(v0, q0, VECTOR_UNMASKED); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); break; case 0x5C: if (!BOX64ENV(dynarec_fastnan)) return 0; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index 280e801a9..6ba9f356c 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -378,7 +378,9 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t nextop = F8; GETEY_vector(q0, 0, VECTOR_SEW32); GETGY_empty_vector(v0); + if (!BOX64ENV(dynarec_fastround)) u8 = sse_setround(dyn, ninst, x6, x4); VFCVT_F_X_V(v0, q0, VECTOR_UNMASKED); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x5C: diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c index 264ea4db9..c5cc7934c 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f.c @@ -93,11 +93,13 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int nextop = F8; GETGXSD(v0); GETED(0); + if (!BOX64ENV(dynarec_fastround)) u8 = sse_setround(dyn, ninst, x6, x4); if (rex.w) { - FCVTDL(v0, ed, RD_RNE); + FCVTDL(v0, ed, !BOX64ENV(dynarec_fastround) ? RD_DYN : RD_RNE); } else { - FCVTDW(v0, ed, RD_RNE); + FCVTDW(v0, ed, !BOX64ENV(dynarec_fastround) ? RD_DYN : RD_RNE); } + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); break; case 0x2C: INST_NAME("CVTTSD2SI Gd, Ex"); diff --git a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c index 06e4f69f2..1005296dd 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c @@ -117,14 +117,19 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i SET_ELEMENT_WIDTH(x3, VECTOR_SEW64, 1); GETGX_vector(v0, 1, VECTOR_SEW64); GETED(0); - FCVTDL(v0, ed, RD_RNE); } else { SET_ELEMENT_WIDTH(x3, VECTOR_SEW32, 1); GETGX_vector(v0, 1, VECTOR_SEW32); GETED(0); - FCVTDW(v0, ed, RD_RNE); + } + if (!BOX64ENV(dynarec_fastround)) u8 = sse_setround(dyn, ninst, x5, x6); + if (rex.w) { + FCVTDL(v0, ed, !BOX64ENV(dynarec_fastround) ? RD_DYN : RD_RNE); + } else { + FCVTDW(v0, ed, !BOX64ENV(dynarec_fastround) ? RD_DYN : RD_RNE); SET_ELEMENT_WIDTH(x3, VECTOR_SEW64, 1); } + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); if (cpuext.xtheadvector) { v1 = fpu_get_scratch(dyn); VFMV_S_F(v1, v0); diff --git a/src/dynarec/rv64/dynarec_rv64_f30f_vector.c b/src/dynarec/rv64/dynarec_rv64_f30f_vector.c index 38386b38b..37512bfc3 100644 --- a/src/dynarec/rv64/dynarec_rv64_f30f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f30f_vector.c @@ -143,14 +143,19 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i SET_ELEMENT_WIDTH(x3, VECTOR_SEW64, 1); GETGX_vector(v0, 1, VECTOR_SEW64); GETED(0); - FCVTSL(v0, ed, RD_RNE); - SET_ELEMENT_WIDTH(x3, VECTOR_SEW32, 1); } else { SET_ELEMENT_WIDTH(x3, VECTOR_SEW32, 1); GETGX_vector(v0, 1, VECTOR_SEW32); GETED(0); - FCVTSW(v0, ed, RD_RNE); } + if (!BOX64ENV(dynarec_fastround)) u8 = sse_setround(dyn, ninst, x5, x6); + if (rex.w) { + FCVTSL(v0, ed, !BOX64ENV(dynarec_fastround) ? RD_DYN : RD_RNE); + SET_ELEMENT_WIDTH(x3, VECTOR_SEW32, 1); + } else { + FCVTSW(v0, ed, !BOX64ENV(dynarec_fastround) ? RD_DYN : RD_RNE); + } + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); if (cpuext.xtheadvector) { v1 = fpu_get_scratch(dyn); VFMV_S_F(v1, v0); From 81e0246b2a2ff1c963428ebc5635e770b7c0b512 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sat, 31 Oct 2026 03:10:33 +0800 Subject: [PATCH 113/156] [DYNAREC] Small fixes to in_used tracking (#4638) --- src/dynarec/arm64/dynarec_arm64_00.c | 6 ++++++ src/dynarec/dynablock.c | 16 +++++++++++++--- src/dynarec/dynarec.c | 2 ++ src/dynarec/dynarec_native_pass.c | 1 + src/dynarec/la64/dynarec_la64_00_3.c | 6 ++++++ src/dynarec/la64/dynarec_la64_helper.c | 4 ++-- src/dynarec/rv64/dynarec_rv64_00_3.c | 6 ++++++ src/dynarec/rv64/dynarec_rv64_helper.c | 4 ++-- src/dynarec/rv64/dynarec_rv64_helper.h | 4 ++++ src/dynarec/rv64/dynarec_rv64_pass2.h | 4 ++++ src/dynarec/rv64/dynarec_rv64_pass3.h | 1 + 11 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index c3fa4fe26..2a35179cb 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -3985,6 +3985,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOV64x(x4, j64); } LDRx_U12(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x1, x2, x3); BR(x4); } CLEARIP(); @@ -4683,6 +4685,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); TABLE64_(x4, j64); LDRx_U12(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x1, x2, x3); BR(x4); } CLEARIP(); @@ -4744,6 +4748,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); TABLE64_(x4, j64); LDRx_U12(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x1, x2, x3); BR(x4); } CLEARIP(); diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c index 4f470b10f..57c425cd1 100644 --- a/src/dynarec/dynablock.c +++ b/src/dynarec/dynablock.c @@ -111,6 +111,8 @@ dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock) return db; } +static void QueueZombieDynablock(dynablock_t* db); + static void RetireOrphanDynablocks(void) { for (int i = 0; i < my_context->db_orphan_count; ) { @@ -119,8 +121,11 @@ static void RetireOrphanDynablocks(void) ++i; continue; } - if (db) FreeDynarecMap((uintptr_t)db->actual_block); my_context->db_orphan[i] = my_context->db_orphan[--my_context->db_orphan_count]; + // released by its last user: requeue it instead of freeing right away, a thread + // may still be running the last instructions of the block (and the enter/leave + // pair is not atomic with the code around it) + if (db) QueueZombieDynablock(db); } } @@ -139,9 +144,8 @@ static void QueueOrphanDynablock(dynablock_t* db) my_context->db_orphan[my_context->db_orphan_count++] = db; } -static void DeferFreeDynablockMap(dynablock_t* db) +static void QueueZombieDynablock(dynablock_t* db) { - if (my_context->db_orphan_count) RetireOrphanDynablocks(); // enq for a deferred free so any threads still running in this block has a better chance to finish. if (my_context->db_zombie_count == DB_ZOMBIE_SIZE) { // Queue full: free the oldest queued block that no running dynarec chain holds (in_used), compact the queue. @@ -186,6 +190,12 @@ static void DeferFreeDynablockMap(dynablock_t* db) } } +static void DeferFreeDynablockMap(dynablock_t* db) +{ + if (my_context->db_orphan_count) RetireOrphanDynablocks(); + QueueZombieDynablock(db); +} + void DeferFreeDynablockClearRange(void* addr, size_t sz) { int head = my_context->db_zombie_head; diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c index 8bdbbb164..33e751c09 100644 --- a/src/dynarec/dynarec.c +++ b/src/dynarec/dynarec.c @@ -103,6 +103,8 @@ void* LinkNextInvalid(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3) int is32bits = (R_CS == 0x23); dynablock_t* db = getDB(addr); if(db) { + // the caller entered this block before running the check that failed here + dynablock_leave_runtime(db); mutex_lock(&my_context->mutex_dyndump); db->done = 0; dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X, gone:%d, autocrc:%d, to_delete:%d) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size, db->hash, db->gone, db->autocrc, db->to_delete, (void*)addr); diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index bb479037e..a9f1011d5 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -186,6 +186,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int doEnterBlock(dyn, 0, x1, x2, x3); if (dyn->insts[0].preload_xmmymm) doPreload(dyn, 0); + ENDPREFIX; } #endif fpu_propagate_stack(dyn, ninst); diff --git a/src/dynarec/la64/dynarec_la64_00_3.c b/src/dynarec/la64/dynarec_la64_00_3.c index caddad588..5571b4d35 100644 --- a/src/dynarec/la64/dynarec_la64_00_3.c +++ b/src/dynarec/la64/dynarec_la64_00_3.c @@ -1435,6 +1435,8 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int MOV64x(x4, j64); } LD_D(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x5, x6, x7); BR(x4); } CLEARIP(); @@ -2139,6 +2141,8 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int if (dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); TABLE64_(x4, j64); LD_D(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x5, x6, x7); BR(x4); } CLEARIP(); @@ -2204,6 +2208,8 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int if (dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); TABLE64_(x4, j64); LD_D(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x5, x6, x7); BR(x4); } CLEARIP(); diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c index 65d1c2922..1edc27c46 100644 --- a/src/dynarec/la64/dynarec_la64_helper.c +++ b/src/dynarec/la64/dynarec_la64_helper.c @@ -414,7 +414,7 @@ void doEnterBlock(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3) LD_D(s1, s1, 0); // load the dynablock pointer ADDI_D(s1, s1, offsetof(dynablock_t, in_used)); MOV32w(s3, 1); - AMADD_W(s2, s3, s1); + AMADD_DB_W(s2, s3, s1); } void doLeaveBlock(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3) @@ -426,7 +426,7 @@ void doLeaveBlock(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3) LD_D(s1, s1, 0); // load the dynablock pointer ADDI_D(s1, s1, offsetof(dynablock_t, in_used)); MOV32w(s3, -1); - AMADD_W(s2, s3, s1); + AMADD_DB_W(s2, s3, s1); } diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 7838e908f..e3ace2ea6 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -1390,6 +1390,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int MOV64x(x4, j64); } LD(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x5, x6, x7); BR(x4); } CLEARIP(); @@ -2013,6 +2015,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); TABLE64_(x4, j64); LD(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x5, x6, x7); BR(x4); } CLEARIP(); @@ -2083,6 +2087,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); TABLE64_(x4, j64); LD(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x5, x6, x7); BR(x4); } CLEARIP(); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index ccd99ca02..3deac28d8 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -443,7 +443,7 @@ void doEnterBlock(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3) LD(s1, s1, 0); // load the dynablock pointer ADDI(s1, s1, offsetof(dynablock_t, in_used)); MOV32w(s3, 1); - AMOADD_W(s2, s3, s1, 0, 0); + AMOADD_W(s2, s3, s1, 0, 1); } void doLeaveBlock(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3) @@ -455,7 +455,7 @@ void doLeaveBlock(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3) LD(s1, s1, 0); // load the dynablock pointer ADDI(s1, s1, offsetof(dynablock_t, in_used)); MOV32w(s3, -1); - AMOADD_W(s2, s3, s1, 0, 0); + AMOADD_W(s2, s3, s1, 0, 1); } #ifdef JMPTABLE_SHIFT4 #error TODO! diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 7eef3e56e..1983446d0 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -20,6 +20,10 @@ #include "../emu/x64primop.h" #include "dynarec_rv64_consts.h" +#ifndef ENDPREFIX +#define ENDPREFIX +#endif + #define F8 *(uint8_t*)(addr++) #define F8S *(int8_t*)(addr++) #define F16 *(uint16_t*)(addr += 2, addr - 2) diff --git a/src/dynarec/rv64/dynarec_rv64_pass2.h b/src/dynarec/rv64/dynarec_rv64_pass2.h index f344368ec..740c11de8 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass2.h +++ b/src/dynarec/rv64/dynarec_rv64_pass2.h @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT #define INIT dyn->native_size = 0 +#define ENDPREFIX \ + dyn->prefixsize = dyn->native_size; \ + dyn->insts[ninst].address = dyn->native_size; \ + dyn->insts[ninst].size = 0 #define FINI \ if (ninst) { \ dyn->insts[ninst].address = (dyn->insts[ninst - 1].address + dyn->insts[ninst - 1].size); \ diff --git a/src/dynarec/rv64/dynarec_rv64_pass3.h b/src/dynarec/rv64/dynarec_rv64_pass3.h index 0503a23f0..0db21da8e 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass3.h +++ b/src/dynarec/rv64/dynarec_rv64_pass3.h @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT #define INIT +#define ENDPREFIX dyn->insts[ninst].size2 = 0 #define FINI \ if (ninst) \ addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst-1].x64.size, dyn->insts[ninst-1].size/4); \ From 6367180c2c6d2e4876e42f75db6ecd8c3d0f37de Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sat, 31 Oct 2026 03:11:44 +0800 Subject: [PATCH 114/156] [ARM64_DYNAREC] Fixed 16-bit BT/BTS/BTR/BTC displacement scale (#4639) --- src/dynarec/arm64/dynarec_arm64_660f.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_660f.c b/src/dynarec/arm64/dynarec_arm64_660f.c index fcf0ef538..38e6b7032 100644 --- a/src/dynarec/arm64/dynarec_arm64_660f.c +++ b/src/dynarec/arm64/dynarec_arm64_660f.c @@ -2478,7 +2478,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n ed = TO_NAT((nextop & 7) + (rex.b << 3)); } else { SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0); + addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, 0); SBFXx(x1, gd, 4, 12); // r1 = (gw>>4) ADDx_REG_LSL(x3, wback, x1, 1); //(&ed)+=r1*2; LDH(x1, x3, fixedaddress); @@ -2539,7 +2539,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n ed = TO_NAT((nextop & 7) + (rex.b << 3)); wback = 0; } else { - addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0); + addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, 0); SBFXx(x4, gd, 4, 12); // r1 = (gw>>4) ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2; LDH(x4, x3, fixedaddress); @@ -2665,7 +2665,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n wback = 0; } else { SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0); + addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, 0); SBFXx(x4, gd, 4, 12); // r1 = (gw>>4) ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2; LDH(x4, x3, fixedaddress); @@ -2810,7 +2810,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n wback = 0; } else { SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0); + addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, 0); SBFXx(x4, gd, 4, 12); // r1 = (gw>>4) ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2; LDH(x4, x3, fixedaddress); From 6dfbebd2d485efe1510db02a45ac0235c1f75ddc Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sat, 31 Oct 2026 03:13:21 +0800 Subject: [PATCH 115/156] [ARM64_DYNAREC] Fixed YMM upper half lost with VPCLMULQDQ fallback (#4632) * [ARM64_DYNAREC] Fixed YMM upper half lost with VPCLMULQDQ fallback native_pclmul_y() reads the Ex operand's upper 128 bits from emu->ymm[ed], but the handler used sse_forget_reg() for Ex, which only marks xmm_used. The upper half was considered dead, so loop merge points skipped materializing its pending zero. Use sse_reflect_reg() like for Vx. * [ARM64_DYNAREC] Fixed sse_forget_reg YMM handling --- src/dynarec/arm64/dynarec_arm64_helper.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index e292d988f..b5f3794e5 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -1563,10 +1563,13 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a) void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a) { dyn->n.xmm_used |= 1<n.ssecache[a].v==-1) - return; - if(dyn->n.neoncache[dyn->n.ssecache[a].reg].t == NEON_CACHE_XMMW) { - VSTR128_U12(dyn->n.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a])); + dyn->n.ymm_used |= 1<n.ssecache[a].v!=-1) { + if(dyn->n.neoncache[dyn->n.ssecache[a].reg].t == NEON_CACHE_XMMW) { + VSTR128_U12(dyn->n.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a])); + } + fpu_free_reg(dyn, dyn->n.ssecache[a].reg); + dyn->n.ssecache[a].v = -1; } // YMM part too if(is_avx_zero_unset(dyn, ninst, a)) { @@ -1584,9 +1587,6 @@ void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a) fpu_free_reg(dyn, i); } - fpu_free_reg(dyn, dyn->n.ssecache[a].reg); - dyn->n.ssecache[a].v = -1; - return; } // purge the SSE cache for XMM0..XMM7 (to use before function native call) void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1) From a7f9094034d27563be4f7b4171699dff4e1b58f1 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sat, 31 Oct 2026 14:56:55 +0800 Subject: [PATCH 116/156] [INTERP] Fixed more unaligned LOCK BT* opcodes (#4641) --- src/emu/x64runf0.c | 314 ++++++++++++++++++++++++++++++--------------- 1 file changed, 210 insertions(+), 104 deletions(-) diff --git a/src/emu/x64runf0.c b/src/emu/x64runf0.c index 583cd0628..218ad3e9f 100644 --- a/src/emu/x64runf0.c +++ b/src/emu/x64runf0.c @@ -401,33 +401,61 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2))); #endif tmp8u&=rex.w?63:31; -#if defined(DYNAREC) && !defined(TEST_INTERPRETER) - if(rex.w) - do { - tmp64u = native_lock_read_dd(ED); - if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) { + SET_FLAG(F_CF); + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + } else { + CLEAR_FLAG(F_CF); + tmp32s = 0; + } + } while(tmp32s); + } else { + do { + tmp64u = native_lock_read_dd(ED); + if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) { + SET_FLAG(F_CF); + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + } else { + CLEAR_FLAG(F_CF); + tmp32s = 0; + } + } while(tmp32s); + } else { + do { + tmp32u = native_lock_read_d(ED); + if(tmp32u & (1<mutex_lock); if(rex.w) { if(ED->q[0] & (1ULL<mutex_lock); -#endif + #endif if(BOX64ENV(dynarec_test)) { CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); @@ -466,20 +494,34 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) CHECK_FLAGS(emu); GETED(1); tmp8u = F8; -#if defined(DYNAREC) && !defined(TEST_INTERPRETER) + #if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) { tmp8u&=63; - do { - tmp64u = native_lock_read_dd(ED); - if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) { + SET_FLAG(F_CF); + tmp32s = 0; + } else { + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + CLEAR_FLAG(F_CF); + } + } while(tmp32s); + } else { + do { + tmp64u = native_lock_read_dd(ED); + if(tmp64u & (1LL<mutex_lock); if(rex.w) { tmp8u&=63; @@ -528,7 +570,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) } } pthread_mutex_unlock(&my_context->mutex_lock); -#endif + #endif if(BOX64ENV(dynarec_test)) { CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); @@ -540,35 +582,63 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) CHECK_FLAGS(emu); GETED(1); tmp8u = F8; -#if defined(DYNAREC) && !defined(TEST_INTERPRETER) + #if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) { - do { - tmp8u&=63; - tmp64u = native_lock_read_dd(ED); - if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) { + SET_FLAG(F_CF); + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + } else { + CLEAR_FLAG(F_CF); + tmp32s = 0; + } + } while(tmp32s); + } else { + do { + tmp64u = native_lock_read_dd(ED); + if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) { + SET_FLAG(F_CF); + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + } else { + CLEAR_FLAG(F_CF); + tmp32s = 0; + } + } while(tmp32s); + } else { + do { + tmp32u = native_lock_read_d(ED); + if(tmp32u & (1<mutex_lock); if(rex.w) { tmp8u&=63; @@ -586,7 +656,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) CLEAR_FLAG(F_CF); } pthread_mutex_unlock(&my_context->mutex_lock); -#endif + #endif if(BOX64ENV(dynarec_test)) { CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); @@ -598,18 +668,30 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) CHECK_FLAGS(emu); GETED(1); tmp8u = F8; -#if defined(DYNAREC) && !defined(TEST_INTERPRETER) + #if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) { tmp8u&=63; - do { - tmp64u = native_lock_read_dd(ED); - if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) + SET_FLAG(F_CF); + else + CLEAR_FLAG(F_CF); + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + } while(tmp32s); + } else { + do { + tmp64u = native_lock_read_dd(ED); + if(tmp64u & (1LL<mutex_lock); if(rex.w) { tmp8u&=63; @@ -652,7 +734,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) ED->dword[0] ^= (1<mutex_lock); -#endif + #endif if(BOX64ENV(dynarec_test)) { CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); @@ -687,31 +769,55 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2))); #endif tmp8u&=rex.w?63:31; -#if defined(DYNAREC) && !defined(TEST_INTERPRETER) - if(rex.w) - do { - tmp64u = native_lock_read_dd(ED); - if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) + SET_FLAG(F_CF); + else + CLEAR_FLAG(F_CF); + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + } while(tmp32s); + } else { + do { + tmp64u = native_lock_read_dd(ED); + if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) + SET_FLAG(F_CF); + else + CLEAR_FLAG(F_CF); + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + } while(tmp32s); + } else { + do { + tmp32u = native_lock_read_d(ED); + if(tmp32u & (1<mutex_lock); if(rex.w) { if(ED->q[0] & (1ULL<dword[0] ^= (1<mutex_lock); -#endif + #endif if(BOX64ENV(dynarec_test)) { CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); From d74ec762c695d1a399284de7617980a9946d6a9f Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sat, 31 Oct 2026 15:06:27 +0800 Subject: [PATCH 117/156] [DYNAREC] Don't run a block that intersects a hot page (#4642) DBGetBlock only checked the page of the block entry address. A block built before one of its pages became hot kept being validated and re-protected, so its own store into that page faulted again on every entry, and the block restarted without making progress. Check all guest pages covered by the existing block and fall back to the interpreter while any of them is hot. --- src/dynarec/dynablock.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c index 57c425cd1..4dcdfe4e4 100644 --- a/src/dynarec/dynablock.c +++ b/src/dynarec/dynablock.c @@ -500,6 +500,20 @@ void FlushZombieDynablocks(void) dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits) { int is_inhotpage = isInHotPage(addr); + if(!is_inhotpage && !BOX64ENV(dynarec_dirty)) { + dynablock_t* db = getDB(addr); + if(db && db->x64_size) { + uintptr_t dbstart = (uintptr_t)db->x64_addr; + uintptr_t dbend = dbstart + db->x64_size; + for(uintptr_t page = (dbstart&~(X86_PAGE_SIZE-1)); page < dbend; page += X86_PAGE_SIZE) { + if(page == (addr&~(X86_PAGE_SIZE-1))) continue; // skip the first page + if(checkInHotPage(page)) { + is_inhotpage = 1; + break; + } + } + } + } if(is_inhotpage && !BOX64ENV(dynarec_dirty)) return NULL; dynablock_t *db = internalDBGetBlock(emu, addr, create, 1, is32bits, 1); From d7124fdd64aa18576653755c1f46e6478dbf4747 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Sat, 31 Oct 2026 11:58:24 +0100 Subject: [PATCH 118/156] [DYNAREC] Reused getDB result is InternalDBGetBlock (linked with #4642) --- src/dynarec/dynablock.c | 16 +++++++++++----- src/dynarec/dynarec.c | 2 +- src/include/dynablock.h | 3 ++- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c index 4dcdfe4e4..b1d1f0c32 100644 --- a/src/dynarec/dynablock.c +++ b/src/dynarec/dynablock.c @@ -385,12 +385,15 @@ dynablock_t* CreateDBnoAlt(x64emu_t* emu, uintptr_t addr, int is32bits) return NULL if block is not found / cannot be created. Don't create if create==0 */ -dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int need_lock, int is32bits, int is_new) +dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int need_lock, int is32bits, int is_new, dynablock_t* block) { const uint32_t req_prot = (box64_pagesize==4096)?(PROT_EXEC|PROT_READ):PROT_READ; if(BOX64ENV(nodynarec_delay) && (addr>=BOX64ENV(nodynarec_start)) && (addrto_delete) { // just delete the block then, so we can create a new one right away FreeDynablock(block, 1, 1); @@ -500,8 +503,9 @@ void FlushZombieDynablocks(void) dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits) { int is_inhotpage = isInHotPage(addr); + dynablock_t* db = NULL; if(!is_inhotpage && !BOX64ENV(dynarec_dirty)) { - dynablock_t* db = getDB(addr); + db = getDB(addr); if(db && db->x64_size) { uintptr_t dbstart = (uintptr_t)db->x64_addr; uintptr_t dbend = dbstart + db->x64_size; @@ -513,10 +517,12 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits) } } } + if(!db) + db = SEARCHED_NO_DYNABLOCK; } if(is_inhotpage && !BOX64ENV(dynarec_dirty)) return NULL; - dynablock_t *db = internalDBGetBlock(emu, addr, create, 1, is32bits, 1); + db = internalDBGetBlock(emu, addr, create, 1, is32bits, 1, db); if(db && db->done && db->block && getNeedTest(addr)) { //if (db->always_test) SchedYield(); // just calm down... uint32_t hash = X31_hash_code((void*)db->x64_readaddr, db->x64_size); @@ -531,7 +537,7 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits) dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X, gone:%d, autocrc:%d, to_delete:%d) for %p\n", db, db->x64_addr, db->x64_addr + db->x64_size, db->hash, db->gone, db->autocrc, db->to_delete, (void*)addr); dynablock_t* old = InvalidDynablock(db, 0); FreeInvalidDynablock(old, 0); - db = internalDBGetBlock(emu, addr, 1, 0, is32bits, 0); + db = internalDBGetBlock(emu, addr, 1, 0, is32bits, 0, SEARCHED_NO_DYNABLOCK); } else { if(is_inhotpage) { db->always_test = 2; diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c index 33e751c09..b5370ce56 100644 --- a/src/dynarec/dynarec.c +++ b/src/dynarec/dynarec.c @@ -110,7 +110,7 @@ void* LinkNextInvalid(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3) dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X, gone:%d, autocrc:%d, to_delete:%d) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size, db->hash, db->gone, db->autocrc, db->to_delete, (void*)addr); dynablock_t* old = InvalidDynablock(db, 0); FreeInvalidDynablock(old, 0); - db = internalDBGetBlock(emu, addr, 1, 0, is32bits, 0); + db = internalDBGetBlock(emu, addr, 1, 0, is32bits, 0, SEARCHED_NO_DYNABLOCK); mutex_unlock(&my_context->mutex_dyndump); if(db && db->done && db->block && (uintptr_t)db->x64_addr == addr) return db->block; diff --git a/src/include/dynablock.h b/src/include/dynablock.h index fb21af301..0adaa6dec 100644 --- a/src/include/dynablock.h +++ b/src/include/dynablock.h @@ -19,7 +19,8 @@ dynablock_t* FindDynablockFromNativeAddress(void* addr); // defined in box64c // Handling of Dynarec block (i.e. an exectable chunk of x64 translated code) dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits); // return NULL if block is not found / cannot be created. Don't create if create==0 -dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int need_lock, int is32bits, int is_new); +#define SEARCHED_NO_DYNABLOCK ((dynablock_t*)-1ULL) +dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int need_lock, int is32bits, int is_new, dynablock_t* block); void FlushZombieDynablocks(void); // for use in signal handler From f60dea9b4b5911b227e1d6c38e7478e779add92d Mon Sep 17 00:00:00 2001 From: Nicklets <151431936+Nicklets@users.noreply.github.com> Date: Sat, 31 Oct 2026 09:37:40 -0300 Subject: [PATCH 119/156] [ARM64_DYNAREC] Keep the guest base register when adding a segment base in geted() (#4645) For %fs:/%gs:-disp(%reg) with a displacement under 4 KiB that the load can't take as an immediate, scratch was left pointing at the guest base register, so grab_segdata() loaded the segment base into it and the next access through that register landed at twice the base. Give the segment base a real scratch register again (fixes #4643). Co-authored-by: Claude Opus 5.5 --- src/dynarec/arm64/dynarec_arm64_helper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index b5f3794e5..4d7f39636 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -227,6 +227,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u ret = hint; } if(rex.seg && !seg_done) { + scratch = (hint>0 && !IS_GPR(hint)) ? hint : x2; if(scratch==ret) scratch=ret+1; grab_segdata(dyn, addr, ninst, scratch, rex.seg); From e86a766cbe1e147fd90ff8248e2bf9beb007ff8e Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Sat, 31 Oct 2026 14:30:55 +0100 Subject: [PATCH 120/156] [ARM64] Added a dection of write error on segfault using extra signal information (for #4644) --- src/include/sigtools.h | 2 +- src/libtools/decopcode.c | 21 +++++++++++++++++++-- src/libtools/signal32.c | 23 ++--------------------- src/libtools/signals.c | 2 +- 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/include/sigtools.h b/src/include/sigtools.h index fc607ff93..77e338368 100644 --- a/src/include/sigtools.h +++ b/src/include/sigtools.h @@ -51,7 +51,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, int unlockMutex(); int checkMutex(uint32_t mask); -int write_opcode(uintptr_t rip, uintptr_t native_ip, int is32bits); +int write_opcode(uintptr_t rip, uintptr_t native_ip, int is32bits, void* ucntx); void adjustregs(x64emu_t* emu, void* pc); void copyUCTXreg2Emu(x64emu_t* emu, ucontext_t* p, dynablock_t* db, uintptr_t ip); diff --git a/src/libtools/decopcode.c b/src/libtools/decopcode.c index 0d21c8a8e..c81b88fea 100644 --- a/src/libtools/decopcode.c +++ b/src/libtools/decopcode.c @@ -1,6 +1,10 @@ // SPDX-License-Identifier: MIT #include #include +#if defined(__aarch64__) +#include +#include +#endif #include "debug.h" #include "x64emu.h" @@ -382,8 +386,21 @@ int decode_opcode(uintptr_t rip, int is32bits) return 0; } -int write_opcode(uintptr_t rip, uintptr_t native_ip, int is32bits) +int write_opcode(uintptr_t rip, uintptr_t native_ip, int is32bits, void* uctx) { - // TODO, on ARM64, RiSCV and LoongArch, it would be easier to analyse the opcode at the native IP instead, as opcode that write to memory are more limited in quantity + #if defined(__aarch64__) + if(uctx) { + struct _aarch64_ctx* ff = (struct _aarch64_ctx*)((ucontext_t*)uctx)->uc_mcontext.__reserved; + while(ff->magic && ff->size && ff->magic!=ESR_MAGIC) + ff = (struct _aarch64_ctx*)((uintptr_t)ff + ff->size); + if(ff->magic==ESR_MAGIC) { + uint64_t esr = ((struct esr_context*)ff)->esr; + if(((esr>>26)==0x24) && !(esr&(1<<8))) + // Data abort from EL0 with WnR set, not a cache maintenance operation (bit 8) + return(esr&(1<<6))?1:0; + } + } + #endif + // TODO, on RiSCV and LoongArch, it would be easier to analyse the opcode at the native IP instead, as opcode that write to memory are more limited in quantity return (decode_opcode(rip, is32bits)&OPCODE_WRITE)?1:0; } diff --git a/src/libtools/signal32.c b/src/libtools/signal32.c index 8c8278999..d12c729f5 100644 --- a/src/libtools/signal32.c +++ b/src/libtools/signal32.c @@ -33,29 +33,11 @@ #include "emu/x87emu_private.h" #include "custommem.h" #include "bridge.h" +#include "sigtools.h" #ifdef DYNAREC #include "dynablock.h" #include "../dynarec/dynablock_private.h" #include "dynarec_native.h" -#if defined(ARM64) -#include "dynarec/arm64/arm64_mapping.h" -#define CONTEXT_REG(P, X) P->uc_mcontext.regs[X] -#define CONTEXT_PC(P) P->uc_mcontext.pc -#elif defined(LA64) -#include "dynarec/la64/la64_mapping.h" -#define CONTEXT_REG(P, X) P->uc_mcontext.__gregs[X] -#define CONTEXT_PC(P) P->uc_mcontext.__pc; -#elif defined(RV64) -#include "dynarec/rv64/rv64_mapping.h" -#define CONTEXT_REG(P, X) P->uc_mcontext.__gregs[X] -#define CONTEXT_PC(P) P->uc_mcontext.__gregs[REG_PC] -#elif defined(PPC64LE) -#include "dynarec/ppc64le/ppc64le_mapping.h" -#define CONTEXT_REG(P, X) P->uc_mcontext.gp_regs[X] -#define CONTEXT_PC(P) P->uc_mcontext.gp_regs[PT_NIP] -#else -#error Unsupported Architecture -#endif //arch #endif @@ -485,7 +467,6 @@ void convert_siginfo_to_32(void* d, void* s, int sig) void relockMutex(int locks); int unlockMutex(); -int write_opcode(uintptr_t rip, uintptr_t native_ip, int is32bits); #define is_memprot_locked (1<<1) #define is_dyndump_locked (1<<8) int my_sigactionhandler_oldcode_32(x64emu_t* emu, int32_t sig, int simple, siginfo_t* info, void * ucntx, int* old_code, void* cur_db) @@ -638,7 +619,7 @@ int my_sigactionhandler_oldcode_32(x64emu_t* emu, int32_t sig, int simple, sigin } else { sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 14; sigcontext->uc_mcontext.gregs[I386_ERR] = 4|((sysmapped && !(real_prot&PROT_READ))?0:1); - if(write_opcode(sigcontext->uc_mcontext.gregs[I386_EIP], (uintptr_t)pc, 1)) + if(write_opcode(sigcontext->uc_mcontext.gregs[I386_EIP], (uintptr_t)pc, 1, ucntx)) sigcontext->uc_mcontext.gregs[I386_ERR] |= 2; } if(info->si_code == SEGV_ACCERR && old_code) diff --git a/src/libtools/signals.c b/src/libtools/signals.c index c48a41fe8..09a8e9297 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -511,7 +511,7 @@ int my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigin } else { sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 14; sigcontext->uc_mcontext.gregs[X64_ERR] = 4|((sysmapped && !(real_prot&PROT_READ))?0:1); - if(write_opcode(sigcontext->uc_mcontext.gregs[X64_RIP], (uintptr_t)pc, (R_CS==0x23))) + if(write_opcode(sigcontext->uc_mcontext.gregs[X64_RIP], (uintptr_t)pc, (R_CS==0x23), ucntx)) sigcontext->uc_mcontext.gregs[X64_ERR] |= 2; } if(info->si_code == SEGV_ACCERR && old_code) From 5177ca4732cec3aa2f56b2de6df3947737161390 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sun, 1 Nov 2026 03:03:18 +0800 Subject: [PATCH 121/156] [LA64_DYNAREC] Fixed AES source being clobbered by AVX cache sync in SCRATCH (#4646) --- src/dynarec/la64/dynarec_la64_660f.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/dynarec/la64/dynarec_la64_660f.c b/src/dynarec/la64/dynarec_la64_660f.c index f0dfa8d65..aabeba92c 100644 --- a/src/dynarec/la64/dynarec_la64_660f.c +++ b/src/dynarec/la64/dynarec_la64_660f.c @@ -804,8 +804,13 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xDB: INST_NAME("AESIMC Gx, Ex"); // AES-NI nextop = F8; - GETEX_AES(q1, 0, 0); - GETGX_empty(q0); + if (MODREG) { + GETEX_AES(q1, 0, 0); + GETGX_empty(q0); + } else { + GETGX_empty(q0); + GETEX_AES(q1, 0, 0); + } if (q0 != q1) { VOR_V(q0, q1, q1); } @@ -815,8 +820,8 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("AESENC Gx, Ex"); // AES-NI nextop = F8; GETG; - GETEX_AES(q1, 0, 0); GETGX(q0, 1); + GETEX_AES(q1, 0, 0); if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) { d0 = SCRATCH; VOR_V(d0, q1, q1); @@ -843,8 +848,8 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("AESDEC Gx, Ex"); // AES-NI nextop = F8; GETG; - GETEX_AES(q1, 0, 0); GETGX(q0, 1); + GETEX_AES(q1, 0, 0); if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) { d0 = SCRATCH; VOR_V(d0, q1, q1); @@ -857,8 +862,8 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("AESDECLAST Gx, Ex"); // AES-NI nextop = F8; GETG; - GETEX_AES(q1, 0, 0); GETGX(q0, 1); + GETEX_AES(q1, 0, 0); if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) { d0 = SCRATCH; VOR_V(d0, q1, q1); From 93c68acd377eacb4b149a94c9d09f4e88661c882 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sun, 1 Nov 2026 03:06:44 +0800 Subject: [PATCH 122/156] [LA64_DYNAREC] Restore pending scalar XMM values on signal exit (#4647) --- src/dynarec/la64/dynarec_la64_arch.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/dynarec/la64/dynarec_la64_arch.c b/src/dynarec/la64/dynarec_la64_arch.c index 040acbf59..44559cecc 100644 --- a/src/dynarec/la64/dynarec_la64_arch.c +++ b/src/dynarec/la64/dynarec_la64_arch.c @@ -32,6 +32,7 @@ typedef struct arch_arch_s uint32_t x87_pos; // vector register of each stack register, 3 bits each uint16_t x87_type; // type of each cached x87 value, 2 bits each int8_t x87delta; // pending x87 stack count at this instruction + uint8_t scalar[8]; // per scalar slot (reg 16..23): guest xmm | 0x10 if double, 0xFF if unused } arch_arch_t; typedef struct arch_build_s @@ -50,6 +51,7 @@ typedef struct arch_build_s uint32_t x87_pos; uint16_t x87_type; int8_t x87delta; + uint8_t scalar[8]; } arch_build_t; static int arch_build(dynarec_la64_t* dyn, int ninst, arch_build_t* arch) @@ -68,6 +70,8 @@ static int arch_build(dynarec_la64_t* dyn, int ninst, arch_build_t* arch) if (dyn->insts[ninst].lsx.ssecache[i].v != -1) arch->xmm |= (uint16_t)(1 << i); if (dyn->insts[ninst].lsx.avxcache[i].v != -1) arch->ymm |= (uint16_t)(1 << i); } + for (int i = 0; i < 8; ++i) arch->scalar[i] = 0xFF; + int scalar_used = 0; for (int i = 16; i < 24; ++i) { int n = dyn->insts[ninst].lsx.lsxcache[i].n; if (dyn->insts[ninst].lsx.lsxcache[i].v) { @@ -85,11 +89,16 @@ static int arch_build(dynarec_la64_t* dyn, int ninst, arch_build_t* arch) case LSX_CACHE_MM: if (i == 16 + n) arch->mmx |= (uint8_t)(1 << n); break; + case LSX_CACHE_XMM_S: + case LSX_CACHE_XMM_D: + arch->scalar[i - 16] = (uint8_t)((n & 0x0F) | ((dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_XMM_D) ? 0x10 : 0)); + scalar_used = 1; + break; default: break; } } } - arch->vec = (arch->xmm || arch->ymm || arch->x87 || arch->mmx); + arch->vec = (arch->xmm || arch->ymm || arch->x87 || arch->mmx || scalar_used); return arch->unaligned || arch->host_call || arch->vec || arch->up32 || arch->ymm_zero || arch->rsp || arch->x87delta; } @@ -137,6 +146,7 @@ static void build_next(arch_arch_t* arch, arch_build_t* build) arch->x87_pos = build->x87_pos; arch->x87_type = build->x87_type; arch->x87delta = build->x87delta; + memcpy(arch->scalar, build->scalar, sizeof(arch->scalar)); } void* populate_arch(dynarec_la64_t* dyn, void* p, size_t sz) @@ -270,6 +280,16 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) } } } + for (int i = 0; i < 8; ++i) { + uint8_t scalar = arch->scalar[i]; + if (scalar == 0xFF) continue; + uint64_t raw = vec[(16 + i) * stride]; + int guest = scalar & 0x0F; + if (scalar & 0x10) + emu->xmm[guest].q[0] = raw; + else + emu->xmm[guest].ud[0] = (uint32_t)raw; + } uint8_t x87 = arch->x87; while (x87) { int i = __builtin_ctz(x87); From 0b046f594c5937b92c2f1c0a5b756571781fc58a Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sun, 1 Nov 2026 18:27:06 +0800 Subject: [PATCH 123/156] [DYNAREC] Fixed deferred 16-bit SHLD/SHRD flags with count>16 (#4648) * [DYNAREC] Fixed deferred 16-bit SHLD/SHRD flags with count>16 * optim --- src/dynarec/arm64/dynarec_arm64_emit_shift.c | 20 ++++- src/dynarec/arm64/updateflags_arm64_pass.c | 78 +++++++++++-------- src/dynarec/la64/dynarec_la64_emit_shift.c | 30 +++++-- src/dynarec/la64/updateflags_la64_pass.c | 36 +++++---- .../ppc64le/dynarec_ppc64le_emit_shift.c | 24 +++++- src/dynarec/rv64/dynarec_rv64_emit_shift.c | 22 +++++- src/dynarec/rv64/updateflags_rv64_pass.c | 75 +++++++++++------- src/emu/x64emu.c | 15 +++- 8 files changed, 205 insertions(+), 95 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c index b5b15abf4..9cdffaeed 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c @@ -1623,8 +1623,13 @@ void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int c&=0x1f; IFX(X_PEND) { MOV32w(s3, c); + if (c > 16) { + ORRw_REG_LSL(s3, s3, s2, 16); // store fill in the upper half, needed for count > 16 + STRw_U12(s3, xEmu, offsetof(x64emu_t, op2)); + } else { + STRH_U12(s3, xEmu, offsetof(x64emu_t, op2)); + } STRH_U12(s1, xEmu, offsetof(x64emu_t, op1)); - STRH_U12(s3, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, d_shrd16); } else { SET_DFNONE(); @@ -1666,7 +1671,8 @@ void emit_shrd16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, { IFX(X_PEND) { STRH_U12(s1, xEmu, offsetof(x64emu_t, op1)); - STRH_U12(s5, xEmu, offsetof(x64emu_t, op2)); + ORRw_REG_LSL(s3, s5, s2, 16); // store fill in the upper half, needed for count > 16 + STRw_U12(s3, xEmu, offsetof(x64emu_t, op2)); // same flags computation as with shl64/shl32 SET_DF(s4, d_shrd16); } else { @@ -1715,8 +1721,13 @@ void emit_shld16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int c&=0x1f; IFX(X_PEND) { MOV32w(s3, c); + if (c > 16) { + ORRw_REG_LSL(s3, s3, s2, 16); // store fill in the upper half, needed for count > 16 + STRw_U12(s3, xEmu, offsetof(x64emu_t, op2)); + } else { + STRH_U12(s3, xEmu, offsetof(x64emu_t, op2)); + } STRH_U12(s1, xEmu, offsetof(x64emu_t, op1)); - STRH_U12(s3, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, d_shld16); } else { SET_DFNONE(); @@ -1770,7 +1781,8 @@ void emit_shld16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, { IFX(X_PEND) { STRH_U12(s1, xEmu, offsetof(x64emu_t, op1)); - STRH_U12(s5, xEmu, offsetof(x64emu_t, op2)); + ORRw_REG_LSL(s3, s5, s2, 16); // store fill in the upper half, needed for count > 16 + STRw_U12(s3, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, d_shld16); } else { SET_DFNONE(); diff --git a/src/dynarec/arm64/updateflags_arm64_pass.c b/src/dynarec/arm64/updateflags_arm64_pass.c index b770173ef..970d7bf5b 100644 --- a/src/dynarec/arm64/updateflags_arm64_pass.c +++ b/src/dynarec/arm64/updateflags_arm64_pass.c @@ -884,30 +884,33 @@ SETMARK(d_ror64); SETMARK(d_shrd16); LDRH_U12(x1, xEmu, offsetof(x64emu_t, res)); LDRH_U12(x2, xEmu, offsetof(x64emu_t, op1)); - LDRH_U12(x3, xEmu, offsetof(x64emu_t, op2)); - CBNZw(x3, 4+4); + LDRw_U12(x3, xEmu, offsetof(x64emu_t, op2)); + ANDw_mask(x4, x3, 0, 4); // count = op2 & 0x1f + CBNZw(x4, 4+4); RET(xLR); + LSRw(x5, x3, 16); // fill = op2 >> 16 if(BOX64ENV(cputype)) { - LSRw(x4, x1, 14); - EORw_REG_LSR(x4, x4, x4, 1); - BFIw(xFlags, x4, F_OF, 1); + LSRw(x3, x1, 14); + EORw_REG_LSR(x3, x3, x3, 1); + BFIw(xFlags, x3, F_OF, 1); ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + SUBw_U12(x3, x4, 1); + LSRw_REG(x3, x2, x3); + CMPSw_U12(x4, 16); + CSELw(x3, xZR, x3, cGT); + BFIw(xFlags, x3, F_CF, 1); } else { - ANDw_mask(x4, x3, 0, 3); // mask = 0x0f - SUBw_U12(x4, x4, 16); - NEGw_REG(x4, x4); - LSRw_REG(x4, x1, x4); - EORw_REG_LSR(x4, x4, x2, 15); - BFIw(xFlags, x4, F_OF, 1); + EORw_REG_LSR(x3, x5, x2, 15); + BFIw(xFlags, x3, F_OF, 1); BFCw(xFlags, F_AF, 1); + CMPSw_U12(x4, 16); + SUBw_U12(x3, x4, 1); + LSRw_REG(x3, x2, x3); // dest >> (count-1) + SUBw_U12(x4, x4, 17); + LSRw_REG(x5, x5, x4); // fill >> (count-17) + CSELw(x3, x5, x3, cGT); + BFIw(xFlags, x3, F_CF, 1); } - SUBw_U12(x4, x3, 1); - LSRw_REG(x4, x2, x4); - if(BOX64ENV(cputype)) { - CMPSw_U12(x3, 15); - CSELw(x4, x4, xZR, cGT); - } - BFIw(xFlags, x4, F_CF, 1); LSRw(x4, x1, 15); BFIw(xFlags, x4, F_SF, 1); TSTw_mask(x1, 0, 15); @@ -976,24 +979,37 @@ SETMARK(d_shrd64); SETMARK(d_shld16); LDRH_U12(x1, xEmu, offsetof(x64emu_t, res)); LDRH_U12(x2, xEmu, offsetof(x64emu_t, op1)); - LDRH_U12(x3, xEmu, offsetof(x64emu_t, op2)); - CBNZw(x3, 4+4); + LDRw_U12(x3, xEmu, offsetof(x64emu_t, op2)); + ANDw_mask(x4, x3, 0, 4); // count = op2 & 0x1f + CBNZw(x4, 4+4); RET(xLR); - SUBw_U12(x4, x3, 16); - NEGw_REG(x4, x4); - LSRw_REG(x4, x2, x4); - BFIw(xFlags, x4, F_CF, 1); + LSRw(x5, x3, 16); // fill = op2 >> 16 if(BOX64ENV(cputype)) { - EORw_REG_LSR(x4, xFlags, x1, 15); - CMPSw_U12(x3, 15); - CSELw(x4, x4, xFlags, cGT); - BFIw(xFlags, x4, F_OF, 1); + MOV32w(x3, 16); + SUBw_REG(x3, x3, x4); + LSRw_REG(x3, x2, x3); // dest >> (16-count) + CMPSw_U12(x4, 16); + CSELw(x3, xZR, x3, cGT); + BFIw(xFlags, x3, F_CF, 1); + EORw_REG_LSR(x3, xFlags, x1, 15); + CMPSw_U12(x4, 15); + CSELw(x3, xFlags, x3, cGT); + BFIw(xFlags, x3, F_OF, 1); ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 } else { - LSRw(x4, x2, 14); - EORw_REG_LSR(x4, x4, x4, 1); - BFIw(xFlags, x4, F_OF, 1); + LSRw(x3, x2, 14); + EORw_REG_LSR(x3, x3, x3, 1); + BFIw(xFlags, x3, F_OF, 1); BFCw(xFlags, F_AF, 1); + CMPSw_U12(x4, 16); + MOV32w(x3, 16); + SUBw_REG(x3, x3, x4); + LSRw_REG(x3, x2, x3); // dest >> (16-count) + MOV32w(x2, 32); + SUBw_REG(x2, x2, x4); + LSRw_REG(x5, x5, x2); // fill >> (32-count) + CSELw(x3, x5, x3, cGT); + BFIw(xFlags, x3, F_CF, 1); } LSRw(x4, x1, 15); BFIw(xFlags, x4, F_SF, 1); diff --git a/src/dynarec/la64/dynarec_la64_emit_shift.c b/src/dynarec/la64/dynarec_la64_emit_shift.c index 8eaa63b2b..fb506a89c 100644 --- a/src/dynarec/la64/dynarec_la64_emit_shift.c +++ b/src/dynarec/la64/dynarec_la64_emit_shift.c @@ -2161,11 +2161,15 @@ void emit_shld16c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin { c &= 0x1f; IFX (X_PEND) { - if (c) { + if (c > 16) { + // store fill in the upper half, as the deferred handler needs it for count > 16 + SLLI_D(s3, s2, 16); + ORI(s3, s3, c); + ST_W(s3, xEmu, offsetof(x64emu_t, op2)); + } else { MOV64x(s3, c); ST_H(s3, xEmu, offsetof(x64emu_t, op2)); - } else - ST_H(xZR, xEmu, offsetof(x64emu_t, op2)); + } ST_H(s1, xEmu, offsetof(x64emu_t, op1)); SET_DF(s4, d_shld16); } else IFXORNAT (X_ALL) { @@ -2230,11 +2234,15 @@ void emit_shrd16c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin c &= 0x1f; IFX (X_PEND) { - if (c) { + if (c > 16) { + // store fill in the upper half, as the deferred handler needs it for count > 16 + SLLI_D(s3, s2, 16); + ORI(s3, s3, c); + ST_W(s3, xEmu, offsetof(x64emu_t, op2)); + } else { MOV64x(s3, c); ST_H(s3, xEmu, offsetof(x64emu_t, op2)); - } else - ST_H(xZR, xEmu, offsetof(x64emu_t, op2)); + } ST_H(s1, xEmu, offsetof(x64emu_t, op1)); SET_DF(s4, d_shrd16); } else IFXORNAT (X_ALL) { @@ -2295,7 +2303,10 @@ void emit_shld16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, { IFX (X_PEND) { ST_H(s1, xEmu, offsetof(x64emu_t, op1)); - ST_H(s3, xEmu, offsetof(x64emu_t, op2)); + // store fill in the upper half, as the deferred handler needs it for count > 16 + SLLI_D(s6, s2, 16); + OR(s6, s6, s3); + ST_W(s6, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, d_shld16); } else IFXORNAT (X_ALL) { SET_DFNONE(); @@ -2353,7 +2364,10 @@ void emit_shrd16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, { IFX (X_PEND) { ST_H(s1, xEmu, offsetof(x64emu_t, op1)); - ST_H(s3, xEmu, offsetof(x64emu_t, op2)); + // store fill in the upper half, as the deferred handler needs it for count > 16 + SLLI_D(s6, s2, 16); + OR(s6, s6, s3); + ST_W(s6, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, d_shrd16); } else IFXORNAT (X_ALL) { SET_DFNONE(); diff --git a/src/dynarec/la64/updateflags_la64_pass.c b/src/dynarec/la64/updateflags_la64_pass.c index 162194adb..1d611c11e 100644 --- a/src/dynarec/la64/updateflags_la64_pass.c +++ b/src/dynarec/la64/updateflags_la64_pass.c @@ -987,19 +987,22 @@ SETMARK(d_ror64); SETMARK(d_shrd16); LD_HU(x1, xEmu, offsetof(x64emu_t, res)); LD_HU(x2, xEmu, offsetof(x64emu_t, op1)); - LD_HU(x3, xEmu, offsetof(x64emu_t, op2)); - ANDI(x4, x3, 0x0f); - ADDI_D(x4, x4, -16); - SUB_D(x4, xZR, x4); - SRL_D(x4, x1, x4); - SRLI_D(x5, x2, 15); + LD_WU(x3, xEmu, offsetof(x64emu_t, op2)); + ANDI(x6, x3, 0x1f); + SRLI_D(x5, x3, 16); + BNEZ(x6, 8 + (cpuext.lbt ? 4 : 0)); + SPILL_EFLAGS(); + BR(xRA); + SRLI_D(x4, x2, 15); XOR(x4, x4, x5); BSTRINS_D(xFlags, x4, F_OF, F_OF); BSTRINS_D(xFlags, xZR, F_AF, F_AF); - BNEZ(x3, 8 + (cpuext.lbt ? 4 : 0)); - SPILL_EFLAGS(); - BR(xRA); - ADDI_D(x4, x3, -1); + ADDI_D(x4, x6, -16); + BGE(xZR, x4, 4 * 4); + ADDI_D(x4, x4, -1); + SRL_D(x4, x5, x4); + B(3 * 4); + ADDI_D(x4, x6, -1); SRL_D(x4, x2, x4); BSTRINS_D(xFlags, x4, F_CF, F_CF); SRLI_D(x4, x1, 15); @@ -1064,10 +1067,17 @@ SETMARK(d_shrd64); SETMARK(d_shld16); LD_HU(x1, xEmu, offsetof(x64emu_t, res)); LD_HU(x2, xEmu, offsetof(x64emu_t, op1)); - LD_HU(x3, xEmu, offsetof(x64emu_t, op2)); - BNEZ(x3, 8); + LD_WU(x3, xEmu, offsetof(x64emu_t, op2)); + ANDI(x6, x3, 0x1f); + BNEZ(x6, 8); BR(xRA); - ADDI_D(x4, x3, -16); + SRLI_D(x5, x3, 16); + ADDI_D(x4, x6, -16); + BGE(xZR, x4, 5 * 4); + SUB_D(x4, xZR, x4); + ADDI_D(x4, x4, 16); + SRL_D(x4, x5, x4); + B(3 * 4); SUB_D(x4, xZR, x4); SRL_D(x4, x2, x4); BSTRINS_D(xFlags, x4, F_CF, F_CF); diff --git a/src/dynarec/ppc64le/dynarec_ppc64le_emit_shift.c b/src/dynarec/ppc64le/dynarec_ppc64le_emit_shift.c index b2010bd82..377d48dec 100644 --- a/src/dynarec/ppc64le/dynarec_ppc64le_emit_shift.c +++ b/src/dynarec/ppc64le/dynarec_ppc64le_emit_shift.c @@ -1890,7 +1890,13 @@ void emit_shld16c(dynarec_ppc64le_t* dyn, int ninst, rex_t rex, int s1, int s2, IFX (X_PEND) { if (c) { MOV64x(s3, c); - STH(s3, offsetof(x64emu_t, op2), xEmu); + if (c > 16) { + SLDI(s4, s2, 16); + OR(s3, s3, s4); + STW(s3, offsetof(x64emu_t, op2), xEmu); + } else { + STH(s3, offsetof(x64emu_t, op2), xEmu); + } } else { LI(s3, 0); STH(s3, offsetof(x64emu_t, op2), xEmu); @@ -1959,7 +1965,9 @@ void emit_shld16(dynarec_ppc64le_t* dyn, int ninst, int s1, int s2, int s3, int { IFX (X_PEND) { STH(s1, offsetof(x64emu_t, op1), xEmu); - STH(s3, offsetof(x64emu_t, op2), xEmu); + SLDI(s5, s2, 16); + OR(s5, s5, s3); + STW(s5, offsetof(x64emu_t, op2), xEmu); SET_DF(s4, d_shld16); } else IFXORNAT (X_ALL) { SET_DFNONE(); @@ -2022,7 +2030,13 @@ void emit_shrd16c(dynarec_ppc64le_t* dyn, int ninst, rex_t rex, int s1, int s2, IFX (X_PEND) { if (c) { MOV64x(s3, c); - STH(s3, offsetof(x64emu_t, op2), xEmu); + if (c > 16) { + SLDI(s4, s2, 16); + OR(s3, s3, s4); + STW(s3, offsetof(x64emu_t, op2), xEmu); + } else { + STH(s3, offsetof(x64emu_t, op2), xEmu); + } } else { LI(s3, 0); STH(s3, offsetof(x64emu_t, op2), xEmu); @@ -2088,7 +2102,9 @@ void emit_shrd16(dynarec_ppc64le_t* dyn, int ninst, int s1, int s2, int s3, int { IFX (X_PEND) { STH(s1, offsetof(x64emu_t, op1), xEmu); - STH(s3, offsetof(x64emu_t, op2), xEmu); + SLDI(s5, s2, 16); + OR(s5, s5, s3); + STW(s5, offsetof(x64emu_t, op2), xEmu); SET_DF(s4, d_shrd16); } else IFXORNAT (X_ALL) { SET_DFNONE(); diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c index 14df60e87..0f703312f 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c @@ -1864,7 +1864,12 @@ void emit_shrd16c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin IFX (X_PEND) { if (c) { MOV64x(s3, c); - SH(s3, xEmu, offsetof(x64emu_t, op2)); + if (c > 16) { + SLLI(s4, s2, 16); + OR(s3, s3, s4); + SW(s3, xEmu, offsetof(x64emu_t, op2)); + } else + SH(s3, xEmu, offsetof(x64emu_t, op2)); } else SH(xZR, xEmu, offsetof(x64emu_t, op2)); SH(s1, xEmu, offsetof(x64emu_t, op1)); @@ -2090,7 +2095,12 @@ void emit_shld16c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin IFX (X_PEND) { if (c) { MOV64x(s3, c); - SH(s3, xEmu, offsetof(x64emu_t, op2)); + if (c > 16) { + SLLI(s4, s2, 16); + OR(s3, s3, s4); + SW(s3, xEmu, offsetof(x64emu_t, op2)); + } else + SH(s3, xEmu, offsetof(x64emu_t, op2)); } else SH(xZR, xEmu, offsetof(x64emu_t, op2)); SH(s1, xEmu, offsetof(x64emu_t, op1)); @@ -2158,7 +2168,9 @@ void emit_shld16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, CLEAR_FLAGS(); IFX (X_PEND) { SH(s1, xEmu, offsetof(x64emu_t, op1)); - SH(s3, xEmu, offsetof(x64emu_t, op2)); + SLLI(s5, s2, 16); + OR(s5, s5, s3); + SW(s5, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, d_shld16); } else IFXORNAT (X_ALL) { SET_DFNONE(); @@ -2220,7 +2232,9 @@ void emit_shrd16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, CLEAR_FLAGS(); IFX (X_PEND) { SH(s1, xEmu, offsetof(x64emu_t, op1)); - SH(s3, xEmu, offsetof(x64emu_t, op2)); + SLLI(s5, s2, 16); + OR(s5, s5, s3); + SW(s5, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, d_shrd16); } else IFXORNAT (X_ALL) { SET_DFNONE(); diff --git a/src/dynarec/rv64/updateflags_rv64_pass.c b/src/dynarec/rv64/updateflags_rv64_pass.c index 4f447affa..5534f2c37 100644 --- a/src/dynarec/rv64/updateflags_rv64_pass.c +++ b/src/dynarec/rv64/updateflags_rv64_pass.c @@ -1023,33 +1023,37 @@ SETMARK(d_ror64); SETMARK(d_shrd16); LHU(x1, xEmu, offsetof(x64emu_t, res)); LHU(x2, xEmu, offsetof(x64emu_t, op1)); - LHU(x3, xEmu, offsetof(x64emu_t, op2)); - BNEZ(x3, 8); + LWU(x3, xEmu, offsetof(x64emu_t, op2)); + ANDI(x6, x3, 0x1f); + BNEZ(x6, 8); BR(xRA); // count == 0, nothing to do + SRLI(x5, x3, 16); // fill if (BOX64ENV(cputype)) { SRLI(x4, x1, 14); - SRLI(x5, x4, 1); - XOR(x4, x4, x5); + SRLI(x3, x4, 1); + XOR(x4, x4, x3); PUTFLAG(x4, F_OF2); ORI(xFlags, xFlags, 1 << F_AF); + ADDI(x4, x6, -1); + SRLW(x4, x2, x4); // CF = bit (count-1) of op1 + SLTI(x3, x6, 17); + BNEZ(x3, 8); + MV(x4, xZR); // count > 16: CF = 0 + PUTFLAG(x4, F_CF); } else { - ANDI(x4, x3, 0x0f); - ADDI(x4, x4, -16); - NEG(x4, x4); - SRL(x4, x1, x4); - SRLI(x5, x2, 15); - XOR(x4, x4, x5); + SRLI(x4, x2, 15); + XOR(x4, x5, x4); // OF = fill ^ (op1 >> 15) PUTFLAG(x4, F_OF2); ANDI(xFlags, xFlags, ~(1 << F_AF)); + ADDI(x4, x6, -1); + SRLW(x4, x2, x4); // CF = bit (count-1) of op1 + ADDI(x3, x6, -17); + SRLW(x5, x5, x3); // or bit (count-17) of fill + SLTI(x3, x6, 17); + BNEZ(x3, 8); + MV(x4, x5); + PUTFLAG(x4, F_CF); } - ADDI(x4, x3, -1); - SRLW(x4, x2, x4); // CF = bit (count-1) of op1 - if (BOX64ENV(cputype)) { - SLTI(x5, x3, 16); - BNEZ(x5, 8); - MV(x4, xZR); // count > 15: CF = 0 - } - PUTFLAG(x4, F_CF); SRLI(x4, x1, 15); PUTFLAG(x4, F_SF); SEQZ(x4, x1); @@ -1125,27 +1129,42 @@ SETMARK(d_shrd64); SETMARK(d_shld16); LHU(x1, xEmu, offsetof(x64emu_t, res)); LHU(x2, xEmu, offsetof(x64emu_t, op1)); - LHU(x3, xEmu, offsetof(x64emu_t, op2)); - BNEZ(x3, 8); + LWU(x3, xEmu, offsetof(x64emu_t, op2)); + ANDI(x6, x3, 0x1f); + BNEZ(x6, 8); BR(xRA); - ADDI(x4, x3, -16); - NEG(x4, x4); - SRLW(x4, x2, x4); // CF = bit (16-count) of op1 - PUTFLAG(x4, F_CF); + SRLI(x5, x3, 16); // fill if (BOX64ENV(cputype)) { + MOV32w(x4, 16); + SUBW(x4, x4, x6); + SRLW(x4, x2, x4); // CF = bit (16-count) of op1 + SLTI(x3, x6, 17); + BNEZ(x3, 8); + MV(x4, xZR); // count > 16: CF = 0 + PUTFLAG(x4, F_CF); SRLI(x4, x1, 15); XOR(x4, x4, xFlags); - SLTI(x5, x3, 16); - BNEZ(x5, 8); + SLTI(x3, x6, 16); + BNEZ(x3, 8); MV(x4, xFlags); // count > 15: OF = CF PUTFLAG(x4, F_OF2); ORI(xFlags, xFlags, 1 << F_AF); } else { SRLI(x4, x2, 14); - SRLI(x5, x4, 1); - XOR(x4, x4, x5); + SRLI(x3, x4, 1); + XOR(x4, x4, x3); PUTFLAG(x4, F_OF2); ANDI(xFlags, xFlags, ~(1 << F_AF)); + MOV32w(x4, 16); + SUBW(x4, x4, x6); + SRLW(x4, x2, x4); // CF = bit (16-count) of op1 + MOV32w(x3, 32); + SUBW(x3, x3, x6); + SRLW(x5, x5, x3); // or bit (32-count) of fill + SLTI(x3, x6, 17); + BNEZ(x3, 8); + MV(x4, x5); + PUTFLAG(x4, F_CF); } SRLI(x4, x1, 15); PUTFLAG(x4, F_SF); diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c index 16c321776..2cb0f7d4f 100644 --- a/src/emu/x64emu.c +++ b/src/emu/x64emu.c @@ -1235,8 +1235,12 @@ void UpdateFlags(x64emu_t* emu) case d_shrd16: cnt = emu->op2.u16; if (cnt > 0) { - cc = emu->op1.u16 & (1 << (cnt - 1)); - if (cnt > 15 && BOX64ENV(cputype)) + // fill operand is stored in the upper half of op2 + if (cnt > 16) + cc = (emu->op2.u64 >> 16) & 0xffff & (1u << (cnt - 17)); + else + cc = emu->op1.u16 & (1 << (cnt - 1)); + if (cnt > 16 && BOX64ENV(cputype)) cc = 0; CONDITIONAL_SET_FLAG(cc, F_CF); CONDITIONAL_SET_FLAG(!emu->res.u16, F_ZF); @@ -1294,7 +1298,12 @@ void UpdateFlags(x64emu_t* emu) case d_shld16: cnt = emu->op2.u16; if (cnt > 0) { - cc = emu->op1.u16 & (1 << (16 - cnt)); + if (cnt > 16) + cc = (emu->op2.u64 >> 16) & 0xffff & (1u << (32 - cnt)); + else + cc = emu->op1.u16 & (1 << (16 - cnt)); + if (cnt > 16 && BOX64ENV(cputype)) + cc = 0; CONDITIONAL_SET_FLAG(cc, F_CF); CONDITIONAL_SET_FLAG(!emu->res.u16, F_ZF); CONDITIONAL_SET_FLAG(emu->res.u16 & 0x8000, F_SF); From 89566077a7cc3a77bd90a2091a7e83bfe695948c Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sun, 1 Nov 2026 20:57:39 +0800 Subject: [PATCH 124/156] [RV64_DYNAREC] Do locked bit ops on the aligned 32-bit word --- src/dynarec/rv64/dynarec_rv64_f0.c | 121 ++++++++++++++++++----------- 1 file changed, 77 insertions(+), 44 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_f0.c b/src/dynarec/rv64/dynarec_rv64_f0.c index fd1c7276b..ac2ba5375 100644 --- a/src/dynarec/rv64/dynarec_rv64_f0.c +++ b/src/dynarec/rv64/dynarec_rv64_f0.c @@ -176,24 +176,22 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETGD; addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); if (rex.w) - SRAI(x1, gd, 6); + SRAI(x1, gd, 3); else - SRAIW(x1, gd, 5); - if (!rex.w && !rex.is32bits) { ADDIW(x1, x1, 0); } - ADDSLy(x3, wback, x1, 2 + rex.w, x1); - ed = x1; - wback = x3; - MARKLOCK; - LRxw(ed, wback, 1, 1); - BEXT(x4, ed, gd, x2); + SRAIW(x1, gd, 3); + ADD(x2, wback, x1); + ANDI(x4, gd, 7); + ANDI(x5, x2, 0b11); + SLLI(x5, x5, 3); + OR(x4, x4, x5); + ANDI(x2, x2, ~0b11); + ADDI(x5, xZR, 1); + SLL(x5, x5, x4); + AMOOR_W(x6, x5, x2, 1, 1); + SRL(x6, x6, x4); + ANDI(x6, x6, 1); ANDI(xFlags, xFlags, ~1); - OR(xFlags, xFlags, x4); - ADDI(x4, xZR, 1); - ANDI(x2, gd, rex.w ? 0x3f : 0x1f); - SLL(x4, x4, x2); - OR(ed, ed, x4); - SCxw(x7, ed, wback, 1, 1); - BNEZ_MARKLOCK(x7); + OR(xFlags, xFlags, x6); } break; case 0xB0: @@ -319,24 +317,55 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETGD; addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); if (rex.w) - SRAI(x1, gd, 6); + SRAI(x1, gd, 3); else - SRAIW(x1, gd, 5); - if (!rex.w && !rex.is32bits) { ADDIW(x1, x1, 0); } - ADDSLy(x3, wback, x1, 2 + rex.w, x1); - ed = x1; - wback = x3; - MARKLOCK; - LRxw(ed, wback, 1, 1); - BEXT(x4, ed, gd, x2); // F_CF is 1 + SRAIW(x1, gd, 3); + ADD(x2, wback, x1); + ANDI(x4, gd, 7); + ANDI(x5, x2, 0b11); + SLLI(x5, x5, 3); + OR(x4, x4, x5); + ANDI(x2, x2, ~0b11); + ADDI(x5, xZR, 1); + SLL(x5, x5, x4); + XORI(x5, x5, -1); + AMOAND_W(x6, x5, x2, 1, 1); + SRL(x6, x6, x4); + ANDI(x6, x6, 1); ANDI(xFlags, xFlags, ~1); - OR(xFlags, xFlags, x4); - ADDI(x4, xZR, 1); - ANDI(x2, gd, rex.w ? 0x3f : 0x1f); - SLL(x4, x4, x2); - ANDN(ed, ed, x4, x4); - SCxw(x7, ed, wback, 1, 1); - BNEZ_MARKLOCK(x7); + OR(xFlags, xFlags, x6); + } + break; + case 0xBB: + nextop = F8; + if (MODREG) { + INST_NAME("Invalid LOCK"); + UDF(); + *need_epilog = 1; + *ok = 0; + } else { + INST_NAME("LOCK BTC Ed, Gd"); + SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); + SET_DFNONE(); + GETGD; + addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); + if (rex.w) + SRAI(x1, gd, 3); + else + SRAIW(x1, gd, 3); + ADD(x2, wback, x1); + ANDI(x4, gd, 7); + ANDI(x5, x2, 0b11); + SLLI(x5, x5, 3); + OR(x4, x4, x5); + ANDI(x2, x2, ~0b11); + ADDI(x5, xZR, 1); + SLL(x5, x5, x4); + AMOXOR_W(x6, x5, x2, 1, 1); + SRL(x6, x6, x4); + ANDI(x6, x6, 1); + ANDI(xFlags, xFlags, ~1); + OR(xFlags, xFlags, x6); } break; case 0xBA: @@ -367,27 +396,31 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); u8 = F8; if (rex.w) u8 &= 63; else u8 &= 31; - ANDI(x3, wback, rex.w ? ~7 : ~3); // aligned word if (((nextop >> 3) & 7) == 4) { LDxw(x4, wback, 0); // read only, no atomic needed - } else { - MOV64xw(x6, 1LL << u8); // bit mask - MARKLOCK; - LRxw(x4, x3, 1, 1); BEXTI(x7, x4, u8); // old bit ANDI(xFlags, xFlags, ~1); OR(xFlags, xFlags, x7); // CF = old bit - SLLI(x7, x7, u8); // old bit at position + } else { + ADDI(x2, wback, u8 >> 3); + ANDI(x4, x2, 0b11); + SLLI(x4, x4, 3); + ORI(x4, x4, u8 & 7); + ANDI(x2, x2, ~0b11); + ADDI(x5, xZR, 1); + SLL(x5, x5, x4); if (((nextop >> 3) & 7) == 5) { - XOR(x7, x6, x7); // toggle only if bit was 0 - XOR(x4, x4, x7); + AMOOR_W(x6, x5, x2, 1, 1); } else if (((nextop >> 3) & 7) == 6) { - XOR(x4, x4, x7); // toggle only if bit was 1 + XORI(x5, x5, -1); + AMOAND_W(x6, x5, x2, 1, 1); } else { - XOR(x4, x4, x6); // always toggle + AMOXOR_W(x6, x5, x2, 1, 1); } - SCxw(x1, x4, x3, 1, 1); - BNEZ_MARKLOCK(x1); + SRL(x6, x6, x4); + ANDI(x6, x6, 1); + ANDI(xFlags, xFlags, ~1); + OR(xFlags, xFlags, x6); } } break; From 9f0814e08f0a93360ebf976d099b4458fcaf5657 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sun, 1 Nov 2026 20:57:39 +0800 Subject: [PATCH 125/156] [RV64_DYNAREC] Zero-extend SHLD/SHRD destination in 32-bit mode --- src/dynarec/rv64/dynarec_rv64_0f.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index 785616a60..eef0a51e1 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -2182,7 +2182,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni WBACK; } else { FAKEED; - if (!rex.w && !rex.is32bits && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } + if (!rex.w && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } F8; } break; @@ -2196,7 +2196,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); // some flags are left undefined GETGD; GETEDsd(0); - if (!rex.w && !rex.is32bits && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } + if (!rex.w && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } ANDI(x3, xRCX, rex.w ? 0x3f : 0x1f); BEQ_NEXT(x3, xZR); emit_shld32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6); @@ -2256,7 +2256,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni WBACK; } else { FAKEED; - if (!rex.w && !rex.is32bits && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } + if (!rex.w && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } F8; } break; @@ -2270,7 +2270,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); GETGD; GETEDsd(0); - if (!rex.w && !rex.is32bits && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } + if (!rex.w && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } ANDI(x3, xRCX, rex.w ? 0x3f : 0x1f); BEQ_NEXT(x3, xZR); emit_shrd32(dyn, ninst, rex, ed, gd, x3, x5, x4, x6); From 5cc72d9d7a684c460d95d33c09ae14a99993fc70 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sun, 1 Nov 2026 20:57:39 +0800 Subject: [PATCH 126/156] [RV64_DYNAREC] Reset vtype tracking after native calls --- src/dynarec/rv64/dynarec_rv64_helper.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 3deac28d8..b66e38f89 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -664,10 +664,8 @@ void call_c(dynarec_rv64_t* dyn, int ninst, rv64_consts_t fnc, int reg, int ret, MV(ret, A0); } - // reinitialize sew, the native function may have changed vtype / vl + // the native function may have changed vtype / vl: force the cache-pop to re-emit it dyn->inst_vl = 0; // force emit, do not rely on tracked state - if (dyn->vector_sew != VECTOR_SEWNA) - vector_vsetvli(dyn, ninst, savereg, dyn->vector_sew, VECTOR_LMUL1, 1); LD(savereg, xSP, 0); ADDI(xSP, xSP, 16); @@ -692,6 +690,11 @@ void call_c(dynarec_rv64_t* dyn, int ninst, rv64_consts_t fnc, int reg, int ret, if (savereg != x87pc && dyn->need_x87check) NATIVE_RESTORE_X87PC(); // SET_NODF(); + // this call can be on a conditional path (for example: IDIV), + // so the vtype is not known at the merge point, let later opcodes emit it again + dyn->vector_sew = VECTOR_SEWNA; + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; CLEARIP(); } @@ -724,14 +727,16 @@ void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w) } // all done, restore all regs - // reinitialize sew, the native function may have changed vtype / vl + // the native function may have changed vtype / vl: force the cache-pop to re-emit it dyn->inst_vl = 0; // force emit, do not rely on tracked state - if (dyn->vector_sew != VECTOR_SEWNA) - vector_vsetvli(dyn, ninst, x3, dyn->vector_sew, VECTOR_LMUL1, 1); fpu_popcache(dyn, ninst, x3, 1); NATIVE_RESTORE_X87PC(); // SET_NODF(); + // the call may be on a conditional path (IDIV), so do not assume the vtype is restored + dyn->vector_sew = VECTOR_SEWNA; + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; } void grab_segdata(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, int reg, int segment) From 59955e15bb3925be7467d3528d2250b4486d55f2 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sun, 1 Nov 2026 20:57:39 +0800 Subject: [PATCH 127/156] [RV64_DYNAREC] Restore YMM upper halves after a native call --- src/dynarec/rv64/dynarec_rv64_helper.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index b66e38f89..d7e0b3b1a 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -2075,7 +2075,7 @@ void fpu_pushcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07) flushed8 = 1; ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VSE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); - avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, 0, 1); + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, dyn->e.ssecache[i].ymm0 ? 0 : 1, 1); } } if (flushed8) @@ -2165,6 +2165,21 @@ void fpu_popcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07) VLE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); } } + if (flushed8 && cpuext.vlen >= 32) { + int nup = 0; + for (int i = start; i < 16; ++i) + if (dyn->e.ssecache[i].v != -1 && dyn->e.ssecache[i].vector && dyn->e.ssecache[i].ymm && !dyn->e.ssecache[i].ymm0) + ++nup; + if (nup) { + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VECTOR_LOAD_VMASK(0xffff0000, s1, 2); + for (int i = start; i < 16; ++i) + if (dyn->e.ssecache[i].v != -1 && dyn->e.ssecache[i].vector && dyn->e.ssecache[i].ymm && !dyn->e.ssecache[i].ymm0) { + ADDI(s1, xEmu, offsetof(x64emu_t, ymm[i]) - 16); + VLE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_MASKED, VECTOR_NFIELD1); + } + } + } if (flushed8) vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); MESSAGE(LOG_DUMP, "\t------- Pop (vector) XMM Cache (%d)\n", n); From 37d91ce5eeec2ef56887f637286fa0f3e691c05f Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sun, 1 Nov 2026 20:57:39 +0800 Subject: [PATCH 128/156] [RV64_DYNAREC] Fixed cache transform on a back-edge to the block start --- src/dynarec/rv64/dynarec_rv64_functions.c | 5 +++- src/dynarec/rv64/dynarec_rv64_helper.c | 34 +++++++++++++++-------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index b9931a6d3..842fa608a 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -372,7 +372,7 @@ int fpuCacheNeedsTransform(dynarec_rv64_t* dyn, int ninst) // if the barrier as already been apply, no transform needed return ((dyn->insts[ninst].x64.barrier & BARRIER_FLOAT)) ? 0 : (isCacheEmpty(dyn, ninst) ? 0 : 1); int ret = 0; - if (!i2) { // just purge + if (!i2) { // restore the state the first instruction was emitted with if (dyn->insts[ninst].e.stack_next) { return 1; } @@ -385,6 +385,9 @@ int fpuCacheNeedsTransform(dynarec_rv64_t* dyn, int ninst) && dyn->insts[ninst].e.extcache[i].n < dyn->insts[ninst].e.stack_pop)) ret = 1; } + for (int i = 0; i < 24 && !ret; ++i) + if (dyn->insts[0].e.extcache[i].v) + ret = 1; return ret; } // Check if ninst can be compatible to i2 diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index d7e0b3b1a..29b17c308 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -2650,22 +2650,34 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in uint16_t dead = vectorDeadAtTarget(dyn, i2, ninst); MESSAGE(LOG_DUMP, "\tCache Transform ---- ninst=%d -> %d\n", ninst, i2); if ((!i2) || (dyn->insts[i2].x64.barrier & BARRIER_FLOAT)) { - if (dyn->e.stack_next) { - dyn->purge_dead_vector = dead; - fpu_purgecache(dyn, ninst, 1, s1, s2, s3); - MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); - return; - } - for (int i = 0; i < 24; ++i) - if (dyn->e.extcache[i].v) { // there is something at ninst for i + if (!i2) { + int any = 0; + for (int i = 0; i < 24 && !any; ++i) + if (dyn->insts[0].e.extcache[i].v) any = 1; + if (!any && !dyn->e.stack_next) { dyn->purge_dead_vector = dead; fpu_purgecache(dyn, ninst, 1, s1, s2, s3); MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); return; } - avx_sync_upper_vector(dyn, ninst, s1, 1); - MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); - return; + } else { + if (dyn->e.stack_next) { + dyn->purge_dead_vector = dead; + fpu_purgecache(dyn, ninst, 1, s1, s2, s3); + MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); + return; + } + for (int i = 0; i < 24; ++i) + if (dyn->e.extcache[i].v) { // there is something at ninst for i + dyn->purge_dead_vector = dead; + fpu_purgecache(dyn, ninst, 1, s1, s2, s3); + MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); + return; + } + avx_sync_upper_vector(dyn, ninst, s1, 1); + MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); + return; + } } extcache_t cache_i2 = dyn->insts[i2].e; extcacheUnwind(&cache_i2); From 74d9149095cf11aee60c87e2a070dd7eab1c2b5b Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sun, 1 Nov 2026 23:12:20 +0800 Subject: [PATCH 129/156] [DYNAREC] Rollbacked a wrong optimization in PR #4648 (#4650) --- src/dynarec/arm64/dynarec_arm64_emit_shift.c | 16 +++--------- src/dynarec/la64/dynarec_la64_emit_shift.c | 26 ++++++------------- .../ppc64le/dynarec_ppc64le_emit_shift.c | 20 +++++--------- src/dynarec/rv64/dynarec_rv64_emit_shift.c | 18 +++++-------- src/emu/x64emu.c | 18 ++++++------- 5 files changed, 33 insertions(+), 65 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c index 9cdffaeed..5467572cb 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c @@ -1623,12 +1623,8 @@ void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int c&=0x1f; IFX(X_PEND) { MOV32w(s3, c); - if (c > 16) { - ORRw_REG_LSL(s3, s3, s2, 16); // store fill in the upper half, needed for count > 16 - STRw_U12(s3, xEmu, offsetof(x64emu_t, op2)); - } else { - STRH_U12(s3, xEmu, offsetof(x64emu_t, op2)); - } + ORRw_REG_LSL(s3, s3, s2, 16); // store fill in the upper half, the deferred handler needs it for OF + STRw_U12(s3, xEmu, offsetof(x64emu_t, op2)); STRH_U12(s1, xEmu, offsetof(x64emu_t, op1)); SET_DF(s4, d_shrd16); } else { @@ -1721,12 +1717,8 @@ void emit_shld16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int c&=0x1f; IFX(X_PEND) { MOV32w(s3, c); - if (c > 16) { - ORRw_REG_LSL(s3, s3, s2, 16); // store fill in the upper half, needed for count > 16 - STRw_U12(s3, xEmu, offsetof(x64emu_t, op2)); - } else { - STRH_U12(s3, xEmu, offsetof(x64emu_t, op2)); - } + ORRw_REG_LSL(s3, s3, s2, 16); // store fill in the upper half, the deferred handler needs it for OF + STRw_U12(s3, xEmu, offsetof(x64emu_t, op2)); STRH_U12(s1, xEmu, offsetof(x64emu_t, op1)); SET_DF(s4, d_shld16); } else { diff --git a/src/dynarec/la64/dynarec_la64_emit_shift.c b/src/dynarec/la64/dynarec_la64_emit_shift.c index fb506a89c..d350c5e7d 100644 --- a/src/dynarec/la64/dynarec_la64_emit_shift.c +++ b/src/dynarec/la64/dynarec_la64_emit_shift.c @@ -2161,15 +2161,10 @@ void emit_shld16c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin { c &= 0x1f; IFX (X_PEND) { - if (c > 16) { - // store fill in the upper half, as the deferred handler needs it for count > 16 - SLLI_D(s3, s2, 16); - ORI(s3, s3, c); - ST_W(s3, xEmu, offsetof(x64emu_t, op2)); - } else { - MOV64x(s3, c); - ST_H(s3, xEmu, offsetof(x64emu_t, op2)); - } + // store fill in the upper half, the deferred handler needs it for the OF flag + SLLI_D(s3, s2, 16); + ORI(s3, s3, c); + ST_W(s3, xEmu, offsetof(x64emu_t, op2)); ST_H(s1, xEmu, offsetof(x64emu_t, op1)); SET_DF(s4, d_shld16); } else IFXORNAT (X_ALL) { @@ -2234,15 +2229,10 @@ void emit_shrd16c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin c &= 0x1f; IFX (X_PEND) { - if (c > 16) { - // store fill in the upper half, as the deferred handler needs it for count > 16 - SLLI_D(s3, s2, 16); - ORI(s3, s3, c); - ST_W(s3, xEmu, offsetof(x64emu_t, op2)); - } else { - MOV64x(s3, c); - ST_H(s3, xEmu, offsetof(x64emu_t, op2)); - } + // store fill in the upper half, the deferred handler needs it for the OF flag + SLLI_D(s3, s2, 16); + ORI(s3, s3, c); + ST_W(s3, xEmu, offsetof(x64emu_t, op2)); ST_H(s1, xEmu, offsetof(x64emu_t, op1)); SET_DF(s4, d_shrd16); } else IFXORNAT (X_ALL) { diff --git a/src/dynarec/ppc64le/dynarec_ppc64le_emit_shift.c b/src/dynarec/ppc64le/dynarec_ppc64le_emit_shift.c index 377d48dec..df2e5b4aa 100644 --- a/src/dynarec/ppc64le/dynarec_ppc64le_emit_shift.c +++ b/src/dynarec/ppc64le/dynarec_ppc64le_emit_shift.c @@ -1890,13 +1890,9 @@ void emit_shld16c(dynarec_ppc64le_t* dyn, int ninst, rex_t rex, int s1, int s2, IFX (X_PEND) { if (c) { MOV64x(s3, c); - if (c > 16) { - SLDI(s4, s2, 16); - OR(s3, s3, s4); - STW(s3, offsetof(x64emu_t, op2), xEmu); - } else { - STH(s3, offsetof(x64emu_t, op2), xEmu); - } + SLDI(s4, s2, 16); + OR(s3, s3, s4); + STW(s3, offsetof(x64emu_t, op2), xEmu); } else { LI(s3, 0); STH(s3, offsetof(x64emu_t, op2), xEmu); @@ -2030,13 +2026,9 @@ void emit_shrd16c(dynarec_ppc64le_t* dyn, int ninst, rex_t rex, int s1, int s2, IFX (X_PEND) { if (c) { MOV64x(s3, c); - if (c > 16) { - SLDI(s4, s2, 16); - OR(s3, s3, s4); - STW(s3, offsetof(x64emu_t, op2), xEmu); - } else { - STH(s3, offsetof(x64emu_t, op2), xEmu); - } + SLDI(s4, s2, 16); + OR(s3, s3, s4); + STW(s3, offsetof(x64emu_t, op2), xEmu); } else { LI(s3, 0); STH(s3, offsetof(x64emu_t, op2), xEmu); diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c index 0f703312f..68a1d461b 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c @@ -1864,12 +1864,9 @@ void emit_shrd16c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin IFX (X_PEND) { if (c) { MOV64x(s3, c); - if (c > 16) { - SLLI(s4, s2, 16); - OR(s3, s3, s4); - SW(s3, xEmu, offsetof(x64emu_t, op2)); - } else - SH(s3, xEmu, offsetof(x64emu_t, op2)); + SLLI(s4, s2, 16); + OR(s3, s3, s4); + SW(s3, xEmu, offsetof(x64emu_t, op2)); } else SH(xZR, xEmu, offsetof(x64emu_t, op2)); SH(s1, xEmu, offsetof(x64emu_t, op1)); @@ -2095,12 +2092,9 @@ void emit_shld16c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin IFX (X_PEND) { if (c) { MOV64x(s3, c); - if (c > 16) { - SLLI(s4, s2, 16); - OR(s3, s3, s4); - SW(s3, xEmu, offsetof(x64emu_t, op2)); - } else - SH(s3, xEmu, offsetof(x64emu_t, op2)); + SLLI(s4, s2, 16); + OR(s3, s3, s4); + SW(s3, xEmu, offsetof(x64emu_t, op2)); } else SH(xZR, xEmu, offsetof(x64emu_t, op2)); SH(s1, xEmu, offsetof(x64emu_t, op1)); diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c index 2cb0f7d4f..1edfe49c6 100644 --- a/src/emu/x64emu.c +++ b/src/emu/x64emu.c @@ -1246,16 +1246,16 @@ void UpdateFlags(x64emu_t* emu) CONDITIONAL_SET_FLAG(!emu->res.u16, F_ZF); CONDITIONAL_SET_FLAG(emu->res.u16 & 0x8000, F_SF); CONDITIONAL_SET_FLAG(PARITY(emu->res.u8), F_PF); + if BOX64ENV (cputype) { + CONDITIONAL_SET_FLAG(XOR2(emu->res.u16 >> 14), F_OF); + } else { + CONDITIONAL_SET_FLAG((((emu->op2.u64 >> 16) & 0xffff) ^ (emu->op1.u16 >> 15)) & 1, F_OF); + } + if (BOX64ENV(cputype)) + SET_FLAG(F_AF); + else + CLEAR_FLAG(F_AF); } - if BOX64ENV (cputype) { - CONDITIONAL_SET_FLAG(XOR2(emu->res.u16 >> 14), F_OF); - } else { - CONDITIONAL_SET_FLAG(((emu->res.u16 >> (16 - (cnt & 15))) ^ (emu->op1.u16 >> 15)) & 1, F_OF); - } - if (BOX64ENV(cputype)) - SET_FLAG(F_AF); - else - CLEAR_FLAG(F_AF); break; case d_shrd32: cnt = emu->op2.u32; From 22f67f2b20400b933336cff77e54c29581bb5e93 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 2 Nov 2026 01:47:28 +0800 Subject: [PATCH 130/156] [DYNAREC] Clear pending df on all DIV/IDIV paths (#4651) --- src/dynarec/la64/dynarec_la64_00_3.c | 1 + src/dynarec/rv64/dynarec_rv64_00_3.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/dynarec/la64/dynarec_la64_00_3.c b/src/dynarec/la64/dynarec_la64_00_3.c index 5571b4d35..f5c4baf17 100644 --- a/src/dynarec/la64/dynarec_la64_00_3.c +++ b/src/dynarec/la64/dynarec_la64_00_3.c @@ -1923,6 +1923,7 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int MARKREGd(xRAX); MARKREGd(xRDX); SET_DFNONE(); + CHECK_DFNONE(1); GETSED(0); if (BOX64ENV(dynarec_div0)) { BNE_MARK3(ed, xZR); diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index e3ace2ea6..ec4c1c37a 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -1576,6 +1576,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("DIV Eb"); MESSAGE(LOG_DUMP, "Need Optimization\n"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); + CHECK_DFNONE(1); GETEB(x1, 0); ZEXTH(x2, xRAX); if (BOX64ENV(dynarec_div0)) { @@ -1738,6 +1739,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("DIV Ed"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); SET_DFNONE(); + CHECK_DFNONE(1); MARKREGd(xRAX); MARKREGd(xRDX); MARKREGs(xRAX); @@ -1829,6 +1831,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); SET_DFNONE(); } + CHECK_DFNONE(1); MARKREGd(xRAX); MARKREGd(xRDX); MARKREGs(xRAX); From 27fd4073188a138455c42e1c42676076320363b8 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 2 Nov 2026 15:50:52 +0800 Subject: [PATCH 131/156] [DYNAREC] Preserved flags when a block is truncated on a fill fault (#4653) --- src/dynarec/dynarec_native.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dynarec/dynarec_native.c b/src/dynarec/dynarec_native.c index 24c89af58..7106c7e0f 100644 --- a/src/dynarec/dynarec_native.c +++ b/src/dynarec/dynarec_native.c @@ -651,6 +651,8 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, if(state==BUILD_PASS0 && helper.size>1) { --helper.size; end = helper.insts[helper.size].x64.addr; + if(interblock_flags_needed(&helper, end, is32bits)) + helper.insts[helper.size - 1].x64.need_after |= X_PEND; printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, truncating at %d(%p)\n", (void*)addr, helper.size, (void*)end); state = BUILD_PASS1; } else { From 23597f62fd57da4da3a2b8feb17c5e5e83e715dd Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Mon, 2 Nov 2026 16:03:40 +0800 Subject: [PATCH 132/156] [RV64_DYNAREC] Keep SEW when flushing YMM upper halves to reduce vsetvli (#4652) --- src/dynarec/rv64/dynarec_rv64_helper.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 29b17c308..083aad5f2 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -3103,20 +3103,23 @@ void fpu_propagate_stack(dynarec_rv64_t* dyn, int ninst) void avx_flush_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int reg, int next, int dead) { - uint8_t sew0, vlmul0, vl0; - vector_save_vtype(dyn, &sew0, &vlmul0, &vl0); if (dyn->e.ssecache[a].ymm0) { // the architectural upper half is zero: write it with scalar stores, no vector state needed SD(xZR, xEmu, offsetof(x64emu_t, ymm[a]) + 0); SD(xZR, xEmu, offsetof(x64emu_t, ymm[a]) + 8); + if (!next) dyn->e.ssecache[a].ymm = 0; + return; } else if (dyn->e.ssecache[a].ymm && dyn->e.ssecache[a].write) { + uint8_t sew0, vlmul0, vl0; + vector_save_vtype(dyn, &sew0, &vlmul0, &vl0); if (dead || dyn->e.fpu_scratch < 7) { int sp = dyn->e.fpu_scratch; int tmp = dead ? reg : fpu_get_scratch(dyn); - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); - VSLIDEDOWN_VI(tmp, reg, 16, VECTOR_UNMASKED); + int sew = sew0 <= VECTOR_SEW64 ? sew0 : VECTOR_SEW8; + vector_vsetvli(dyn, ninst, s1, sew, VECTOR_LMUL1, 1); + VSLIDEDOWN_VI(tmp, reg, 16 >> sew, VECTOR_UNMASKED); ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a])); - VSE8_V(tmp, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + VSE_V(tmp, s1, sew, VECTOR_UNMASKED, VECTOR_NFIELD1); dyn->e.fpu_scratch = sp; } else { dyn->inst_sew = VECTOR_SEWNA; @@ -3127,10 +3130,9 @@ void avx_flush_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int r VSE8_V(reg, s1, VECTOR_MASKED, VECTOR_NFIELD1); vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); } - } else - return; - if (!next) dyn->e.ssecache[a].ymm = 0; - vector_restore_vtype(dyn, ninst, s1, sew0, vlmul0, vl0); + if (!next) dyn->e.ssecache[a].ymm = 0; + vector_restore_vtype(dyn, ninst, s1, sew0, vlmul0, vl0); + } } void avx_promote_upper(dynarec_rv64_t* dyn, int ninst, int s1, uint16_t mask) From 20807c208c0c825f7f3fe3b89fec12531e00980d Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 3 Nov 2026 15:56:35 +0800 Subject: [PATCH 133/156] [RV64_DYNAREC] Reuse zero-extended operands in fused 32-bit compares (#4657) --- src/dynarec/rv64/dynarec_rv64_emit_tests.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_emit_tests.c b/src/dynarec/rv64/dynarec_rv64_emit_tests.c index bc82e7594..edfe69491 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_tests.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_tests.c @@ -232,17 +232,25 @@ void emit_cmp32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s NAT_FLAGS_ENABLE_CARRY(); NAT_FLAGS_ENABLE_SIGN(); if (dyn->insts[ninst].nat_flags_fusion) { - if (rex.w) { + if (rex.w) NAT_FLAGS_OPS(s1, s2, s3, s4); - } else { + else { + int op1 = s3; + int op2 = s4; if (dyn->insts[ninst].nat_flags_needsign) { SEXT_W(s3, s1); SEXT_W(s4, s2); } else { - ZEXTW2(s3, s1); - ZEXTW2(s4, s2); + if (isUpper32Zero(dyn, ninst, s1)) + op1 = s1; + else + ZEXTW2(s3, s1); + if (isUpper32Zero(dyn, ninst, s2)) + op2 = s2; + else + ZEXTW2(s4, s2); } - NAT_FLAGS_OPS(s3, s4, s5, xZR); + NAT_FLAGS_OPS(op1, op2, s5, s6); } } } From d338d4660e2d828d38ad4cb9e915d7da30f3f82b Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 3 Nov 2026 15:57:33 +0800 Subject: [PATCH 134/156] [RV64] Reset RVV extensions when vector is disabled (#4658) --- src/os/hostext_linux.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/os/hostext_linux.c b/src/os/hostext_linux.c index a1b3b6c6d..95423b796 100644 --- a/src/os/hostext_linux.c +++ b/src/os/hostext_linux.c @@ -337,6 +337,14 @@ int DetectHostCpuFeatures(void) p = strtok(NULL, ","); } } + if (!cpuext.vector) { + cpuext.vlen = 0; + cpuext.zvkned = 0; + cpuext.zvknha = 0; + cpuext.zvknhb = 0; + cpuext.zvbb = 0; + cpuext.zvfh = 0; + } } #elif defined(PPC64LE) unsigned long hwcap = real_getauxval(AT_HWCAP); From b8171c2402e49aa4049f1a51dcfc7637ea2b4293 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 3 Nov 2026 15:58:32 +0800 Subject: [PATCH 135/156] [RV64_DYNAREC] Track zero-extension of LEA and SRLIW results (#4659) --- src/dynarec/rv64/dynarec_rv64_00_2.c | 3 ++- src/dynarec/rv64/dynarec_rv64_emit_shift.c | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_00_2.c b/src/dynarec/rv64/dynarec_rv64_00_2.c index 6423ff20f..3a288a582 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_2.c +++ b/src/dynarec/rv64/dynarec_rv64_00_2.c @@ -511,8 +511,9 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ZEXTW2(gd, ed); else MVxw(gd, ed); + if (!rex.w) UP32_ZERO(gd); } else if (!rex.w && !rex.is32bits) { - ZEROUP(gd); // truncate the higher 32bits as asked + ZEROUP_RESULT(gd); // truncate the higher 32bits as asked } } break; diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c index 68a1d461b..2e758209a 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c @@ -839,8 +839,11 @@ void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, SET_FLAGS_LTZ(s1, F_SF, s3, s4); } UP32_WRITE32(s1); - if (!rex.w && c == 0) { - ZEROUP_RESULT(s1); + if (!rex.w) { + if (c == 0) + ZEROUP_RESULT(s1); + else + UP32_ZERO(s1); // SRLIW with c>0 always clears bit 31 } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); From 03d689bf5659d418f5a1447e67742ada351ba7bb Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 3 Nov 2026 16:00:28 +0800 Subject: [PATCH 136/156] [RV64_DYNAREC] Materialize direct call return address from xRIP (#4660) --- src/dynarec/rv64/dynarec_rv64_00_3.c | 12 ++---------- src/dynarec/rv64/dynarec_rv64_helper.h | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index ec4c1c37a..c69131e9b 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -1323,11 +1323,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 1: // this is call to next step, so just push the return address to the stack - if (dyn->need_reloc) { - TABLE64(x2, addr); - } else { - MOV64x(x2, addr); - } + GETRETADDR(addr, x2, x3); PUSH1z(x2); break; default: @@ -1337,11 +1333,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags to "dont'care" state } // regular call - if (dyn->need_reloc) { - TABLE64(x2, addr); - } else { - MOV64x(x2, addr); - } + GETRETADDR(addr, x2, x3); BARRIER(BARRIER_FLOAT); PUSH1z(x2); int can_continue = (addr < (dyn->start + dyn->isize)); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 1983446d0..c47c2fa82 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1623,6 +1623,7 @@ #if STEP < 2 #define GETIP(A, scratch) #define GETIP_(A, scratch) +#define GETRETADDR(A, reg, scratch) #else #define GETIP_(A, scratch) \ do { \ @@ -1654,6 +1655,21 @@ GETIP_(A, scratch); \ dyn->last_ip = (A); +#define GETRETADDR(A, reg, scratch) \ + do { \ + ssize_t _delta_ra = (ssize_t)(A) - (ssize_t)dyn->last_ip; \ + if (dyn->last_ip && _delta_ra >= -2048 && _delta_ra < 2048) { \ + if (_delta_ra) \ + ADDI(reg, xRIP, _delta_ra); \ + else \ + MV(reg, xRIP); \ + } else if (dyn->need_reloc) { \ + TABLE64(reg, (A)); \ + } else { \ + MOV64x(reg, (A)); \ + } \ + } while (0) + #endif #define CLEARIP() dyn->last_ip = 0 From 3d48b55edb7400ab1e1291be9a741ea3ea2f4d03 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 3 Nov 2026 16:01:21 +0800 Subject: [PATCH 137/156] [RV64_DYNAREC] Extend nativeflags to 1+N pattern (#4661) --- src/dynarec/rv64/dynarec_rv64_functions.c | 32 +++++++++++---- src/dynarec/rv64/dynarec_rv64_helper.h | 48 ++++++++++++++--------- src/dynarec/rv64/dynarec_rv64_pass0.h | 2 +- src/dynarec/rv64/dynarec_rv64_private.h | 1 + 4 files changed, 57 insertions(+), 26 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index 842fa608a..c0aa7940c 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -880,28 +880,46 @@ int fpu_is_st_freed(dynarec_rv64_t* dyn, int ninst, int st) return (dyn->e.tags & (0b11 << (st * 2))) ? 1 : 0; } +static int hasLinearPredecessor(const dynarec_rv64_t* dyn, int ninst); + void updateNativeFlags(dynarec_rv64_t* dyn) { if (!BOX64ENV(dynarec_nativeflags)) return; - for (int i = 1; i < dyn->size; ++i) + for (int i = 0; i < dyn->size; ++i) if (dyn->insts[i].nat_flags_fusion) { int j = i - 1; int found = 0; - if (dyn->insts[i].pred_sz == 1 && dyn->insts[i].pred[0] == j) { + int last_fused = 0; + if (hasLinearPredecessor(dyn, i)) { while (j >= 0) { if (dyn->insts[j].x64.set_flags && (dyn->insts[i].x64.use_flags & dyn->insts[j].x64.set_flags) == dyn->insts[i].x64.use_flags) { + int needsign = (dyn->insts[i].x64.use_flags & X_SF) ? 1 : 0; + int needunsigned = (dyn->insts[i].x64.use_flags & X_CF) ? 1 : 0; + if (dyn->insts[j].nat_flags_fusion && ((needsign && dyn->insts[j].nat_flags_needunsigned) || (needunsigned && dyn->insts[j].nat_flags_needsign))) + break; // not compatible, stop here dyn->insts[j].nat_flags_fusion = 1; - if (dyn->insts[i].x64.use_flags & X_SF) { + if (needsign) dyn->insts[j].nat_flags_needsign = 1; - } + if (needunsigned) + dyn->insts[j].nat_flags_needunsigned = 1; dyn->insts[i].x64.use_flags = 0; - dyn->insts[j].nat_next_inst = i; + if (last_fused) { + dyn->insts[last_fused].nat_next_inst = i; + } else { + uint16_t* next = &dyn->insts[j].nat_next_inst; + while (*next) + next = &dyn->insts[*next].nat_next_inst; + *next = i; + } dyn->insts[i].up32_read |= dyn->insts[j].up32_write32; found = 1; break; - } else if (j && dyn->insts[j].pred_sz == 1 && dyn->insts[j].pred[0] == j - 1 - && dyn->insts[j].no_scratch_usage && !dyn->insts[j].x64.set_flags && !dyn->insts[j].x64.use_flags) { + } else if (hasLinearPredecessor(dyn, j) && dyn->insts[j].nat_flags_fusion && dyn->insts[j].x64.jmp && !dyn->insts[j].x64.set_flags && !dyn->insts[j].x64.use_flags) { + // already fused Jcc consumer + if (!last_fused) last_fused = j; + j -= 1; + } else if (hasLinearPredecessor(dyn, j) && dyn->insts[j].no_scratch_usage && !dyn->insts[j].x64.set_flags && !dyn->insts[j].x64.use_flags) { j -= 1; } else break; diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index c47c2fa82..dee90fe07 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1506,24 +1506,36 @@ READFLAGS(A) #endif -#define NAT_FLAGS_OPS(op1, op2, s1, s2) \ - do { \ - dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op1 = op1; \ - dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op2 = op2; \ - if (dyn->insts[ninst + 1].no_scratch_usage && IS_GPR(op1)) { \ - if (dyn->insts[ninst].up32_read & (1 << TO_X64(op1))) \ - MV(s1, op1); \ - else \ - ZEXTW2(s1, op1); \ - dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op1 = s1; \ - } \ - if (dyn->insts[ninst + 1].no_scratch_usage && IS_GPR(op2)) { \ - if (dyn->insts[ninst].up32_read & (1 << TO_X64(op2))) \ - MV(s2, op2); \ - else \ - ZEXTW2(s2, op2); \ - dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op2 = s2; \ - } \ +#define NAT_FLAGS_OPS(op1, op2, s1, s2) \ + do { \ + int nat_op1 = op1; \ + int nat_op2 = op2; \ + int nat_next = dyn->insts[ninst].nat_next_inst; \ + int nat_last = nat_next; \ + while (nat_last && dyn->insts[nat_last].nat_next_inst) \ + nat_last = dyn->insts[nat_last].nat_next_inst; \ + int nat_copy = 0; \ + for (int nat_i = ninst + 1; nat_i < nat_last; ++nat_i) \ + if (dyn->insts[nat_i].no_scratch_usage) \ + nat_copy = 1; \ + if (nat_copy && IS_GPR(nat_op1)) { \ + if (dyn->insts[ninst].up32_read & (1 << TO_X64(nat_op1))) \ + MV(s1, nat_op1); \ + else \ + ZEXTW2(s1, nat_op1); \ + nat_op1 = s1; \ + } \ + if (nat_copy && IS_GPR(nat_op2)) { \ + if (dyn->insts[ninst].up32_read & (1 << TO_X64(nat_op2))) \ + MV(s2, nat_op2); \ + else \ + ZEXTW2(s2, nat_op2); \ + nat_op2 = s2; \ + } \ + for (int nat_i = nat_next; nat_i; nat_i = dyn->insts[nat_i].nat_next_inst) { \ + dyn->insts[nat_i].nat_flags_op1 = nat_op1; \ + dyn->insts[nat_i].nat_flags_op2 = nat_op2; \ + } \ } while (0) #define NAT_FLAGS_ENABLE_CARRY() dyn->insts[ninst].nat_flags_carry = 1 diff --git a/src/dynarec/rv64/dynarec_rv64_pass0.h b/src/dynarec/rv64/dynarec_rv64_pass0.h index cf493b341..e8186bfc2 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass0.h +++ b/src/dynarec/rv64/dynarec_rv64_pass0.h @@ -19,7 +19,7 @@ #define READFLAGS_FUSION(A, s1, s2, s3, s4, s5) \ if (BOX64ENV(dynarec_nativeflags) && ninst > 0) { \ int prev = ninst - 1; \ - while (prev && dyn->insts[prev].no_scratch_usage) \ + while (prev && (dyn->insts[prev].no_scratch_usage || dyn->insts[prev].nat_flags_fusion)) \ prev -= 1; \ if (!dyn->insts[prev].nat_flags_nofusion) { \ if ((A) == (X_ZF)) \ diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index e5b178978..8f5075fb9 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -141,6 +141,7 @@ typedef struct instruction_rv64_s { uint8_t nat_flags_carry:1; uint8_t nat_flags_sign:1; uint8_t nat_flags_needsign:1; + uint8_t nat_flags_needunsigned:1; uint8_t unaligned:1; // this opcode can be re-generated for unaligned special case uint8_t x87precision:1; // this opcode can handle x87pc uint8_t no_scratch_usage:1; // this opcode does not use scratch register From 6bee368bd2b0fa42c6bc497614307bb9b332bf53 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 3 Nov 2026 16:02:07 +0800 Subject: [PATCH 138/156] [RV64_DYNAREC] Fence stores at RET by default (#4655) --- src/dynarec/rv64/dynarec_rv64_helper.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 083aad5f2..fc9d8c157 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -566,6 +566,8 @@ void ret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex) ADDI(xSP, xSP, 16); // pop if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x7); + else if (!BOX64DRENV(dynarec_strongmem)) + FENCE_W_W(); BNE(x6, xRIP, 2 * 4); // is it the right address? BR(xRA); // not the correct return address, regular jump, but purge the stack first, it's unsync now... From 9c5e8a541a18c2a806b7f0a2de70b0acdd1f469d Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 3 Nov 2026 18:55:35 +0800 Subject: [PATCH 139/156] [RV64_DYNAREC] Include up32 and rsp in arch state detection (#4662) --- src/dynarec/rv64/dynarec_rv64_arch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dynarec/rv64/dynarec_rv64_arch.c b/src/dynarec/rv64/dynarec_rv64_arch.c index 391b10b19..409f673d6 100644 --- a/src/dynarec/rv64/dynarec_rv64_arch.c +++ b/src/dynarec/rv64/dynarec_rv64_arch.c @@ -166,7 +166,7 @@ static int arch_build(dynarec_rv64_t* dyn, int ninst, arch_build_t* arch) arch->mmx = 1; if (arch->sse_.sse) arch->sse = 1; - return arch->flags + arch->x87 + arch->mmx + arch->sse + arch->ymm + arch->unaligned; + return arch->flags + arch->x87 + arch->mmx + arch->sse + arch->ymm + arch->unaligned + (arch->up32 != 0) + (arch->rsp != 0); } size_t get_size_arch(dynarec_rv64_t* dyn) From b640a570b34ddd0ae271b37bfb2fac64d6d77c57 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 3 Nov 2026 19:18:50 +0800 Subject: [PATCH 140/156] [RV64_DYNAREC] Use fence.tso for RET and strongmem barriers (#4663) --- src/dynarec/dynarec_helper.h | 12 ++++++++---- src/dynarec/rv64/dynarec_rv64_helper.c | 2 +- src/dynarec/rv64/rv64_emitter.h | 8 ++++++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/dynarec/dynarec_helper.h b/src/dynarec/dynarec_helper.h index fd63918ce..662733385 100644 --- a/src/dynarec/dynarec_helper.h +++ b/src/dynarec/dynarec_helper.h @@ -110,7 +110,7 @@ if (STRONGMEM_LEVEL() >= STRONGMEM_SEQ_WRITE) { \ if (++dyn->smwrite >= 3 /* Every third memory write */ \ || STRONGMEM_LEVEL() >= STRONGMEM_QEMU) { \ - DMB_ISH(); \ + DMB_TSO(); \ dyn->smwrite = 1; \ } \ } else { \ @@ -163,14 +163,14 @@ if (BOX64ENV(dynarec_weakbarrier)) \ DMB_ISHLD(); \ else \ - DMB_ISH(); \ + DMB_TSO(); \ } else if (STRONGMEM_LEVEL() >= STRONGMEM_LAST_WRITE && BOX64ENV(dynarec_weakbarrier) != 2 \ && dyn->insts[ninst].last_write) { \ /* Last write, put a barrier */ \ if (BOX64ENV(dynarec_weakbarrier)) \ DMB_ISHST(); \ else \ - DMB_ISH(); \ + DMB_TSO(); \ } \ } while (0) @@ -200,7 +200,7 @@ if (BOX64ENV(dynarec_weakbarrier)) \ DMB_ISHST(); \ else \ - DMB_ISH(); \ + DMB_TSO(); \ } \ } \ dyn->smwrite = 0; \ @@ -236,4 +236,8 @@ int is_addr_autosmc(uintptr_t addr); #error Unsupported architecture #endif +#ifndef DMB_TSO +#define DMB_TSO() DMB_ISH() +#endif + #endif //__DYNAREC_HELPER__H_ diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index fc9d8c157..e98076fb0 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -567,7 +567,7 @@ void ret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex) if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x7); else if (!BOX64DRENV(dynarec_strongmem)) - FENCE_W_W(); + DMB_TSO(); BNE(x6, xRIP, 2 * 4); // is it the right address? BR(xRA); // not the correct return address, regular jump, but purge the stack first, it's unsync now... diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index a44b46091..9fb6a3dd0 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -603,10 +603,18 @@ #define FENCE_R_RW() EMIT(FENCE_gen(2, 3)) #define FENCE_W_W() EMIT(FENCE_gen(1, 1)) #define FENCE_RW_RW() EMIT(FENCE_gen(3, 3)) +#define FENCE_TSO() EMIT(FENCE_gen(3, 3) | (8u << 28)) #define DMB_ISH() FENCE_RW_RW() #define DMB_ISHLD() FENCE_R_RW() #define DMB_ISHST() FENCE_W_W() +#define DMB_TSO() \ + do { \ + if (cpuext.vector && !cpuext.xtheadvector) \ + FENCE_TSO(); \ + else \ + FENCE_RW_RW(); \ + } while (0) #define FENCE_I_gen() ((0b001 << 12) | 0b0001111) #define FENCE_I() EMIT(FENCE_I_gen()) From b71b00322ec41fa49ea0c2e0a466424433622ca4 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 3 Nov 2026 22:08:09 +0800 Subject: [PATCH 141/156] [RV64_DYNAREC] Added autocrc support (#4664) --- src/dynarec/dynarec_arch.h | 8 ++ src/dynarec/dynarec_native_pass.c | 20 +--- src/dynarec/rv64/dynarec_rv64_consts.c | 6 ++ src/dynarec/rv64/dynarec_rv64_consts.h | 3 + src/dynarec/rv64/dynarec_rv64_helper.c | 16 +++ src/dynarec/rv64/dynarec_rv64_helper.h | 7 ++ src/dynarec/rv64/rv64_lock.S | 135 +++++++++++++++++++++++++ src/dynarec/rv64/rv64_next.S | 49 ++++++++- 8 files changed, 223 insertions(+), 21 deletions(-) diff --git a/src/dynarec/dynarec_arch.h b/src/dynarec/dynarec_arch.h index 8c55c93e6..30a27944d 100644 --- a/src/dynarec/dynarec_arch.h +++ b/src/dynarec/dynarec_arch.h @@ -129,6 +129,14 @@ extern void la64_next_invalid(); #define ARCH_UNALIGNED(A, B) arch_unaligned(A, B) #define ARCH_HOST_CALL(A, B, C) 0 +extern uint32_t rv64_crc(void* p, uint32_t len); +extern uint32_t rv64_crc_zbc(void* p, uint32_t len); +extern void rv64_crc_autocrc(); +extern void rv64_crc_autocrc_zbc(); +#define ARCH_CRC(A, B) return cpuext.zbc ? rv64_crc_zbc(A, B) : rv64_crc(A, B) +#define ARCH_CRC_INLINE +extern void rv64_next_invalid(); + #define ARCH_NOP 0b0010011 #define ARCH_UDF 0xc0001073 diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index a9f1011d5..7d05b86c9 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -159,17 +159,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int NATIVE_RESTORE_X87PC(); } ip = addr; - #ifdef ARM64 - if(!ninst) { - if (BOX64DRENV(dynarec_callret) >= 3) - doEnterBlock(dyn, 0, x1, x2, x3); - if(dyn->always_test) - checkCRC(dyn, 0); - if(dyn->insts[0].preload_xmmymm) - doPreload(dyn, 0); - ENDPREFIX; - } - #elif defined(LA64) + #if defined(ARM64) || defined(LA64) || defined(RV64) if(!ninst) { if (BOX64DRENV(dynarec_callret) >= 3) doEnterBlock(dyn, 0, x1, x2, x3); @@ -180,14 +170,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int } ENDPREFIX; } - #elif defined(RV64) - if(!ninst) { - if (BOX64DRENV(dynarec_callret) >= 3) - doEnterBlock(dyn, 0, x1, x2, x3); - if (dyn->insts[0].preload_xmmymm) - doPreload(dyn, 0); - ENDPREFIX; - } #endif fpu_propagate_stack(dyn, ninst); if (reset_n!=-1) { diff --git a/src/dynarec/rv64/dynarec_rv64_consts.c b/src/dynarec/rv64/dynarec_rv64_consts.c index 26f7cb184..75ebd0123 100644 --- a/src/dynarec/rv64/dynarec_rv64_consts.c +++ b/src/dynarec/rv64/dynarec_rv64_consts.c @@ -31,6 +31,9 @@ void PrintTrace() {} #endif void* create_updateflags(); +extern void rv64_next_invalid(); +extern void rv64_crc_autocrc(); +extern void rv64_crc_autocrc_zbc(); uintptr_t getConst(rv64_consts_t which) { @@ -140,6 +143,9 @@ uintptr_t getConst(rv64_consts_t which) case const_context: return (uintptr_t)my_context; case const_lead0tab: return (uintptr_t)lead0tab; case const_deBruijn64tab: return (uintptr_t)deBruijn64tab; + case const_native_next_invalid: return (uintptr_t)rv64_next_invalid; + case const_rv64_crc_autocrc: return (uintptr_t)rv64_crc_autocrc; + case const_rv64_crc_autocrc_zbc: return (uintptr_t)rv64_crc_autocrc_zbc; case const_last: dynarec_log(LOG_NONE, "Warning, const last used\n"); return (uintptr_t)native_ud; diff --git a/src/dynarec/rv64/dynarec_rv64_consts.h b/src/dynarec/rv64/dynarec_rv64_consts.h index 0cb183de5..7c80d431f 100644 --- a/src/dynarec/rv64/dynarec_rv64_consts.h +++ b/src/dynarec/rv64/dynarec_rv64_consts.h @@ -108,6 +108,9 @@ typedef enum rv64_consts_s { const_context, const_lead0tab, const_deBruijn64tab, + const_native_next_invalid, + const_rv64_crc_autocrc, + const_rv64_crc_autocrc_zbc, const_last } rv64_consts_t; diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index e98076fb0..5e2dea282 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -580,6 +580,22 @@ void ret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex) CLEARIP(); } +void checkCRC(dynarec_rv64_t* dyn, int ninst) +{ + MAYUSE(ninst); + int delta = -(dyn->native_size + sizeof(void*)); + AUIPC(x6, SPLIT20(delta)); + LD(x6, x6, SPLIT12(delta)); + LD(x3, x6, offsetof(dynablock_t, x64_addr)); + LWU(x4, x6, offsetof(dynablock_t, x64_size)); + TABLE64C(x1, cpuext.zbc ? const_rv64_crc_autocrc_zbc : const_rv64_crc_autocrc); + JALR(xRA, x1); + LWU(x1, x6, offsetof(dynablock_t, hash)); + BEQ(x2, x1, 4 * 4); + TABLE64C(x1, const_native_next_invalid); + JALR(xZR, x1); +} + void iret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is32bits, int is64bits) { int64_t j64; diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index dee90fe07..b219719de 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1632,6 +1632,11 @@ dyn->inst_vlmul = VECTOR_LMUL1; \ dyn->inst_vl = 0; +#undef PREFLAGSNEEDED +#define PREFLAGSNEEDED() \ + if (dyn->always_test && ninst && dyn->insts[ninst - 1].x64.has_callret) \ + checkCRC(dyn, ninst); + #if STEP < 2 #define GETIP(A, scratch) #define GETIP_(A, scratch) @@ -1893,6 +1898,7 @@ #define jump_to_epilog_fast STEPNAME(jump_to_epilog_fast) #define jump_to_next STEPNAME(jump_to_next) #define ret_to_next STEPNAME(ret_to_next) +#define checkCRC STEPNAME(checkCRC) #define doEnterBlock STEPNAME(doEnterBlock) #define doLeaveBlock STEPNAME(doLeaveBlock) #define iret_to_next STEPNAME(iret_to_next) @@ -2092,6 +2098,7 @@ void doEnterBlock(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3); void doLeaveBlock(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3); void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is32bits); void ret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex); +void checkCRC(dynarec_rv64_t* dyn, int ninst); void iret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is32bits, int is64bits); void call_c(dynarec_rv64_t* dyn, int ninst, rv64_consts_t fnc, int reg, int ret, int saveflags, int savereg, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6); void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w); diff --git a/src/dynarec/rv64/rv64_lock.S b/src/dynarec/rv64/rv64_lock.S index a27694af3..ce293887e 100644 --- a/src/dynarec/rv64/rv64_lock.S +++ b/src/dynarec/rv64/rv64_lock.S @@ -26,6 +26,10 @@ .global rv64_lock_get_b .global rv64_lock_get_d .global rv64_lock_get_dd +.global rv64_crc +.global rv64_crc_autocrc +.global rv64_crc_zbc +.global rv64_crc_autocrc_zbc rv64_lock_xchg_dd: // address is a0, value is a1, return old value in a0 @@ -271,3 +275,134 @@ rv64_lock_get_dd: fence rw, rw ld a0, 0(a0) ret + +rv64_crc: + // a0 = address, a1 = length, returns uint32_t hash in a0 + li a2, 0xcbf29ce484222325 + li a7, 0x100000001b3 + li a3, 8 +1: + bltu a1, a3, 2f + ld a4, 0(a0) + xor a2, a2, a4 + mul a2, a2, a7 + addi a0, a0, 8 + addi a1, a1, -8 + bnez a1, 1b +2: + beqz a1, 3f + lbu a4, 0(a0) + xor a2, a2, a4 + mul a2, a2, a7 + addi a0, a0, 1 + addi a1, a1, -1 + bnez a1, 2b +3: + mv a0, a2 + addiw a0, a0, 0 + ret + +rv64_crc_autocrc: + // t3 = address, t4 = length, t2 = hash, t6 is preserved + li t2, 0xcbf29ce484222325 + li a7, 0x100000001b3 + li t5, 8 +1: + bltu t4, t5, 2f + ld t1, 0(t3) + xor t2, t2, t1 + mul t2, t2, a7 + addi t3, t3, 8 + addi t4, t4, -8 + bnez t4, 1b +2: + beqz t4, 3f + lbu t1, 0(t3) + xor t2, t2, t1 + mul t2, t2, a7 + addi t3, t3, 1 + addi t4, t4, -1 + bnez t4, 2b +3: + slli t2, t2, 32 + srli t2, t2, 32 + ret + + .option arch, +zbc +rv64_crc_zbc: + // a0 = address, a1 = length, returns uint32_t CRC32C in a0 + li a2, 0 + li a3, 8 +1: + bltu a1, a3, 2f + slli a2, a2, 32 + srli a2, a2, 32 + ld a4, 0(a0) + xor a4, a4, a2 + li a7, 0x4869EC38DEA713F1 + clmul a4, a4, a7 + li a7, 0x105EC76F1 + clmulh a4, a4, a7 + mv a2, a4 + addi a0, a0, 8 + addi a1, a1, -8 + bnez a1, 1b +2: + beqz a1, 3f + slli a2, a2, 32 + srli a2, a2, 32 + lbu a4, 0(a0) + xor a4, a4, a2 + slli a4, a4, 56 + li a7, 0x4869EC38DEA713F1 + clmul a4, a4, a7 + li a7, 0x105EC76F1 + clmulh a4, a4, a7 + srli a3, a2, 8 + xor a2, a4, a3 + addi a0, a0, 1 + addi a1, a1, -1 + bnez a1, 2b +3: + mv a0, a2 + addiw a0, a0, 0 + ret + +rv64_crc_autocrc_zbc: + // t3 = address, t4 = length, t2 = CRC32C, t6 is preserved + li t2, 0 + li t5, 8 +1: + bltu t4, t5, 2f + slli t2, t2, 32 + srli t2, t2, 32 + ld t1, 0(t3) + xor t1, t1, t2 + li a7, 0x4869EC38DEA713F1 + clmul t1, t1, a7 + li a7, 0x105EC76F1 + clmulh t1, t1, a7 + mv t2, t1 + addi t3, t3, 8 + addi t4, t4, -8 + bnez t4, 1b +2: + beqz t4, 3f + slli t2, t2, 32 + srli t2, t2, 32 + lbu t1, 0(t3) + xor t1, t1, t2 + slli t1, t1, 56 + li a7, 0x4869EC38DEA713F1 + clmul t1, t1, a7 + li a7, 0x105EC76F1 + clmulh t1, t1, a7 + srli t5, t2, 8 + xor t2, t1, t5 + addi t3, t3, 1 + addi t4, t4, -1 + bnez t4, 2b +3: + slli t2, t2, 32 + srli t2, t2, 32 + ret diff --git a/src/dynarec/rv64/rv64_next.S b/src/dynarec/rv64/rv64_next.S index 3e4434cbf..5cabb705b 100644 --- a/src/dynarec/rv64/rv64_next.S +++ b/src/dynarec/rv64/rv64_next.S @@ -7,8 +7,10 @@ .align 4 .extern LinkNext +.extern LinkNextInvalid .global rv64_next +.global rv64_next_invalid // NULL pointer before rv64_next, for getDB .8byte 0 @@ -33,9 +35,7 @@ rv64_next: mv a0, Emu mv a1, RIP -#ifdef HAVE_TRACE mv a2, ra // "from" is in ra, so put in a2 -#endif addi a3, sp, 8*8 // a3 is address to change rip // call the function @@ -61,3 +61,48 @@ rv64_next: // return offset is jump address jr t3 +rv64_next_invalid: + sd RSP, (8 * 4)(Emu) + sd RIP, (8 * 17)(Emu) + + // 16 bytes aligned + addi sp, sp, -(8 * 10) + + // push regs we care that might be destoryed + sd RDI, (0*8)(sp) + sd RSI, (1*8)(sp) + sd RDX, (2*8)(sp) + sd RCX, (3*8)(sp) + sd R8, (4*8)(sp) + sd R9, (5*8)(sp) + sd RAX, (6*8)(sp) + sd RIP, (8*8)(sp) + + mv a0, Emu + mv a1, RIP + mv a2, ra // "from" is in ra, so put in a2 + addi a3, sp, 8*8 // a3 is address to change rip + + // call the function +1: + auipc t4, %pcrel_hi(LinkNextInvalid) + jalr t4, %pcrel_lo(1b) + + // reserve return value + mv t3, a0 + + // pop regs + ld RDI, (0*8)(sp) + ld RSI, (1*8)(sp) + ld RDX, (2*8)(sp) + ld RCX, (3*8)(sp) + ld R8, (4*8)(sp) + ld R9, (5*8)(sp) + ld RAX, (6*8)(sp) + ld RIP, (8*8)(sp) + + addi sp, sp, (8 * 10) + + // return offset is jump address + jr t3 + From 27a2d1f81df2c0166162cc859eafb61a178aa440 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 4 Nov 2026 01:01:15 +0800 Subject: [PATCH 142/156] [WRAPPER] Wrapped CRYPTO_set_mem_functions for libcrypto.so.3 (#4665) --- src/wrapped/generated/functions_list.txt | 1 + src/wrapped/generated/wrappedcrypto3types.h | 1 + src/wrapped/wrappedcrypto3.c | 76 +++++++++++++++++++++ src/wrapped/wrappedcrypto3_private.h | 2 +- 4 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/wrapped/generated/functions_list.txt b/src/wrapped/generated/functions_list.txt index 29ddbcf0c..1d5802a78 100644 --- a/src/wrapped/generated/functions_list.txt +++ b/src/wrapped/generated/functions_list.txt @@ -4428,6 +4428,7 @@ wrappedcrypto3: - EVP_MD_do_all_provided - iFppp: - ASN1_i2d_bio + - CRYPTO_set_mem_functions - iFppV: - BIO_printf - pFppp: diff --git a/src/wrapped/generated/wrappedcrypto3types.h b/src/wrapped/generated/wrappedcrypto3types.h index 05ea31e67..8eb7bd031 100644 --- a/src/wrapped/generated/wrappedcrypto3types.h +++ b/src/wrapped/generated/wrappedcrypto3types.h @@ -62,6 +62,7 @@ typedef void* (*pFpppppppp_t)(void*, void*, void*, void*, void*, void*, void*, v GO(UI_method_set_writer, iFpp_t) \ GO(EVP_MD_do_all_provided, vFppp_t) \ GO(ASN1_i2d_bio, iFppp_t) \ + GO(CRYPTO_set_mem_functions, iFppp_t) \ GO(BIO_printf, iFppV_t) \ GO(OPENSSL_sk_deep_copy, pFppp_t) \ GO(OSSL_PARAM_construct_int, pFppp_t) \ diff --git a/src/wrapped/wrappedcrypto3.c b/src/wrapped/wrappedcrypto3.c index 419ad501a..dbd24002a 100644 --- a/src/wrapped/wrappedcrypto3.c +++ b/src/wrapped/wrappedcrypto3.c @@ -628,6 +628,82 @@ static void* find_ECDH_KDF_Fct(void* fct) return NULL; } +// mem_malloc +#define GO(A) \ +static uintptr_t my3_mem_malloc_fct_##A = 0; \ +static void* my3_mem_malloc_##A(size_t a, void* b, int c) \ +{ \ + return (void*)RunFunctionFmt(my3_mem_malloc_fct_##A, "Lpi", a, b, c); \ +} +SUPER() +#undef GO +static void* find_mem_malloc_Fct(void* fct) +{ + if(!fct) return NULL; + void* p; + if((p = GetNativeFnc((uintptr_t)fct))) return p; + #define GO(A) if(my3_mem_malloc_fct_##A == (uintptr_t)fct) return my3_mem_malloc_##A; + SUPER() + #undef GO + #define GO(A) if(my3_mem_malloc_fct_##A == 0) {my3_mem_malloc_fct_##A = (uintptr_t)fct; return my3_mem_malloc_##A; } + SUPER() + #undef GO + printf_log(LOG_NONE, "Warning, no more slot for libcrypto mem_malloc callback\n"); + return NULL; +} +// mem_realloc +#define GO(A) \ +static uintptr_t my3_mem_realloc_fct_##A = 0; \ +static void* my3_mem_realloc_##A(void* a, size_t b, void* c, int d) \ +{ \ + return (void*)RunFunctionFmt(my3_mem_realloc_fct_##A, "pLpi", a, b, c, d); \ +} +SUPER() +#undef GO +static void* find_mem_realloc_Fct(void* fct) +{ + if(!fct) return NULL; + void* p; + if((p = GetNativeFnc((uintptr_t)fct))) return p; + #define GO(A) if(my3_mem_realloc_fct_##A == (uintptr_t)fct) return my3_mem_realloc_##A; + SUPER() + #undef GO + #define GO(A) if(my3_mem_realloc_fct_##A == 0) {my3_mem_realloc_fct_##A = (uintptr_t)fct; return my3_mem_realloc_##A; } + SUPER() + #undef GO + printf_log(LOG_NONE, "Warning, no more slot for libcrypto mem_realloc callback\n"); + return NULL; +} +// mem_free +#define GO(A) \ +static uintptr_t my3_mem_free_fct_##A = 0; \ +static void my3_mem_free_##A(void* a, void* b, int c) \ +{ \ + RunFunctionFmt(my3_mem_free_fct_##A, "ppi", a, b, c); \ +} +SUPER() +#undef GO +static void* find_mem_free_Fct(void* fct) +{ + if(!fct) return NULL; + void* p; + if((p = GetNativeFnc((uintptr_t)fct))) return p; + #define GO(A) if(my3_mem_free_fct_##A == (uintptr_t)fct) return my3_mem_free_##A; + SUPER() + #undef GO + #define GO(A) if(my3_mem_free_fct_##A == 0) {my3_mem_free_fct_##A = (uintptr_t)fct; return my3_mem_free_##A; } + SUPER() + #undef GO + printf_log(LOG_NONE, "Warning, no more slot for libcrypto mem_free callback\n"); + return NULL; +} + +EXPORT int my3_CRYPTO_set_mem_functions(x64emu_t* emu, void* m, void* r, void* f) +{ + (void)emu; + return my->CRYPTO_set_mem_functions(find_mem_malloc_Fct(m), find_mem_realloc_Fct(r), find_mem_free_Fct(f)); +} + EXPORT int my3_CRYPTO_get_ex_new_index(x64emu_t* emu, int idx, long argl, void* argp, void* new_func, void* dup_func, void* free_func) { (void)emu; diff --git a/src/wrapped/wrappedcrypto3_private.h b/src/wrapped/wrappedcrypto3_private.h index e8b2fe1f8..31027348b 100644 --- a/src/wrapped/wrappedcrypto3_private.h +++ b/src/wrapped/wrappedcrypto3_private.h @@ -918,7 +918,7 @@ GOM(CRYPTO_set_locking_callback, vFEp) //GO(CRYPTO_set_mem_debug_functions, //GO(CRYPTO_set_mem_debug_options, //GO(CRYPTO_set_mem_ex_functions, -//GOM(CRYPTO_set_mem_functions, iFEppp) +GOM(CRYPTO_set_mem_functions, iFEppp) GO(CRYPTO_strdup, pFppi) //GO(CRYPTO_thread_id, //GO(CRYPTO_THREADID_cmp, From 83935bc13410efdf40de519aaad29dc59ae66741 Mon Sep 17 00:00:00 2001 From: airidosas252 Date: Thu, 5 Nov 2026 06:04:41 +0200 Subject: [PATCH 143/156] [BOX64EC] Compile Dynarec emitters, add Box64EC register mapping (#4666) * [BOX64EC] Add the ARM64EC register mapping to the Dynarec x18 is the TEB and x6 is guest R9 there, so the scratch registers are x1 to x5. * [BOX64EC] Keep guest R9 out of the Dynarec scratch registers x6 is R9 in the ARM64EC mapping, so the emitters use x1 to x5 only, with the same code on every target where it is the same size. * [BOX64EC] Pass PCMPESTRx REX.W without clobbering guest R9 REX.W goes in bit 8 of the imm8 argument, which a small wrapper unpacks. * [BOX64EC] Adapt Dynarec helper calls to the ARM64EC register map C calls use LR for the call address, spill R10 and R11 and reload x18 as the TEB, and checkCRC keeps emu on the stack instead of in x6. * [BOX64EC] Compile Dynarec sources without linking them The DLL still runs the interpreter. --- CMakeLists.txt | 1 + src/dynarec/arm64/arm64_mapping.h | 39 ++++++++++++ src/dynarec/arm64/dynarec_arm64_00.c | 10 +-- src/dynarec/arm64/dynarec_arm64_660f.c | 54 ++++++++++++---- src/dynarec/arm64/dynarec_arm64_66f0.c | 28 +++------ src/dynarec/arm64/dynarec_arm64_avx_0f38.c | 6 +- src/dynarec/arm64/dynarec_arm64_avx_66_0f.c | 2 +- src/dynarec/arm64/dynarec_arm64_avx_66_0f3a.c | 6 +- src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c | 3 +- src/dynarec/arm64/dynarec_arm64_consts.c | 2 +- src/dynarec/arm64/dynarec_arm64_db.c | 14 ++++- src/dynarec/arm64/dynarec_arm64_emit_shift.c | 38 ++++++++--- src/dynarec/arm64/dynarec_arm64_f0.c | 56 +++++------------ src/dynarec/arm64/dynarec_arm64_helper.c | 63 +++++++++++++++---- src/dynarec/arm64/dynarec_arm64_helper.h | 44 +++++++++---- src/emu/x64compstrings.c | 6 ++ src/emu/x64compstrings.h | 1 + wine/box64ec/CMakeLists.txt | 24 ++++++- 18 files changed, 276 insertions(+), 121 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 84ef537d7..d7128ffc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1677,6 +1677,7 @@ if(ARM64EC) SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/wine/box64ec" CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/wine/toolchain_mingw_arm64ec.cmake + -DDYNAREC_PASS_STR=${DYNAREC_PASS_STR} -DINTERPRETER_STR=${INTERPRETER_STR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} INSTALL_COMMAND "" diff --git a/src/dynarec/arm64/arm64_mapping.h b/src/dynarec/arm64/arm64_mapping.h index 407308a4a..a30a5764c 100644 --- a/src/dynarec/arm64/arm64_mapping.h +++ b/src/dynarec/arm64/arm64_mapping.h @@ -39,6 +39,32 @@ p0-p3 are used to pass scalable predicate arguments to a subroutine and to retur */ // x86 Register mapping +#ifdef BOX64EC +// x18 is the TEB and x6 is guest R9, the other scratch registers are x1 to x5 +#define xRAX 10 +#define xRCX 11 +#define xRDX 12 +#define xRBX 8 +#define xRSP 20 +#define xRBP 21 +#define xRSI 16 +#define xRDI 17 +#define xR8 15 +#define xR9 6 +#define xR10 23 +#define xR11 9 +#define xR12 22 +#define xR13 25 +#define xR14 26 +#define xR15 19 +#define xFlags 7 +#define xRIP 27 + +// convert a x86 register to native according to the register mapping +#define TO_NAT(A) (((uint8_t[]){10, 11, 12, 8, 20, 21, 16, 17, 15, 6, 23, 9, 22, 25, 26, 19})[(A)]) +#define IS_GPR(A) (((uint8_t[]){0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, \ + 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0})[(A)]) +#else #define xRAX 10 #define xRCX 11 #define xRDX 12 @@ -62,6 +88,9 @@ p0-p3 are used to pass scalable predicate arguments to a subroutine and to retur // convert a x86 register to native according to the register mapping #define TO_NAT(A) (xRAX + (A)) #define IS_GPR(A) ((A)>=xRAX && (A)<=xRIP) +#endif +// the Windows platform register, reloaded with the TEB after C calls +#define xTEB 18 // 32bits version #define wEAX xRAX @@ -87,8 +116,14 @@ p0-p3 are used to pass scalable predicate arguments to a subroutine and to retur #define x3 3 #define x4 4 #define x5 5 +#ifdef BOX64EC +#define x6 BOX64EC_x6_IS_GUEST_R9_USE_xR9 +// x87pc is x5, a normal scratch: BOX64_DYNAREC_X87DOUBLE=2 precision tracking is not supported on Box64EC +#define x87pc 5 +#else #define x6 6 #define x87pc 7 +#endif // x87 can be a scratch, but check if it's used as x87 PC and restore if needed in that case // 32bits version of scratch #define w1 x1 @@ -96,7 +131,11 @@ p0-p3 are used to pass scalable predicate arguments to a subroutine and to retur #define w3 x3 #define w4 x4 #define w5 x5 +#ifdef BOX64EC +#define w6 BOX64EC_w6_IS_GUEST_R9_USE_wR9 +#else #define w6 x6 +#endif #define w87pc x87pc // emu is r0 #define xEmu 0 diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 2a35179cb..31c21a90c 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -1014,10 +1014,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin GETEW(x1, 0); GETGW(x2); // Extract RPL (low 2 bits) - UBFXw(x6, ed, 0, 2); + UBFXw(x5, ed, 0, 2); UBFXw(x4, gd, 0, 2); // need_update = (dst_rpl < src_rpl) - CMPSw_REG(x6, x4); + CMPSw_REG(x5, x4); CSETw(x5, cLT); // ZF = need_update BFIw(xFlags, x5, F_ZF, 1); @@ -1480,7 +1480,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin nextop=F8; GETGD; GETED(0); - emit_test32(dyn, ninst, rex, ed, gd, x3, x5, x6); + emit_test32(dyn, ninst, rex, ed, gd, x3, x5, x4); break; case 0x86: INST_NAME("(LOCK)XCHG Eb, Gb"); @@ -3584,7 +3584,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin GETED(0); if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);} CBZw_NEXT(x3); - emit_rcl32(dyn, ninst, rex, ed, x3, x5, x4, x6); + emit_rcl32(dyn, ninst, rex, ed, x3, x5, x4); WBACK; break; case 3: @@ -3603,7 +3603,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin GETED(0); if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);} CBZw_NEXT(x3); - emit_rcr32(dyn, ninst, rex, ed, x3, x5, x4, x6); + emit_rcr32(dyn, ninst, rex, ed, x3, x5, x4); WBACK; break; case 4: diff --git a/src/dynarec/arm64/dynarec_arm64_660f.c b/src/dynarec/arm64/dynarec_arm64_660f.c index 38e6b7032..2eeaacbe4 100644 --- a/src/dynarec/arm64/dynarec_arm64_660f.c +++ b/src/dynarec/arm64/dynarec_arm64_660f.c @@ -1336,8 +1336,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n MOVx_REG(x2, xRDX); MOVx_REG(x4, xRAX); u8 = F8; - MOV32w(x5, u8); - MOV32w(x6, rex.w); + MOV32w(x5, u8 | (rex.w << 8)); // REX.W in bit 8 of the imm8 argument CALL(const_sse42_compare_string_explicit_len, x1); q0 = sse_get_reg_empty(dyn, ninst, x2, 0); if(u8&0b1000000) { @@ -1415,6 +1414,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n VMOVBto(x2, d0, 0); BFIw(x1, x2, 8, 8); // insert } +#ifdef BOX64EC + int lreg = x2; // no x6 (guest R9): lreg is lost in min(lmem, lreg) and recomputed for SF +#else + int lreg = x6; +#endif // get abs of eax / edx and find min ADDSxw_U12(x2, xRAX, 0); Bcond(cPL, 4+4); @@ -1427,20 +1431,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n CMPSx_REG(x3, x4); CSELx(x3, x3, x4, cLO); // x3 is lmem CMPSx_REG(x2, x4); - CSELx(x6, x2, x4, cLO); // x6 is lreg + CSELx(lreg, x2, x4, cLO); } else { CMPSw_REG(x3, x4); CSELw(x3, x3, x4, cLO); // x3 is lmem CMPSw_REG(x2, x4); - CSELw(x6, x2, x4, cLO); // x6 is lreg + CSELw(lreg, x2, x4, cLO); } - CMPSw_REG(x6, x3); - CSELw(x5, x3, x6, cLT); // x5 is max(lmem, lreg) - CSELw(x2, x6, x3, cLT); // x2 is min(lmem, lreg) + CMPSw_REG(lreg, x3); + CSELw(x5, x3, lreg, cLT); // x5 is max(lmem, lreg) + CSELw(x2, lreg, x3, cLT); // x2 is min(lmem, lreg) // x2 is min length 0-n_packed MVNw_REG(x4, xZR); - LSLw_REG(x87pc, x4, x2); - BICw_REG(x1, x1, x87pc); + LSLw_REG(x2, x4, x2); + BICw_REG(x1, x1, x2); LSLw_REG(x4, x4, x5); ORRw_REG(x1, x1, x4); ANDw_mask(x1, x1, 0, (u8&1)?7:15); @@ -1472,8 +1476,17 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n BFIw(xFlags, x5, F_ZF, 1); } IFX(X_SF) { +#ifdef BOX64EC + // lreg was overwritten by min(lmem, lreg), recompute it from abs(RAX) + ADDSxw_U12(x2, xRAX, 0); + Bcond(cPL, 4+4); + NEGxw_REG(x2, x2); + CMPSxw_REG(x2, x4); + CSETw(x5, cLO); +#else CMPSw_REG(x6, x4); CSETw(x5, cLT); +#endif BFIw(xFlags, x5, F_SF, 1); } } @@ -1517,8 +1530,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n MOVx_REG(x2, xRDX); MOVx_REG(x4, xRAX); u8 = F8; - MOV32w(x5, u8); - MOV32w(x6, rex.w); + MOV32w(x5, u8 | (rex.w << 8)); // REX.W in bit 8 of the imm8 argument CALL(const_sse42_compare_string_explicit_len, x1); } if(u8&0b1000000) { @@ -2522,7 +2534,14 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n UFLAG_IF { CBZw_NEXT(x4); } +#ifdef BOX64EC + // x1 to x5 are all in use and x6 is guest R9, so the address in x3 goes through the emu + if(wback==x3) STRx_U12(x3, xEmu, offsetof(x64emu_t, scratch[0])); + emit_shld16(dyn, ninst, ed, gd, x4, x5, x3); + if(wback==x3) LDRx_U12(x3, xEmu, offsetof(x64emu_t, scratch[0])); +#else emit_shld16(dyn, ninst, ed, gd, x4, x5, x6); +#endif EWBACK; break; @@ -2592,7 +2611,14 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n CBZw_NEXT(x4); } else { } +#ifdef BOX64EC + // as SHLD, the address in x3 goes through the emu + if(wback==x3) STRx_U12(x3, xEmu, offsetof(x64emu_t, scratch[0])); + emit_shrd16(dyn, ninst, ed, gd, x4, x5, x3); + if(wback==x3) LDRx_U12(x3, xEmu, offsetof(x64emu_t, scratch[0])); +#else emit_shrd16(dyn, ninst, ed, gd, x4, x5, x6); +#endif EWBACK; break; case 0xAE: @@ -2951,10 +2977,12 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n GETGW(x1); GETEW(x2, 0); u8 = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)); - if (!(MODREG && wback == u8)) MOVx_REG(x6, ed); emit_add16(dyn, ninst, ed, gd, x4, x5); EWBACK; - if (!(MODREG && wback == u8)) BFIx(u8, x6, 0, 16); + if (!(MODREG && wback == u8)) { + SUBw_REG(gd, ed, gd); // the old Ew is the sum minus Gw + BFIx(u8, gd, 0, 16); + } break; case 0xC2: INST_NAME("CMPPD Gx, Ex, Ib"); diff --git a/src/dynarec/arm64/dynarec_arm64_66f0.c b/src/dynarec/arm64/dynarec_arm64_66f0.c index 5568a05b2..7a02c4517 100644 --- a/src/dynarec/arm64/dynarec_arm64_66f0.c +++ b/src/dynarec/arm64/dynarec_arm64_66f0.c @@ -115,7 +115,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n INST_NAME("LOCK CMPXCHG Ew, Gw"); SETFLAGS(X_ALL, SF_SET_PENDING); GETGD; - UXTHw(x6, xRAX); + UXTHw(x5, xRAX); addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0); if(!ALIGNED_ATOMICH) { if(cpuext.uscat) { @@ -129,12 +129,12 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n } // Aligned version if(cpuext.atomics) { - MOVw_REG(x1, x6); + MOVw_REG(x1, x5); CASALH(x1, gd, wback); } else { MARKLOCK; LDAXRH(x1, wback); - CMPSw_REG(x6, x1); + CMPSw_REG(x5, x1); B_MARK(cNE); // EAX == Ed STLXRH(x4, gd, wback); @@ -149,7 +149,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n LDAXRB(x3, wback); // dummy read, to arm the write... SUBw_UXTB(x3, x3, x1); CBNZw_MARK3(x3); - CMPSw_REG(x6, x1); + CMPSw_REG(x5, x1); B_MARK(cNE); // EAX == Ed STLXRB(x4, gd, wback); @@ -158,7 +158,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n } MARK; // Common part (and fallback for EAX != Ed) - UFLAG_IF {emit_cmp16(dyn, ninst, x6, x1, x3, x4, x5);} + UFLAG_IF {emit_cmp16(dyn, ninst, x5, x1, x3, x4, x2);} BFIx(xRAX, x1, 0, 16); } break; @@ -211,11 +211,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n SETFLAGS(X_ALL, SF_SET_PENDING); GETGW(x5); addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0); - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRH(x1, wback); emit_adc16(dyn, ninst, x1, x5, x3, x4); STLXRH(x3, x1, wback); @@ -362,11 +358,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1); if(opcode==0x81) i16 = F16S; else i16 = F8S; MOV32w(x5, (uint16_t)i16); - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRH(x1, wback); emit_adc16(dyn, ninst, x1, x5, x3, x4); STLXRH(x3, x1, wback); @@ -387,11 +379,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1); if(opcode==0x81) i16 = F16S; else i16 = F8S; MOV32w(x5, (uint16_t)i16); - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRH(x1, wback); emit_sbb16(dyn, ninst, x1, x5, x3, x4); STLXRH(x3, x1, wback); diff --git a/src/dynarec/arm64/dynarec_arm64_avx_0f38.c b/src/dynarec/arm64/dynarec_arm64_avx_0f38.c index c67c4b4c2..97fe0b184 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_0f38.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_0f38.c @@ -254,15 +254,15 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i GETGD; GETED(0); GETVD; - UXTBw(x6, vd); - CMPSw_U12(x6, rex.w ? 64 : 32); + UXTBw(x5, vd); + CMPSw_U12(x5, rex.w ? 64 : 32); CSETMxw(x2, cPL); IFX(X_CF) { BFIw(xFlags, x2, F_CF, 1); } MVNxw_REG(x2, x2); //prepare mask B_MARK(cPL); - LSLxw_REG(x2, x2, x6); + LSLxw_REG(x2, x2, x5); MARK; need_tst = 0; IFX(X_ZF) need_tst = 1; diff --git a/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c b/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c index 0528125a4..7765aea54 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c @@ -443,7 +443,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, case 0x5B: INST_NAME("VCVTPS2DQ Gx, Ex"); nextop = F8; - u8 = sse_setround(dyn, ninst, x1, x2, x6); + u8 = sse_setround(dyn, ninst, x3, x2, x4); // the address below can use x2 and x3, x4 keeps the old FPCR if(!BOX64ENV(dynarec_fastround) && !cpuext.frintts) { d0 = fpu_get_scratch(dyn, ninst); d1 = fpu_get_scratch(dyn, ninst); diff --git a/src/dynarec/arm64/dynarec_arm64_avx_66_0f3a.c b/src/dynarec/arm64/dynarec_arm64_avx_66_0f3a.c index e445260fd..188444db9 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_66_0f3a.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_66_0f3a.c @@ -510,17 +510,17 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip } u8 = F8; if(u8&4) { - s0 = sse_setround(dyn, ninst, x1, x2, x6); + s0 = sse_setround(dyn, ninst, x1, x2, x5); } else { u8&=3; if(u8==1) u8=2; else if(u8==2) u8=1; MRS_fpcr(x1); // get fpscr MOV32w(x2, u8); - MOVx_REG(x6, x1); + MOVx_REG(x5, x1); BFIx(x1, x2, 22, 2); // inject new round MSR_fpcr(x1); // put new fpscr - s0 = x6; + s0 = x5; } FCVTN16(v1, v0); if(vex.l) { diff --git a/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c b/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c index fc7e7fd37..8757f7836 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c @@ -586,11 +586,12 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, case 0xE6: INST_NAME("VCVTPD2DQ Gx, Ex"); nextop = F8; - u8 = sse_setround(dyn, ninst, x1, x2, x6); for(int l=0; l<1+vex.l; ++l) { if(!l) { GETEX_Y(v1, 0, 0); GETGX_empty(v0); + // after the address, so x2 can keep the old FPCR + u8 = sse_setround(dyn, ninst, x4, x5, x2); if(!BOX64ENV(dynarec_fastround) || vex.l) d0 = fpu_get_scratch(dyn, ninst); } else { diff --git a/src/dynarec/arm64/dynarec_arm64_consts.c b/src/dynarec/arm64/dynarec_arm64_consts.c index c5e2ebacb..83ef32d3f 100644 --- a/src/dynarec/arm64/dynarec_arm64_consts.c +++ b/src/dynarec/arm64/dynarec_arm64_consts.c @@ -125,7 +125,7 @@ uintptr_t getConst(arm64_consts_t which) case const_fpu_xrstor: return (uintptr_t)fpu_xrstor; case const_fpu_fbld: return (uintptr_t)fpu_fbld; case const_fpu_fbst: return (uintptr_t)fpu_fbst; - case const_sse42_compare_string_explicit_len: return (uintptr_t)sse42_compare_string_explicit_len; + case const_sse42_compare_string_explicit_len: return (uintptr_t)sse42_compare_string_explicit_len_imm8w; case const_sse42_compare_string_implicit_len: return (uintptr_t)sse42_compare_string_implicit_len; case const_x64test_step: return (uintptr_t)x64test_step; case const_printtrace: return (uintptr_t)PrintTrace; diff --git a/src/dynarec/arm64/dynarec_arm64_db.c b/src/dynarec/arm64/dynarec_arm64_db.c index fd4bda1bd..9f0f436ef 100644 --- a/src/dynarec/arm64/dynarec_arm64_db.c +++ b/src/dynarec/arm64/dynarec_arm64_db.c @@ -276,7 +276,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin NOTEST(x5); // the FLD is immediatly followed by an FSTP LDRx_U12(x5, ed, 0); - LDRH_U12(x6, ed, 8); + LDRH_U12(x4, ed, 8); // no persistant scratch register, so unrool both instruction here... MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n"); nextop = F8; // 0xDB or rex @@ -288,7 +288,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin nextop = F8; //modrm addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0); STRx_U12(x5, ed, 0); - STRH_U12(x6, ed, 8); + STRH_U12(x4, ed, 8); } else { if(BOX64ENV(x87_no80bits)) { X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D); @@ -357,11 +357,21 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin ORRx_mask(x5, x1, 1, 1, 0); //0x8000000000000000 x5 = mantisse B_MARK3_nocond; // denormals +#ifdef BOX64EC + // no x6 (guest R9) and x2 can be the address: x3 is free here (exp11 == 0), at the cost of the MOV + CLZx(x3, x1); + ADDw_U12(x3, x3, 1); // "one" + SUBw_REG(x4, x4, x3); // x4 = exp16 + ORRw_REG(x4, x4, x5); // x4 = sign | exp16 + LSLx_REG(x5, x1, x3); // x5 = mantisse + MOVw_REG(x3, x4); +#else CLZx(x6, x1); ADDw_U12(x6, x6, 1); // "one" SUBw_REG(x3, x4, x6); // x3 = exp16 ORRw_REG(x3, x3, x5); // x3 = sign | exp16 LSLx_REG(x5, x1, x6); // x5 = mantisse +#endif MARK3; STRx_U12(x5, wback, 0); STRH_U12(x3, wback, 8); diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c index 5467572cb..580d9c9b8 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c @@ -1275,9 +1275,14 @@ void emit_rcr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i } // emit RCL32/RCL64 instruction, from s1 , shift s2 (destroyed), store result in s1 using s3 and s4 as scratch -void emit_rcl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5) +void emit_rcl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4) { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); +#ifdef BOX64EC + int s5 = s3; // no x6 (guest R9), so s3 is reused and the new CF waits in F_res2 +#else + int s5 = x6; +#endif if(BOX64ENV(cputype)) { IFX(X_OF|X_CF) { @@ -1292,6 +1297,11 @@ void emit_rcl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 LSRxw_REG(s3, s1, s4); } } +#ifdef BOX64EC + IFX(BOX64ENV(cputype)?(X_OF|X_CF):X_CF) { + BFIw(xFlags, s3, F_res2, 1); + } +#endif if(!BOX64ENV(cputype)) IFX(X_OF) { LSRxw(s4, s1, rex.w?62:30); @@ -1319,15 +1329,27 @@ void emit_rcl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 ORRxw_REG(s1, s1, s4); } IFX(X_CF) { +#ifdef BOX64EC + BFXILw(xFlags, xFlags, F_res2, 1); +#else BFIw(xFlags, s3, F_CF, 1); +#endif } IFX2(X_OF, && BOX64ENV(cputype)) { +#ifdef BOX64EC + UBFXw(s3, xFlags, F_res2, 1); +#endif EORxw_REG_LSR(s3, s3, s1, rex.w?63:31); BFIw(xFlags, s3, F_OF, 1); } +#ifdef BOX64EC + IFX(BOX64ENV(cputype)?(X_OF|X_CF):X_CF) { + BFCw(xFlags, F_res2, 1); + } +#endif } -// emit RCR32/RCR64 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch -void emit_rcr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5) +// emit RCR32/RCR64 instruction, from s1 , shift s2 (destroyed), store result in s1 using s3 and s4 as scratch +void emit_rcr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4) { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); @@ -1349,15 +1371,15 @@ void emit_rcr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 } /*else*/ { - LSRxw_REG(s5, s1, s2); - UBFXw(s4, xFlags, 0, 1); + LSRxw_REG(s4, s1, s2); MOVZw(s3, (rex.w?64:32)); SUBx_REG(s3, s3, s2); - LSLxw_REG(s4, s4, s3); - ORRxw_REG(s5, s5, s4); + UBFXw(s2, xFlags, 0, 1); // s2 is not needed anymore + LSLxw_REG(s2, s2, s3); + ORRxw_REG(s4, s4, s2); ADDx_U12(s3, s3, 1); LSLxw_REG(s1, s1, s3); - ORRxw_REG(s1, s1, s5); + ORRxw_REG(s1, s1, s4); } IFX(X_CF) { BFXILw(xFlags, xFlags, F_res2, 1); diff --git a/src/dynarec/arm64/dynarec_arm64_f0.c b/src/dynarec/arm64/dynarec_arm64_f0.c index 40d84d67e..8470c1542 100644 --- a/src/dynarec/arm64/dynarec_arm64_f0.c +++ b/src/dynarec/arm64/dynarec_arm64_f0.c @@ -239,28 +239,28 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin INST_NAME("LOCK CMPXCHG Eb, Gb"); SETFLAGS(X_ALL, SF_SET_PENDING); GETGB(x1); - UBFXx(x6, xRAX, 0, 8); + UBFXx(x5, xRAX, 0, 8); addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0); if(cpuext.atomics) { UFLAG_IF { - MOVw_REG(x2, x6); - CASALB(x6, gd, wback); - emit_cmp8(dyn, ninst, x2, x6, x3, x4, x5); + MOVw_REG(x2, x5); + CASALB(x5, gd, wback); + emit_cmp8(dyn, ninst, x2, x5, x3, x4, x1); } else { - CASALB(x6, gd, wback); + CASALB(x5, gd, wback); } - BFIx(xRAX, x6, 0, 8); + BFIx(xRAX, x5, 0, 8); } else { MARKLOCK; LDAXRB(x2, wback); - CMPSxw_REG(x6, x2); + CMPSxw_REG(x5, x2); B_MARK(cNE); // EAX == Ed STLXRB(x4, gd, wback); CBNZx_MARKLOCK(x4); // done MARK; - UFLAG_IF {emit_cmp8(dyn, ninst, x6, x2, x3, x4, x5);} + UFLAG_IF {emit_cmp8(dyn, ninst, x5, x2, x3, x4, x1);} BFIx(xRAX, x2, 0, 8); } } @@ -283,7 +283,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETGD; addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0); - UFLAG_IF { MOVxw_REG(x6, xRAX); } + UFLAG_IF { MOVxw_REG(x5, xRAX); } if(!ALIGNED_ATOMICxw) { if(cpuext.uscat) { ANDx_mask(x1, wback, 1, 0, 3); // mask = F @@ -345,7 +345,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } MARK; UFLAG_IF { - emit_cmp32(dyn, ninst, rex, x6, x1, x3, x4, x5); + emit_cmp32(dyn, ninst, rex, x5, x1, x3, x4, x2); } } break; @@ -823,11 +823,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETGB(x2); addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0); - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRB(x1, wback); emit_adc8(dyn, ninst, x1, x2, x4, x5); STLXRB(x4, x1, wback); @@ -848,11 +844,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETGD; addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0); - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRxw(x1, wback); emit_adc32(dyn, ninst, rex, x1, gd, x4, x5); STLXRxw(x4, x1, wback); @@ -1107,11 +1099,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1); u8 = F8; wb1 = 1; - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRB(x1, wback); emit_adc8c(dyn, ninst, x1, u8, x2, x4, x3); STLXRB(x3, x1, wback); @@ -1132,11 +1120,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1); u8 = F8; wb1 = 1; - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRB(x1, wback); emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x3); STLXRB(x3, x1, wback); @@ -1369,11 +1353,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1); if(opcode==0x81) i64 = F32S; else i64 = F8S; MOV64xw(x5, i64); - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRxw(x1, wback); emit_adc32(dyn, ninst, rex, x1, x5, x3, x4); STLXRxw(x3, x1, wback); @@ -1394,11 +1374,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1); if(opcode==0x81) i64 = F32S; else i64 = F8S; MOV64xw(x5, i64); - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRxw(x1, wback); emit_sbb32(dyn, ninst, rex, x1, x5, x3, x4); STLXRxw(x3, x1, wback); diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index 4d7f39636..3ed5deb79 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -50,7 +50,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u uint8_t scratch = x2; *fixaddress = 0; if(hint>0) ret = hint; - if(hint>0 && hint0 && !IS_GPR(hint)) scratch = hint; int absmin = 0; if(s) absmin=-absmax; int seg_done = 0; @@ -204,7 +204,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u } ADDy_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib>>6)); } else { - PASS3(int tmp = TO_NAT(sib & 0x07) + (rex.b << 3)); + PASS3(int tmp = TO_NAT((sib & 0x07) + (rex.b << 3))); if(sub) { SUBy_REG(ret, tmp, scratch); } else { @@ -229,7 +229,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u if(rex.seg && !seg_done) { scratch = (hint>0 && !IS_GPR(hint)) ? hint : x2; if(scratch==ret) - scratch=ret+1; + scratch = xLR; // dead between opcodes, ret+1 can be a guest register grab_segdata(dyn, addr, ninst, scratch, rex.seg); //seg offset is 64bits, so no truncation here ADDx_REGy(hint, scratch, ret); @@ -321,7 +321,7 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, if(rex.seg) { if(scratch==ret) - scratch=ret+1; + scratch = xLR; grab_segdata(dyn, addr, ninst, scratch, rex.seg); //seg offset is 64bits, so no truncation here if(IS_GPR(ret)) { @@ -350,8 +350,10 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog); SMEND(); CHECK_DFNONE(0); +#ifndef BOX64EC // no CALLRET on Box64EC yet if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); +#endif BR(x2); } @@ -426,8 +428,10 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32 if(reg!=x1) { MOVx_REG(x1, xRIP); } +#ifndef BOX64EC // no CALLRET on Box64EC yet if(BOX64DRENV(dynarec_callret) >= 3 && !dyn->insts[ninst].x64.has_callret) doLeaveBlock(dyn, ninst, x4, x5, x6); +#endif // #ifdef HAVE_TRACE // The BLR form is only for gdb backtraces, but it breaks the // return-address-stack prediction on every block-to-block jump, which is @@ -448,6 +452,7 @@ void ret_to_next(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex) CHECK_DFNONE(0); MOVz_REG(x1, xRIP); SMEND(); +#ifndef BOX64EC // no CALLRET on Box64EC yet if(BOX64DRENV(dynarec_callret)) { // pop the actual return address for ARM stack LDPx_S7_postindex(xLR, x6, xSP, 16); @@ -459,6 +464,7 @@ void ret_to_next(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex) // not the correct return address, regular jump, but purge the stack first, it's unsync now... SUBx_U12(xSP, xSavedSP, 16); } +#endif NOTEST(x2); int dest = indirect_lookup(dyn, ninst, rex.is32bits, x2, x3); #ifdef HAVE_TRACE @@ -566,12 +572,16 @@ void call_c(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int reg, int ret, STPx_S7_offset(xRSP, xRBP, xEmu, offsetof(x64emu_t, regs[_SP])); STPx_S7_offset(xRSI, xRDI, xEmu, offsetof(x64emu_t, regs[_SI])); STPx_S7_offset(xR8, xR9, xEmu, offsetof(x64emu_t, regs[_R8])); +#ifdef BOX64EC + // R10 and R11 are not preserved by the C call in the EC map + STPx_S7_offset(xR10, xR11, xEmu, offsetof(x64emu_t, regs[_R10])); +#endif fpu_pushcache(dyn, ninst, savereg, 0); for(int i=0; in.fpu_scratch; ++i) VSTR128_S9_preindex(SCRATCH0+i, xSP, -16); } #ifdef _WIN32 - LDRx_U12(xR8, xEmu, offsetof(x64emu_t, win64_teb)); + LDRx_U12(xTEB, xEmu, offsetof(x64emu_t, win64_teb)); #endif TABLE64C(reg, fnc); BLR(reg); @@ -594,15 +604,23 @@ void call_c(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int reg, int ret, GO(RSP, RBP); GO(RSI, RDI); GO(R8, R9); +#ifdef BOX64EC + GO(R10, R11); +#endif #undef GO fpu_popcache(dyn, ninst, savereg, 0); // savereg will not be used } if(saveflags) { LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); } +#ifdef BOX64EC + // x87pc is x5, the pop above restored an argument: reload it + NATIVE_RESTORE_X87PC(); +#else if(savereg!=x87pc && dyn->need_x87check) { NATIVE_RESTORE_X87PC(); } +#endif //SET_NODF(); } @@ -623,11 +641,14 @@ void call_d(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int ret, int arg1 STPx_S7_offset(xRSP, xRBP, xEmu, offsetof(x64emu_t, regs[_SP])); STPx_S7_offset(xRSI, xRDI, xEmu, offsetof(x64emu_t, regs[_SI])); STPx_S7_offset(xR8, xR9, xEmu, offsetof(x64emu_t, regs[_R8])); +#ifdef BOX64EC + STPx_S7_offset(xR10, xR11, xEmu, offsetof(x64emu_t, regs[_R10])); // not preserved by the C call, as in call_c +#endif STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); fpu_pushcache(dyn, ninst, x87pc, 0); #ifdef _WIN32 - LDRx_U12(xR8, xEmu, offsetof(x64emu_t, win64_teb)); + LDRx_U12(xTEB, xEmu, offsetof(x64emu_t, win64_teb)); #endif if(arg1!=-1) FMOVD(0, arg1); @@ -647,6 +668,9 @@ void call_d(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int ret, int arg1 GO(RSP, RBP); GO(RSI, RDI); GO(R8, R9); +#ifdef BOX64EC + GO(R10, R11); +#endif #undef GO LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); fpu_popcache(dyn, ninst, x1, 0); // savereg will not be used @@ -2355,12 +2379,25 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst) j64 = (GETMARKF2)-(dyn->native_size); CBZw(x1, j64); } - if(dyn->insts[ninst].need_nat_flags) + if(dyn->insts[ninst].need_nat_flags) { +#ifdef BOX64EC + // updateflags uses x1 to x5 and x6 is guest R9: NZCV goes through the emu + MRS_nzcv(x1); + STRx_U12(x1, xEmu, offsetof(x64emu_t, scratch[0])); +#else MRS_nzcv(x6); +#endif + } TABLE64C(x1, const_updateflags_arm64); BLR(x1); - if(dyn->insts[ninst].need_nat_flags) + if(dyn->insts[ninst].need_nat_flags) { +#ifdef BOX64EC + LDRx_U12(x1, xEmu, offsetof(x64emu_t, scratch[0])); + MSR_nzcv(x1); +#else MSR_nzcv(x6); +#endif + } MARKF2; } MESSAGE(LOG_DUMP, "\t---- Flags fetch\n"); @@ -2985,8 +3022,8 @@ void checkCRC(dynarec_arm_t* dyn, int ninst) // grab the dynablock address in x5, as this on will not be erased by crc functions int delta = -(dyn->native_size + sizeof(void*)); LDRx_literal(x5, delta); - // move away xEMU to X6, should be safe there - MOVx_REG(x6, xEmu); + // move away xEMU to the stack, x6 is guest R9 on Box64EC + STPx_S7_preindex(xEmu, xZR, xSP, -16); // prepare and call the crc function TABLE64C(x3, cpuext.crc32?const_native_crc32:const_native_x31); LDRx_U12(xEmu, x5, offsetof(dynablock_t, x64_addr)); @@ -2994,10 +3031,14 @@ void checkCRC(dynarec_arm_t* dyn, int ninst) BLR(x3); // done, move away result and restore xEmu MOVw_REG(x1, xEmu); - MOVx_REG(xEmu, x6); + LDPx_S7_postindex(xEmu, xZR, xSP, 16); LDRw_U12(x2, x5, offsetof(dynablock_t, hash)); SUBw_REG(x1, x1, x2); CBZw(x1, 4+2*4); TABLE64C(x3, const_native_next_invalidate); BLR(x3); +#ifdef BOX64EC + // x5 held the dynablock, which is x87pc here + NATIVE_RESTORE_X87PC(); +#endif } diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index e846f61f8..e916e964b 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -578,15 +578,15 @@ #define ALIGNED_ATOMICxw ((fixedaddress && !(fixedaddress&(((1<<(2+rex.w))-1)))) || BOX64ENV(dynarec_aligned_atomics)) #define ALIGNED_ATOMICH ((fixedaddress && !(fixedaddress&1)) || BOX64ENV(dynarec_aligned_atomics)) -// CALL will use x7 for the call address. Return value can be put in ret (unless ret is -1) +// CALL will use xLR for the call address. Return value can be put in ret (unless ret is -1) // R0 will not be pushed/popd if ret is -2 -#define CALL(F, ret) call_c(dyn, ninst, F, x87pc, ret, 1, 0) -// CALL_ will use x7 for the call address. Return value can be put in ret (unless ret is -1) +#define CALL(F, ret) call_c(dyn, ninst, F, xLR, ret, 1, 0) +// CALL_ will use xLR for the call address. Return value can be put in ret (unless ret is -1) // R0 will not be pushed/popd if ret is -2 -#define CALL_(F, ret, reg) call_c(dyn, ninst, F, x87pc, ret, 1, reg) -// CALL_S will use x7 for the call address. Return value can be put in ret (unless ret is -1) +#define CALL_(F, ret, reg) call_c(dyn, ninst, F, xLR, ret, 1, reg) +// CALL_S will use xLR for the call address. Return value can be put in ret (unless ret is -1) // R0 will not be pushed/popd if ret is -2. Flags are not save/restored -#define CALL_S(F, ret) call_c(dyn, ninst, F, x87pc, ret, 0, 0) +#define CALL_S(F, ret) call_c(dyn, ninst, F, xLR, ret, 0, 0) // CALL_D will use x7 for the call address. Use for function having 1 or 2 double args and returning 1 double // All regs are saved, including xmm0-7, will move arg1/arg2 to D0, D1, return D0 to ret (unless any is -1) #define CALL_D(F, ret, arg1, arg2, sav1, sav2) call_d(dyn, ninst, F, ret, arg1, arg2, sav1, sav2) @@ -604,6 +604,26 @@ #define MARKSEG dyn->insts[ninst].markseg = dyn->native_size #define GETMARKSEG dyn->insts[ninst].markseg #define MARKLOCK dyn->insts[ninst].marklock = dyn->native_size +#ifdef BOX64EC +// x6 is guest R9 and x87pc is x5, so keep the flags in the emu across the retry loop +#define MARKLOCK_SAVE_FLAGS() do { \ + STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); \ + MRS_nzcv(x4); \ + STRx_U12(x4, xEmu, offsetof(x64emu_t, scratch[0])); \ + MARKLOCK; \ + LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); \ + LDRx_U12(x4, xEmu, offsetof(x64emu_t, scratch[0])); \ + MSR_nzcv(x4); \ +} while (0) +#else +#define MARKLOCK_SAVE_FLAGS() do { \ + MOVx_REG(x6, xFlags); \ + MRS_nzcv(x87pc); \ + MARKLOCK; \ + MOVx_REG(xFlags, x6); \ + MSR_nzcv(x87pc); \ +} while (0) +#endif #define GETMARKLOCK dyn->insts[ninst].marklock // Branch to MARK if cond (use j64) @@ -1029,8 +1049,8 @@ #define READFLAGS(A) \ if((A)!=X_PEND \ && (dyn->f==status_unk)) { \ - TABLE64C(x6, const_updateflags_arm64); \ - BLR(x6); \ + TABLE64C(x5, const_updateflags_arm64); \ + BLR(x5); \ dyn->f = status_none; \ } else if((A)==X_ALL) flushNative(dyn, ninst); #endif @@ -1038,8 +1058,8 @@ #define GRABFLAGS(A) \ if((A)!=X_PEND \ && ((dyn->f==status_unk) || (dyn->f==status_set))) { \ - TABLE64C(x6, const_updateflags_arm64); \ - BLR(x6); \ + TABLE64C(x5, const_updateflags_arm64); \ + BLR(x5); \ dyn->f = status_none; \ } @@ -1483,8 +1503,8 @@ void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int void emit_rcr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4); void emit_rcl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); void emit_rcr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); -void emit_rcl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); -void emit_rcr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); +void emit_rcl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); +void emit_rcr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4); void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4); void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s5, int s3, int s4); diff --git a/src/emu/x64compstrings.c b/src/emu/x64compstrings.c index 666196cff..b9642d922 100644 --- a/src/emu/x64compstrings.c +++ b/src/emu/x64compstrings.c @@ -134,3 +134,9 @@ uint32_t sse42_compare_string_implicit_len(x64emu_t* emu, sse_regs_t* mem, sse_r } return sse42_compare_string_explicit_len(emu, mem, lmem, reg, lreg, imm8, 0); } + +// for the dynarec: REX.W is passed in bit 8 of imm8_w, to spare a register +uint32_t sse42_compare_string_explicit_len_imm8w(x64emu_t* emu, sse_regs_t* mem, int64_t lmem, sse_regs_t* reg, int64_t lreg, uint32_t imm8_w) +{ + return sse42_compare_string_explicit_len(emu, mem, lmem, reg, lreg, imm8_w & 0xff, (imm8_w >> 8) & 1); +} diff --git a/src/emu/x64compstrings.h b/src/emu/x64compstrings.h index 0cf5dad5d..cd29311ca 100644 --- a/src/emu/x64compstrings.h +++ b/src/emu/x64compstrings.h @@ -10,5 +10,6 @@ typedef struct x64emu_s x64emu_t; uint32_t sse42_compare_string_explicit_len(x64emu_t* emu, sse_regs_t* a, int64_t la, sse_regs_t* b, int64_t lb, uint8_t imm8, int w); uint32_t sse42_compare_string_implicit_len(x64emu_t* emu, sse_regs_t* a, sse_regs_t* b, uint8_t imm8); +uint32_t sse42_compare_string_explicit_len_imm8w(x64emu_t* emu, sse_regs_t* a, int64_t la, sse_regs_t* b, int64_t lb, uint32_t imm8_w); #endif //__X64_CMPSTRINGS_H__ \ No newline at end of file diff --git a/wine/box64ec/CMakeLists.txt b/wine/box64ec/CMakeLists.txt index 148b525cc..cd7de0b4c 100644 --- a/wine/box64ec/CMakeLists.txt +++ b/wine/box64ec/CMakeLists.txt @@ -5,6 +5,7 @@ find_package(Python3 REQUIRED COMPONENTS Interpreter) set(BOX64_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../..") +string(REPLACE "," ";" DYNAREC_PASS "${DYNAREC_PASS_STR}") string(REPLACE "," ";" INTERPRETER "${INTERPRETER_STR}") if(NOT INTERPRETER) message(FATAL_ERROR "Build Box64EC from the parent project with -DARM64EC=ON") @@ -51,7 +52,28 @@ add_library(box64ec SHARED "${BOX64_ROOT}/external/musl/sqrt_data.c" "${BOX64_ROOT}/external/musl/sqrtf.c" ) -foreach(target box64ec box64ec_interpreter) +set(BOX64EC_TARGETS box64ec box64ec_interpreter) + +# The Dynarec emitters are only compiled for now, the DLL does not link them yet. +if(DYNAREC_PASS) + add_library(box64ec_dynarec_helpers OBJECT + "${BOX64_ROOT}/src/dynarec/arm64/arm64_immenc.c" + "${BOX64_ROOT}/src/dynarec/arm64/arm64_printer.c" + "${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_arch.c" + "${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_functions.c" + "${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_jmpnext.c" + "${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_consts.c" + "${BOX64_ROOT}/src/dynarec/arm64/updateflags_arm64.c") + target_compile_definitions(box64ec_dynarec_helpers PRIVATE DYNAREC) + list(APPEND BOX64EC_TARGETS box64ec_dynarec_helpers) + foreach(STEP_VALUE RANGE 3) + add_library(box64ec_dynarec_pass${STEP_VALUE} OBJECT ${DYNAREC_PASS}) + target_compile_definitions(box64ec_dynarec_pass${STEP_VALUE} PRIVATE DYNAREC STEP=${STEP_VALUE}) + list(APPEND BOX64EC_TARGETS box64ec_dynarec_pass${STEP_VALUE}) + endforeach() +endif() + +foreach(target ${BOX64EC_TARGETS}) target_include_directories(${target} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" "${BOX64_ROOT}/src/include" From 59b3eb1555406db697941ddd5e414c7085b90e4f Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Thu, 5 Nov 2026 12:07:06 +0800 Subject: [PATCH 144/156] [RV64_DYNAREC] Reuse sew to remove vsetvli for avx_load_reg_vector (#4668) --- src/dynarec/rv64/dynarec_rv64_helper.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 5e2dea282..9f566ee5d 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -3236,11 +3236,12 @@ void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a int hi = fpu_get_scratch(dyn); dyn->inst_sew = VECTOR_SEWNA; dyn->inst_vl = 0; // real vtype here is unknown, never elide vsetvli - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + int sew0 = sew <= VECTOR_SEW64 ? sew : VECTOR_SEW8; + vector_vsetvli(dyn, ninst, s1, sew0, VECTOR_LMUL1, 1); ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a])); - VLE8_V(hi, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); - VSLIDEUP_VI(low, hi, 16, VECTOR_UNMASKED); + VLE_V(hi, s1, sew0, VECTOR_UNMASKED, VECTOR_NFIELD1); + vector_vsetvli(dyn, ninst, s1, sew0, VECTOR_LMUL1, 2); + VSLIDEUP_VI(low, hi, 16 >> sew0, VECTOR_UNMASKED); dyn->e.fpu_scratch = sp; } dyn->e.ssecache[a].ymm = 1; From 5c60cf8f429346647d56cd7bd4d4eef15a14bc6d Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Thu, 5 Nov 2026 11:39:06 +0100 Subject: [PATCH 145/156] [ARM64_DYNAREC] Small optimsation for test emitters --- src/dynarec/arm64/dynarec_arm64_00.c | 14 ++- src/dynarec/arm64/dynarec_arm64_66.c | 6 +- src/dynarec/arm64/dynarec_arm64_emit_tests.c | 90 ++++++++++---------- src/dynarec/arm64/dynarec_arm64_helper.h | 12 +-- src/dynarec/arm64/updateflags_arm64_pass.c | 8 +- 5 files changed, 64 insertions(+), 66 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 31c21a90c..94d79265a 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -1472,7 +1472,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin nextop=F8; GETEB(x1, 0); GETGB(x2); - emit_test8(dyn, ninst, x1, x2, x3, x4, x5); + emit_test8(dyn, ninst, x1, x2, x3, x4); break; case 0x85: INST_NAME("TEST Ed, Gd"); @@ -1480,7 +1480,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin nextop=F8; GETGD; GETED(0); - emit_test32(dyn, ninst, rex, ed, gd, x3, x5, x4); + emit_test32(dyn, ninst, rex, ed, gd, x3, x5); break; case 0x86: INST_NAME("(LOCK)XCHG Eb, Gb"); @@ -2258,14 +2258,13 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); UXTBx(x1, xRAX); u8 = F8; - MOV32w(x2, u8); - emit_test8(dyn, ninst, x1, x2, x3, x4, x5); + emit_test8c(dyn, ninst, x1, u8, x3, x4); break; case 0xA9: INST_NAME("TEST EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING); i64 = F32S; - emit_test32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5); + emit_test32c(dyn, ninst, rex, xRAX, i64, x3, x4); break; case 0xAA: if(rex.rep) { @@ -4125,8 +4124,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETEB(x1, 1); u8 = F8; - MOV32w(x2, u8); - emit_test8(dyn, ninst, x1, x2, x3, x4, x5); + emit_test8c(dyn, ninst, x1, u8, x3, x4); break; case 2: INST_NAME("NOT Eb"); @@ -4291,7 +4289,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETEDH(x1, 4); i64 = F32S; - emit_test32c(dyn, ninst, rex, ed, i64, x3, x4, x5); + emit_test32c(dyn, ninst, rex, ed, i64, x3, x4); break; case 2: INST_NAME("NOT Ed"); diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c index a3bbce9c1..a4f8aa40c 100644 --- a/src/dynarec/arm64/dynarec_arm64_66.c +++ b/src/dynarec/arm64/dynarec_arm64_66.c @@ -605,7 +605,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin nextop = F8; GETEW(x1, 0); GETGW(x2); - emit_test16(dyn, ninst, x1, x2, x3, x4, x5); + emit_test16(dyn, ninst, x1, x2, x3, x4); break; case 0x87: @@ -977,7 +977,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); u16 = F16; UBFXx(x1, xRAX, 0, 16); - emit_test16c(dyn, ninst, x1, u16, x3, x4, x5); + emit_test16c(dyn, ninst, x1, u16, x3, x4); break; case 0xAB: @@ -1565,7 +1565,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETEW(x1, 2); u16 = F16; - emit_test16c(dyn, ninst, x1, u16, x3, x4, x5); + emit_test16c(dyn, ninst, x1, u16, x3, x4); break; case 2: INST_NAME("NOT Ew"); diff --git a/src/dynarec/arm64/dynarec_arm64_emit_tests.c b/src/dynarec/arm64/dynarec_arm64_emit_tests.c index f74c201d7..03887a719 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_tests.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_tests.c @@ -310,8 +310,8 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4) } } -// emit TEST32 instruction, from test s1, s2, using s3, s4 and s5 as scratch -void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5) +// emit TEST32 instruction, from test s1, s2, using s3 and s4 as scratch +void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4) { MAYUSE(s1); MAYUSE(s2); MAYUSE(s3); MAYUSE(s4); IFX_PENDOR0 { @@ -349,12 +349,12 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s } } IFX(X_PF) { - emit_pf(dyn, ninst, s3, s5); + emit_pf(dyn, ninst, s3, s4); } } -// emit TEST32 instruction, from test s1, s2, using s3, s4 and s5 as scratch -void emit_test32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5) +// emit TEST32 instruction, from test s1, s2, using s3 and s4 as scratch +void emit_test32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4) { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); int mask = convert_bitmask_xw(c); @@ -398,12 +398,12 @@ void emit_test32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i } } IFX(X_PF) { - emit_pf(dyn, ninst, s3, s5); + emit_pf(dyn, ninst, s3, s4); } } -// emit TEST16 instruction, from test s1, s2, using s3, s4 and s5 as scratch -void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) +// emit TEST16 instruction, from test s1, s2, using s3 and s4 as scratch +void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) { MAYUSE(s1); MAYUSE(s2); IFX_PENDOR0 { @@ -412,8 +412,8 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, SET_DFNONE(); } IFX(X_CF|X_ZF|X_SF|X_OF) { - LSLw(s5, s1, 16); - ANDSw_REG_LSL(s5, s5, s2, 16); + LSLw(s3, s1, 16); + ANDSw_REG_LSL(s3, s3, s2, 16); IFX(X_ZF) { IFNATIVE(NF_EQ) {} else { CSETw(s4, cEQ); @@ -433,24 +433,24 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, } } IFX(X_PF|X_PEND) { - LSRw(s5, s5, 16); + LSRw(s3, s3, 16); } } else { - ANDw_REG(s5, s1, s2); // res = s1 & s2 + ANDw_REG(s3, s1, s2); // res = s1 & s2 } IFX(X_AF) { BFCw(xFlags, F_AF, 1); } IFX_PENDOR0 { - STRH_U12(s5, xEmu, offsetof(x64emu_t, res)); + STRH_U12(s3, xEmu, offsetof(x64emu_t, res)); } IFX(X_PF) { - emit_pf(dyn, ninst, s5, s4); + emit_pf(dyn, ninst, s3, s4); } } -// emit TEST16 instruction, from test s1, s2, using s3, s4 and s5 as scratch -void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5) +// emit TEST16 instruction, from test s1, s2, using s3 and s4 as scratch +void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) { MAYUSE(s1); int mask = 0; @@ -460,13 +460,13 @@ void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int SET_DFNONE(); } IFX(X_CF|X_ZF|X_SF|X_OF) { - LSLw(s5, s1, 16); + LSLw(s3, s1, 16); mask = convert_bitmask_w(c<<16); if(mask) { - ANDSw_mask(s5, s5, mask&0x3F, (mask>>6)&0x3F); + ANDSw_mask(s3, s3, mask&0x3F, (mask>>6)&0x3F); } else { - MOV32w(s3, c); - ANDSw_REG_LSL(s5, s5, s3, 16); + MOV32w(s4, c); + ANDSw_REG_LSL(s3, s3, s4, 16); } IFX(X_ZF) { IFNATIVE(NF_EQ) {} else { @@ -487,30 +487,30 @@ void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int } } IFX(X_PF|X_PEND) { - LSRw(s5, s5, 16); + LSRw(s3, s3, 16); } } else { mask = convert_bitmask_w(c); if(mask) { - ANDw_mask(s5, s1, mask&0x3F, (mask>>6)&0x3F); + ANDw_mask(s3, s1, mask&0x3F, (mask>>6)&0x3F); } else { - MOV32w(s5, c); - ANDw_REG(s5, s1, s5); // res = s1 & s2 + MOV32w(s3, c); + ANDw_REG(s3, s1, s3); // res = s1 & s2 } } IFX(X_AF) { BFCw(xFlags, F_AF, 1); } IFX_PENDOR0 { - STRH_U12(s5, xEmu, offsetof(x64emu_t, res)); + STRH_U12(s3, xEmu, offsetof(x64emu_t, res)); } IFX(X_PF) { - emit_pf(dyn, ninst, s5, s4); + emit_pf(dyn, ninst, s3, s4); } } -// emit TEST8 instruction, from test s1, s2, using s3, s4 and s5 as scratch -void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) +// emit TEST8 instruction, from test s1, s2, using s3 and s4 as scratch +void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) { MAYUSE(s1); MAYUSE(s2); IFX_PENDOR0 { @@ -519,8 +519,8 @@ void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i SET_DFNONE(); } IFX(X_CF|X_ZF|X_SF|X_OF) { - LSLw(s5, s1, 24); - ANDSw_REG_LSL(s5, s5, s2, 24); + LSLw(s3, s1, 24); + ANDSw_REG_LSL(s3, s3, s2, 24); IFX(X_ZF) { IFNATIVE(NF_EQ) {} else { CSETw(s4, cEQ); @@ -540,24 +540,24 @@ void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i } } IFX(X_PF|X_PEND) { - LSRw(s5, s5, 24); + LSRw(s3, s3, 24); } } else { - ANDw_REG(s5, s1, s2); // res = s1 & s2 + ANDw_REG(s3, s1, s2); // res = s1 & s2 } IFX(X_AF) { BFCw(xFlags, F_AF, 1); } IFX_PENDOR0 { - STRB_U12(s5, xEmu, offsetof(x64emu_t, res)); + STRB_U12(s3, xEmu, offsetof(x64emu_t, res)); } IFX(X_PF) { - emit_pf(dyn, ninst, s5, s4); + emit_pf(dyn, ninst, s3, s4); } } // emit TEST8 instruction, from test s1, s2, using s3, s4 and s5 as scratch -void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5) +void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) { MAYUSE(s1); int mask = 0; @@ -567,13 +567,13 @@ void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int SET_DFNONE(); } IFX(X_CF|X_ZF|X_SF|X_OF) { - LSLw(s5, s1, 24); + LSLw(s3, s1, 24); mask = convert_bitmask_w(c<<24); if(mask) { - ANDSw_mask(s5, s5, mask&0x3F, (mask>>6)&0x3F); + ANDSw_mask(s3, s3, mask&0x3F, (mask>>6)&0x3F); } else { - MOV32w(s3, c); - ANDSw_REG_LSL(s5, s5, s3, 24); + MOV32w(s4, c); + ANDSw_REG_LSL(s3, s3, s4, 24); } IFX(X_ZF) { IFNATIVE(NF_EQ) {} else { @@ -594,24 +594,24 @@ void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int } } IFX(X_PF|X_PEND) { - LSRw(s5, s5, 24); + LSRw(s3, s3, 24); } } else { mask = convert_bitmask_w(c); if(mask) { - ANDw_mask(s5, s1, mask&0x3F, (mask>>6)&0x3F); + ANDw_mask(s3, s1, mask&0x3F, (mask>>6)&0x3F); } else { - MOV32w(s5, c); - ANDw_REG(s5, s1, s5); // res = s1 & s2 + MOV32w(s3, c); + ANDw_REG(s3, s1, s3); // res = s1 & s2 } } IFX(X_AF) { BFCw(xFlags, F_AF, 1); } IFX_PENDOR0 { - STRB_U12(s5, xEmu, offsetof(x64emu_t, res)); + STRB_U12(s3, xEmu, offsetof(x64emu_t, res)); } IFX(X_PF) { - emit_pf(dyn, ninst, s5, s4); + emit_pf(dyn, ninst, s3, s4); } } diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index e916e964b..191aac020 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -1416,12 +1416,12 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4); -void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); -void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5); -void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); -void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5); -void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); -void emit_test32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5); +void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); +void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4); +void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); +void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4); +void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); +void emit_test32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4); void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5); void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); diff --git a/src/dynarec/arm64/updateflags_arm64_pass.c b/src/dynarec/arm64/updateflags_arm64_pass.c index 970d7bf5b..a07b1dc09 100644 --- a/src/dynarec/arm64/updateflags_arm64_pass.c +++ b/src/dynarec/arm64/updateflags_arm64_pass.c @@ -500,24 +500,24 @@ SETMARK(d_cmp64); SETMARK(d_tst8); LDRB_U12(x1, xEmu, offsetof(x64emu_t, res)); MOV32w(x2, 0xff); - emit_test8(dyn, ninst, x1, x2, x3, x4, x5); + emit_test8(dyn, ninst, x1, x2, x3, x4); RET(xLR); SETMARK(d_tst16); LDRH_U12(x1, xEmu, offsetof(x64emu_t, res)); MOV32w(x2, 0xffff); - emit_test16(dyn, ninst, x1, x2, x3, x4, x5); + emit_test16(dyn, ninst, x1, x2, x3, x4); RET(xLR); SETMARK(d_tst32); LDRw_U12(x1, xEmu, offsetof(x64emu_t, res)); MOV32w(x2, 0xffffffff); rex.w = 0; - emit_test32(dyn, ninst, rex, x1, x2, x3, x4, x5); + emit_test32(dyn, ninst, rex, x1, x2, x3, x4); RET(xLR); SETMARK(d_tst64); LDRx_U12(x1, xEmu, offsetof(x64emu_t, res)); MOV64x(x2, 0xffffffffffffffffULL); rex.w = 1; - emit_test32(dyn, ninst, rex, x1, x2, x3, x4, x5); + emit_test32(dyn, ninst, rex, x1, x2, x3, x4); rex.w = 0; RET(xLR); // for ADC & SBB, the emit_adcX cannot be used because the CF state is not saved From 4049ceacf0751bb89e4a918bfb495dd04fefa24e Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Fri, 6 Nov 2026 12:02:52 +0100 Subject: [PATCH 146/156] Windows builds needs ULL to be 64bits --- src/include/debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/debug.h b/src/include/debug.h index e11f471cf..f6b3b8673 100644 --- a/src/include/debug.h +++ b/src/include/debug.h @@ -12,7 +12,7 @@ typedef struct box64context_s box64context_t; extern box64env_t box64env; extern box64env_t* cur_box64env; -#define X86_PAGE_SIZE 4096UL +#define X86_PAGE_SIZE 4096ULL #define ALIGN(p) (((p)+box64_pagesize-1)&~(box64_pagesize-1)) #define ALIGN_DOWN(p) ((p)&~(box64_pagesize-1)) From 0b5002e8df7e3bc997871ba8f9afcbbce99124c0 Mon Sep 17 00:00:00 2001 From: Alex Beverage Date: Fri, 6 Nov 2026 09:35:49 -1000 Subject: [PATCH 147/156] [SIGNAL] Restore FPU state and drop deferred flags when a handler changes the context (#4679) * [SIGNAL] Restore FPU state and drop deferred flags when a handler changes the context When a guest signal handler returns a modified context, my_sigactionhandler_oldcode_64 leaves through native_next or siglongjmp, and neither goes back through my_sigactionhandler_oldcode, where the emu state is saved and restored around the handler. The interrupted code then resumed with the handler's SSE/AVX/x87 registers and its deferred-flags record. Restore the FPU state from the frame, as sigreturn would, and drop the deferred flags, since eflags is loaded from the context. CoreCLR does this on every GC suspension that moves an object a thread holds in a register (seen as wrong vectorised string compares and wrongly taken bounds checks). Co-Authored-By: Claude Opus 5.5 * [SIGNAL] Remove comment in context change path Co-Authored-By: Claude Opus 5.5 --------- Co-authored-by: Claude Opus 5.5 --- src/libtools/signals.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 09a8e9297..43e1412cf 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -622,6 +622,8 @@ int my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigin emu->eflags.x64 = old_eflags; if(memcmp(sigcontext, &sigcontext_copy, sizeof(x64_ucontext_t))) { + fpu_xrstor_mask(emu, xstate, 0, 0b111); + emu->df = d_none; #if defined(DYNAREC) if(db || emu->jmpbuf) mctx2emu(emu, &sigcontext->uc_mcontext); From 50855a1e2bdb0bd09135bb84d6904223775f16a5 Mon Sep 17 00:00:00 2001 From: Alex Beverage Date: Fri, 6 Nov 2026 09:36:04 -1000 Subject: [PATCH 148/156] [ARM64_DYNAREC] Fix native flags record in signal arch info (#4678) * [ARM64_DYNAREC] Fix native flags record in signal arch info The one-bit fields of arch_flags_t were assigned flags&NF_xx directly; only NF_EQ is bit 0, so SF, OF, CF and PF were always recorded as clear, and a signal landing on a conditional jump got those flags from emu->df or x26 instead of NZCV. Also drop a stale emu->df when the record isn't deferred, so the caller's CHECK_FLAGS doesn't recompute the native bits from it. Co-Authored-By: Claude Opus 5.5 * [ARM64_DYNAREC] Remove comment in adjust_arch Co-Authored-By: Claude Opus 5.5 --------- Co-authored-by: Claude Opus 5.5 --- src/dynarec/arm64/dynarec_arm64_arch.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_arch.c b/src/dynarec/arm64/dynarec_arm64_arch.c index 792da2217..ff4fdc22d 100644 --- a/src/dynarec/arm64/dynarec_arm64_arch.c +++ b/src/dynarec/arm64/dynarec_arm64_arch.c @@ -99,13 +99,13 @@ static int arch_build(dynarec_arm_t* dyn, int ninst, arch_build_t* arch, int noa arch->flags = 1; arch->flags_.defered = (dyn->insts[ninst].f_entry!=status_none && dyn->insts[ninst].f_entry!=status_none_pending); uint8_t flags = dyn->insts[ninst].need_nat_flags | dyn->insts[ninst].before_nat_flags; - arch->flags_.vf = flags&NF_VF; - arch->flags_.nf = flags&NF_SF; - arch->flags_.eq = flags&NF_EQ; - arch->flags_.cf = flags&NF_CF; + arch->flags_.vf = !!(flags&NF_VF); + arch->flags_.nf = !!(flags&NF_SF); + arch->flags_.eq = !!(flags&NF_EQ); + arch->flags_.cf = !!(flags&NF_CF); if(arch->flags_.cf) arch->flags_.inv_cf = !dyn->insts[ninst].normal_carry; - arch->flags_.pf_v = flags&NF_PF_V; + arch->flags_.pf_v = !!(flags&NF_PF_V); } // opcode can handle unaligned arch->unaligned = dyn->insts[ninst].unaligned; @@ -320,6 +320,8 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) if(flags->defered) { CHECK_FLAGS(emu); //return; + } else { + emu->df = d_none; } if(flags->nf) { CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1< Date: Sat, 7 Nov 2026 10:44:59 +0100 Subject: [PATCH 149/156] Fixed proc/self/maps formating (for #4681) --- src/elfs/elfloader.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 0217e9c43..6e042a9da 100644 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -1937,9 +1937,11 @@ void CreateMemorymapFile(box64context_t* context, int fd) elfheader_t* h = FindElfAddress(my_context, start); int l = strlen(line); if(h && l<73) { + line[strcspn(line, "\n")] = '\0'; sprintf(buff, "%s%*s\n", line, 74-l, h->name); dummy = write(fd, buff, strlen(buff)); } else if(start==(uintptr_t)my_context->stack) { + line[strcspn(line, "\n")] = '\0'; sprintf(buff, "%s%*s\n", line, 74-l, "[stack]"); dummy = write(fd, buff, strlen(buff)); } else if (strstr(line, "[stack]")) { From 37f5e4b7b0002a247c04866a44d0321e92cfef3c Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Sat, 7 Nov 2026 11:26:50 +0100 Subject: [PATCH 150/156] Expand special names in DT_NEEDED names too (for #4682) --- src/elfs/elfloader.c | 154 ++++++++++++++++++++----------------- src/include/box64context.h | 3 + src/include/elfloader.h | 1 + src/librarian/library.c | 29 +++++++ 4 files changed, 116 insertions(+), 71 deletions(-) diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 6e042a9da..70906e5a2 100644 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -1138,6 +1138,81 @@ page description of the -r option). For more details of this token expansion, se uname(1) man page description of the -i option). For more details of this token expansion, see “System Specific Shared Objects” */ +char* ExpandNeededLibs(elfheader_t* h, char* rpath) +{ + if(!rpath || !h) return rpath; + char* rpathref = rpath; + while(strstr(rpath, "$$ORIGIN")) { + char* origin = box_strdup(h->path); + char* p = strrchr(origin, '/'); + if(p) *p = '\0'; // remove file name to have only full path, without last '/' + char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("$$ORIGIN")+strlen(origin)+1); + p = strstr(rpath, "$$ORIGIN"); + memcpy(tmp, rpath, p-rpath); + strcat(tmp, origin); + strcat(tmp, p+strlen("$$ORIGIN")); + if(rpath!=rpathref) + box_free(rpath); + rpath = tmp; + box_free(origin); + } + while(strstr(rpath, "$ORIGIN")) { + char* origin = box_strdup(h->path); + char* p = strrchr(origin, '/'); + if(p) *p = '\0'; // remove file name to have only full path, without last '/' + char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("$ORIGIN")+strlen(origin)+1); + p = strstr(rpath, "$ORIGIN"); + memcpy(tmp, rpath, p-rpath); + strcat(tmp, origin); + strcat(tmp, p+strlen("$ORIGIN")); + if(rpath!=rpathref) + box_free(rpath); + rpath = tmp; + box_free(origin); + } + while(strstr(rpath, "${ORIGIN}")) { + char* origin = box_strdup(h->path); + char* p = strrchr(origin, '/'); + if(p) *p = '\0'; // remove file name to have only full path, without last '/' + char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${ORIGIN}")+strlen(origin)+1); + p = strstr(rpath, "${ORIGIN}"); + memcpy(tmp, rpath, p-rpath); + strcat(tmp, origin); + strcat(tmp, p+strlen("${ORIGIN}")); + if(rpath!=rpathref) + box_free(rpath); + rpath = tmp; + box_free(origin); + if(!FileExist(rpath, 0) && strstr(rpath, "/../../")) { + tmp = (char*)box_calloc(1, strlen(rpath)+1); + strcpy(tmp, rpath); + // check if one "/.." could be removed for the folder to exist + char* p = strstr(tmp, "/../../"); + memmove(p, p+3, strlen(p+3)+1); + if(FileExist(tmp, 0)) { + if(rpath!=rpathref) + box_free(rpath); + rpath = tmp; + } else + box_free(tmp); + } + } + while(strstr(rpath, "${PLATFORM}")) { + char* platform = box_strdup("x86_64"); + char* p = strrchr(platform, '/'); + if(p) *p = '\0'; // remove file name to have only full path, without last '/' + char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${PLATFORM}")+strlen(platform)+1); + p = strstr(rpath, "${PLATFORM}"); + memcpy(tmp, rpath, p-rpath); + strcat(tmp, platform); + strcat(tmp, p+strlen("${PLATFORM}")); + if(rpath!=rpathref) + box_free(rpath); + rpath = tmp; + box_free(platform); + } + return rpath; +} int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int deepbind, box64context_t *box64, x64emu_t* emu) { if(h->needed) // already done @@ -1150,75 +1225,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int de if(tag==DT_RPATH || tag==DT_RUNPATH) { char *rpathref = h->DynStrTab+h->delta+(box64_is32bits?h->Dynamic._32[i].d_un.d_val:h->Dynamic._64[i].d_un.d_val); char* rpath = rpathref; - while(strstr(rpath, "$$ORIGIN")) { - char* origin = box_strdup(h->path); - char* p = strrchr(origin, '/'); - if(p) *p = '\0'; // remove file name to have only full path, without last '/' - char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("$$ORIGIN")+strlen(origin)+1); - p = strstr(rpath, "$$ORIGIN"); - memcpy(tmp, rpath, p-rpath); - strcat(tmp, origin); - strcat(tmp, p+strlen("$$ORIGIN")); - if(rpath!=rpathref) - box_free(rpath); - rpath = tmp; - box_free(origin); - } - while(strstr(rpath, "$ORIGIN")) { - char* origin = box_strdup(h->path); - char* p = strrchr(origin, '/'); - if(p) *p = '\0'; // remove file name to have only full path, without last '/' - char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("$ORIGIN")+strlen(origin)+1); - p = strstr(rpath, "$ORIGIN"); - memcpy(tmp, rpath, p-rpath); - strcat(tmp, origin); - strcat(tmp, p+strlen("$ORIGIN")); - if(rpath!=rpathref) - box_free(rpath); - rpath = tmp; - box_free(origin); - } - while(strstr(rpath, "${ORIGIN}")) { - char* origin = box_strdup(h->path); - char* p = strrchr(origin, '/'); - if(p) *p = '\0'; // remove file name to have only full path, without last '/' - char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${ORIGIN}")+strlen(origin)+1); - p = strstr(rpath, "${ORIGIN}"); - memcpy(tmp, rpath, p-rpath); - strcat(tmp, origin); - strcat(tmp, p+strlen("${ORIGIN}")); - if(rpath!=rpathref) - box_free(rpath); - rpath = tmp; - box_free(origin); - if(!FileExist(rpath, 0) && strstr(rpath, "/../../")) { - tmp = (char*)box_calloc(1, strlen(rpath)+1); - strcpy(tmp, rpath); - // check if one "/.." could be removed for the folder to exist - char* p = strstr(tmp, "/../../"); - memmove(p, p+3, strlen(p+3)+1); - if(FileExist(tmp, 0)) { - if(rpath!=rpathref) - box_free(rpath); - rpath = tmp; - } else - box_free(tmp); - } - } - while(strstr(rpath, "${PLATFORM}")) { - char* platform = box_strdup("x86_64"); - char* p = strrchr(platform, '/'); - if(p) *p = '\0'; // remove file name to have only full path, without last '/' - char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${PLATFORM}")+strlen(platform)+1); - p = strstr(rpath, "${PLATFORM}"); - memcpy(tmp, rpath, p-rpath); - strcat(tmp, platform); - strcat(tmp, p+strlen("${PLATFORM}")); - if(rpath!=rpathref) - box_free(rpath); - rpath = tmp; - box_free(platform); - } + rpath = ExpandNeededLibs(h, rpath); if(strchr(rpath, '$')) { printf_log(LOG_INFO, "Warning, RPATH with $ variable not supported yet (%s)\n", rpath); } else { @@ -1255,8 +1262,13 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int de my_context->neededlibs = h->needed; int j=0; for (size_t i=0; inumDynamic; ++i) - if((box64_is32bits?h->Dynamic._32[i].d_tag:h->Dynamic._64[i].d_tag)==DT_NEEDED) - h->needed->names[j++] = h->DynStrTab+h->delta+(box64_is32bits?h->Dynamic._32[i].d_un.d_val:h->Dynamic._64[i].d_un.d_val); + if((box64_is32bits?h->Dynamic._32[i].d_tag:h->Dynamic._64[i].d_tag)==DT_NEEDED) { + char* path = h->DynStrTab+h->delta+(box64_is32bits?h->Dynamic._32[i].d_un.d_val:h->Dynamic._64[i].d_un.d_val); + char* newpath = ExpandNeededLibs(h, path); + if(path!=newpath) + path = add1nsname(h->needed, newpath); + h->needed->names[j++] = path; + } #ifndef ANDROID if(box64_is32bits && strstr(h->name, "lsteamclient.dll.so")) h->needed->names[j++] = "libgcc_s.so.1"; diff --git a/src/include/box64context.h b/src/include/box64context.h index 6de8ae6e9..49c065904 100644 --- a/src/include/box64context.h +++ b/src/include/box64context.h @@ -79,6 +79,8 @@ typedef struct needed_libs_s { library_t** libs; path_collection_t* rpath; int nb_done; + char** nonstaticnames; + int ns_size; } needed_libs_t; void free_neededlib(needed_libs_t* needed); @@ -88,6 +90,7 @@ void add1_neededlib(needed_libs_t* needed); void add1lib_neededlib(needed_libs_t* needed, library_t* lib, const char* name); void add1lib_neededlib_name(needed_libs_t* needed, library_t* lib, const char* name); void add1libref_neededlib(needed_libs_t* needed, library_t* lib); +char* add1nsname(needed_libs_t* needed, char* nsname); typedef struct base_segment_s { uintptr_t base; diff --git a/src/include/elfloader.h b/src/include/elfloader.h index 7dee4434e..ef564b722 100644 --- a/src/include/elfloader.h +++ b/src/include/elfloader.h @@ -54,6 +54,7 @@ uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h); uintptr_t GetLastByte(elfheader_t* h); void AddSymbols(lib_t *maplib, elfheader_t* h); int NeededLibs(elfheader_t* h); +char* ExpandNeededLibs(elfheader_t* h, char* rpath); int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int deepbind, box64context_t *box64, x64emu_t* emu); needed_libs_t* GetELfNeededLibs(elfheader_t* h); uintptr_t GetElfInit(elfheader_t* h); diff --git a/src/librarian/library.c b/src/librarian/library.c index 1c5b04459..45a8f907b 100644 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -1323,6 +1323,13 @@ void free_neededlib(needed_libs_t* needed) FreeCollection(needed->rpath); box_free(needed->rpath); } + if(needed->nonstaticnames) { + for(int i=0; ins_size; ++i) + box_free(needed->nonstaticnames[i]); + box_free(needed->nonstaticnames); + needed->ns_size = 0; + needed->nonstaticnames = NULL; + } box_free(needed); } void add1_neededlib(needed_libs_t* needed) @@ -1406,8 +1413,30 @@ needed_libs_t* copy_neededlib(needed_libs_t* needed) ret->names = (char**)box_calloc(ret->cap, sizeof(char*)); memcpy(ret->libs, needed->libs, ret->size*sizeof(library_t*)); memcpy(ret->names, needed->names, ret->size*sizeof(char*)); + if(needed->nonstaticnames) { + ret->ns_size = needed->ns_size; + ret->nonstaticnames = (char**)box_malloc(ret->ns_size*sizeof(char*)); + for(int i=0; ins_size; ++i) + ret->nonstaticnames[i] = box_strdup(needed->nonstaticnames[i]); + } return ret; } +char* add1nsname(needed_libs_t* needed, char* nsname) +{ + if(!needed->ns_size) { + needed->ns_size = 1; + needed->nonstaticnames = (char**)box_malloc(needed->ns_size*sizeof(char*)); + needed->nonstaticnames[0] = nsname; + return needed->nonstaticnames[0]; + } + for(int i=0; ins_size; ++i) + if(!strcmp(needed->nonstaticnames[i], nsname)) + return needed->nonstaticnames[i]; + int i = needed->ns_size++; + needed->nonstaticnames = (char**)box_realloc(needed->nonstaticnames, (i+1)*sizeof(char*)); + needed->nonstaticnames[i] = nsname; + return needed->nonstaticnames[i]; +} void setNeededLibs(library_t* lib, int n, ...) { From 20cff3b264a05296df1fedab28fe7d5f34e2ade1 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Sun, 8 Nov 2026 12:59:45 +0100 Subject: [PATCH 151/156] [WINE] Allows wine 11.21+ to start --- src/tools/wine_tools.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/wine_tools.c b/src/tools/wine_tools.c index 28eb436b4..e59afb0fd 100644 --- a/src/tools/wine_tools.c +++ b/src/tools/wine_tools.c @@ -25,7 +25,7 @@ typedef struct wine_prereserve_32_s #include "box32.h" #endif // only the prereseve argument is reserved, not the other zone that wine-preloader reserve -static wine_prereserve_t my_wine_reserve[] = {{(void*)0x00010000, 0x00008000}, {(void*)0x00110000, 0x30000000}, {(void*)0x7f000000, 0x03000000}, {0, 0}, {0, 0}}; +static wine_prereserve_t my_wine_reserve[] = {{(void*)0x00010000, 0x00010000}, {(void*)0x00110000, 0x30000000}, {(void*)0x7f000000, 0x03000000}, {0, 0}, {0, 0}}; int wine_preloaded = 0; From 5daced4476095c9cc0d19e66ccd623fa1c747651 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Sun, 8 Nov 2026 13:00:43 +0100 Subject: [PATCH 152/156] [WINE] Fixed some issues with vc_redist.x64.exe that fails to install properly --- src/tools/env.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/env.c b/src/tools/env.c index 38f74625c..5c710f51d 100644 --- a/src/tools/env.c +++ b/src/tools/env.c @@ -867,7 +867,7 @@ void RecordEnvMappings(uintptr_t addr, size_t length, int fd) if(new_mapping) { // First time we see this file if (box64_wine && BOX64ENV(unityplayer)) DetectUnityPlayer(lowercase_filename+1); - if (box64_wine && !box64_is32bits && BOX64ENV(dynarec_volatile_metadata)) ParseVolatileMetadata(fullname, (void*)addr); + if (box64_wine && !box64_is32bits && BOX64ENV(dynarec_volatile_metadata) && (getProtection(addr)&PROT_READ)) ParseVolatileMetadata(fullname, (void*)addr); #if defined(DYNAREC) && !defined(WIN32) int dynacache = box64env.dynacache; if(mapping->env && mapping->env->is_dynacache_overridden) From c8ad5c3782ca4d2d3fff662bf30474b849a2d12b Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Sun, 8 Nov 2026 13:42:15 +0100 Subject: [PATCH 153/156] [VULKAN] Added 1 more extension --- src/wrapped/wrappedvulkan_private.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wrapped/wrappedvulkan_private.h b/src/wrapped/wrappedvulkan_private.h index b6e466b3e..6d751c6d7 100644 --- a/src/wrapped/wrappedvulkan_private.h +++ b/src/wrapped/wrappedvulkan_private.h @@ -1179,6 +1179,9 @@ GO(vkCmdBeginCustomResolveEXT, vFpp) // VK_NV_compute_occupancy_priority GO(vkCmdSetComputeOccupancyPriorityNV, vFpp) +// VK_EXT_cooperative_matrix_maintenance1 +GO(vkGetPhysicalDeviceCooperativeMatrixProperties2EXT, iFpppp) + // Layer stuffs GO(vk_icdNegotiateLoaderICDInterfaceVersion, iFp) //GO(vkNegotiateLoaderLayerInterfaceVersion, iFp) From 7a7da0ca2b73f1b3bf3cab0de6743772bdba4caf Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 9 Nov 2026 09:28:44 +0100 Subject: [PATCH 154/156] Musl build 01 housekeeping (#4670) * global GNU_SOURCE Signed-off-by: Pepper Gray * global lfs Signed-off-by: Pepper Gray * lfs: use fseeko Signed-off-by: Pepper Gray * lfs: use ino_t, off_t Signed-off-by: Pepper Gray * lfs: mmap Signed-off-by: Pepper Gray * lfs: fsblkcnt_t, fsfilcnt_t Signed-off-by: Pepper Gray * lfs: stat Signed-off-by: Pepper Gray * lfs: dirent Signed-off-by: Pepper Gray * lfs: alphasort Signed-off-by: Pepper Gray * lfs: f/open Signed-off-by: Pepper Gray * lfs: l/f/stat, fstatat, statfs Signed-off-by: Pepper Gray * lfs: get/setrlimit, struct rlimit Signed-off-by: Pepper Gray * lfs: n/ftw Signed-off-by: Pepper Gray * lfs: scandir/at, readdir Signed-off-by: Pepper Gray * lfs: glob, globfree, glob_t Signed-off-by: Pepper Gray * replace legacy isnanf/isinff with isnan/isinf Signed-off-by: Pepper Gray --------- Signed-off-by: Pepper Gray Co-authored-by: ptitSeb --- CMakeLists.txt | 2 + external/musl/sincos.c | 1 - src/box64context.c | 1 - src/custommem.c | 1 - src/custommmap.c | 1 - src/dynarec/arm64/dynarec_arm64_functions.c | 1 - src/dynarec/dynarec_native_functions.c | 1 - src/dynarec/la64/dynarec_la64_functions.c | 1 - .../ppc64le/dynarec_ppc64le_functions.c | 1 - src/dynarec/rv64/dynarec_rv64_functions.c | 1 - src/elfs/elfhacks.c | 1 - src/elfs/elfhash.c | 1 - src/elfs/elfhash32.c | 1 - src/elfs/elfloader.c | 5 +- src/elfs/elfloader32.c | 19 +- src/elfs/elfparser.c | 13 +- src/elfs/elfparser32.c | 9 +- src/emu/x64int3.c | 1 - src/emu/x64run.c | 1 - src/emu/x64run0f.c | 35 ++-- src/emu/x64run66.c | 1 - src/emu/x64run660f.c | 13 +- src/emu/x64run66d9.c | 1 - src/emu/x64run66dd.c | 1 - src/emu/x64run66f0.c | 1 - src/emu/x64run66f20f.c | 1 - src/emu/x64run66f30f.c | 1 - src/emu/x64run_private.c | 1 - src/emu/x64runavx.c | 1 - src/emu/x64runavx0f.c | 61 +++--- src/emu/x64runavx0f38.c | 1 - src/emu/x64runavx660f.c | 5 +- src/emu/x64runavx660f38.c | 1 - src/emu/x64runavx660f3a.c | 19 +- src/emu/x64runavxf20f.c | 61 +++--- src/emu/x64runavxf20f38.c | 1 - src/emu/x64runavxf20f3a.c | 1 - src/emu/x64runavxf30f.c | 41 ++-- src/emu/x64runavxf30f38.c | 1 - src/emu/x64runavxf30f3a.c | 1 - src/emu/x64rund8.c | 1 - src/emu/x64rund9.c | 1 - src/emu/x64runda.c | 1 - src/emu/x64rundb.c | 1 - src/emu/x64rundc.c | 1 - src/emu/x64rundd.c | 1 - src/emu/x64runde.c | 1 - src/emu/x64rundf.c | 1 - src/emu/x64runf0.c | 1 - src/emu/x64runf20f.c | 55 +++-- src/emu/x64runf30f.c | 43 ++-- src/emu/x64syscall.c | 5 +- src/emu/x64test.c | 1 - src/emu/x86int3.c | 1 - src/emu/x86syscall.c | 1 - src/emu/x86syscall_32.c | 1 - src/include/os.h | 8 - src/librarian/globalsymbols.c | 1 - src/librarian/globalsymbols32.c | 1 - src/librarian/library.c | 1 - src/libtools/libc_net32.c | 1 - src/libtools/libdl.c | 1 - src/libtools/myalign64_32.c | 12 +- src/libtools/obstack.c | 3 - src/libtools/signal32.c | 1 - src/libtools/signals.c | 1 - src/libtools/syscall_user_dispatch.c | 1 - src/libtools/threads.c | 3 +- src/libtools/threads32.c | 3 +- src/libtools/vulkanoverlay.c | 1 - src/mallochook.c | 1 - src/os/my_cpuid.c | 1 - src/os/os_linux.c | 1 - src/os/sysinfo.c | 1 - src/tools/bridge.c | 1 - src/tools/cpumask.c | 1 - src/tools/fileutils.c | 1 - src/tools/gtkclass.c | 1 - src/wrapped/wrappedalure.c | 1 - src/wrapped/wrappedalut.c | 1 - src/wrapped/wrappedandroidshmem.c | 1 - src/wrapped/wrappedandroidsupport.c | 1 - src/wrapped/wrappedanl.c | 1 - src/wrapped/wrappedatk.c | 1 - src/wrapped/wrappedatkbridge.c | 1 - src/wrapped/wrappedatomic.c | 1 - src/wrapped/wrappedatspi.c | 1 - src/wrapped/wrappedavahiclient.c | 1 - src/wrapped/wrappedavahicommon.c | 1 - src/wrapped/wrappedayatanaappindicator3.c | 1 - src/wrapped/wrappedayatanaido3.c | 1 - src/wrapped/wrappedayatanaindicator3.c | 1 - src/wrapped/wrappedbrotlidec.c | 1 - src/wrapped/wrappedbz2.c | 1 - src/wrapped/wrappedcairo.c | 1 - src/wrapped/wrappedcairogobject.c | 1 - src/wrapped/wrappedcap.c | 1 - src/wrapped/wrappedcrypto.c | 1 - src/wrapped/wrappedcrypto3.c | 1 - src/wrapped/wrappedcuda.c | 1 - src/wrapped/wrappedcurl.c | 1 - src/wrapped/wrappedd3dadapter9.c | 1 - src/wrapped/wrappeddbus.c | 1 - src/wrapped/wrappeddbusglib1.c | 1 - src/wrapped/wrappeddbusmenuglib.c | 1 - src/wrapped/wrappeddecor0.c | 1 - src/wrapped/wrappedevent21.c | 1 - src/wrapped/wrappedexpat.c | 1 - src/wrapped/wrappedfaudio.c | 1 - src/wrapped/wrappedflac.c | 1 - src/wrapped/wrappedfontconfig.c | 1 - src/wrapped/wrappedfreebl3.c | 1 - src/wrapped/wrappedfreetype.c | 1 - src/wrapped/wrappedgbm.c | 1 - src/wrapped/wrappedgconf2.c | 1 - src/wrapped/wrappedgcrypt.c | 1 - src/wrapped/wrappedgdk3.c | 1 - src/wrapped/wrappedgdkpixbuf2.c | 1 - src/wrapped/wrappedgdkx112.c | 1 - src/wrapped/wrappedgio2.c | 1 - src/wrapped/wrappedglesv2.c | 1 - src/wrapped/wrappedglib2.c | 1 - src/wrapped/wrappedgmodule2.c | 1 - src/wrapped/wrappedgmp.c | 1 - src/wrapped/wrappedgnutls.c | 1 - src/wrapped/wrappedgobject2.c | 1 - src/wrapped/wrappedgomp.c | 1 - src/wrapped/wrappedgssapi.c | 1 - src/wrapped/wrappedgssapikrb5.c | 1 - src/wrapped/wrappedgstallocators.c | 1 - src/wrapped/wrappedgstapp.c | 1 - src/wrapped/wrappedgstaudio.c | 1 - src/wrapped/wrappedgstbase.c | 1 - src/wrapped/wrappedgstcheck.c | 1 - src/wrapped/wrappedgstcontroller.c | 1 - src/wrapped/wrappedgstfft.c | 1 - src/wrapped/wrappedgstgl.c | 1 - src/wrapped/wrappedgstnet.c | 1 - src/wrapped/wrappedgstpbutils.c | 1 - src/wrapped/wrappedgstreamer.c | 1 - src/wrapped/wrappedgstriff.c | 1 - src/wrapped/wrappedgstrtp.c | 1 - src/wrapped/wrappedgstrtsp.c | 1 - src/wrapped/wrappedgstsdp.c | 1 - src/wrapped/wrappedgsttag.c | 1 - src/wrapped/wrappedgstvideo.c | 1 - src/wrapped/wrappedgthread2.c | 1 - src/wrapped/wrappedgtk3.c | 1 - src/wrapped/wrappedgtkx112.c | 1 - src/wrapped/wrappedharfbuzzsubset.c | 1 - src/wrapped/wrappediconv.c | 1 - src/wrapped/wrappedicui18n64.c | 1 - src/wrapped/wrappedicui18n66.c | 1 - src/wrapped/wrappedicui18n67.c | 1 - src/wrapped/wrappedicui18n68.c | 1 - src/wrapped/wrappedicui18n72.c | 1 - src/wrapped/wrappedicui18n73.c | 1 - src/wrapped/wrappedicui18n74.c | 1 - src/wrapped/wrappedicui18n75.c | 1 - src/wrapped/wrappedicui18n76.c | 1 - src/wrapped/wrappedicuuc64.c | 1 - src/wrapped/wrappedicuuc66.c | 1 - src/wrapped/wrappedicuuc67.c | 1 - src/wrapped/wrappedicuuc68.c | 1 - src/wrapped/wrappedicuuc72.c | 1 - src/wrapped/wrappedicuuc73.c | 1 - src/wrapped/wrappedicuuc74.c | 1 - src/wrapped/wrappedicuuc75.c | 1 - src/wrapped/wrappedicuuc76.c | 1 - src/wrapped/wrappedidn2.c | 1 - src/wrapped/wrappedkrb5.c | 1 - src/wrapped/wrappedlber.c | 1 - src/wrapped/wrappedlcms2.c | 1 - src/wrapped/wrappedldapr.c | 1 - src/wrapped/wrappedldlinux.c | 1 - src/wrapped/wrappedlibasound.c | 1 - src/wrapped/wrappedlibavcodec58.c | 1 - src/wrapped/wrappedlibavformat58.c | 1 - src/wrapped/wrappedlibavutil56.c | 1 - src/wrapped/wrappedlibblas.c | 1 - src/wrapped/wrappedlibbsd.c | 1 - src/wrapped/wrappedlibc.c | 67 +++--- src/wrapped/wrappedlibcmusl.c | 1 - src/wrapped/wrappedlibcrypt.c | 1 - src/wrapped/wrappedlibcups.c | 1 - src/wrapped/wrappedlibcupsimage.c | 1 - src/wrapped/wrappedlibdl.c | 1 - src/wrapped/wrappedlibdrm.c | 1 - src/wrapped/wrappedlibdrmamdgpu.c | 1 - src/wrapped/wrappedlibegl.c | 1 - src/wrapped/wrappedlibform.c | 1 - src/wrapped/wrappedlibformw.c | 1 - src/wrapped/wrappedlibformw6.c | 1 - src/wrapped/wrappedlibfuse.c | 1 - src/wrapped/wrappedlibgl.c | 1 - src/wrapped/wrappedlibglu.c | 1 - src/wrapped/wrappedlibglx.c | 1 - src/wrapped/wrappedlibglxnvidia.c | 1 - src/wrapped/wrappedlibgpgme.c | 1 - src/wrapped/wrappedlibharfbuzz.c | 1 - src/wrapped/wrappedlibhogweed6.c | 1 - src/wrapped/wrappedlibibus.c | 1 - src/wrapped/wrappedlibice.c | 1 - src/wrapped/wrappedliblapack.c | 1 - src/wrapped/wrappedlibm.c | 1 - src/wrapped/wrappedlibmvec.c | 1 - src/wrapped/wrappedlibncurses.c | 1 - src/wrapped/wrappedlibncurses6.c | 1 - src/wrapped/wrappedlibncursesw.c | 1 - src/wrapped/wrappedlibncursesw6.c | 1 - src/wrapped/wrappedlibnettle8.c | 1 - src/wrapped/wrappedlibnuma.c | 1 - src/wrapped/wrappedlibogg.c | 1 - src/wrapped/wrappedlibomp.c | 1 - src/wrapped/wrappedlibopus.c | 1 - src/wrapped/wrappedlibpanel.c | 1 - src/wrapped/wrappedlibpci.c | 1 - src/wrapped/wrappedlibpcre.c | 1 - src/wrapped/wrappedlibpcre216.c | 1 - src/wrapped/wrappedlibpthread.c | 1 - src/wrapped/wrappedlibresolv.c | 1 - src/wrapped/wrappedlibrt.c | 1 - src/wrapped/wrappedlibsm.c | 1 - src/wrapped/wrappedlibsndfile.c | 1 - src/wrapped/wrappedlibsqlite3.c | 1 - src/wrapped/wrappedlibssh2.c | 1 - src/wrapped/wrappedlibssl.c | 1 - src/wrapped/wrappedlibssl3.c | 1 - src/wrapped/wrappedlibtasn1.c | 1 - src/wrapped/wrappedlibtiff5.c | 1 - src/wrapped/wrappedlibtinfo.c | 1 - src/wrapped/wrappedlibtinfo6.c | 1 - src/wrapped/wrappedlibunistring2.c | 1 - src/wrapped/wrappedlibusb1.c | 1 - src/wrapped/wrappedlibuuid.c | 1 - src/wrapped/wrappedlibva.c | 1 - src/wrapped/wrappedlibvadrm.c | 1 - src/wrapped/wrappedlibvawayland.c | 1 - src/wrapped/wrappedlibvax11.c | 1 - src/wrapped/wrappedlibvdpau.c | 1 - src/wrapped/wrappedlibvorbis.c | 1 - src/wrapped/wrappedlibvpx.c | 1 - src/wrapped/wrappedlibx11.c | 1 - src/wrapped/wrappedlibx11xcb.c | 1 - src/wrapped/wrappedlibxau.c | 1 - src/wrapped/wrappedlibxaw.c | 1 - src/wrapped/wrappedlibxcb.c | 1 - src/wrapped/wrappedlibxcbcursor.c | 1 - src/wrapped/wrappedlibxcbdri2.c | 1 - src/wrapped/wrappedlibxcbdri3.c | 1 - src/wrapped/wrappedlibxcbglx.c | 1 - src/wrapped/wrappedlibxcbicccm.c | 1 - src/wrapped/wrappedlibxcbimage.c | 1 - src/wrapped/wrappedlibxcbkeysyms.c | 1 - src/wrapped/wrappedlibxcbpresent.c | 1 - src/wrapped/wrappedlibxcbrandr.c | 1 - src/wrapped/wrappedlibxcbrender.c | 1 - src/wrapped/wrappedlibxcbrenderutil.c | 1 - src/wrapped/wrappedlibxcbres.c | 1 - src/wrapped/wrappedlibxcbshape.c | 1 - src/wrapped/wrappedlibxcbshm.c | 1 - src/wrapped/wrappedlibxcbsync.c | 1 - src/wrapped/wrappedlibxcbutil.c | 1 - src/wrapped/wrappedlibxcbxfixes.c | 1 - src/wrapped/wrappedlibxcbxinerama.c | 1 - src/wrapped/wrappedlibxcbxinput.c | 1 - src/wrapped/wrappedlibxcbxkb.c | 1 - src/wrapped/wrappedlibxcbxtest.c | 1 - src/wrapped/wrappedlibxcomposite.c | 1 - src/wrapped/wrappedlibxcursor.c | 1 - src/wrapped/wrappedlibxdamage.c | 1 - src/wrapped/wrappedlibxdmcp.c | 1 - src/wrapped/wrappedlibxext.c | 1 - src/wrapped/wrappedlibxfixes.c | 1 - src/wrapped/wrappedlibxft.c | 1 - src/wrapped/wrappedlibxi.c | 1 - src/wrapped/wrappedlibxmu.c | 1 - src/wrapped/wrappedlibxpm.c | 1 - src/wrapped/wrappedlibxpresent.c | 1 - src/wrapped/wrappedlibxrandr.c | 1 - src/wrapped/wrappedlibxrender.c | 1 - src/wrapped/wrappedlibxss.c | 1 - src/wrapped/wrappedlibxt.c | 1 - src/wrapped/wrappedlibxtst.c | 1 - src/wrapped/wrappedlibxxf86vm.c | 1 - src/wrapped/wrappedlibz.c | 1 - src/wrapped/wrappedlz4.c | 1 - src/wrapped/wrappedlzma.c | 1 - src/wrapped/wrappedmimalloc.c | 1 - src/wrapped/wrappedmpg123.c | 1 - src/wrapped/wrappednotify.c | 1 - src/wrapped/wrappednsl.c | 1 - src/wrapped/wrappednspr4.c | 1 - src/wrapped/wrappednss3.c | 1 - src/wrapped/wrappednssutil3.c | 1 - src/wrapped/wrappednvml.c | 1 - src/wrapped/wrappedopenal.c | 1 - src/wrapped/wrappedopencl.c | 1 - src/wrapped/wrappedp11kit.c | 1 - src/wrapped/wrappedpam.c | 1 - src/wrapped/wrappedpango.c | 1 - src/wrapped/wrappedpangocairo.c | 1 - src/wrapped/wrappedpangoft2.c | 1 - src/wrapped/wrappedpcap.c | 1 - src/wrapped/wrappedpixman1.c | 1 - src/wrapped/wrappedplc4.c | 1 - src/wrapped/wrappedplds4.c | 1 - src/wrapped/wrappedpng16.c | 1 - src/wrapped/wrappedproxy.c | 1 - src/wrapped/wrappedpsl5.c | 1 - src/wrapped/wrappedpulse.c | 1 - src/wrapped/wrappedpulsemainloopglib.c | 1 - src/wrapped/wrappedpulsesimple.c | 1 - src/wrapped/wrappedsdl1.c | 1 - src/wrapped/wrappedsdl1image.c | 1 - src/wrapped/wrappedsdl1mixer.c | 1 - src/wrapped/wrappedsdl1net.c | 1 - src/wrapped/wrappedsdl1sound.c | 1 - src/wrapped/wrappedsdl1ttf.c | 1 - src/wrapped/wrappedsdl2.c | 1 - src/wrapped/wrappedsdl2image.c | 1 - src/wrapped/wrappedsdl2mixer.c | 1 - src/wrapped/wrappedsdl2net.c | 1 - src/wrapped/wrappedsdl2ttf.c | 1 - src/wrapped/wrappedsdl3.c | 1 - src/wrapped/wrappedsdl3ttf.c | 1 - src/wrapped/wrappedsecret1.c | 1 - src/wrapped/wrappedselinux.c | 1 - src/wrapped/wrappedsmbclient.c | 1 - src/wrapped/wrappedsmime3.c | 1 - src/wrapped/wrappedsmpeg.c | 1 - src/wrapped/wrappedsmpeg2.c | 1 - src/wrapped/wrappedsoftokn3.c | 1 - src/wrapped/wrappedssh4.c | 1 - src/wrapped/wrappedssl3.c | 1 - src/wrapped/wrappedsystemd.c | 1 - src/wrapped/wrappedtbbbind.c | 1 - src/wrapped/wrappedtbbmalloc.c | 1 - src/wrapped/wrappedtbbmallocproxy.c | 1 - src/wrapped/wrappedtcmallocminimal.c | 1 - src/wrapped/wrappedtermuxexec.c | 1 - src/wrapped/wrappedudev0.c | 1 - src/wrapped/wrappedudev1.c | 1 - src/wrapped/wrappedunwind.c | 1 - src/wrapped/wrappedutil.c | 1 - src/wrapped/wrappedvorbisfile.c | 1 - src/wrapped/wrappedvulkan.c | 1 - src/wrapped/wrappedwaylandclient.c | 1 - src/wrapped/wrappedwaylandcursor.c | 1 - src/wrapped/wrappedwaylandegl.c | 1 - src/wrapped/wrappedxinerama.c | 1 - src/wrapped/wrappedxkbcommon.c | 1 - src/wrapped/wrappedxkbcommonx11.c | 1 - src/wrapped/wrappedxkbfile.c | 1 - src/wrapped/wrappedxkbregistry.c | 1 - src/wrapped/wrappedxml2.c | 1 - src/wrapped/wrappedxshmfence.c | 1 - src/wrapped/wrappedxslt.c | 1 - src/wrapped/wrappedzstd.c | 1 - src/wrapped32/wrappedblkid.c | 1 - src/wrapped32/wrappedcairo.c | 1 - src/wrapped32/wrappedcurl.c | 1 - src/wrapped32/wrappeddbus.c | 1 - src/wrapped32/wrappedexpat.c | 1 - src/wrapped32/wrappedfontconfig.c | 1 - src/wrapped32/wrappedfreetype.c | 1 - src/wrapped32/wrappedgbm.c | 1 - src/wrapped32/wrappedgnutls.c | 1 - src/wrapped32/wrappedldlinux.c | 1 - src/wrapped32/wrappedlibasound.c | 1 - src/wrapped32/wrappedlibc.c | 190 +++++++++--------- src/wrapped32/wrappedlibcups.c | 1 - src/wrapped32/wrappedlibdl.c | 1 - src/wrapped32/wrappedlibdrm.c | 1 - src/wrapped32/wrappedlibegl.c | 1 - src/wrapped32/wrappedlibgl.c | 1 - src/wrapped32/wrappedlibglu.c | 1 - src/wrapped32/wrappedlibglx.c | 1 - src/wrapped32/wrappedlibglxnvidia.c | 1 - src/wrapped32/wrappedlibm.c | 1 - src/wrapped32/wrappedlibogg.c | 1 - src/wrapped32/wrappedlibpthread.c | 1 - src/wrapped32/wrappedlibresolv.c | 1 - src/wrapped32/wrappedlibrt.c | 1 - src/wrapped32/wrappedlibuuid.c | 1 - src/wrapped32/wrappedlibvdpau.c | 1 - src/wrapped32/wrappedlibvorbis.c | 1 - src/wrapped32/wrappedlibx11.c | 1 - src/wrapped32/wrappedlibx11xcb.c | 1 - src/wrapped32/wrappedlibxcb.c | 1 - src/wrapped32/wrappedlibxcbres.c | 1 - src/wrapped32/wrappedlibxcomposite.c | 1 - src/wrapped32/wrappedlibxcursor.c | 1 - src/wrapped32/wrappedlibxdamage.c | 1 - src/wrapped32/wrappedlibxext.c | 1 - src/wrapped32/wrappedlibxfixes.c | 1 - src/wrapped32/wrappedlibxi.c | 1 - src/wrapped32/wrappedlibxrandr.c | 1 - src/wrapped32/wrappedlibxrender.c | 1 - src/wrapped32/wrappedlibxss.c | 1 - src/wrapped32/wrappedlibxxf86vm.c | 1 - src/wrapped32/wrappedmount.c | 1 - src/wrapped32/wrappednsl.c | 1 - src/wrapped32/wrappednvml.c | 1 - src/wrapped32/wrappedopenal.c | 1 - src/wrapped32/wrappedpulsesimple.c | 1 - src/wrapped32/wrappedsdl1.c | 1 - src/wrapped32/wrappedsdl2.c | 1 - src/wrapped32/wrappedsdl2image.c | 1 - src/wrapped32/wrappedselinux.c | 1 - src/wrapped32/wrappedtcmallocminimal.c | 1 - src/wrapped32/wrappedudev0.c | 1 - src/wrapped32/wrappedudev1.c | 1 - src/wrapped32/wrappedxinerama.c | 1 - tests/test17.c | 2 +- tests/test30.c | 2 +- tests32/test17.c | 2 +- wrapperhelper/example-libc.h | 1 - 418 files changed, 323 insertions(+), 748 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d7128ffc0..c4f82ab5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -385,6 +385,8 @@ endif() set(BOX64_ROOT ${CMAKE_SOURCE_DIR}) add_definitions(-std=gnu11 -funwind-tables -fvisibility=hidden) +add_definitions(-D_GNU_SOURCE=1) +add_definitions(-D_FILE_OFFSET_BITS=64) if(USE_CCACHE) find_program(CCACHE_FOUND ccache) diff --git a/external/musl/sincos.c b/external/musl/sincos.c index c8d866ba9..5183e43c1 100644 --- a/external/musl/sincos.c +++ b/external/musl/sincos.c @@ -10,7 +10,6 @@ * ==================================================== */ -#define _GNU_SOURCE #include "libm.h" void __cdecl sincos(double x, double *sin, double *cos) diff --git a/src/box64context.c b/src/box64context.c index 751b301ba..0756ca8f9 100644 --- a/src/box64context.c +++ b/src/box64context.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/custommem.c b/src/custommem.c index ec388e587..ea291f530 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/custommmap.c b/src/custommmap.c index d5ff368e1..ddd2646b1 100644 --- a/src/custommmap.c +++ b/src/custommmap.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/dynarec/arm64/dynarec_arm64_functions.c b/src/dynarec/arm64/dynarec_arm64_functions.c index c8151c060..e61a44452 100644 --- a/src/dynarec/arm64/dynarec_arm64_functions.c +++ b/src/dynarec/arm64/dynarec_arm64_functions.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/dynarec/dynarec_native_functions.c b/src/dynarec/dynarec_native_functions.c index fa8c58d56..2a6a7f301 100644 --- a/src/dynarec/dynarec_native_functions.c +++ b/src/dynarec/dynarec_native_functions.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/dynarec/la64/dynarec_la64_functions.c b/src/dynarec/la64/dynarec_la64_functions.c index 8d3273f18..26a25d5d4 100644 --- a/src/dynarec/la64/dynarec_la64_functions.c +++ b/src/dynarec/la64/dynarec_la64_functions.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/dynarec/ppc64le/dynarec_ppc64le_functions.c b/src/dynarec/ppc64le/dynarec_ppc64le_functions.c index 62c466e14..15794c5d0 100644 --- a/src/dynarec/ppc64le/dynarec_ppc64le_functions.c +++ b/src/dynarec/ppc64le/dynarec_ppc64le_functions.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index c0aa7940c..a5ae005c7 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/elfs/elfhacks.c b/src/elfs/elfhacks.c index a7509023c..1817408bd 100644 --- a/src/elfs/elfhacks.c +++ b/src/elfs/elfhacks.c @@ -7,7 +7,6 @@ */ #ifndef _GNU_SOURCE -#define _GNU_SOURCE #endif #include diff --git a/src/elfs/elfhash.c b/src/elfs/elfhash.c index 71b817feb..e4fb7dc94 100644 --- a/src/elfs/elfhash.c +++ b/src/elfs/elfhash.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/elfs/elfhash32.c b/src/elfs/elfhash32.c index d742d874c..f27bc7145 100644 --- a/src/elfs/elfhash32.c +++ b/src/elfs/elfhash32.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 70906e5a2..255e06c21 100644 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -433,7 +432,7 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin) setProtection_elf((uintptr_t)p, asize, prot); head->multiblocks[n].p = p; if (file_read_size) { - fseeko64(head->file, head->multiblocks[n].offs, SEEK_SET); + fseeko(head->file, head->multiblocks[n].offs, SEEK_SET); if(fread((void*)head->multiblocks[n].paddr, file_read_size, 1, head->file)!=1) { printf_log(LOG_NONE, "Cannot read elf block (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)head->multiblocks[n].offs, head->multiblocks[n].asize, (box64_pagesize - 1), head->name); return 1; @@ -458,7 +457,7 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin) char* dest = (char*)(context->tlsdata+context->tlssize+head->tlsbase); printf_log(LOG_DEBUG, "Loading TLS block #%zu @%p (0x%zx/0x%zx)\n", i, dest, e->p_filesz, e->p_memsz); if(e->p_filesz) { - fseeko64(head->file, e->p_offset, SEEK_SET); + fseeko(head->file, e->p_offset, SEEK_SET); if(fread(dest, e->p_filesz, 1, head->file)!=1) { mutex_unlock(&context->mutex_tls); printf_log(LOG_NONE, "Fail to read PT_TLS part #%zu (size=%zd)\n", i, e->p_filesz); diff --git a/src/elfs/elfloader32.c b/src/elfs/elfloader32.c index 766393884..f5798e23e 100644 --- a/src/elfs/elfloader32.c +++ b/src/elfs/elfloader32.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -156,14 +155,14 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin void* image = NULL; if(!head->vaddr) { sz += head->align; - raw = mmap64(from_ptrv(offs), sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); + raw = mmap(from_ptrv(offs), sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); image = (void*)(((uintptr_t)raw+max_align)&~max_align); } else { if(from_ptr(head->vaddr)&(box64_pagesize-1)) { // load address is not page-aligned, round down and increase size uintptr_t aligned_addr = ALIGN_DOWN(from_ptr(head->vaddr)); size_t extra = from_ptr(head->vaddr) - aligned_addr; - raw = mmap64((void*)aligned_addr, sz + extra, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); + raw = mmap((void*)aligned_addr, sz + extra, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); if(raw != MAP_FAILED && (uintptr_t)raw == aligned_addr) { image = from_ptrv(head->vaddr); sz += extra; @@ -171,7 +170,7 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin image = raw; } } else { - image = raw = mmap64(from_ptrv(head->vaddr), sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); + image = raw = mmap(from_ptrv(head->vaddr), sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); } } if(image!=MAP_FAILED && !head->vaddr && image!=from_ptrv(offs)) { @@ -231,7 +230,7 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin try_mmap = 0; if(try_mmap) { printf_dump(log_level, "Mmaping 0x%lx(0x%lx) bytes @%p for Elf \"%s\"\n", head->multiblocks[n].size, head->multiblocks[n].asize, (void*)head->multiblocks[n].paddr, head->name); - void* p = mmap64( + void* p = mmap( (void*)head->multiblocks[n].paddr, head->multiblocks[n].size, prot, @@ -269,7 +268,7 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin file_map_addr += box64_pagesize; if(file_map_addr < head->multiblocks[n].paddr + e->p_filesz) { size_t file_map_delta = file_map_addr - paddr; - void* file_map = mmap64((void*)file_map_addr, file_size - file_map_delta, prot | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, head->fileno, file_offset + file_map_delta); + void* file_map = mmap((void*)file_map_addr, file_size - file_map_delta, prot | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, head->fileno, file_offset + file_map_delta); mapped_file = file_map == (void*)file_map_addr; if(mapped_file) { p = (void*)paddr; @@ -283,7 +282,7 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin } if (!mapped_file && !file_delta) { printf_dump(log_level, "Allocating 0x%zx (0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", asize, e->p_memsz, (void*)paddr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name); - p = mmap64((void*)paddr, asize, prot | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + p = mmap((void*)paddr, asize, prot | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); } else if (!mapped_file) { // difference in pagesize, so need to mmap only what needed to be... //check startint point @@ -299,7 +298,7 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin } if(new_size>0) { printf_dump(log_level, "Allocating 0x%zx (0x%zx/0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", ALIGN(new_size), paddr, e->p_memsz, (void*)new_addr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name); - p = mmap64( + p = mmap( (void*)new_addr, ALIGN(new_size), prot|PROT_WRITE, @@ -326,7 +325,7 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin setProtection_elf((uintptr_t)p, asize, prot); head->multiblocks[n].p = p; if (file_read_size) { - fseeko64(head->file, head->multiblocks[n].offs, SEEK_SET); + fseeko(head->file, head->multiblocks[n].offs, SEEK_SET); if(fread((void*)head->multiblocks[n].paddr, file_read_size, 1, head->file)!=1) { printf_log(LOG_NONE, "Cannot read elf block (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)head->multiblocks[n].offs, head->multiblocks[n].asize, (box64_pagesize - 1), head->name); return 1; @@ -351,7 +350,7 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin char* dest = (char*)(context->tlsdata+context->tlssize+head->tlsbase); printf_log(LOG_DEBUG, "Loading TLS block #%zu @%p (0x%zx/0x%zx)\n", i, dest, e->p_filesz, e->p_memsz); if(e->p_filesz) { - fseeko64(head->file, e->p_offset, SEEK_SET); + fseeko(head->file, e->p_offset, SEEK_SET); if(fread(dest, e->p_filesz, 1, head->file)!=1) { mutex_unlock(&context->mutex_tls); printf_log(LOG_NONE, "Fail to read PT_TLS part #%zu (size=%zd)\n", i, e->p_filesz); diff --git a/src/elfs/elfparser.c b/src/elfs/elfparser.c index 2d63cf4d4..116672283 100644 --- a/src/elfs/elfparser.c +++ b/src/elfs/elfparser.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -28,7 +27,7 @@ static int LoadSH(FILE *f, Elf64_Shdr *s, void** SH, const char* name, uint32_t printf_log(LOG_INFO, "Section Header \"%s\" (off=%ld, size=%ld) has size (not multiple of %ld)\n", name, s->sh_offset, s->sh_size, sizeof(Elf64_Sym)); } *SH = box_calloc(1, s->sh_size); - fseeko64(f, s->sh_offset ,SEEK_SET); + fseeko(f, s->sh_offset ,SEEK_SET); if(fread(*SH, s->sh_size, 1, f)!=1) { printf_log(LOG_INFO, "Cannot read Section Header \"%s\" (off=%ld, size=%ld)\n", name, s->sh_offset, s->sh_size); return -1; @@ -71,7 +70,7 @@ static void LoadProgramSection(FILE *f, elfheader_t* h, int size, uint32_t type, for (size_t i=0; inumPHEntries && !*what; ++i) { if(h->PHEntries._64[i].p_type == type) { *what = box_calloc(1, h->PHEntries._64[i].p_memsz); - fseeko64(f, h->PHEntries._64[i].p_offset ,SEEK_SET); + fseeko(f, h->PHEntries._64[i].p_offset ,SEEK_SET); if(fread(h->Dynamic._64, h->PHEntries._64[i].p_filesz, 1, f)!=1) { printf_log(LOG_INFO, "Cannot read Program Header %zd \"%s\" (off=%ld, size=%ld)\n", i, "PT_DYNAMIC", h->PHEntries._64[i].p_offset, h->PHEntries._64[i].p_filesz); box_free(*what); @@ -104,7 +103,7 @@ static void* LoadSubLoadSection(FILE *f, elfheader_t* h, uintptr_t offset, size_ size = end - start; } ret = box_calloc(1, size); - fseeko64(f, h->PHEntries._64[i].p_offset + offset - h->PHEntries._64[i].p_vaddr, SEEK_SET); + fseeko(f, h->PHEntries._64[i].p_offset + offset - h->PHEntries._64[i].p_vaddr, SEEK_SET); size_t to_read = size; if (size + offset - h->PHEntries._64[i].p_vaddr > h->PHEntries._64[i].p_filesz) to_read -= (size + offset - h->PHEntries._64[i].p_vaddr) - h->PHEntries._64[i].p_filesz; @@ -197,7 +196,7 @@ elfheader_t* ParseElfHeader64(FILE* f, const char* name, int exec) if(header.e_shentsize && !h->numSHEntries && header.e_shoff) { printf_dump(LOG_DEBUG, "Read number of Sections in 1st Section\n"); // read 1st section header and grab actual number from here - fseeko64(f, header.e_shoff, SEEK_SET); + fseeko(f, header.e_shoff, SEEK_SET); Elf64_Shdr section; if(fread(§ion, sizeof(Elf64_Shdr), 1, f)!=1) { box_free(h); @@ -210,7 +209,7 @@ elfheader_t* ParseElfHeader64(FILE* f, const char* name, int exec) // now read all section headers printf_dump(LOG_DEBUG, "Read %zu Section header\n", h->numSHEntries); h->SHEntries._64 = (Elf64_Shdr*)box_calloc(h->numSHEntries, sizeof(Elf64_Shdr)); - fseeko64(f, header.e_shoff ,SEEK_SET); + fseeko(f, header.e_shoff ,SEEK_SET); if(fread(h->SHEntries._64, sizeof(Elf64_Shdr), h->numSHEntries, f)!=h->numSHEntries) { FreeElfHeader(&h); printf_log(LOG_INFO, "Cannot read all Section Header\n"); @@ -226,7 +225,7 @@ elfheader_t* ParseElfHeader64(FILE* f, const char* name, int exec) printf_dump(LOG_DEBUG, "Read %zu Program header\n", h->numPHEntries); h->PHEntries._64 = (Elf64_Phdr*)box_calloc(h->numPHEntries, sizeof(Elf64_Phdr)); - fseeko64(f, header.e_phoff ,SEEK_SET); + fseeko(f, header.e_phoff ,SEEK_SET); if(fread(h->PHEntries._64, sizeof(Elf64_Phdr), h->numPHEntries, f)!=h->numPHEntries) { FreeElfHeader(&h); printf_log(LOG_INFO, "Cannot read all Program Header\n"); diff --git a/src/elfs/elfparser32.c b/src/elfs/elfparser32.c index a7901f960..b11d42acb 100755 --- a/src/elfs/elfparser32.c +++ b/src/elfs/elfparser32.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -26,7 +25,7 @@ static int LoadSH(FILE *f, Elf32_Shdr *s, void** SH, const char* name, uint32_t printf_log(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has size (not multiple of %ld)\n", name, s->sh_offset, s->sh_size, sizeof(Elf32_Sym)); } *SH = actual_calloc(1, s->sh_size); - fseeko64(f, s->sh_offset ,SEEK_SET); + fseeko(f, s->sh_offset ,SEEK_SET); if(fread(*SH, s->sh_size, 1, f)!=1) { printf_log(LOG_INFO, "Cannot read Section Header \"%s\" (off=%d, size=%d)\n", name, s->sh_offset, s->sh_size); return -1; @@ -128,7 +127,7 @@ elfheader_t* ParseElfHeader32(FILE* f, const char* name, int exec) if(h->numSHEntries == 0) { printf_log(LOG_DEBUG, "Read number of Sections in 1st Section\n"); // read 1st section header and grab actual number from here - fseeko64(f, header.e_shoff, SEEK_SET); + fseeko(f, header.e_shoff, SEEK_SET); Elf32_Shdr section; if(fread(§ion, sizeof(Elf32_Shdr), 1, f)!=1) { actual_free(h); @@ -140,7 +139,7 @@ elfheader_t* ParseElfHeader32(FILE* f, const char* name, int exec) // now read all section headers printf_log(LOG_DEBUG, "Read %d Section header\n", h->numSHEntries); h->SHEntries._32 = (Elf32_Shdr*)actual_calloc(h->numSHEntries, sizeof(Elf32_Shdr)); - fseeko64(f, header.e_shoff ,SEEK_SET); + fseeko(f, header.e_shoff ,SEEK_SET); if(fread(h->SHEntries._32, sizeof(Elf32_Shdr), h->numSHEntries, f)!=h->numSHEntries) { FreeElfHeader(&h); printf_log(LOG_INFO, "Cannot read all Section Header\n"); @@ -156,7 +155,7 @@ elfheader_t* ParseElfHeader32(FILE* f, const char* name, int exec) printf_log(LOG_DEBUG, "Read %d Program header\n", h->numPHEntries); h->PHEntries._32 = (Elf32_Phdr*)actual_calloc(h->numPHEntries, sizeof(Elf32_Phdr)); - fseeko64(f, header.e_phoff ,SEEK_SET); + fseeko(f, header.e_phoff ,SEEK_SET); if(fread(h->PHEntries._32, sizeof(Elf32_Phdr), h->numPHEntries, f)!=h->numPHEntries) { FreeElfHeader(&h); printf_log(LOG_INFO, "Cannot read all Program Header\n"); diff --git a/src/emu/x64int3.c b/src/emu/x64int3.c index c72aa714d..922800471 100644 --- a/src/emu/x64int3.c +++ b/src/emu/x64int3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/emu/x64run.c b/src/emu/x64run.c index 6079b3e50..6d18e0138 100644 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c index 5efea698a..1eb668e97 100644 --- a/src/emu/x64run0f.c +++ b/src/emu/x64run0f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -388,14 +387,14 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETEX8(0); GETGM; tmp64s = EX->f[1]; - if (tmp64s==(int32_t)tmp64s && !isnanf(EX->f[1])) + if (tmp64s==(int32_t)tmp64s && !isnan(EX->f[1])) GM->sd[1] = (int32_t)tmp64s; else { mxcsr_raise_invalid(emu); GM->sd[1] = INT32_MIN; } tmp64s = EX->f[0]; - if (tmp64s==(int32_t)tmp64s && !isnanf(EX->f[0])) + if (tmp64s==(int32_t)tmp64s && !isnan(EX->f[0])) GM->sd[0] = (int32_t)tmp64s; else { mxcsr_raise_invalid(emu); @@ -408,7 +407,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETEX8(0); GETGM; for(int i=1; i>=0; --i) { - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) tmp64s = INT32_MIN; else switch(emu->mxcsr.f.MXCSR_RC) { @@ -444,7 +443,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) nextop = F8; GETEX4(0); GETGX; - if(isnanf(GX->f[0]) || isnanf(EX->f[0])) { + if(isnan(GX->f[0]) || isnan(EX->f[0])) { SET_FLAG(F_ZF); SET_FLAG(F_PF); SET_FLAG(F_CF); } else if(isgreater(GX->f[0], EX->f[0])) { CLEAR_FLAG(F_ZF); CLEAR_FLAG(F_PF); CLEAR_FLAG(F_CF); @@ -855,13 +854,13 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(GX->f[i])) { + if(isnan(GX->f[i])) { GX->ud[i] |= 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] += EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } fesetround(oldround); @@ -873,13 +872,13 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(GX->f[i])) { + if(isnan(GX->f[i])) { GX->ud[i] |= 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] *= EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } fesetround(oldround); @@ -891,7 +890,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; #ifdef RV64 for(int i=1; i>=0; --i) { - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) GX->q[i] = ((uint64_t)(EX->ud[i] & 0x80000000) << 32) | ((uint64_t)(EX->ud[i] & 0x007fffff) << 29) | 0x7ff8000000000000ULL; @@ -921,13 +920,13 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(GX->f[i])) { + if(isnan(GX->f[i])) { GX->ud[i] |= 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] -= EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } fesetround(oldround); @@ -948,13 +947,13 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(GX->f[i])) { + if(isnan(GX->f[i])) { GX->ud[i] |= 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] /= EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } fesetround(oldround); diff --git a/src/emu/x64run66.c b/src/emu/x64run66.c index 25b94d21e..5018fd0e4 100644 --- a/src/emu/x64run66.c +++ b/src/emu/x64run66.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c index a6bb2f8e3..cfee100af 100644 --- a/src/emu/x64run660f.c +++ b/src/emu/x64run660f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -901,7 +900,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) fesetround(FE_TONEAREST); for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; else #endif @@ -912,7 +911,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) case ROUND_Down: for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; else #endif @@ -921,7 +920,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) case ROUND_Up: for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; else #endif @@ -930,7 +929,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) case ROUND_Chop: for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; else #endif @@ -996,7 +995,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) GETGX; tmp8u = F8; // ignoring bit 3 interupt thingy #ifdef RV64 - if(isnanf(EX->f[0])) { + if(isnan(EX->f[0])) { GX->ud[0] = EX->ud[0] | 0x00400000; break; } @@ -1462,7 +1461,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) GETEX(0); GETGX; for(int i=0; i<4; ++i) { - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) tmp64s = INT32_MIN; else switch(emu->mxcsr.f.MXCSR_RC) { diff --git a/src/emu/x64run66d9.c b/src/emu/x64run66d9.c index aee6f59ac..c4bf264c2 100644 --- a/src/emu/x64run66d9.c +++ b/src/emu/x64run66d9.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64run66dd.c b/src/emu/x64run66dd.c index 19614b1f1..d50f29bb2 100644 --- a/src/emu/x64run66dd.c +++ b/src/emu/x64run66dd.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64run66f0.c b/src/emu/x64run66f0.c index f39ec0cee..842c568e1 100644 --- a/src/emu/x64run66f0.c +++ b/src/emu/x64run66f0.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64run66f20f.c b/src/emu/x64run66f20f.c index b263302ee..0b39668aa 100644 --- a/src/emu/x64run66f20f.c +++ b/src/emu/x64run66f20f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64run66f30f.c b/src/emu/x64run66f30f.c index bd6d3d33e..abd2d7baf 100644 --- a/src/emu/x64run66f30f.c +++ b/src/emu/x64run66f30f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index f7748992c..6e8c41636 100644 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/emu/x64runavx.c b/src/emu/x64runavx.c index 36ac7031a..daed5d04f 100644 --- a/src/emu/x64runavx.c +++ b/src/emu/x64runavx.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runavx0f.c b/src/emu/x64runavx0f.c index 11a86ac53..b6a973e1b 100644 --- a/src/emu/x64runavx0f.c +++ b/src/emu/x64runavx0f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -399,26 +398,26 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETGY; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(VX->f[i])) { + if(isnan(VX->f[i])) { GX->ud[i] = VX->ud[i] | 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] = VX->f[i] + EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } if(vex.l) { GETEY; GETVY; for(int i=0; i<4; ++i) { - if(isnanf(VY->f[i])) { + if(isnan(VY->f[i])) { GY->ud[i] = VY->ud[i] | 0x00400000; - } else if(isnanf(EY->f[i])) { + } else if(isnan(EY->f[i])) { GY->ud[i] = EY->ud[i] | 0x00400000; } else { GY->f[i] = VY->f[i] + EY->f[i]; - if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; + if(isnan(GY->f[i])) GY->ud[i] |= 0x80000000; } } } else @@ -434,26 +433,26 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETGY; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(VX->f[i])) { + if(isnan(VX->f[i])) { GX->ud[i] = VX->ud[i] | 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] = VX->f[i] * EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } if(vex.l) { GETEY; GETVY; for(int i=0; i<4; ++i) { - if(isnanf(VY->f[i])) { + if(isnan(VY->f[i])) { GY->ud[i] = VY->ud[i] | 0x00400000; - } else if(isnanf(EY->f[i])) { + } else if(isnan(EY->f[i])) { GY->ud[i] = EY->ud[i] | 0x00400000; } else { GY->f[i] = VY->f[i] * EY->f[i]; - if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; + if(isnan(GY->f[i])) GY->ud[i] |= 0x80000000; } } } else @@ -469,7 +468,7 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) if (vex.l) { #ifdef RV64 for (int i = 1; i >= 0; --i) { - if (isnanf(EX->f[i + 2])) + if (isnan(EX->f[i + 2])) GY->q[i] = ((uint64_t)(EX->ud[i + 2] & 0x80000000) << 32) | ((uint64_t)(EX->ud[i + 2] & 0x007fffff) << 29) | 0x7ff8000000000000ULL; @@ -484,7 +483,7 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GY->u128 = 0; #ifdef RV64 for (int i = 1; i >= 0; --i) { - if (isnanf(EX->f[i])) + if (isnan(EX->f[i])) GX->q[i] = ((uint64_t)(EX->ud[i] & 0x80000000) << 32) | ((uint64_t)(EX->ud[i] & 0x007fffff) << 29) | 0x7ff8000000000000ULL; @@ -526,26 +525,26 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETGY; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(VX->f[i])) { + if(isnan(VX->f[i])) { GX->ud[i] = VX->ud[i] | 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] = VX->f[i] - EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } if(vex.l) { GETEY; GETVY; for(int i=0; i<4; ++i) { - if(isnanf(VY->f[i])) { + if(isnan(VY->f[i])) { GY->ud[i] = VY->ud[i] | 0x00400000; - } else if(isnanf(EY->f[i])) { + } else if(isnan(EY->f[i])) { GY->ud[i] = EY->ud[i] | 0x00400000; } else { GY->f[i] = VY->f[i] - EY->f[i]; - if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; + if(isnan(GY->f[i])) GY->ud[i] |= 0x80000000; } } } else @@ -560,7 +559,7 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETVX; GETGY; for(int i=0; i<4; ++i) - if (isnanf(VX->f[i]) || isnanf(EX->f[i]) || islessequal(EX->f[i], VX->f[i])) + if (isnan(VX->f[i]) || isnan(EX->f[i]) || islessequal(EX->f[i], VX->f[i])) GX->f[i] = EX->f[i]; else GX->f[i] = VX->f[i]; @@ -568,7 +567,7 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETEY; GETVY; for(int i=0; i<4; ++i) - if (isnanf(VY->f[i]) || isnanf(EY->f[i]) || islessequal(EY->f[i], VY->f[i])) + if (isnan(VY->f[i]) || isnan(EY->f[i]) || islessequal(EY->f[i], VY->f[i])) GY->f[i] = EY->f[i]; else GY->f[i] = VY->f[i]; @@ -583,26 +582,26 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETGY; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(VX->f[i])) { + if(isnan(VX->f[i])) { GX->ud[i] = VX->ud[i] | 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] = VX->f[i] / EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } if(vex.l) { GETEY; GETVY; for(int i=0; i<4; ++i) { - if(isnanf(VY->f[i])) { + if(isnan(VY->f[i])) { GY->ud[i] = VY->ud[i] | 0x00400000; - } else if(isnanf(EY->f[i])) { + } else if(isnan(EY->f[i])) { GY->ud[i] = EY->ud[i] | 0x00400000; } else { GY->f[i] = VY->f[i] / EY->f[i]; - if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; + if(isnan(GY->f[i])) GY->ud[i] |= 0x80000000; } } } else @@ -617,7 +616,7 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETVX; GETGY; for(int i=0; i<4; ++i) - if (isnanf(VX->f[i]) || isnanf(EX->f[i]) || isgreaterequal(EX->f[i], VX->f[i])) + if (isnan(VX->f[i]) || isnan(EX->f[i]) || isgreaterequal(EX->f[i], VX->f[i])) GX->f[i] = EX->f[i]; else GX->f[i] = VX->f[i]; @@ -625,7 +624,7 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETEY; GETVY; for(int i=0; i<4; ++i) - if (isnanf(VY->f[i]) || isnanf(EY->f[i]) || isgreaterequal(EY->f[i], VY->f[i])) + if (isnan(VY->f[i]) || isnan(EY->f[i]) || isgreaterequal(EY->f[i], VY->f[i])) GY->f[i] = EY->f[i]; else GY->f[i] = VY->f[i]; diff --git a/src/emu/x64runavx0f38.c b/src/emu/x64runavx0f38.c index bae5b3208..137432ef5 100644 --- a/src/emu/x64runavx0f38.c +++ b/src/emu/x64runavx0f38.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runavx660f.c b/src/emu/x64runavx660f.c index 9123f7945..9ab9be574 100644 --- a/src/emu/x64runavx660f.c +++ b/src/emu/x64runavx660f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -440,7 +439,7 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETGX; GETGY; for(int i=0; i<4; ++i) { - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) tmp64s = INT32_MIN; else switch(emu->mxcsr.f.MXCSR_RC) { @@ -471,7 +470,7 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) if(vex.l) { GETEY; for(int i=0; i<4; ++i) { - if(isnanf(EY->f[i])) + if(isnan(EY->f[i])) tmp64s = INT32_MIN; else switch(emu->mxcsr.f.MXCSR_RC) { diff --git a/src/emu/x64runavx660f38.c b/src/emu/x64runavx660f38.c index eeeb59238..bc19c0f63 100644 --- a/src/emu/x64runavx660f38.c +++ b/src/emu/x64runavx660f38.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runavx660f3a.c b/src/emu/x64runavx660f3a.c index ea78c745a..eb7d74311 100644 --- a/src/emu/x64runavx660f3a.c +++ b/src/emu/x64runavx660f3a.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -191,7 +190,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) fesetround(FE_TONEAREST); for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; else #endif @@ -202,7 +201,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) case ROUND_Down: for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; else #endif @@ -211,7 +210,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) case ROUND_Up: for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; else #endif @@ -220,7 +219,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) case ROUND_Chop: for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; else #endif @@ -235,7 +234,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) fesetround(FE_TONEAREST); for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EY->f[i])) + if(isnan(EY->f[i])) GY->ud[i] = EY->ud[i] | 0x00400000; else #endif @@ -246,7 +245,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) case ROUND_Down: for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EY->f[i])) + if(isnan(EY->f[i])) GY->ud[i] = EY->ud[i] | 0x00400000; else #endif @@ -255,7 +254,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) case ROUND_Up: for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EY->f[i])) + if(isnan(EY->f[i])) GY->ud[i] = EY->ud[i] | 0x00400000; else #endif @@ -264,7 +263,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) case ROUND_Chop: for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EY->f[i])) + if(isnan(EY->f[i])) GY->ud[i] = EY->ud[i] | 0x00400000; else #endif @@ -378,7 +377,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETGX; GETVX; GETGY; tmp8u = F8; // ignoring bit 3 interupt thingy #ifdef RV64 - if(isnanf(EX->f[0])) { + if(isnan(EX->f[0])) { GX->ud[0] = EX->ud[0] | 0x00400000; } else #endif diff --git a/src/emu/x64runavxf20f.c b/src/emu/x64runavxf20f.c index 5b63d208d..7a73caee6 100644 --- a/src/emu/x64runavxf20f.c +++ b/src/emu/x64runavxf20f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -368,9 +367,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) int oldround = mxcsr_setround(emu); for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(VX->f[j])) GX->ud[i] = VX->ud[j] | 0x00400000; - else if(isnanf(VX->f[j+1])) GX->ud[i] = VX->ud[j+1] | 0x00400000; - else { GX->f[i] = VX->f[j] + VX->f[j+1]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; } + if(isnan(VX->f[j])) GX->ud[i] = VX->ud[j] | 0x00400000; + else if(isnan(VX->f[j+1])) GX->ud[i] = VX->ud[j+1] | 0x00400000; + else { GX->f[i] = VX->f[j] + VX->f[j+1]; if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } if(EX==VX) { GX->ud[2] = GX->ud[0]; @@ -378,17 +377,17 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) } else { for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(EX->f[j])) GX->ud[i+2] = EX->ud[j] | 0x00400000; - else if(isnanf(EX->f[j+1])) GX->ud[i+2] = EX->ud[j+1] | 0x00400000; - else { GX->f[i+2] = EX->f[j] + EX->f[j+1]; if(isnanf(GX->f[i+2])) GX->ud[i+2] |= 0x80000000; } + if(isnan(EX->f[j])) GX->ud[i+2] = EX->ud[j] | 0x00400000; + else if(isnan(EX->f[j+1])) GX->ud[i+2] = EX->ud[j+1] | 0x00400000; + else { GX->f[i+2] = EX->f[j] + EX->f[j+1]; if(isnan(GX->f[i+2])) GX->ud[i+2] |= 0x80000000; } } } if(vex.l) { for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(VY->f[j])) GY->ud[i] = VY->ud[j] | 0x00400000; - else if(isnanf(VY->f[j+1])) GY->ud[i] = VY->ud[j+1] | 0x00400000; - else { GY->f[i] = VY->f[j] + VY->f[j+1]; if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; } + if(isnan(VY->f[j])) GY->ud[i] = VY->ud[j] | 0x00400000; + else if(isnan(VY->f[j+1])) GY->ud[i] = VY->ud[j+1] | 0x00400000; + else { GY->f[i] = VY->f[j] + VY->f[j+1]; if(isnan(GY->f[i])) GY->ud[i] |= 0x80000000; } } if(EY==VY) { GY->ud[2] = GY->ud[0]; @@ -396,9 +395,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) } else { for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(EY->f[j])) GY->ud[i+2] = EY->ud[j] | 0x00400000; - else if(isnanf(EY->f[j+1])) GY->ud[i+2] = EY->ud[j+1] | 0x00400000; - else { GY->f[i+2] = EY->f[j] + EY->f[j+1]; if(isnanf(GY->f[i+2])) GY->ud[i+2] |= 0x80000000; } + if(isnan(EY->f[j])) GY->ud[i+2] = EY->ud[j] | 0x00400000; + else if(isnan(EY->f[j+1])) GY->ud[i+2] = EY->ud[j+1] | 0x00400000; + else { GY->f[i+2] = EY->f[j] + EY->f[j+1]; if(isnan(GY->f[i+2])) GY->ud[i+2] |= 0x80000000; } } } } else @@ -426,9 +425,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) int oldround = mxcsr_setround(emu); for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(VX->f[j])) GX->ud[i] = VX->ud[j] | 0x00400000; - else if(isnanf(VX->f[j+1])) GX->ud[i] = VX->ud[j+1] | 0x00400000; - else { GX->f[i] = VX->f[j] - VX->f[j+1]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; } + if(isnan(VX->f[j])) GX->ud[i] = VX->ud[j] | 0x00400000; + else if(isnan(VX->f[j+1])) GX->ud[i] = VX->ud[j+1] | 0x00400000; + else { GX->f[i] = VX->f[j] - VX->f[j+1]; if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } if (EX == VX) { GX->ud[2] = GX->ud[0]; @@ -436,17 +435,17 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) } else { for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(EX->f[j])) GX->ud[i+2] = EX->ud[j] | 0x00400000; - else if(isnanf(EX->f[j+1])) GX->ud[i+2] = EX->ud[j+1] | 0x00400000; - else { GX->f[i+2] = EX->f[j] - EX->f[j+1]; if(isnanf(GX->f[i+2])) GX->ud[i+2] |= 0x80000000; } + if(isnan(EX->f[j])) GX->ud[i+2] = EX->ud[j] | 0x00400000; + else if(isnan(EX->f[j+1])) GX->ud[i+2] = EX->ud[j+1] | 0x00400000; + else { GX->f[i+2] = EX->f[j] - EX->f[j+1]; if(isnan(GX->f[i+2])) GX->ud[i+2] |= 0x80000000; } } } if (vex.l) { for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(VY->f[j])) GY->ud[i] = VY->ud[j] | 0x00400000; - else if(isnanf(VY->f[j+1])) GY->ud[i] = VY->ud[j+1] | 0x00400000; - else { GY->f[i] = VY->f[j] - VY->f[j+1]; if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; } + if(isnan(VY->f[j])) GY->ud[i] = VY->ud[j] | 0x00400000; + else if(isnan(VY->f[j+1])) GY->ud[i] = VY->ud[j+1] | 0x00400000; + else { GY->f[i] = VY->f[j] - VY->f[j+1]; if(isnan(GY->f[i])) GY->ud[i] |= 0x80000000; } } if (EY == VY) { GY->ud[2] = GY->ud[0]; @@ -454,9 +453,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) } else { for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(EY->f[j])) GY->ud[i+2] = EY->ud[j] | 0x00400000; - else if(isnanf(EY->f[j+1])) GY->ud[i+2] = EY->ud[j+1] | 0x00400000; - else { GY->f[i+2] = EY->f[j] - EY->f[j+1]; if(isnanf(GY->f[i+2])) GY->ud[i+2] |= 0x80000000; } + if(isnan(EY->f[j])) GY->ud[i+2] = EY->ud[j] | 0x00400000; + else if(isnan(EY->f[j+1])) GY->ud[i+2] = EY->ud[j+1] | 0x00400000; + else { GY->f[i+2] = EY->f[j] - EY->f[j+1]; if(isnan(GY->f[i+2])) GY->ud[i+2] |= 0x80000000; } } } } else @@ -509,15 +508,15 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) } int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(VX->f[i])) { GX->ud[i] = VX->ud[i] | 0x00400000; } - else if(isnanf(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } - else { if(i&1) GX->f[i] = VX->f[i] + EX->f[i]; else GX->f[i] = VX->f[i] - EX->f[i]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; } + if(isnan(VX->f[i])) { GX->ud[i] = VX->ud[i] | 0x00400000; } + else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } + else { if(i&1) GX->f[i] = VX->f[i] + EX->f[i]; else GX->f[i] = VX->f[i] - EX->f[i]; if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } if(vex.l) { for(int i=0; i<4; ++i) { - if(isnanf(VY->f[i])) { GY->ud[i] = VY->ud[i] | 0x00400000; } - else if(isnanf(EY->f[i])) { GY->ud[i] = EY->ud[i] | 0x00400000; } - else { if(i&1) GY->f[i] = VY->f[i] + EY->f[i]; else GY->f[i] = VY->f[i] - EY->f[i]; if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; } + if(isnan(VY->f[i])) { GY->ud[i] = VY->ud[i] | 0x00400000; } + else if(isnan(EY->f[i])) { GY->ud[i] = EY->ud[i] | 0x00400000; } + else { if(i&1) GY->f[i] = VY->f[i] + EY->f[i]; else GY->f[i] = VY->f[i] - EY->f[i]; if(isnan(GY->f[i])) GY->ud[i] |= 0x80000000; } } } else GY->u128 = 0; diff --git a/src/emu/x64runavxf20f38.c b/src/emu/x64runavxf20f38.c index 4a8d9a923..23ff84df3 100644 --- a/src/emu/x64runavxf20f38.c +++ b/src/emu/x64runavxf20f38.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runavxf20f3a.c b/src/emu/x64runavxf20f3a.c index e53c8fb71..720ab7e7d 100644 --- a/src/emu/x64runavxf20f3a.c +++ b/src/emu/x64runavxf20f3a.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runavxf30f.c b/src/emu/x64runavxf30f.c index f7bad00f1..ca4fd014b 100644 --- a/src/emu/x64runavxf30f.c +++ b/src/emu/x64runavxf30f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -140,13 +139,13 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETEX(0); GETGD; if (rex.w) { - if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { + if(isnan(EX->f[0]) || isinf(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { mxcsr_raise_invalid(emu); GD->q[0] = 0x8000000000000000LL; } else GD->sq[0] = EX->f[0]; } else { - if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x7fffffff) { + if(isnan(EX->f[0]) || isinf(EX->f[0]) || EX->f[0]>=(float)0x7fffffff) { mxcsr_raise_invalid(emu); GD->dword[0] = 0x80000000; } else @@ -159,7 +158,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETEX(0); GETGD; if(rex.w) { - if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { + if(isnan(EX->f[0]) || isinf(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { mxcsr_raise_invalid(emu); GD->q[0] = 0x8000000000000000LL; } else @@ -182,7 +181,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; } } else { - if(isnanf(EX->f[0])) + if(isnan(EX->f[0])) tmp64s = INT32_MIN; else switch(emu->mxcsr.f.MXCSR_RC) { @@ -220,7 +219,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) int oldround = mxcsr_setround(emu); if(EX->f[0]<0.0 ) GX->f[0] = -NAN; - else if(isnanf(EX->f[0])) + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; else GX->f[0] = sqrt(EX->f[0]); @@ -271,9 +270,9 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETVX; GETGY; int oldround = mxcsr_setround(emu); - if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; - else { GX->f[0] = VX->f[0] + EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + else { GX->f[0] = VX->f[0] + EX->f[0]; if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } if(GX!=VX) { GX->ud[1] = VX->ud[1]; GX->q[1] = VX->q[1]; @@ -289,9 +288,9 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETVX; GETGY; int oldround = mxcsr_setround(emu); - if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; - else { GX->f[0] = VX->f[0] * EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + else { GX->f[0] = VX->f[0] * EX->f[0]; if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } if(GX!=VX) { GX->ud[1] = VX->ud[1]; GX->q[1] = VX->q[1]; @@ -307,7 +306,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETVX; GETGY; #ifdef RV64 - if(isnanf(EX->f[0])) + if(isnan(EX->f[0])) GX->q[0] = ((uint64_t)(EX->ud[0] & 0x80000000) << 32) | ((uint64_t)(EX->ud[0] & 0x007fffff) << 29) | 0x7ff8000000000000ULL; @@ -325,7 +324,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETGX; GETGY; for(int i=0; i<4; ++i) { - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) tmp64s = INT32_MIN; else tmp64s = EX->f[i]; @@ -339,7 +338,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) if(vex.l) { GETEY; for(int i=0; i<4; ++i) { - if(isnanf(EY->f[i])) + if(isnan(EY->f[i])) tmp64s = INT32_MIN; else tmp64s = EY->f[i]; @@ -360,9 +359,9 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETVX; GETGY; int oldround = mxcsr_setround(emu); - if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; - else { GX->f[0] = VX->f[0] - EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + else { GX->f[0] = VX->f[0] - EX->f[0]; if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } if(GX!=VX) { GX->ud[1] = VX->ud[1]; GX->q[1] = VX->q[1]; @@ -395,9 +394,9 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETVX; GETGY; int oldround = mxcsr_setround(emu); - if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; - else { GX->f[0] = VX->f[0] / EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + else { GX->f[0] = VX->f[0] / EX->f[0]; if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } if(GX!=VX) { GX->ud[1] = VX->ud[1]; GX->q[1] = VX->q[1]; diff --git a/src/emu/x64runavxf30f38.c b/src/emu/x64runavxf30f38.c index cd15c5aae..3084606a2 100644 --- a/src/emu/x64runavxf30f38.c +++ b/src/emu/x64runavxf30f38.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runavxf30f3a.c b/src/emu/x64runavxf30f3a.c index c67fcd9b8..caacf91c0 100644 --- a/src/emu/x64runavxf30f3a.c +++ b/src/emu/x64runavxf30f3a.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64rund8.c b/src/emu/x64rund8.c index eec0a27e5..092ca2863 100644 --- a/src/emu/x64rund8.c +++ b/src/emu/x64rund8.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64rund9.c b/src/emu/x64rund9.c index f92592235..ef652ee70 100644 --- a/src/emu/x64rund9.c +++ b/src/emu/x64rund9.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runda.c b/src/emu/x64runda.c index 0c4b869ac..c9e0b520f 100644 --- a/src/emu/x64runda.c +++ b/src/emu/x64runda.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64rundb.c b/src/emu/x64rundb.c index 256129fc4..0998a035a 100644 --- a/src/emu/x64rundb.c +++ b/src/emu/x64rundb.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64rundc.c b/src/emu/x64rundc.c index f42bc67b3..56447e83b 100644 --- a/src/emu/x64rundc.c +++ b/src/emu/x64rundc.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64rundd.c b/src/emu/x64rundd.c index 059e239c6..acd9c2898 100644 --- a/src/emu/x64rundd.c +++ b/src/emu/x64rundd.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runde.c b/src/emu/x64runde.c index 2ff42e124..5f0bbb31a 100644 --- a/src/emu/x64runde.c +++ b/src/emu/x64runde.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64rundf.c b/src/emu/x64rundf.c index 092dd6af9..9bb19df71 100644 --- a/src/emu/x64rundf.c +++ b/src/emu/x64rundf.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runf0.c b/src/emu/x64runf0.c index 218ad3e9f..05b10c371 100644 --- a/src/emu/x64runf0.c +++ b/src/emu/x64runf0.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runf20f.c b/src/emu/x64runf20f.c index 543e98487..af15a4825 100644 --- a/src/emu/x64runf20f.c +++ b/src/emu/x64runf20f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -373,40 +372,40 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; int oldround = mxcsr_setround(emu); eax1 = *GX; - if(isnanf(eax1.f[0])) { + if(isnan(eax1.f[0])) { GX->ud[0] = eax1.ud[0] | 0x00400000; - } else if(isnanf(eax1.f[1])) { + } else if(isnan(eax1.f[1])) { GX->ud[0] = eax1.ud[1] | 0x00400000; } else { GX->f[0] = eax1.f[0] + eax1.f[1]; - if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; + if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } - if(isnanf(eax1.f[2])) { + if(isnan(eax1.f[2])) { GX->ud[1] = eax1.ud[2] | 0x00400000; - } else if(isnanf(eax1.f[3])) { + } else if(isnan(eax1.f[3])) { GX->ud[1] = eax1.ud[3] | 0x00400000; } else { GX->f[1] = eax1.f[2] + eax1.f[3]; - if(isnanf(GX->f[1])) GX->ud[1] |= 0x80000000; + if(isnan(GX->f[1])) GX->ud[1] |= 0x80000000; } if(EX==GX) { GX->q[1] = GX->q[0]; } else { - if(isnanf(EX->f[0])) { + if(isnan(EX->f[0])) { GX->ud[2] = EX->ud[0] | 0x00400000; - } else if(isnanf(EX->f[1])) { + } else if(isnan(EX->f[1])) { GX->ud[2] = EX->ud[1] | 0x00400000; } else { GX->f[2] = EX->f[0] + EX->f[1]; - if(isnanf(GX->f[2])) GX->ud[2] |= 0x80000000; + if(isnan(GX->f[2])) GX->ud[2] |= 0x80000000; } - if(isnanf(EX->f[2])) { + if(isnan(EX->f[2])) { GX->ud[3] = EX->ud[2] | 0x00400000; - } else if(isnanf(EX->f[3])) { + } else if(isnan(EX->f[3])) { GX->ud[3] = EX->ud[3] | 0x00400000; } else { GX->f[3] = EX->f[2] + EX->f[3]; - if(isnanf(GX->f[3])) GX->ud[3] |= 0x80000000; + if(isnan(GX->f[3])) GX->ud[3] |= 0x80000000; } } fesetround(oldround); @@ -418,40 +417,40 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; int oldround = mxcsr_setround(emu); eax1 = *GX; - if(isnanf(eax1.f[0])) { + if(isnan(eax1.f[0])) { GX->ud[0] = eax1.ud[0] | 0x00400000; - } else if(isnanf(eax1.f[1])) { + } else if(isnan(eax1.f[1])) { GX->ud[0] = eax1.ud[1] | 0x00400000; } else { GX->f[0] = eax1.f[0] - eax1.f[1]; - if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; + if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } - if(isnanf(eax1.f[2])) { + if(isnan(eax1.f[2])) { GX->ud[1] = eax1.ud[2] | 0x00400000; - } else if(isnanf(eax1.f[3])) { + } else if(isnan(eax1.f[3])) { GX->ud[1] = eax1.ud[3] | 0x00400000; } else { GX->f[1] = eax1.f[2] - eax1.f[3]; - if(isnanf(GX->f[1])) GX->ud[1] |= 0x80000000; + if(isnan(GX->f[1])) GX->ud[1] |= 0x80000000; } if(EX==GX) { GX->q[1] = GX->q[0]; } else { - if(isnanf(EX->f[0])) { + if(isnan(EX->f[0])) { GX->ud[2] = EX->ud[0] | 0x00400000; - } else if(isnanf(EX->f[1])) { + } else if(isnan(EX->f[1])) { GX->ud[2] = EX->ud[1] | 0x00400000; } else { GX->f[2] = EX->f[0] - EX->f[1]; - if(isnanf(GX->f[2])) GX->ud[2] |= 0x80000000; + if(isnan(GX->f[2])) GX->ud[2] |= 0x80000000; } - if(isnanf(EX->f[2])) { + if(isnan(EX->f[2])) { GX->ud[3] = EX->ud[2] | 0x00400000; - } else if(isnanf(EX->f[3])) { + } else if(isnan(EX->f[3])) { GX->ud[3] = EX->ud[3] | 0x00400000; } else { GX->f[3] = EX->f[2] - EX->f[3]; - if(isnanf(GX->f[3])) GX->ud[3] |= 0x80000000; + if(isnan(GX->f[3])) GX->ud[3] |= 0x80000000; } } fesetround(oldround); @@ -511,9 +510,9 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(GX->f[i])) GX->ud[i] |= 0x00400000; - else if(isnanf(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; - else { if(i&1) GX->f[i] += EX->f[i]; else GX->f[i] -= EX->f[i]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; } + if(isnan(GX->f[i])) GX->ud[i] |= 0x00400000; + else if(isnan(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; + else { if(i&1) GX->f[i] += EX->f[i]; else GX->f[i] -= EX->f[i]; if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } fesetround(oldround); } diff --git a/src/emu/x64runf30f.c b/src/emu/x64runf30f.c index cc678f853..b049711b6 100644 --- a/src/emu/x64runf30f.c +++ b/src/emu/x64runf30f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -112,13 +111,13 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) GETEX4(0); GETGD; if (rex.w) { - if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { + if(isnan(EX->f[0]) || isinf(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { mxcsr_raise_invalid(emu); GD->q[0] = 0x8000000000000000LL; } else GD->sq[0] = EX->f[0]; } else { - if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x7fffffff) { + if(isnan(EX->f[0]) || isinf(EX->f[0]) || EX->f[0]>=(float)0x7fffffff) { mxcsr_raise_invalid(emu); GD->dword[0] = 0x80000000; } else @@ -131,7 +130,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) GETEX4(0); GETGD; if(rex.w) { - if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { + if(isnan(EX->f[0]) || isinf(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { mxcsr_raise_invalid(emu); GD->q[0] = 0x8000000000000000LL; } else @@ -154,7 +153,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) break; } } else { - if(isnanf(EX->f[0])) + if(isnan(EX->f[0])) tmp64s = INT32_MIN; else switch(emu->mxcsr.f.MXCSR_RC) { @@ -236,7 +235,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) GETGX; if (EX->f[0]<0) GX->f[0] = -NAN; - else if (isnanf(EX->f[0])) + else if (isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; else{ int oldround = mxcsr_setround(emu); @@ -263,22 +262,22 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) nextop = F8; GETEX(0); GETGX; - if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; - else { GX->f[0] = 1.0f/EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + else { GX->f[0] = 1.0f/EX->f[0]; if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } break; case 0x58: /* ADDSS Gx, Ex */ nextop = F8; GETEX(0); GETGX; - if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + if(isnan(GX->f[0])) GX->ud[0] |= 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; else { int oldround = mxcsr_setround(emu); GX->f[0] += EX->f[0]; fesetround(oldround); - if(isnanf(GX->f[0])) + if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } break; @@ -286,20 +285,20 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) nextop = F8; GETEX4(0); GETGX; - if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + if(isnan(GX->f[0])) GX->ud[0] |= 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; else { int oldround = mxcsr_setround(emu); GX->f[0] *= EX->f[0]; fesetround(oldround); - if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } break; case 0x5A: /* CVTSS2SD Gx, Ex */ nextop = F8; GETEX4(0); GETGX; #ifdef RV64 - if(isnanf(EX->f[0])) + if(isnan(EX->f[0])) GX->q[0] = ((uint64_t)(EX->ud[0] & 0x80000000) << 32) | ((uint64_t)(EX->ud[0] & 0x007fffff) << 29) | 0x7ff8000000000000ULL; @@ -314,7 +313,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) GETEX(0); GETGX; for(int i=0; i<4; ++i) { - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) tmp64s = INT32_MIN; else tmp64s = EX->f[i]; @@ -330,13 +329,13 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) nextop = F8; GETEX4(0); GETGX; - if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + if(isnan(GX->f[0])) GX->ud[0] |= 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; else { int oldround = mxcsr_setround(emu); GX->f[0] -= EX->f[0]; fesetround(oldround); - if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } break; case 0x5D: /* MINSS Gx, Ex */ nextop = F8; @@ -349,13 +348,13 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) nextop = F8; GETEX4(0); GETGX; - if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + if(isnan(GX->f[0])) GX->ud[0] |= 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; else { int oldround = mxcsr_setround(emu); GX->f[0] /= EX->f[0]; fesetround(oldround); - if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } break; case 0x5F: /* MAXSS Gx, Ex */ nextop = F8; diff --git a/src/emu/x64syscall.c b/src/emu/x64syscall.c index e5f29a7bc..5c0f54a7b 100644 --- a/src/emu/x64syscall.c +++ b/src/emu/x64syscall.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include @@ -431,8 +430,8 @@ typedef struct x86_linux_dirent_s { } x86_linux_dirent_t; typedef struct nat_linux_dirent64_s { - ino64_t d_ino; - off64_t d_off; + ino_t d_ino; + off_t d_off; unsigned short d_reclen; unsigned char d_type; char d_name[]; diff --git a/src/emu/x64test.c b/src/emu/x64test.c index 36a04c380..259d43424 100644 --- a/src/emu/x64test.c +++ b/src/emu/x64test.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x86int3.c b/src/emu/x86int3.c index 8bd32a73f..4e86ff038 100755 --- a/src/emu/x86int3.c +++ b/src/emu/x86int3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/emu/x86syscall.c b/src/emu/x86syscall.c index 7e831b423..267259246 100755 --- a/src/emu/x86syscall.c +++ b/src/emu/x86syscall.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/emu/x86syscall_32.c b/src/emu/x86syscall_32.c index edac2ae4d..e0ab78bd9 100644 --- a/src/emu/x86syscall_32.c +++ b/src/emu/x86syscall_32.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/include/os.h b/src/include/os.h index e2f8d50c3..f66400db3 100644 --- a/src/include/os.h +++ b/src/include/os.h @@ -98,14 +98,6 @@ const char* GetBridgeName(void* p); #define PROT_WRITE 0x2 #define PROT_EXEC 0x4 -#if defined(__clang__) && !defined(_WIN32) -extern int isinff(float); -extern int isnanf(float); -#elif defined(_WIN32) -#define isnanf isnan -#define isinff isinf -#endif - void PrintfFtrace(int prefix, const char* fmt, ...); void* GetEnv(const char* name); diff --git a/src/librarian/globalsymbols.c b/src/librarian/globalsymbols.c index c328ad061..42c904770 100644 --- a/src/librarian/globalsymbols.c +++ b/src/librarian/globalsymbols.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/librarian/globalsymbols32.c b/src/librarian/globalsymbols32.c index 4d565fcfd..5264c59f0 100644 --- a/src/librarian/globalsymbols32.c +++ b/src/librarian/globalsymbols32.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/librarian/library.c b/src/librarian/library.c index 45a8f907b..8aa9ad605 100644 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #define __USE_GNU #include #include diff --git a/src/libtools/libc_net32.c b/src/libtools/libc_net32.c index e2017ce40..aac38a317 100644 --- a/src/libtools/libc_net32.c +++ b/src/libtools/libc_net32.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/libtools/libdl.c b/src/libtools/libdl.c index fe8062130..c4c8147be 100644 --- a/src/libtools/libdl.c +++ b/src/libtools/libdl.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/libtools/myalign64_32.c b/src/libtools/myalign64_32.c index d2eac77fd..871022f8e 100755 --- a/src/libtools/myalign64_32.c +++ b/src/libtools/myalign64_32.c @@ -129,12 +129,12 @@ struct native_statvfs { unsigned long int f_bsize; unsigned long int f_frsize; #ifndef ANDROID - __fsblkcnt64_t f_blocks; - __fsblkcnt64_t f_bfree; - __fsblkcnt64_t f_bavail; - __fsfilcnt64_t f_files; - __fsfilcnt64_t f_ffree; - __fsfilcnt64_t f_favail; + fsblkcnt_t f_blocks; + fsblkcnt_t f_bfree; + fsblkcnt_t f_bavail; + fsfilcnt_t f_files; + fsfilcnt_t f_ffree; + fsfilcnt_t f_favail; #else fsblkcnt_t f_blocks; fsblkcnt_t f_bfree; diff --git a/src/libtools/obstack.c b/src/libtools/obstack.c index 19a9a9999..4b40fee61 100644 --- a/src/libtools/obstack.c +++ b/src/libtools/obstack.c @@ -1,7 +1,4 @@ // SPDX-License-Identifier: MIT -#define _LARGEFILE_SOURCE 1 -#define _FILE_OFFSET_BITS 64 -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/libtools/signal32.c b/src/libtools/signal32.c index d12c729f5..78314e2ed 100644 --- a/src/libtools/signal32.c +++ b/src/libtools/signal32.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 43e1412cf..8d7271632 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/libtools/syscall_user_dispatch.c b/src/libtools/syscall_user_dispatch.c index 68c6efc41..83675104b 100644 --- a/src/libtools/syscall_user_dispatch.c +++ b/src/libtools/syscall_user_dispatch.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/libtools/threads.c b/src/libtools/threads.c index a5eb14819..8b44a8478 100644 --- a/src/libtools/threads.c +++ b/src/libtools/threads.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT // __USE_UNIX98 is needed for sttype / gettype definition #define __USE_UNIX98 -#define _GNU_SOURCE #include #include #include @@ -278,7 +277,7 @@ x64emu_t* thread_get_emu(void) int stacksize = 256*1024; void* stack = NULL; if(box64_is32bits) - stack = mmap64(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0); + stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0); else stack = InternalMmap(NULL, stacksize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0); if(stack!=MAP_FAILED && !box64_quit) // to avoid marking memory when box64 is quitting diff --git a/src/libtools/threads32.c b/src/libtools/threads32.c index a5220cfc4..924fed3d5 100755 --- a/src/libtools/threads32.c +++ b/src/libtools/threads32.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT // __USE_UNIX98 is needed for sttype / gettype definition #define __USE_UNIX98 -#define _GNU_SOURCE #include #include #include @@ -273,7 +272,7 @@ void* my32_prepare_thread(x64emu_t *emu, void* f, void* arg, int ssize, void** p { int stacksize = (ssize)?ssize:(2*1024*1024); //default stack size is 2Mo //void* stack = malloc(stacksize); - void* stack = mmap64(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0); + void* stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0); if(stack==MAP_FAILED) return NULL; emuthread_t *et = (emuthread_t*)box_calloc(1, sizeof(emuthread_t)); diff --git a/src/libtools/vulkanoverlay.c b/src/libtools/vulkanoverlay.c index e67201024..3b5830bd3 100644 --- a/src/libtools/vulkanoverlay.c +++ b/src/libtools/vulkanoverlay.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/mallochook.c b/src/mallochook.c index 80f7696b1..ad8d28646 100644 --- a/src/mallochook.c +++ b/src/mallochook.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/os/my_cpuid.c b/src/os/my_cpuid.c index 8ebcde97a..be1e7d64f 100644 --- a/src/os/my_cpuid.c +++ b/src/os/my_cpuid.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include diff --git a/src/os/os_linux.c b/src/os/os_linux.c index 141ba0c90..948d723a3 100644 --- a/src/os/os_linux.c +++ b/src/os/os_linux.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/os/sysinfo.c b/src/os/sysinfo.c index 9daa7ce2d..db78a126e 100644 --- a/src/os/sysinfo.c +++ b/src/os/sysinfo.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/tools/bridge.c b/src/tools/bridge.c index 3f9324fec..b3aced3e1 100644 --- a/src/tools/bridge.c +++ b/src/tools/bridge.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/tools/cpumask.c b/src/tools/cpumask.c index 7db40e396..62f9afa4d 100644 --- a/src/tools/cpumask.c +++ b/src/tools/cpumask.c @@ -1,6 +1,5 @@ // SPDX-License-Identifier: MIT #ifndef _WIN32 -#define _GNU_SOURCE #include #endif #include diff --git a/src/tools/fileutils.c b/src/tools/fileutils.c index 6e4487758..9093e6978 100644 --- a/src/tools/fileutils.c +++ b/src/tools/fileutils.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _FILE_OFFSET_BITS 64 #include #include #include diff --git a/src/tools/gtkclass.c b/src/tools/gtkclass.c index ef3fca573..8ebe256fd 100644 --- a/src/tools/gtkclass.c +++ b/src/tools/gtkclass.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedalure.c b/src/wrapped/wrappedalure.c index 5d5852779..7217db8da 100644 --- a/src/wrapped/wrappedalure.c +++ b/src/wrapped/wrappedalure.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedalut.c b/src/wrapped/wrappedalut.c index 418b08380..46636d404 100644 --- a/src/wrapped/wrappedalut.c +++ b/src/wrapped/wrappedalut.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedandroidshmem.c b/src/wrapped/wrappedandroidshmem.c index 50ad62a7f..f3facfa0f 100755 --- a/src/wrapped/wrappedandroidshmem.c +++ b/src/wrapped/wrappedandroidshmem.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedandroidsupport.c b/src/wrapped/wrappedandroidsupport.c index 82f1eb638..95dd71882 100644 --- a/src/wrapped/wrappedandroidsupport.c +++ b/src/wrapped/wrappedandroidsupport.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedanl.c b/src/wrapped/wrappedanl.c index 74f869afb..88655e226 100644 --- a/src/wrapped/wrappedanl.c +++ b/src/wrapped/wrappedanl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedatk.c b/src/wrapped/wrappedatk.c index 156cbe539..7581d7454 100644 --- a/src/wrapped/wrappedatk.c +++ b/src/wrapped/wrappedatk.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedatkbridge.c b/src/wrapped/wrappedatkbridge.c index 7049d60b4..1e17a59d6 100644 --- a/src/wrapped/wrappedatkbridge.c +++ b/src/wrapped/wrappedatkbridge.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedatomic.c b/src/wrapped/wrappedatomic.c index d1a3b3c80..a7e8de798 100644 --- a/src/wrapped/wrappedatomic.c +++ b/src/wrapped/wrappedatomic.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedatspi.c b/src/wrapped/wrappedatspi.c index b50f57ee0..4b80a0c36 100644 --- a/src/wrapped/wrappedatspi.c +++ b/src/wrapped/wrappedatspi.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedavahiclient.c b/src/wrapped/wrappedavahiclient.c index a4b1c05e3..5433a1ad2 100644 --- a/src/wrapped/wrappedavahiclient.c +++ b/src/wrapped/wrappedavahiclient.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedavahicommon.c b/src/wrapped/wrappedavahicommon.c index ac1a6706c..670e2cab4 100644 --- a/src/wrapped/wrappedavahicommon.c +++ b/src/wrapped/wrappedavahicommon.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedayatanaappindicator3.c b/src/wrapped/wrappedayatanaappindicator3.c index 9302834f8..5acebbb90 100644 --- a/src/wrapped/wrappedayatanaappindicator3.c +++ b/src/wrapped/wrappedayatanaappindicator3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedayatanaido3.c b/src/wrapped/wrappedayatanaido3.c index bf68467c0..5a433c55c 100644 --- a/src/wrapped/wrappedayatanaido3.c +++ b/src/wrapped/wrappedayatanaido3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedayatanaindicator3.c b/src/wrapped/wrappedayatanaindicator3.c index e3c64a021..d2e34048d 100644 --- a/src/wrapped/wrappedayatanaindicator3.c +++ b/src/wrapped/wrappedayatanaindicator3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedbrotlidec.c b/src/wrapped/wrappedbrotlidec.c index 91ec1c3da..dab1dd329 100644 --- a/src/wrapped/wrappedbrotlidec.c +++ b/src/wrapped/wrappedbrotlidec.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped/wrappedbz2.c b/src/wrapped/wrappedbz2.c index 6824e8ff5..5a49d8c4a 100644 --- a/src/wrapped/wrappedbz2.c +++ b/src/wrapped/wrappedbz2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedcairo.c b/src/wrapped/wrappedcairo.c index 78fa2dcbb..eaf417662 100644 --- a/src/wrapped/wrappedcairo.c +++ b/src/wrapped/wrappedcairo.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedcairogobject.c b/src/wrapped/wrappedcairogobject.c index fb77d935d..95c0a8585 100644 --- a/src/wrapped/wrappedcairogobject.c +++ b/src/wrapped/wrappedcairogobject.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedcap.c b/src/wrapped/wrappedcap.c index f497c1186..0a5423c40 100644 --- a/src/wrapped/wrappedcap.c +++ b/src/wrapped/wrappedcap.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedcrypto.c b/src/wrapped/wrappedcrypto.c index eed765240..e9a1f82d6 100644 --- a/src/wrapped/wrappedcrypto.c +++ b/src/wrapped/wrappedcrypto.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedcrypto3.c b/src/wrapped/wrappedcrypto3.c index dbd24002a..109d591d4 100644 --- a/src/wrapped/wrappedcrypto3.c +++ b/src/wrapped/wrappedcrypto3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedcuda.c b/src/wrapped/wrappedcuda.c index 61e0e6a0e..92c1854ea 100644 --- a/src/wrapped/wrappedcuda.c +++ b/src/wrapped/wrappedcuda.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedcurl.c b/src/wrapped/wrappedcurl.c index fb4b3ffc1..c082b13d2 100644 --- a/src/wrapped/wrappedcurl.c +++ b/src/wrapped/wrappedcurl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedd3dadapter9.c b/src/wrapped/wrappedd3dadapter9.c index c868602ae..a20f1dd22 100644 --- a/src/wrapped/wrappedd3dadapter9.c +++ b/src/wrapped/wrappedd3dadapter9.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappeddbus.c b/src/wrapped/wrappeddbus.c index a000729e3..dd76acf22 100644 --- a/src/wrapped/wrappeddbus.c +++ b/src/wrapped/wrappeddbus.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappeddbusglib1.c b/src/wrapped/wrappeddbusglib1.c index cbfb00484..6c87824e9 100644 --- a/src/wrapped/wrappeddbusglib1.c +++ b/src/wrapped/wrappeddbusglib1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappeddbusmenuglib.c b/src/wrapped/wrappeddbusmenuglib.c index cca46cc59..0951ed0ab 100644 --- a/src/wrapped/wrappeddbusmenuglib.c +++ b/src/wrapped/wrappeddbusmenuglib.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappeddecor0.c b/src/wrapped/wrappeddecor0.c index e6bdb3d37..e38e50ae2 100644 --- a/src/wrapped/wrappeddecor0.c +++ b/src/wrapped/wrappeddecor0.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedevent21.c b/src/wrapped/wrappedevent21.c index a4f5037d0..fe569ce36 100644 --- a/src/wrapped/wrappedevent21.c +++ b/src/wrapped/wrappedevent21.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedexpat.c b/src/wrapped/wrappedexpat.c index 5ca18bb0b..c8be7b1bd 100644 --- a/src/wrapped/wrappedexpat.c +++ b/src/wrapped/wrappedexpat.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedfaudio.c b/src/wrapped/wrappedfaudio.c index a0a708957..23f321f17 100644 --- a/src/wrapped/wrappedfaudio.c +++ b/src/wrapped/wrappedfaudio.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedflac.c b/src/wrapped/wrappedflac.c index f531a1917..5faa1b63f 100644 --- a/src/wrapped/wrappedflac.c +++ b/src/wrapped/wrappedflac.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedfontconfig.c b/src/wrapped/wrappedfontconfig.c index cc237f75f..747cb4341 100644 --- a/src/wrapped/wrappedfontconfig.c +++ b/src/wrapped/wrappedfontconfig.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedfreebl3.c b/src/wrapped/wrappedfreebl3.c index b24216937..c8c12de66 100644 --- a/src/wrapped/wrappedfreebl3.c +++ b/src/wrapped/wrappedfreebl3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedfreetype.c b/src/wrapped/wrappedfreetype.c index 8fbc755eb..092fd6d7e 100644 --- a/src/wrapped/wrappedfreetype.c +++ b/src/wrapped/wrappedfreetype.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgbm.c b/src/wrapped/wrappedgbm.c index 02de742b9..ad2a6df96 100644 --- a/src/wrapped/wrappedgbm.c +++ b/src/wrapped/wrappedgbm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgconf2.c b/src/wrapped/wrappedgconf2.c index 2c1250c98..e8e4ee016 100644 --- a/src/wrapped/wrappedgconf2.c +++ b/src/wrapped/wrappedgconf2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgcrypt.c b/src/wrapped/wrappedgcrypt.c index 24d769429..dc3e3e7c3 100644 --- a/src/wrapped/wrappedgcrypt.c +++ b/src/wrapped/wrappedgcrypt.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgdk3.c b/src/wrapped/wrappedgdk3.c index a9cf7c72b..7f6b85d14 100644 --- a/src/wrapped/wrappedgdk3.c +++ b/src/wrapped/wrappedgdk3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedgdkpixbuf2.c b/src/wrapped/wrappedgdkpixbuf2.c index d07e28911..6b7ca4f66 100644 --- a/src/wrapped/wrappedgdkpixbuf2.c +++ b/src/wrapped/wrappedgdkpixbuf2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgdkx112.c b/src/wrapped/wrappedgdkx112.c index 39a438239..a2fac3da4 100644 --- a/src/wrapped/wrappedgdkx112.c +++ b/src/wrapped/wrappedgdkx112.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgio2.c b/src/wrapped/wrappedgio2.c index 4e8cdf030..8710af15d 100644 --- a/src/wrapped/wrappedgio2.c +++ b/src/wrapped/wrappedgio2.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedglesv2.c b/src/wrapped/wrappedglesv2.c index 025c96ab7..6a8f8758c 100644 --- a/src/wrapped/wrappedglesv2.c +++ b/src/wrapped/wrappedglesv2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedglib2.c b/src/wrapped/wrappedglib2.c index 11bfff627..b21a3c23b 100644 --- a/src/wrapped/wrappedglib2.c +++ b/src/wrapped/wrappedglib2.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedgmodule2.c b/src/wrapped/wrappedgmodule2.c index 85e669a62..9157544a2 100644 --- a/src/wrapped/wrappedgmodule2.c +++ b/src/wrapped/wrappedgmodule2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgmp.c b/src/wrapped/wrappedgmp.c index aada01df3..add288b54 100644 --- a/src/wrapped/wrappedgmp.c +++ b/src/wrapped/wrappedgmp.c @@ -3,7 +3,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgnutls.c b/src/wrapped/wrappedgnutls.c index 0fdbbf9b8..2dd72b680 100644 --- a/src/wrapped/wrappedgnutls.c +++ b/src/wrapped/wrappedgnutls.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgobject2.c b/src/wrapped/wrappedgobject2.c index 4dfc63602..304b26530 100644 --- a/src/wrapped/wrappedgobject2.c +++ b/src/wrapped/wrappedgobject2.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedgomp.c b/src/wrapped/wrappedgomp.c index 88f3bc599..69eedeb17 100644 --- a/src/wrapped/wrappedgomp.c +++ b/src/wrapped/wrappedgomp.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgssapi.c b/src/wrapped/wrappedgssapi.c index ca9046439..940dc4f91 100644 --- a/src/wrapped/wrappedgssapi.c +++ b/src/wrapped/wrappedgssapi.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgssapikrb5.c b/src/wrapped/wrappedgssapikrb5.c index aaba3dcaa..ef806b2a8 100644 --- a/src/wrapped/wrappedgssapikrb5.c +++ b/src/wrapped/wrappedgssapikrb5.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstallocators.c b/src/wrapped/wrappedgstallocators.c index 59e706508..839a1ebc5 100644 --- a/src/wrapped/wrappedgstallocators.c +++ b/src/wrapped/wrappedgstallocators.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstapp.c b/src/wrapped/wrappedgstapp.c index 0647da993..a478c47d5 100644 --- a/src/wrapped/wrappedgstapp.c +++ b/src/wrapped/wrappedgstapp.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstaudio.c b/src/wrapped/wrappedgstaudio.c index 6bdecec1d..6e172ed1b 100644 --- a/src/wrapped/wrappedgstaudio.c +++ b/src/wrapped/wrappedgstaudio.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstbase.c b/src/wrapped/wrappedgstbase.c index 6da33294e..c5e53fd45 100644 --- a/src/wrapped/wrappedgstbase.c +++ b/src/wrapped/wrappedgstbase.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstcheck.c b/src/wrapped/wrappedgstcheck.c index 7a799eac2..51a27f11a 100644 --- a/src/wrapped/wrappedgstcheck.c +++ b/src/wrapped/wrappedgstcheck.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstcontroller.c b/src/wrapped/wrappedgstcontroller.c index 16893c730..9e4d26df4 100644 --- a/src/wrapped/wrappedgstcontroller.c +++ b/src/wrapped/wrappedgstcontroller.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstfft.c b/src/wrapped/wrappedgstfft.c index 7d95f0500..e7f808c04 100644 --- a/src/wrapped/wrappedgstfft.c +++ b/src/wrapped/wrappedgstfft.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstgl.c b/src/wrapped/wrappedgstgl.c index c3b9155f1..1455b09b2 100644 --- a/src/wrapped/wrappedgstgl.c +++ b/src/wrapped/wrappedgstgl.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedgstnet.c b/src/wrapped/wrappedgstnet.c index c6b7fafa6..a23f0549a 100644 --- a/src/wrapped/wrappedgstnet.c +++ b/src/wrapped/wrappedgstnet.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstpbutils.c b/src/wrapped/wrappedgstpbutils.c index 4287ed972..2732fecd4 100644 --- a/src/wrapped/wrappedgstpbutils.c +++ b/src/wrapped/wrappedgstpbutils.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstreamer.c b/src/wrapped/wrappedgstreamer.c index a1b60778c..06adf2ee1 100644 --- a/src/wrapped/wrappedgstreamer.c +++ b/src/wrapped/wrappedgstreamer.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedgstriff.c b/src/wrapped/wrappedgstriff.c index baf46f071..e07bd29fc 100644 --- a/src/wrapped/wrappedgstriff.c +++ b/src/wrapped/wrappedgstriff.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstrtp.c b/src/wrapped/wrappedgstrtp.c index 0a6b4d69c..b8678dcde 100644 --- a/src/wrapped/wrappedgstrtp.c +++ b/src/wrapped/wrappedgstrtp.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstrtsp.c b/src/wrapped/wrappedgstrtsp.c index a6b14a9fd..569cc2f57 100644 --- a/src/wrapped/wrappedgstrtsp.c +++ b/src/wrapped/wrappedgstrtsp.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstsdp.c b/src/wrapped/wrappedgstsdp.c index 67f647411..dd2d55eac 100644 --- a/src/wrapped/wrappedgstsdp.c +++ b/src/wrapped/wrappedgstsdp.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgsttag.c b/src/wrapped/wrappedgsttag.c index 5436ccb43..e7b9f63d1 100644 --- a/src/wrapped/wrappedgsttag.c +++ b/src/wrapped/wrappedgsttag.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstvideo.c b/src/wrapped/wrappedgstvideo.c index 444a60c6a..d857f8ee7 100644 --- a/src/wrapped/wrappedgstvideo.c +++ b/src/wrapped/wrappedgstvideo.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgthread2.c b/src/wrapped/wrappedgthread2.c index b0d455142..e4bd71385 100644 --- a/src/wrapped/wrappedgthread2.c +++ b/src/wrapped/wrappedgthread2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgtk3.c b/src/wrapped/wrappedgtk3.c index 17d5a2a6b..3cd6ab335 100644 --- a/src/wrapped/wrappedgtk3.c +++ b/src/wrapped/wrappedgtk3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedgtkx112.c b/src/wrapped/wrappedgtkx112.c index d5efa8962..4c761de3c 100644 --- a/src/wrapped/wrappedgtkx112.c +++ b/src/wrapped/wrappedgtkx112.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedharfbuzzsubset.c b/src/wrapped/wrappedharfbuzzsubset.c index 4d03ba7b2..42bba0889 100644 --- a/src/wrapped/wrappedharfbuzzsubset.c +++ b/src/wrapped/wrappedharfbuzzsubset.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappediconv.c b/src/wrapped/wrappediconv.c index 685ade1aa..bb7e694c5 100644 --- a/src/wrapped/wrappediconv.c +++ b/src/wrapped/wrappediconv.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n64.c b/src/wrapped/wrappedicui18n64.c index 10c207124..451d45ec6 100644 --- a/src/wrapped/wrappedicui18n64.c +++ b/src/wrapped/wrappedicui18n64.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n66.c b/src/wrapped/wrappedicui18n66.c index 4f75d5337..94ebbe4b2 100644 --- a/src/wrapped/wrappedicui18n66.c +++ b/src/wrapped/wrappedicui18n66.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n67.c b/src/wrapped/wrappedicui18n67.c index 36decb15e..53fd0ea4a 100644 --- a/src/wrapped/wrappedicui18n67.c +++ b/src/wrapped/wrappedicui18n67.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n68.c b/src/wrapped/wrappedicui18n68.c index 9b9c909e4..1d953ca3c 100644 --- a/src/wrapped/wrappedicui18n68.c +++ b/src/wrapped/wrappedicui18n68.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n72.c b/src/wrapped/wrappedicui18n72.c index 450262dd2..b6d34e7a3 100644 --- a/src/wrapped/wrappedicui18n72.c +++ b/src/wrapped/wrappedicui18n72.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n73.c b/src/wrapped/wrappedicui18n73.c index 0054f66da..3af8d15a3 100644 --- a/src/wrapped/wrappedicui18n73.c +++ b/src/wrapped/wrappedicui18n73.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n74.c b/src/wrapped/wrappedicui18n74.c index 978411b9f..f36e2989d 100644 --- a/src/wrapped/wrappedicui18n74.c +++ b/src/wrapped/wrappedicui18n74.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n75.c b/src/wrapped/wrappedicui18n75.c index 51b388dfb..2854bc2e0 100644 --- a/src/wrapped/wrappedicui18n75.c +++ b/src/wrapped/wrappedicui18n75.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n76.c b/src/wrapped/wrappedicui18n76.c index 647ab4902..a26673ac2 100644 --- a/src/wrapped/wrappedicui18n76.c +++ b/src/wrapped/wrappedicui18n76.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc64.c b/src/wrapped/wrappedicuuc64.c index af4dbdd0c..c5cff9fdd 100644 --- a/src/wrapped/wrappedicuuc64.c +++ b/src/wrapped/wrappedicuuc64.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc66.c b/src/wrapped/wrappedicuuc66.c index 368e1eb90..154e5fb4b 100644 --- a/src/wrapped/wrappedicuuc66.c +++ b/src/wrapped/wrappedicuuc66.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc67.c b/src/wrapped/wrappedicuuc67.c index ba6c70357..e3130edef 100644 --- a/src/wrapped/wrappedicuuc67.c +++ b/src/wrapped/wrappedicuuc67.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc68.c b/src/wrapped/wrappedicuuc68.c index 7ad658313..13a120f99 100644 --- a/src/wrapped/wrappedicuuc68.c +++ b/src/wrapped/wrappedicuuc68.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc72.c b/src/wrapped/wrappedicuuc72.c index 2147909f6..9a71af36d 100644 --- a/src/wrapped/wrappedicuuc72.c +++ b/src/wrapped/wrappedicuuc72.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc73.c b/src/wrapped/wrappedicuuc73.c index 5eda8a97c..92e6698c7 100644 --- a/src/wrapped/wrappedicuuc73.c +++ b/src/wrapped/wrappedicuuc73.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc74.c b/src/wrapped/wrappedicuuc74.c index d76a48c50..92dc67e7d 100644 --- a/src/wrapped/wrappedicuuc74.c +++ b/src/wrapped/wrappedicuuc74.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc75.c b/src/wrapped/wrappedicuuc75.c index 484dc50d4..e0984b73c 100644 --- a/src/wrapped/wrappedicuuc75.c +++ b/src/wrapped/wrappedicuuc75.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc76.c b/src/wrapped/wrappedicuuc76.c index 3a2d4d721..38f5891b1 100644 --- a/src/wrapped/wrappedicuuc76.c +++ b/src/wrapped/wrappedicuuc76.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedidn2.c b/src/wrapped/wrappedidn2.c index af6e9fade..adef4e98d 100644 --- a/src/wrapped/wrappedidn2.c +++ b/src/wrapped/wrappedidn2.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedkrb5.c b/src/wrapped/wrappedkrb5.c index efd2651e3..7419131f0 100644 --- a/src/wrapped/wrappedkrb5.c +++ b/src/wrapped/wrappedkrb5.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlber.c b/src/wrapped/wrappedlber.c index 5f76acb0c..041e3cdcc 100644 --- a/src/wrapped/wrappedlber.c +++ b/src/wrapped/wrappedlber.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlcms2.c b/src/wrapped/wrappedlcms2.c index c95fc9969..5986d3913 100644 --- a/src/wrapped/wrappedlcms2.c +++ b/src/wrapped/wrappedlcms2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedldapr.c b/src/wrapped/wrappedldapr.c index b51afe860..0a37685e9 100644 --- a/src/wrapped/wrappedldapr.c +++ b/src/wrapped/wrappedldapr.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedldlinux.c b/src/wrapped/wrappedldlinux.c index d84d3228e..9b6584ec5 100644 --- a/src/wrapped/wrappedldlinux.c +++ b/src/wrapped/wrappedldlinux.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibasound.c b/src/wrapped/wrappedlibasound.c index f4663de51..33ea2d072 100644 --- a/src/wrapped/wrappedlibasound.c +++ b/src/wrapped/wrappedlibasound.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped/wrappedlibavcodec58.c b/src/wrapped/wrappedlibavcodec58.c index a805f0709..e7a50e04c 100644 --- a/src/wrapped/wrappedlibavcodec58.c +++ b/src/wrapped/wrappedlibavcodec58.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibavformat58.c b/src/wrapped/wrappedlibavformat58.c index 6197466f9..8472477a5 100644 --- a/src/wrapped/wrappedlibavformat58.c +++ b/src/wrapped/wrappedlibavformat58.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibavutil56.c b/src/wrapped/wrappedlibavutil56.c index 0a70b375a..7eb5e4601 100644 --- a/src/wrapped/wrappedlibavutil56.c +++ b/src/wrapped/wrappedlibavutil56.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #define __STDC_WANT_LIB_EXT2__ 1 // for vasprintf diff --git a/src/wrapped/wrappedlibblas.c b/src/wrapped/wrappedlibblas.c index 32a559fea..5b0b8ec69 100644 --- a/src/wrapped/wrappedlibblas.c +++ b/src/wrapped/wrappedlibblas.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibbsd.c b/src/wrapped/wrappedlibbsd.c index 3c1e9de83..5c1c7edcf 100644 --- a/src/wrapped/wrappedlibbsd.c +++ b/src/wrapped/wrappedlibbsd.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index 10c0f34d4..39f07fcae 100644 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -1,7 +1,4 @@ // SPDX-License-Identifier: MIT -#define _LARGEFILE_SOURCE 1 -#define _FILE_OFFSET_BITS 64 -#define _GNU_SOURCE /* See feature_test_macros(7) */ #if !defined(TERMUX) && !defined(ANDROID) # if defined(__has_include) # if __has_include() @@ -67,6 +64,7 @@ extern const char *const sys_siglist[] __asm__("__sys_siglist"); #include #include #include +#include #undef LOG_INFO #undef LOG_DEBUG @@ -444,7 +442,7 @@ static void* findcompare_dirFct(void* fct) // filter64 #define GO(A) \ static uintptr_t my_filter64_fct_##A = 0; \ -static int my_filter64_##A(const struct dirent64* a) \ +static int my_filter64_##A(const struct dirent* a) \ { \ return (int)RunFunctionFmt(my_filter64_fct_##A, "p", a); \ } @@ -467,7 +465,7 @@ static void* findfilter64Fct(void* fct) // compare64 #define GO(A) \ static uintptr_t my_compare64_fct_##A = 0; \ -static int my_compare64_##A(const struct dirent64* a, const struct dirent64* b) \ +static int my_compare64_##A(const struct dirent* a, const struct dirent* b) \ { \ return (int)RunFunctionFmt(my_compare64_fct_##A, "pp", a, b); \ } @@ -1705,8 +1703,8 @@ EXPORT void my__ITM_deregisterTMCloneTable(x64emu_t* emu, void* p) { (void)emu; EXPORT int my___fxstat(x64emu_t *emu, int vers, int fd, void* buf) { (void)emu; (void)vers; - struct stat64 st; - int r = fstat64(fd, buf?&st:buf); + struct stat st; + int r = fstat(fd, buf?&st:buf); if(buf && !r) UnalignStat64(&st, buf); return r; @@ -1747,8 +1745,8 @@ EXPORT int my___xmknodat(x64emu_t* emu, int v, int dirfd, char* path, uint32_t m EXPORT int my___xstat(x64emu_t* emu, int v, void* path, void* buf) { (void)emu; (void)v; - struct stat64 st; - int r = stat64((const char*)path, buf?&st:buf); + struct stat st; + int r = stat((const char*)path, buf?&st:buf); if(buf && !r) UnalignStat64(&st, buf); return r; @@ -1758,8 +1756,8 @@ EXPORT int my___xstat64(x64emu_t* emu, int v, void* path, void* buf) __attribute EXPORT int my___lxstat(x64emu_t* emu, int v, void* name, void* buf) { (void)emu; (void)v; - struct stat64 st; - int r = lstat64((const char*)name, buf?&st:buf); + struct stat st; + int r = lstat((const char*)name, buf?&st:buf); if(buf && !r) UnalignStat64(&st, buf); return r; @@ -1769,8 +1767,8 @@ EXPORT int my___lxstat64(x64emu_t* emu, int v, void* name, void* buf) __attribut EXPORT int my___fxstatat(x64emu_t* emu, int v, int d, void* path, void* buf, int flags) { (void)emu; (void)v; - struct stat64 st; - int r = fstatat64(d, path, &st, flags); + struct stat st; + int r = fstatat(d, path, &st, flags); if(!r) UnalignStat64(&st, buf); return r; @@ -1823,7 +1821,7 @@ EXPORT int my_fstatat64(x64emu_t *emu, int fd, const char* path, void* buf, int EXPORT int my__IO_file_stat(x64emu_t* emu, void* f, void* buf) { - struct stat64 st; + struct stat st; int r = my->_IO_file_stat(f, &st); UnalignStat64(&st, buf); return r; @@ -1832,16 +1830,16 @@ EXPORT int my__IO_file_stat(x64emu_t* emu, void* f, void* buf) #if 0 EXPORT int my_fstatfs64(int fd, void* buf) { - struct statfs64 st; - int r = fstatfs64(fd, &st); + struct statfs st; + int r = fstatfs(fd, &st); UnalignStatFS64(&st, buf); return r; } EXPORT int my_statfs64(const char* path, void* buf) { - struct statfs64 st; - int r = statfs64(path, &st); + struct statfs st; + int r = statfs(path, &st); UnalignStatFS64(&st, buf); return r; } @@ -2032,7 +2030,7 @@ EXPORT void* my_readdir(x64emu_t* emu, void* dirp) { if (BOX64ENV(fix_64bit_inodes)) { - struct dirent64 *dp64 = readdir64((DIR *)dirp); + struct dirent *dp64 = readdir((DIR *)dirp); if (!dp64) return NULL; uint32_t ino32 = dp64->d_ino ^ (dp64->d_ino >> 32); int32_t off32 = dp64->d_off; @@ -2057,7 +2055,7 @@ EXPORT void* my_readdir(x64emu_t* emu, void* dirp) EXPORT int32_t my_readdir_r(x64emu_t* emu, void* dirp, void* entry, void** result) { - struct dirent64 d64, *dp64; + struct dirent d64, *dp64; if (BOX64ENV(fix_64bit_inodes) && (sizeof(d64.d_name) > 1)) { static iFppp_t f = NULL; @@ -2068,7 +2066,7 @@ EXPORT int32_t my_readdir_r(x64emu_t* emu, void* dirp, void* entry, void** resul *result = NULL; return 0; } - f = (iFppp_t)dlsym(lib->w.lib, "readdir64_r"); + f = (iFppp_t)dlsym(lib->w.lib, "readdir_r"); } int r = f(dirp, &d64, &dp64); @@ -2079,7 +2077,7 @@ EXPORT int32_t my_readdir_r(x64emu_t* emu, void* dirp, void* entry, void** resul } struct i386_dirent *dp32 = (struct i386_dirent *)entry; - int namelen = dp64->d_reclen - offsetof(struct dirent64, d_name); + int namelen = dp64->d_reclen - offsetof(struct dirent, d_name); if (namelen > sizeof(dp32->d_name)) { *result = NULL; @@ -2387,16 +2385,11 @@ enum { static int32_t open_func_fallback(char *pathname, int32_t flags, uint32_t open_mode, char *fopen_mode, int type, FILE **file) { - if (type == FOPEN64_TYPE) { - *file = fopen64(pathname, fopen_mode); - return 0; - } else if (type == FOPEN_TYPE) { + if (type == FOPEN_TYPE || type == FOPEN64_TYPE) { *file = fopen(pathname, fopen_mode); return 0; - } else if (type == OPEN_TYPE) { + } else if (type == OPEN_TYPE || type == OPEN64_TYPE) { return open(pathname, flags, open_mode); - } else if (type == OPEN64_TYPE) { - return open64(pathname, flags, open_mode); } return -1; } @@ -2654,7 +2647,7 @@ EXPORT int32_t my_epoll_pwait2(x64emu_t* emu, int epfd, void* events, int maxeve EXPORT int32_t my_glob64(x64emu_t *emu, void* pat, int32_t flags, void* errfnc, void* pglob) { (void)emu; - return glob64(pat, flags, findgloberrFct(errfnc), pglob); + return glob(pat, flags, findgloberrFct(errfnc), pglob); } EXPORT int32_t my_glob(x64emu_t *emu, void* pat, int32_t flags, void* errfnc, void* pglob) __attribute__((alias("my_glob64"))); #endif @@ -2662,7 +2655,7 @@ EXPORT int32_t my_glob(x64emu_t *emu, void* pat, int32_t flags, void* errfnc, vo EXPORT int my_scandir64(x64emu_t *emu, void* dir, void* namelist, void* sel, void* comp) { (void)emu; - return scandir64(dir, namelist, findfilter64Fct(sel), findcompare64Fct(comp)); + return scandir(dir, namelist, findfilter64Fct(sel), findcompare64Fct(comp)); } EXPORT int my_scandir(x64emu_t *emu, void* dir, void* namelist, void* sel, void* comp) __attribute__((alias("my_scandir64"))); @@ -2675,20 +2668,20 @@ EXPORT int my_scandirat(x64emu_t *emu, int dirfd, void* dirp, void* namelist, vo EXPORT int my_scandirat64(x64emu_t *emu, int dirfd, void* dirp, void* namelist, void* sel, void* comp) { (void)emu; - return scandirat64(dirfd, dirp, namelist, findfilter64Fct(sel), findcompare64Fct(comp)); + return scandirat(dirfd, dirp, namelist, findfilter64Fct(sel), findcompare64Fct(comp)); } EXPORT int my_ftw64(x64emu_t* emu, void* filename, void* func, int descriptors) { (void)emu; - return ftw64(filename, findftw64Fct(func), descriptors); + return ftw(filename, findftw64Fct(func), descriptors); } EXPORT int my_ftw(x64emu_t* emu, void* filename, void* func, int descriptors) __attribute__((alias("my_ftw64"))); EXPORT int32_t my_nftw64(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd, int32_t flags) { (void)emu; - return nftw64(pathname, findnftw64Fct(B), nopenfd, flags); + return nftw(pathname, findnftw64Fct(B), nopenfd, flags); } EXPORT int my_nftw(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd, int32_t flags) __attribute__((alias("my_nftw64"))); @@ -4262,7 +4255,7 @@ static ssize_t my_cookie_write(void *p, const char *buf, size_t size) my_cookie_t* cookie = (my_cookie_t*)p; return (ssize_t)RunFunctionFmt(cookie->w, "ppL", cookie->cookie, buf, size) ; } -static int my_cookie_seek(void *p, off64_t *offset, int whence) +static int my_cookie_seek(void *p, off_t *offset, int whence) { my_cookie_t* cookie = (my_cookie_t*)p; return RunFunctionFmt(cookie->s, "ppi", cookie->cookie, offset, whence) ; @@ -4382,10 +4375,10 @@ EXPORT int my_getrlimit(x64emu_t* emu, uint32_t resource, struct rlimit* rlim) return my___getrlimit(emu, resource, rlim); } -EXPORT int my_getrlimit64(x64emu_t* emu, uint32_t resource, struct rlimit64* rlim) +EXPORT int my_getrlimit64(x64emu_t* emu, uint32_t resource, struct rlimit* rlim) { (void)emu; - return check_getrlimit_buffer(rlim, sizeof(*rlim)) ? getrlimit64(resource, rlim) : -1; + return check_getrlimit_buffer(rlim, sizeof(*rlim)) ? getrlimit(resource, rlim) : -1; } EXPORT int my_setrlimit(x64emu_t* emu, int ressource, const struct rlimit *rlim) diff --git a/src/wrapped/wrappedlibcmusl.c b/src/wrapped/wrappedlibcmusl.c index e66471df0..603beb4b3 100644 --- a/src/wrapped/wrappedlibcmusl.c +++ b/src/wrapped/wrappedlibcmusl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibcrypt.c b/src/wrapped/wrappedlibcrypt.c index f033d705b..cf75b4da3 100644 --- a/src/wrapped/wrappedlibcrypt.c +++ b/src/wrapped/wrappedlibcrypt.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibcups.c b/src/wrapped/wrappedlibcups.c index ecd745377..33ae36a10 100644 --- a/src/wrapped/wrappedlibcups.c +++ b/src/wrapped/wrappedlibcups.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibcupsimage.c b/src/wrapped/wrappedlibcupsimage.c index aee69284a..2aa4f44b5 100644 --- a/src/wrapped/wrappedlibcupsimage.c +++ b/src/wrapped/wrappedlibcupsimage.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c index 0d69d80ff..38cfc2b58 100644 --- a/src/wrapped/wrappedlibdl.c +++ b/src/wrapped/wrappedlibdl.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibdrm.c b/src/wrapped/wrappedlibdrm.c index 47a6f59c2..a7cc51041 100644 --- a/src/wrapped/wrappedlibdrm.c +++ b/src/wrapped/wrappedlibdrm.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibdrmamdgpu.c b/src/wrapped/wrappedlibdrmamdgpu.c index 08778ec36..d8aa6b626 100644 --- a/src/wrapped/wrappedlibdrmamdgpu.c +++ b/src/wrapped/wrappedlibdrmamdgpu.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibegl.c b/src/wrapped/wrappedlibegl.c index 23e16305a..f0177990f 100644 --- a/src/wrapped/wrappedlibegl.c +++ b/src/wrapped/wrappedlibegl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibform.c b/src/wrapped/wrappedlibform.c index e435049c1..d995e4b97 100644 --- a/src/wrapped/wrappedlibform.c +++ b/src/wrapped/wrappedlibform.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibformw.c b/src/wrapped/wrappedlibformw.c index 0a8b178d3..9a51cb742 100644 --- a/src/wrapped/wrappedlibformw.c +++ b/src/wrapped/wrappedlibformw.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibformw6.c b/src/wrapped/wrappedlibformw6.c index dbe66b9fd..7a39583a8 100644 --- a/src/wrapped/wrappedlibformw6.c +++ b/src/wrapped/wrappedlibformw6.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibfuse.c b/src/wrapped/wrappedlibfuse.c index f062a5f4c..f03eeda10 100644 --- a/src/wrapped/wrappedlibfuse.c +++ b/src/wrapped/wrappedlibfuse.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped/wrappedlibgl.c b/src/wrapped/wrappedlibgl.c index f813ef2c9..7969aeba4 100644 --- a/src/wrapped/wrappedlibgl.c +++ b/src/wrapped/wrappedlibgl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibglu.c b/src/wrapped/wrappedlibglu.c index 0bc1f48f4..46d513465 100644 --- a/src/wrapped/wrappedlibglu.c +++ b/src/wrapped/wrappedlibglu.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibglx.c b/src/wrapped/wrappedlibglx.c index 1d78a166c..102119103 100644 --- a/src/wrapped/wrappedlibglx.c +++ b/src/wrapped/wrappedlibglx.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibglxnvidia.c b/src/wrapped/wrappedlibglxnvidia.c index b61e57942..b007693df 100644 --- a/src/wrapped/wrappedlibglxnvidia.c +++ b/src/wrapped/wrappedlibglxnvidia.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibgpgme.c b/src/wrapped/wrappedlibgpgme.c index a3bfe92b7..f5df43cfe 100644 --- a/src/wrapped/wrappedlibgpgme.c +++ b/src/wrapped/wrappedlibgpgme.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibharfbuzz.c b/src/wrapped/wrappedlibharfbuzz.c index 07d10cede..6b5f9411f 100644 --- a/src/wrapped/wrappedlibharfbuzz.c +++ b/src/wrapped/wrappedlibharfbuzz.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" #include "wrapper.h" diff --git a/src/wrapped/wrappedlibhogweed6.c b/src/wrapped/wrappedlibhogweed6.c index 6041a06b9..3e5f759ae 100644 --- a/src/wrapped/wrappedlibhogweed6.c +++ b/src/wrapped/wrappedlibhogweed6.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibibus.c b/src/wrapped/wrappedlibibus.c index 2b1e638ef..63cfbfa98 100644 --- a/src/wrapped/wrappedlibibus.c +++ b/src/wrapped/wrappedlibibus.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibice.c b/src/wrapped/wrappedlibice.c index c09c6184f..a4f4094f7 100644 --- a/src/wrapped/wrappedlibice.c +++ b/src/wrapped/wrappedlibice.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedliblapack.c b/src/wrapped/wrappedliblapack.c index 9354fa15f..ed3383a92 100644 --- a/src/wrapped/wrappedliblapack.c +++ b/src/wrapped/wrappedliblapack.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibm.c b/src/wrapped/wrappedlibm.c index af20b872a..e35569a70 100644 --- a/src/wrapped/wrappedlibm.c +++ b/src/wrapped/wrappedlibm.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedlibmvec.c b/src/wrapped/wrappedlibmvec.c index 6a7cbaf93..39534c089 100644 --- a/src/wrapped/wrappedlibmvec.c +++ b/src/wrapped/wrappedlibmvec.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedlibncurses.c b/src/wrapped/wrappedlibncurses.c index 93fd9a41c..a0ca7522f 100644 --- a/src/wrapped/wrappedlibncurses.c +++ b/src/wrapped/wrappedlibncurses.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibncurses6.c b/src/wrapped/wrappedlibncurses6.c index b9e5dcac0..9e77ba5c6 100644 --- a/src/wrapped/wrappedlibncurses6.c +++ b/src/wrapped/wrappedlibncurses6.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibncursesw.c b/src/wrapped/wrappedlibncursesw.c index c7d9dba46..23e7ec53d 100644 --- a/src/wrapped/wrappedlibncursesw.c +++ b/src/wrapped/wrappedlibncursesw.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibncursesw6.c b/src/wrapped/wrappedlibncursesw6.c index efc9319e3..a306e7190 100644 --- a/src/wrapped/wrappedlibncursesw6.c +++ b/src/wrapped/wrappedlibncursesw6.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibnettle8.c b/src/wrapped/wrappedlibnettle8.c index 11bb66ebb..925fefaa6 100644 --- a/src/wrapped/wrappedlibnettle8.c +++ b/src/wrapped/wrappedlibnettle8.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibnuma.c b/src/wrapped/wrappedlibnuma.c index 2921e3fce..53933dd2a 100644 --- a/src/wrapped/wrappedlibnuma.c +++ b/src/wrapped/wrappedlibnuma.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibogg.c b/src/wrapped/wrappedlibogg.c index 42281b64f..3a69d1e16 100644 --- a/src/wrapped/wrappedlibogg.c +++ b/src/wrapped/wrappedlibogg.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibomp.c b/src/wrapped/wrappedlibomp.c index 75bb90f8e..e4dc3e0e2 100644 --- a/src/wrapped/wrappedlibomp.c +++ b/src/wrapped/wrappedlibomp.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibopus.c b/src/wrapped/wrappedlibopus.c index 956c36066..1a9cdd3e5 100644 --- a/src/wrapped/wrappedlibopus.c +++ b/src/wrapped/wrappedlibopus.c @@ -3,7 +3,6 @@ #include #include #include -#define _GNU_SOURCE #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibpanel.c b/src/wrapped/wrappedlibpanel.c index 3f7cd2b98..ae3e38f3f 100644 --- a/src/wrapped/wrappedlibpanel.c +++ b/src/wrapped/wrappedlibpanel.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibpci.c b/src/wrapped/wrappedlibpci.c index 24753ed72..8f5a671b4 100644 --- a/src/wrapped/wrappedlibpci.c +++ b/src/wrapped/wrappedlibpci.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibpcre.c b/src/wrapped/wrappedlibpcre.c index 248a7a85d..143a67460 100644 --- a/src/wrapped/wrappedlibpcre.c +++ b/src/wrapped/wrappedlibpcre.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibpcre216.c b/src/wrapped/wrappedlibpcre216.c index 8e538f926..ea499bffc 100644 --- a/src/wrapped/wrappedlibpcre216.c +++ b/src/wrapped/wrappedlibpcre216.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibpthread.c b/src/wrapped/wrappedlibpthread.c index 91330f299..be0761272 100644 --- a/src/wrapped/wrappedlibpthread.c +++ b/src/wrapped/wrappedlibpthread.c @@ -1,6 +1,5 @@ // SPDX-License-Identifier: MIT #define __USE_UNIX98 -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedlibresolv.c b/src/wrapped/wrappedlibresolv.c index 12dfe7bdf..e99c02b01 100644 --- a/src/wrapped/wrappedlibresolv.c +++ b/src/wrapped/wrappedlibresolv.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibrt.c b/src/wrapped/wrappedlibrt.c index 46e4c03c3..f1c2239ad 100644 --- a/src/wrapped/wrappedlibrt.c +++ b/src/wrapped/wrappedlibrt.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedlibsm.c b/src/wrapped/wrappedlibsm.c index 7f34ec59d..d89968f53 100644 --- a/src/wrapped/wrappedlibsm.c +++ b/src/wrapped/wrappedlibsm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibsndfile.c b/src/wrapped/wrappedlibsndfile.c index ce5346d6a..cb45a8efc 100644 --- a/src/wrapped/wrappedlibsndfile.c +++ b/src/wrapped/wrappedlibsndfile.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibsqlite3.c b/src/wrapped/wrappedlibsqlite3.c index 192e0ac15..fe709166b 100644 --- a/src/wrapped/wrappedlibsqlite3.c +++ b/src/wrapped/wrappedlibsqlite3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibssh2.c b/src/wrapped/wrappedlibssh2.c index 6d552271c..a4d8edd80 100644 --- a/src/wrapped/wrappedlibssh2.c +++ b/src/wrapped/wrappedlibssh2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibssl.c b/src/wrapped/wrappedlibssl.c index 4fb8f5df6..7e7747440 100644 --- a/src/wrapped/wrappedlibssl.c +++ b/src/wrapped/wrappedlibssl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibssl3.c b/src/wrapped/wrappedlibssl3.c index 1f9369517..f9417531e 100644 --- a/src/wrapped/wrappedlibssl3.c +++ b/src/wrapped/wrappedlibssl3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibtasn1.c b/src/wrapped/wrappedlibtasn1.c index 429146806..0dd1d2648 100644 --- a/src/wrapped/wrappedlibtasn1.c +++ b/src/wrapped/wrappedlibtasn1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibtiff5.c b/src/wrapped/wrappedlibtiff5.c index 2b661a7e4..6c72de86b 100644 --- a/src/wrapped/wrappedlibtiff5.c +++ b/src/wrapped/wrappedlibtiff5.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibtinfo.c b/src/wrapped/wrappedlibtinfo.c index f0485f3b0..129368542 100644 --- a/src/wrapped/wrappedlibtinfo.c +++ b/src/wrapped/wrappedlibtinfo.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibtinfo6.c b/src/wrapped/wrappedlibtinfo6.c index af63d9520..e2f9ed400 100644 --- a/src/wrapped/wrappedlibtinfo6.c +++ b/src/wrapped/wrappedlibtinfo6.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibunistring2.c b/src/wrapped/wrappedlibunistring2.c index 53d4988a1..8bdbb6690 100644 --- a/src/wrapped/wrappedlibunistring2.c +++ b/src/wrapped/wrappedlibunistring2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibusb1.c b/src/wrapped/wrappedlibusb1.c index cf23b6f78..5b2bf3c69 100644 --- a/src/wrapped/wrappedlibusb1.c +++ b/src/wrapped/wrappedlibusb1.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibuuid.c b/src/wrapped/wrappedlibuuid.c index 51690304d..0ab12666b 100644 --- a/src/wrapped/wrappedlibuuid.c +++ b/src/wrapped/wrappedlibuuid.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibva.c b/src/wrapped/wrappedlibva.c index a51bf6a0a..3d4349401 100644 --- a/src/wrapped/wrappedlibva.c +++ b/src/wrapped/wrappedlibva.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibvadrm.c b/src/wrapped/wrappedlibvadrm.c index 9ff2dbfea..51ea4b1a3 100644 --- a/src/wrapped/wrappedlibvadrm.c +++ b/src/wrapped/wrappedlibvadrm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibvawayland.c b/src/wrapped/wrappedlibvawayland.c index 0a940e919..454320b7a 100644 --- a/src/wrapped/wrappedlibvawayland.c +++ b/src/wrapped/wrappedlibvawayland.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibvax11.c b/src/wrapped/wrappedlibvax11.c index 174b5e189..af0669fbe 100644 --- a/src/wrapped/wrappedlibvax11.c +++ b/src/wrapped/wrappedlibvax11.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibvdpau.c b/src/wrapped/wrappedlibvdpau.c index 358438ce9..52b3632f1 100644 --- a/src/wrapped/wrappedlibvdpau.c +++ b/src/wrapped/wrappedlibvdpau.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibvorbis.c b/src/wrapped/wrappedlibvorbis.c index e9e896e30..478030d6a 100644 --- a/src/wrapped/wrappedlibvorbis.c +++ b/src/wrapped/wrappedlibvorbis.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibvpx.c b/src/wrapped/wrappedlibvpx.c index 1d10a6c6b..97f6bd3e7 100644 --- a/src/wrapped/wrappedlibvpx.c +++ b/src/wrapped/wrappedlibvpx.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibx11.c b/src/wrapped/wrappedlibx11.c index e31c6c52e..40281ff85 100644 --- a/src/wrapped/wrappedlibx11.c +++ b/src/wrapped/wrappedlibx11.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibx11xcb.c b/src/wrapped/wrappedlibx11xcb.c index 3fb4e54d3..075de6e1c 100644 --- a/src/wrapped/wrappedlibx11xcb.c +++ b/src/wrapped/wrappedlibx11xcb.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxau.c b/src/wrapped/wrappedlibxau.c index c1236771f..5803acccc 100644 --- a/src/wrapped/wrappedlibxau.c +++ b/src/wrapped/wrappedlibxau.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxaw.c b/src/wrapped/wrappedlibxaw.c index ae5e48257..c5c2d4db9 100644 --- a/src/wrapped/wrappedlibxaw.c +++ b/src/wrapped/wrappedlibxaw.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcb.c b/src/wrapped/wrappedlibxcb.c index 6ba006319..0241f0b36 100644 --- a/src/wrapped/wrappedlibxcb.c +++ b/src/wrapped/wrappedlibxcb.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbcursor.c b/src/wrapped/wrappedlibxcbcursor.c index 6c92e9c68..10fee4fad 100644 --- a/src/wrapped/wrappedlibxcbcursor.c +++ b/src/wrapped/wrappedlibxcbcursor.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbdri2.c b/src/wrapped/wrappedlibxcbdri2.c index 59110263f..92f46d682 100644 --- a/src/wrapped/wrappedlibxcbdri2.c +++ b/src/wrapped/wrappedlibxcbdri2.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibxcbdri3.c b/src/wrapped/wrappedlibxcbdri3.c index 9969f507b..95d01d9a9 100644 --- a/src/wrapped/wrappedlibxcbdri3.c +++ b/src/wrapped/wrappedlibxcbdri3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibxcbglx.c b/src/wrapped/wrappedlibxcbglx.c index 4737db47d..3dc021b34 100644 --- a/src/wrapped/wrappedlibxcbglx.c +++ b/src/wrapped/wrappedlibxcbglx.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbicccm.c b/src/wrapped/wrappedlibxcbicccm.c index 89d90c56d..7b0f46ce7 100644 --- a/src/wrapped/wrappedlibxcbicccm.c +++ b/src/wrapped/wrappedlibxcbicccm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbimage.c b/src/wrapped/wrappedlibxcbimage.c index 602a91aa2..9c796eebd 100644 --- a/src/wrapped/wrappedlibxcbimage.c +++ b/src/wrapped/wrappedlibxcbimage.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbkeysyms.c b/src/wrapped/wrappedlibxcbkeysyms.c index 21993bd93..6ee2db016 100644 --- a/src/wrapped/wrappedlibxcbkeysyms.c +++ b/src/wrapped/wrappedlibxcbkeysyms.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbpresent.c b/src/wrapped/wrappedlibxcbpresent.c index 516178c7c..c48331836 100644 --- a/src/wrapped/wrappedlibxcbpresent.c +++ b/src/wrapped/wrappedlibxcbpresent.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbrandr.c b/src/wrapped/wrappedlibxcbrandr.c index 4e8f8578e..b24afae30 100644 --- a/src/wrapped/wrappedlibxcbrandr.c +++ b/src/wrapped/wrappedlibxcbrandr.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbrender.c b/src/wrapped/wrappedlibxcbrender.c index 3a867fbc4..0e7ff71b2 100644 --- a/src/wrapped/wrappedlibxcbrender.c +++ b/src/wrapped/wrappedlibxcbrender.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbrenderutil.c b/src/wrapped/wrappedlibxcbrenderutil.c index 27573195e..8af643215 100644 --- a/src/wrapped/wrappedlibxcbrenderutil.c +++ b/src/wrapped/wrappedlibxcbrenderutil.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbres.c b/src/wrapped/wrappedlibxcbres.c index 972a18578..547f86da8 100644 --- a/src/wrapped/wrappedlibxcbres.c +++ b/src/wrapped/wrappedlibxcbres.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbshape.c b/src/wrapped/wrappedlibxcbshape.c index 501da8a1b..e11ed2458 100644 --- a/src/wrapped/wrappedlibxcbshape.c +++ b/src/wrapped/wrappedlibxcbshape.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbshm.c b/src/wrapped/wrappedlibxcbshm.c index 1514236e7..1144356dc 100644 --- a/src/wrapped/wrappedlibxcbshm.c +++ b/src/wrapped/wrappedlibxcbshm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbsync.c b/src/wrapped/wrappedlibxcbsync.c index ec633c423..97e21e8bb 100644 --- a/src/wrapped/wrappedlibxcbsync.c +++ b/src/wrapped/wrappedlibxcbsync.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbutil.c b/src/wrapped/wrappedlibxcbutil.c index f453aac79..cdc5df9fb 100644 --- a/src/wrapped/wrappedlibxcbutil.c +++ b/src/wrapped/wrappedlibxcbutil.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbxfixes.c b/src/wrapped/wrappedlibxcbxfixes.c index da2ace20d..bd67a0ae1 100644 --- a/src/wrapped/wrappedlibxcbxfixes.c +++ b/src/wrapped/wrappedlibxcbxfixes.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbxinerama.c b/src/wrapped/wrappedlibxcbxinerama.c index 76835fdf2..f611973ea 100644 --- a/src/wrapped/wrappedlibxcbxinerama.c +++ b/src/wrapped/wrappedlibxcbxinerama.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbxinput.c b/src/wrapped/wrappedlibxcbxinput.c index b5a339763..af80dadc3 100644 --- a/src/wrapped/wrappedlibxcbxinput.c +++ b/src/wrapped/wrappedlibxcbxinput.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbxkb.c b/src/wrapped/wrappedlibxcbxkb.c index 3f0751c4f..ea656e90e 100644 --- a/src/wrapped/wrappedlibxcbxkb.c +++ b/src/wrapped/wrappedlibxcbxkb.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbxtest.c b/src/wrapped/wrappedlibxcbxtest.c index 23e6c39fe..372e38099 100644 --- a/src/wrapped/wrappedlibxcbxtest.c +++ b/src/wrapped/wrappedlibxcbxtest.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcomposite.c b/src/wrapped/wrappedlibxcomposite.c index ef25c209d..de5918bbb 100644 --- a/src/wrapped/wrappedlibxcomposite.c +++ b/src/wrapped/wrappedlibxcomposite.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcursor.c b/src/wrapped/wrappedlibxcursor.c index fc5bdd564..009fa3842 100644 --- a/src/wrapped/wrappedlibxcursor.c +++ b/src/wrapped/wrappedlibxcursor.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxdamage.c b/src/wrapped/wrappedlibxdamage.c index 3d7510e4b..438b43438 100644 --- a/src/wrapped/wrappedlibxdamage.c +++ b/src/wrapped/wrappedlibxdamage.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxdmcp.c b/src/wrapped/wrappedlibxdmcp.c index 0a32487a0..e94cc36cc 100644 --- a/src/wrapped/wrappedlibxdmcp.c +++ b/src/wrapped/wrappedlibxdmcp.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxext.c b/src/wrapped/wrappedlibxext.c index 4f1d19d94..ef257f2e5 100644 --- a/src/wrapped/wrappedlibxext.c +++ b/src/wrapped/wrappedlibxext.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxfixes.c b/src/wrapped/wrappedlibxfixes.c index c981c2667..74cac9bbc 100644 --- a/src/wrapped/wrappedlibxfixes.c +++ b/src/wrapped/wrappedlibxfixes.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxft.c b/src/wrapped/wrappedlibxft.c index cd2590c1b..b27f746d1 100644 --- a/src/wrapped/wrappedlibxft.c +++ b/src/wrapped/wrappedlibxft.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxi.c b/src/wrapped/wrappedlibxi.c index 34105a733..cb2b2b5a3 100644 --- a/src/wrapped/wrappedlibxi.c +++ b/src/wrapped/wrappedlibxi.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxmu.c b/src/wrapped/wrappedlibxmu.c index 56ec97a7f..d862846d5 100644 --- a/src/wrapped/wrappedlibxmu.c +++ b/src/wrapped/wrappedlibxmu.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxpm.c b/src/wrapped/wrappedlibxpm.c index f3fef5c4e..975359a50 100644 --- a/src/wrapped/wrappedlibxpm.c +++ b/src/wrapped/wrappedlibxpm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxpresent.c b/src/wrapped/wrappedlibxpresent.c index d73c668f0..7b56275cd 100644 --- a/src/wrapped/wrappedlibxpresent.c +++ b/src/wrapped/wrappedlibxpresent.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxrandr.c b/src/wrapped/wrappedlibxrandr.c index ddc40c2eb..cc00de4c7 100644 --- a/src/wrapped/wrappedlibxrandr.c +++ b/src/wrapped/wrappedlibxrandr.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxrender.c b/src/wrapped/wrappedlibxrender.c index ba79706c0..6983b408a 100644 --- a/src/wrapped/wrappedlibxrender.c +++ b/src/wrapped/wrappedlibxrender.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxss.c b/src/wrapped/wrappedlibxss.c index 507216e16..06d4cd6e3 100644 --- a/src/wrapped/wrappedlibxss.c +++ b/src/wrapped/wrappedlibxss.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxt.c b/src/wrapped/wrappedlibxt.c index 4e305ee42..0bf3056fd 100644 --- a/src/wrapped/wrappedlibxt.c +++ b/src/wrapped/wrappedlibxt.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxtst.c b/src/wrapped/wrappedlibxtst.c index e17621a33..c18842a07 100644 --- a/src/wrapped/wrappedlibxtst.c +++ b/src/wrapped/wrappedlibxtst.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxxf86vm.c b/src/wrapped/wrappedlibxxf86vm.c index d5d04c332..104874386 100644 --- a/src/wrapped/wrappedlibxxf86vm.c +++ b/src/wrapped/wrappedlibxxf86vm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibz.c b/src/wrapped/wrappedlibz.c index e57fb21c1..2daf998e1 100644 --- a/src/wrapped/wrappedlibz.c +++ b/src/wrapped/wrappedlibz.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlz4.c b/src/wrapped/wrappedlz4.c index 1b789e75e..5e2867949 100644 --- a/src/wrapped/wrappedlz4.c +++ b/src/wrapped/wrappedlz4.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlzma.c b/src/wrapped/wrappedlzma.c index 6ccce691c..0c19775ed 100644 --- a/src/wrapped/wrappedlzma.c +++ b/src/wrapped/wrappedlzma.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedmimalloc.c b/src/wrapped/wrappedmimalloc.c index 242fd29d7..ce9b4409f 100644 --- a/src/wrapped/wrappedmimalloc.c +++ b/src/wrapped/wrappedmimalloc.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedmpg123.c b/src/wrapped/wrappedmpg123.c index 1f5fb47ed..ea6f3d166 100644 --- a/src/wrapped/wrappedmpg123.c +++ b/src/wrapped/wrappedmpg123.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappednotify.c b/src/wrapped/wrappednotify.c index 0d9954e59..27a2ee79a 100644 --- a/src/wrapped/wrappednotify.c +++ b/src/wrapped/wrappednotify.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappednsl.c b/src/wrapped/wrappednsl.c index fa47f9ec5..c410be90d 100644 --- a/src/wrapped/wrappednsl.c +++ b/src/wrapped/wrappednsl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappednspr4.c b/src/wrapped/wrappednspr4.c index 689dde185..6023f54a4 100644 --- a/src/wrapped/wrappednspr4.c +++ b/src/wrapped/wrappednspr4.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappednss3.c b/src/wrapped/wrappednss3.c index 39425ff55..5d3fa4625 100644 --- a/src/wrapped/wrappednss3.c +++ b/src/wrapped/wrappednss3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappednssutil3.c b/src/wrapped/wrappednssutil3.c index 045b0cb5a..dba8d0669 100644 --- a/src/wrapped/wrappednssutil3.c +++ b/src/wrapped/wrappednssutil3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappednvml.c b/src/wrapped/wrappednvml.c index 21acd75cc..9863535bc 100644 --- a/src/wrapped/wrappednvml.c +++ b/src/wrapped/wrappednvml.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedopenal.c b/src/wrapped/wrappedopenal.c index 76eb0f81c..3f56b888a 100644 --- a/src/wrapped/wrappedopenal.c +++ b/src/wrapped/wrappedopenal.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedopencl.c b/src/wrapped/wrappedopencl.c index 881b640a5..806b31e1e 100644 --- a/src/wrapped/wrappedopencl.c +++ b/src/wrapped/wrappedopencl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedp11kit.c b/src/wrapped/wrappedp11kit.c index 490d96fdf..ef8b33505 100644 --- a/src/wrapped/wrappedp11kit.c +++ b/src/wrapped/wrappedp11kit.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpam.c b/src/wrapped/wrappedpam.c index 7b5f22a52..31a1c5f92 100644 --- a/src/wrapped/wrappedpam.c +++ b/src/wrapped/wrappedpam.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpango.c b/src/wrapped/wrappedpango.c index b5c4a5a5f..86de1792d 100644 --- a/src/wrapped/wrappedpango.c +++ b/src/wrapped/wrappedpango.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpangocairo.c b/src/wrapped/wrappedpangocairo.c index 89a60438f..eb6bfb808 100644 --- a/src/wrapped/wrappedpangocairo.c +++ b/src/wrapped/wrappedpangocairo.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpangoft2.c b/src/wrapped/wrappedpangoft2.c index 7fb9d7077..182e8a1b9 100644 --- a/src/wrapped/wrappedpangoft2.c +++ b/src/wrapped/wrappedpangoft2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpcap.c b/src/wrapped/wrappedpcap.c index 188301b31..b0661f3a1 100644 --- a/src/wrapped/wrappedpcap.c +++ b/src/wrapped/wrappedpcap.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedpixman1.c b/src/wrapped/wrappedpixman1.c index 02b2c8a8d..77b029a0d 100644 --- a/src/wrapped/wrappedpixman1.c +++ b/src/wrapped/wrappedpixman1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedplc4.c b/src/wrapped/wrappedplc4.c index 0987cf42e..b4a083e9a 100644 --- a/src/wrapped/wrappedplc4.c +++ b/src/wrapped/wrappedplc4.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedplds4.c b/src/wrapped/wrappedplds4.c index 4fbcd07e3..0b5c39830 100644 --- a/src/wrapped/wrappedplds4.c +++ b/src/wrapped/wrappedplds4.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpng16.c b/src/wrapped/wrappedpng16.c index 98db87773..c08379457 100644 --- a/src/wrapped/wrappedpng16.c +++ b/src/wrapped/wrappedpng16.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedproxy.c b/src/wrapped/wrappedproxy.c index c423b81b7..97f4f745d 100644 --- a/src/wrapped/wrappedproxy.c +++ b/src/wrapped/wrappedproxy.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpsl5.c b/src/wrapped/wrappedpsl5.c index 9c196b281..7a548604e 100644 --- a/src/wrapped/wrappedpsl5.c +++ b/src/wrapped/wrappedpsl5.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpulse.c b/src/wrapped/wrappedpulse.c index af4dc3c72..d0a041876 100644 --- a/src/wrapped/wrappedpulse.c +++ b/src/wrapped/wrappedpulse.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedpulsemainloopglib.c b/src/wrapped/wrappedpulsemainloopglib.c index 3e03e05f5..72e5c9abd 100644 --- a/src/wrapped/wrappedpulsemainloopglib.c +++ b/src/wrapped/wrappedpulsemainloopglib.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpulsesimple.c b/src/wrapped/wrappedpulsesimple.c index 26f6d9339..1f60dca50 100644 --- a/src/wrapped/wrappedpulsesimple.c +++ b/src/wrapped/wrappedpulsesimple.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl1.c b/src/wrapped/wrappedsdl1.c index a257d4b02..a6c0acba9 100644 --- a/src/wrapped/wrappedsdl1.c +++ b/src/wrapped/wrappedsdl1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl1image.c b/src/wrapped/wrappedsdl1image.c index 39522662a..bcbff5522 100644 --- a/src/wrapped/wrappedsdl1image.c +++ b/src/wrapped/wrappedsdl1image.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl1mixer.c b/src/wrapped/wrappedsdl1mixer.c index 4ea78e97d..da53b37fe 100644 --- a/src/wrapped/wrappedsdl1mixer.c +++ b/src/wrapped/wrappedsdl1mixer.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl1net.c b/src/wrapped/wrappedsdl1net.c index f29aeb536..244330d64 100644 --- a/src/wrapped/wrappedsdl1net.c +++ b/src/wrapped/wrappedsdl1net.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl1sound.c b/src/wrapped/wrappedsdl1sound.c index 760a06a66..3538ecf45 100644 --- a/src/wrapped/wrappedsdl1sound.c +++ b/src/wrapped/wrappedsdl1sound.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl1ttf.c b/src/wrapped/wrappedsdl1ttf.c index 79c9d784d..051847e80 100644 --- a/src/wrapped/wrappedsdl1ttf.c +++ b/src/wrapped/wrappedsdl1ttf.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl2.c b/src/wrapped/wrappedsdl2.c index 7f482e6da..bee79df9e 100644 --- a/src/wrapped/wrappedsdl2.c +++ b/src/wrapped/wrappedsdl2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped/wrappedsdl2image.c b/src/wrapped/wrappedsdl2image.c index 2c15efdfe..8ebcc3aeb 100644 --- a/src/wrapped/wrappedsdl2image.c +++ b/src/wrapped/wrappedsdl2image.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl2mixer.c b/src/wrapped/wrappedsdl2mixer.c index 6b35e24c1..2864dac29 100644 --- a/src/wrapped/wrappedsdl2mixer.c +++ b/src/wrapped/wrappedsdl2mixer.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl2net.c b/src/wrapped/wrappedsdl2net.c index 05039c155..28ccf6ed3 100644 --- a/src/wrapped/wrappedsdl2net.c +++ b/src/wrapped/wrappedsdl2net.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl2ttf.c b/src/wrapped/wrappedsdl2ttf.c index 71951b566..55a4cb4b3 100644 --- a/src/wrapped/wrappedsdl2ttf.c +++ b/src/wrapped/wrappedsdl2ttf.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl3.c b/src/wrapped/wrappedsdl3.c index b71d4bde7..1bdd34a6f 100644 --- a/src/wrapped/wrappedsdl3.c +++ b/src/wrapped/wrappedsdl3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl3ttf.c b/src/wrapped/wrappedsdl3ttf.c index 7efcfd3bd..836d66acf 100644 --- a/src/wrapped/wrappedsdl3ttf.c +++ b/src/wrapped/wrappedsdl3ttf.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsecret1.c b/src/wrapped/wrappedsecret1.c index 058b91991..5cd189eed 100644 --- a/src/wrapped/wrappedsecret1.c +++ b/src/wrapped/wrappedsecret1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedselinux.c b/src/wrapped/wrappedselinux.c index 038b771c7..426607dcf 100644 --- a/src/wrapped/wrappedselinux.c +++ b/src/wrapped/wrappedselinux.c @@ -5,7 +5,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsmbclient.c b/src/wrapped/wrappedsmbclient.c index 7d4bbae25..659c6f269 100644 --- a/src/wrapped/wrappedsmbclient.c +++ b/src/wrapped/wrappedsmbclient.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsmime3.c b/src/wrapped/wrappedsmime3.c index 49a010332..d6f19dd8f 100644 --- a/src/wrapped/wrappedsmime3.c +++ b/src/wrapped/wrappedsmime3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsmpeg.c b/src/wrapped/wrappedsmpeg.c index f5242dbda..58a408d89 100644 --- a/src/wrapped/wrappedsmpeg.c +++ b/src/wrapped/wrappedsmpeg.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsmpeg2.c b/src/wrapped/wrappedsmpeg2.c index 0c06c9169..6985a7383 100644 --- a/src/wrapped/wrappedsmpeg2.c +++ b/src/wrapped/wrappedsmpeg2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsoftokn3.c b/src/wrapped/wrappedsoftokn3.c index 5115a3f78..feee9554f 100644 --- a/src/wrapped/wrappedsoftokn3.c +++ b/src/wrapped/wrappedsoftokn3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedssh4.c b/src/wrapped/wrappedssh4.c index 6c9a1757a..4613f7c7d 100644 --- a/src/wrapped/wrappedssh4.c +++ b/src/wrapped/wrappedssh4.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedssl3.c b/src/wrapped/wrappedssl3.c index 0f61b6f51..481a01b4d 100644 --- a/src/wrapped/wrappedssl3.c +++ b/src/wrapped/wrappedssl3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsystemd.c b/src/wrapped/wrappedsystemd.c index edb90fe77..ce9d94229 100644 --- a/src/wrapped/wrappedsystemd.c +++ b/src/wrapped/wrappedsystemd.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedtbbbind.c b/src/wrapped/wrappedtbbbind.c index cf8f94e74..0ba838c9e 100644 --- a/src/wrapped/wrappedtbbbind.c +++ b/src/wrapped/wrappedtbbbind.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedtbbmalloc.c b/src/wrapped/wrappedtbbmalloc.c index f3563a16f..822c65af0 100644 --- a/src/wrapped/wrappedtbbmalloc.c +++ b/src/wrapped/wrappedtbbmalloc.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedtbbmallocproxy.c b/src/wrapped/wrappedtbbmallocproxy.c index 78ee5e7b1..fb803969f 100644 --- a/src/wrapped/wrappedtbbmallocproxy.c +++ b/src/wrapped/wrappedtbbmallocproxy.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedtcmallocminimal.c b/src/wrapped/wrappedtcmallocminimal.c index cd1ed3ea2..f1912ac57 100644 --- a/src/wrapped/wrappedtcmallocminimal.c +++ b/src/wrapped/wrappedtcmallocminimal.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedtermuxexec.c b/src/wrapped/wrappedtermuxexec.c index 0fdf9f110..f7fcdda42 100644 --- a/src/wrapped/wrappedtermuxexec.c +++ b/src/wrapped/wrappedtermuxexec.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedudev0.c b/src/wrapped/wrappedudev0.c index 65eba557c..cf7aecb60 100644 --- a/src/wrapped/wrappedudev0.c +++ b/src/wrapped/wrappedudev0.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped/wrappedudev1.c b/src/wrapped/wrappedudev1.c index 57304fe96..58da26349 100644 --- a/src/wrapped/wrappedudev1.c +++ b/src/wrapped/wrappedudev1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped/wrappedunwind.c b/src/wrapped/wrappedunwind.c index aae8965a1..fa99bb80c 100644 --- a/src/wrapped/wrappedunwind.c +++ b/src/wrapped/wrappedunwind.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedutil.c b/src/wrapped/wrappedutil.c index 456a79b5d..8d09a6dd6 100644 --- a/src/wrapped/wrappedutil.c +++ b/src/wrapped/wrappedutil.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedvorbisfile.c b/src/wrapped/wrappedvorbisfile.c index 721b59d47..4a86f84ba 100644 --- a/src/wrapped/wrappedvorbisfile.c +++ b/src/wrapped/wrappedvorbisfile.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedvulkan.c b/src/wrapped/wrappedvulkan.c index adf0b938d..a88d7e30f 100644 --- a/src/wrapped/wrappedvulkan.c +++ b/src/wrapped/wrappedvulkan.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedwaylandclient.c b/src/wrapped/wrappedwaylandclient.c index ae548714c..c052e4707 100644 --- a/src/wrapped/wrappedwaylandclient.c +++ b/src/wrapped/wrappedwaylandclient.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped/wrappedwaylandcursor.c b/src/wrapped/wrappedwaylandcursor.c index fa2ad8b5f..e2fcd06d6 100644 --- a/src/wrapped/wrappedwaylandcursor.c +++ b/src/wrapped/wrappedwaylandcursor.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedwaylandegl.c b/src/wrapped/wrappedwaylandegl.c index 57da6b275..316614639 100644 --- a/src/wrapped/wrappedwaylandegl.c +++ b/src/wrapped/wrappedwaylandegl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedxinerama.c b/src/wrapped/wrappedxinerama.c index c83211a35..9ddf458ce 100644 --- a/src/wrapped/wrappedxinerama.c +++ b/src/wrapped/wrappedxinerama.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedxkbcommon.c b/src/wrapped/wrappedxkbcommon.c index 96c0d4aab..845163df7 100644 --- a/src/wrapped/wrappedxkbcommon.c +++ b/src/wrapped/wrappedxkbcommon.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedxkbcommonx11.c b/src/wrapped/wrappedxkbcommonx11.c index 91aa6d5b9..1546c9919 100644 --- a/src/wrapped/wrappedxkbcommonx11.c +++ b/src/wrapped/wrappedxkbcommonx11.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedxkbfile.c b/src/wrapped/wrappedxkbfile.c index 7b5130e6d..04c9c418a 100644 --- a/src/wrapped/wrappedxkbfile.c +++ b/src/wrapped/wrappedxkbfile.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedxkbregistry.c b/src/wrapped/wrappedxkbregistry.c index 957fc2848..81579623d 100644 --- a/src/wrapped/wrappedxkbregistry.c +++ b/src/wrapped/wrappedxkbregistry.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedxml2.c b/src/wrapped/wrappedxml2.c index 799e63676..26e9aece4 100644 --- a/src/wrapped/wrappedxml2.c +++ b/src/wrapped/wrappedxml2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped/wrappedxshmfence.c b/src/wrapped/wrappedxshmfence.c index 8baad58a5..3b45991f5 100644 --- a/src/wrapped/wrappedxshmfence.c +++ b/src/wrapped/wrappedxshmfence.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedxslt.c b/src/wrapped/wrappedxslt.c index e9dbb6ce9..fe299d6b6 100644 --- a/src/wrapped/wrappedxslt.c +++ b/src/wrapped/wrappedxslt.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedzstd.c b/src/wrapped/wrappedzstd.c index d0495f4db..fdb016466 100644 --- a/src/wrapped/wrappedzstd.c +++ b/src/wrapped/wrappedzstd.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped32/wrappedblkid.c b/src/wrapped32/wrappedblkid.c index 5e007e5a1..8edad5e42 100644 --- a/src/wrapped32/wrappedblkid.c +++ b/src/wrapped32/wrappedblkid.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedcairo.c b/src/wrapped32/wrappedcairo.c index 389a68825..c93512b55 100644 --- a/src/wrapped32/wrappedcairo.c +++ b/src/wrapped32/wrappedcairo.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedcurl.c b/src/wrapped32/wrappedcurl.c index 82fc7676c..af0471254 100644 --- a/src/wrapped32/wrappedcurl.c +++ b/src/wrapped32/wrappedcurl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappeddbus.c b/src/wrapped32/wrappeddbus.c index fc12e41eb..2f3a9983e 100644 --- a/src/wrapped32/wrappeddbus.c +++ b/src/wrapped32/wrappeddbus.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedexpat.c b/src/wrapped32/wrappedexpat.c index 5c7a7865f..b190d5236 100644 --- a/src/wrapped32/wrappedexpat.c +++ b/src/wrapped32/wrappedexpat.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped32/wrappedfontconfig.c b/src/wrapped32/wrappedfontconfig.c index c88b1a932..d0bd6cbeb 100644 --- a/src/wrapped32/wrappedfontconfig.c +++ b/src/wrapped32/wrappedfontconfig.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped32/wrappedfreetype.c b/src/wrapped32/wrappedfreetype.c index f7e0f26bf..702d876a4 100644 --- a/src/wrapped32/wrappedfreetype.c +++ b/src/wrapped32/wrappedfreetype.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedgbm.c b/src/wrapped32/wrappedgbm.c index cb8f54963..2ffaa6f04 100644 --- a/src/wrapped32/wrappedgbm.c +++ b/src/wrapped32/wrappedgbm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedgnutls.c b/src/wrapped32/wrappedgnutls.c index ac7cfbb39..b48a55b02 100644 --- a/src/wrapped32/wrappedgnutls.c +++ b/src/wrapped32/wrappedgnutls.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedldlinux.c b/src/wrapped32/wrappedldlinux.c index 869d60d9f..355af9f7e 100755 --- a/src/wrapped32/wrappedldlinux.c +++ b/src/wrapped32/wrappedldlinux.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped32/wrappedlibasound.c b/src/wrapped32/wrappedlibasound.c index f001b2e1d..ebc280c45 100644 --- a/src/wrapped32/wrappedlibasound.c +++ b/src/wrapped32/wrappedlibasound.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped32/wrappedlibc.c b/src/wrapped32/wrappedlibc.c index ae0af7f56..e420f91c9 100755 --- a/src/wrapped32/wrappedlibc.c +++ b/src/wrapped32/wrappedlibc.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include @@ -49,6 +48,7 @@ #endif #include #include +#include #include "wrappedlibs.h" @@ -207,7 +207,7 @@ struct i386_stat { uint32_t __unused5; } __attribute__((packed)); -static int FillStatFromStat64(int vers, const struct stat64 *st64, void *st32) +static int FillStatFromStat64(int vers, const struct stat *st64, void *st32) { struct i386_stat *i386st = (struct i386_stat *)st32; @@ -434,7 +434,7 @@ static void* findgloberrFct(void* fct) // filter_dir #define GO(A) \ static uintptr_t my32_filter_dir_fct_##A = 0; \ -static int my32_filter_dir_##A(const struct dirent64* a) \ +static int my32_filter_dir_##A(const struct dirent* a) \ { \ static struct i386_dirent d = {0}; \ UnalignDirent_32(a, &d); \ @@ -473,7 +473,7 @@ static void* findcompare_dirFct(void* fct) { if(!fct) return NULL; void* p; - if((p = GetNativeFnc((uintptr_t)fct))) { if(p==my32_alphasort64) return alphasort64; else return p; } + if((p = GetNativeFnc((uintptr_t)fct))) { if(p==my32_alphasort64) return alphasort; else return p; } #define GO(A) if(my32_compare_dir_fct_##A == (uintptr_t)fct) return my32_compare_dir_##A; SUPER() #undef GO @@ -486,7 +486,7 @@ static void* findcompare_dirFct(void* fct) // filter64 #define GO(A) \ static uintptr_t my32_filter64_fct_##A = 0; \ -static int my32_filter64_##A(const struct dirent64* a) \ +static int my32_filter64_##A(const struct dirent* a) \ { \ return (int)RunFunctionFmt(my32_filter64_fct_##A, "p", a); \ } @@ -509,7 +509,7 @@ static void* findfilter64Fct(void* fct) // compare64 #define GO(A) \ static uintptr_t my32_compare64_fct_##A = 0; \ -static int my32_compare64_##A(const struct dirent64* a, const struct dirent64* b) \ +static int my32_compare64_##A(const struct dirent* a, const struct dirent* b) \ { \ return (int)RunFunctionFmt(my32_compare64_fct_##A, "pp", a, b); \ } @@ -519,7 +519,7 @@ static void* findcompare64Fct(void* fct) { if(!fct) return NULL; void* p; - if((p = GetNativeFnc((uintptr_t)fct))) { if(p==my32_alphasort64) return alphasort64; else return p; } + if((p = GetNativeFnc((uintptr_t)fct))) { if(p==my32_alphasort64) return alphasort; else return p; } #define GO(A) if(my32_compare64_fct_##A == (uintptr_t)fct) return my32_compare64_##A; SUPER() #undef GO @@ -598,9 +598,9 @@ EXPORT int my32_fstatvfs(x64emu_t* emu, int fd, void* r) EXPORT int my32_fstatat(x64emu_t* emu, int fd, void* name, void* buff, int flags) { - struct stat64 s = {0}; - struct stat64* p = buff?&s:NULL; - int ret = fstatat64(fd, name, p, flags); + struct stat s = {0}; + struct stat* p = buff?&s:NULL; + int ret = fstatat(fd, name, p, flags); if(buff) FillStatFromStat64(3, &s, buff); return ret; @@ -608,9 +608,9 @@ EXPORT int my32_fstatat(x64emu_t* emu, int fd, void* name, void* buff, int flags EXPORT int my32_fstatat64(x64emu_t* emu, int fd, void* name, void* buff, int flags) { - struct stat64 s = {0}; - struct stat64* p = buff?&s:NULL; - int ret = fstatat64(fd, name, p, flags); + struct stat s = {0}; + struct stat* p = buff?&s:NULL; + int ret = fstatat(fd, name, p, flags); if(buff) UnalignStat64_32(&s, buff); return ret; @@ -618,9 +618,9 @@ EXPORT int my32_fstatat64(x64emu_t* emu, int fd, void* name, void* buff, int fla EXPORT int my32___stat64_time64(x64emu_t* emu, void* f, void* r) { - struct stat64 s = {0}; - struct stat64* p = r?&s:NULL; - int ret = stat64(f, p); + struct stat s = {0}; + struct stat* p = r?&s:NULL; + int ret = stat(f, p); if(r) UnalignStat64_32_t64(&s, r); return ret; @@ -628,9 +628,9 @@ EXPORT int my32___stat64_time64(x64emu_t* emu, void* f, void* r) EXPORT int my32___lstat64_time64(x64emu_t* emu, void* f, void* r) { - struct stat64 s = {0}; - struct stat64* p = r?&s:NULL; - int ret = lstat64(f, p); + struct stat s = {0}; + struct stat* p = r?&s:NULL; + int ret = lstat(f, p); if(r) UnalignStat64_32_t64(&s, r); return ret; @@ -638,9 +638,9 @@ EXPORT int my32___lstat64_time64(x64emu_t* emu, void* f, void* r) EXPORT int my32___fstat64_time64(x64emu_t* emu, int fd, void* r) { - struct stat64 s = {0}; - struct stat64* p = r?&s:NULL; - int ret = fstat64(fd, p); + struct stat s = {0}; + struct stat* p = r?&s:NULL; + int ret = fstat(fd, p); if(r) UnalignStat64_32_t64(&s, r); return ret; @@ -1230,32 +1230,32 @@ EXPORT void my32__ITM_deregisterTMCloneTable(x64emu_t* emu, void* p) {} EXPORT int my32_stat(char* path, void* buf) { - struct stat64 st; - int r = stat64(path, &st); + struct stat st; + int r = stat(path, &st); FillStatFromStat64(3, &st, buf); return r; } EXPORT int my32_fstat(int fd, void* buf) { - struct stat64 st; - int r = fstat64(fd, &st); + struct stat st; + int r = fstat(fd, &st); FillStatFromStat64(3, &st, buf); return r; } EXPORT int my32_lstat(char* path, void* buf) { - struct stat64 st; - int r = lstat64(path, &st); + struct stat st; + int r = lstat(path, &st); FillStatFromStat64(3, &st, buf); return r; } EXPORT int my32___fxstat(x64emu_t *emu, int vers, int fd, void* buf) { - struct stat64 st; - int r = fstat64(fd, &st); + struct stat st; + int r = fstat(fd, &st); if (r) return r; r = FillStatFromStat64(vers, &st, buf); return r; @@ -1263,8 +1263,8 @@ EXPORT int my32___fxstat(x64emu_t *emu, int vers, int fd, void* buf) EXPORT int my32___fxstat64(x64emu_t *emu, int vers, int fd, void* buf) { - struct stat64 st; - int r = fstat64(fd, &st); + struct stat st; + int r = fstat(fd, &st); //int r = syscall(__NR_stat64, fd, &st); UnalignStat64_32(&st, buf); return r; @@ -1293,30 +1293,30 @@ EXPORT int my32_statx(x64emu_t* emu, int dirfd, void* path, int flags, uint32_t EXPORT int my32_stat64(void* path, void* buf) { - struct stat64 st; - int r = stat64(path, &st); + struct stat st; + int r = stat(path, &st); UnalignStat64_32(&st, buf); return r; } EXPORT int my32_lstat64(void* path, void* buf) { - struct stat64 st; - int r = lstat64(path, &st); + struct stat st; + int r = lstat(path, &st); UnalignStat64_32(&st, buf); return r; } EXPORT int my32_fstat64(int fd, void* buf) { - struct stat64 st; - int r = fstat64(fd, &st); + struct stat st; + int r = fstat(fd, &st); UnalignStat64_32(&st, buf); return r; } EXPORT int my32___xstat(x64emu_t* emu, int v, void* path, void* buf) { - struct stat64 st; - int r = stat64((const char*)path, &st); + struct stat st; + int r = stat((const char*)path, &st); if (r) return r; r = FillStatFromStat64(v, &st, buf); return r; @@ -1324,16 +1324,16 @@ EXPORT int my32___xstat(x64emu_t* emu, int v, void* path, void* buf) EXPORT int my32___xstat64(x64emu_t* emu, int v, void* path, void* buf) { - struct stat64 st; - int r = stat64((const char*)path, &st); + struct stat st; + int r = stat((const char*)path, &st); UnalignStat64_32(&st, buf); return r; } EXPORT int my32___lxstat(x64emu_t* emu, int v, void* name, void* buf) { - struct stat64 st; - int r = lstat64((const char*)name, &st); + struct stat st; + int r = lstat((const char*)name, &st); if (r) return r; r = FillStatFromStat64(v, &st, buf); return r; @@ -1341,16 +1341,16 @@ EXPORT int my32___lxstat(x64emu_t* emu, int v, void* name, void* buf) EXPORT int my32___lxstat64(x64emu_t* emu, int v, void* name, void* buf) { - struct stat64 st; - int r = lstat64((const char*)name, &st); + struct stat st; + int r = lstat((const char*)name, &st); UnalignStat64_32(&st, buf); return r; } #if 0 EXPORT int my32___fxstatat(x64emu_t* emu, int v, int d, void* path, void* buf, int flags) { - struct stat64 st; - int r = fstatat64(d, path, &st, flags); + struct stat st; + int r = fstatat(d, path, &st, flags); if (r) return r; r = FillStatFromStat64(v, &st, buf); return r; @@ -1358,15 +1358,15 @@ EXPORT int my32___fxstatat(x64emu_t* emu, int v, int d, void* path, void* buf, i #endif EXPORT int my32___fxstatat64(x64emu_t* emu, int v, int d, void* path, void* buf, int flags) { - struct stat64 st; - int r = fstatat64(d, path, &st, flags); + struct stat st; + int r = fstatat(d, path, &st, flags); UnalignStat64_32(&st, buf); return r; } #if 0 EXPORT int my32__IO_file_stat(x64emu_t* emu, void* f, void* buf) { - struct stat64 st; + struct stat st; libc_my32_t *my = (libc_my32_t *)emu->context->libclib->priv.w.p2; int r = my->_IO_file_stat(f, &st); UnalignStat64(&st, buf); @@ -1375,30 +1375,30 @@ EXPORT int my32__IO_file_stat(x64emu_t* emu, void* f, void* buf) #endif EXPORT int my32_fstatfs(int fd, void* buf) { - struct statfs64 st; - int r = fstatfs64(fd, &st); + struct statfs st; + int r = fstatfs(fd, &st); UnalignStatFS_32(&st, buf); return r; } EXPORT int my32_fstatfs64(int fd, void* buf) { - struct statfs64 st; - int r = fstatfs64(fd, &st); + struct statfs st; + int r = fstatfs(fd, &st); UnalignStatFS64_32(&st, buf); return r; } EXPORT int my32_statfs(const char* path, void* buf) { - struct statfs64 st; - int r = statfs64(path, &st); + struct statfs st; + int r = statfs(path, &st); UnalignStatFS_32(&st, buf); return r; } EXPORT int my32_statfs64(const char* path, void* buf) { - struct statfs64 st; - int r = statfs64(path, &st); + struct statfs st; + int r = statfs(path, &st); UnalignStatFS64_32(&st, buf); return r; } @@ -1497,7 +1497,7 @@ EXPORT void* my32_fts_open(x64emu_t* emu, void* path, int options, void* c) EXPORT void* my32_readdir(x64emu_t* emu, void* dirp) { - struct dirent64 *dp64 = readdir64((DIR *)dirp); + struct dirent *dp64 = readdir((DIR *)dirp); if (!dp64) return NULL; static struct i386_dirent dp32 = {0}; uint32_t ino32 = dp64->d_ino ^ (dp64->d_ino >> 32); @@ -1513,7 +1513,7 @@ EXPORT void* my32_readdir(x64emu_t* emu, void* dirp) EXPORT int32_t my32_readdir_r(x64emu_t* emu, void* dirp, void* entry, void** result) { - struct dirent64 d64, *dp64; + struct dirent d64, *dp64; if (BOX64ENV(fix_64bit_inodes) && (sizeof(d64.d_name) > 1)) { static iFppp_t f = NULL; @@ -1524,7 +1524,7 @@ EXPORT int32_t my32_readdir_r(x64emu_t* emu, void* dirp, void* entry, void** res *result = NULL; return 0; } - f = (iFppp_t)dlsym(lib->priv.w.lib, "readdir64_r"); + f = (iFppp_t)dlsym(lib->priv.w.lib, "readdir_r"); } int r = f(dirp, &d64, &dp64); @@ -1535,7 +1535,7 @@ EXPORT int32_t my32_readdir_r(x64emu_t* emu, void* dirp, void* entry, void** res } struct i386_dirent *dp32 = (struct i386_dirent *)entry; - int namelen = dp64->d_reclen - offsetof(struct dirent64, d_name); + int namelen = dp64->d_reclen - offsetof(struct dirent, d_name); if (namelen > sizeof(dp32->d_name)) { *result = NULL; @@ -1695,18 +1695,18 @@ EXPORT int my32_mkstemps64(x64emu_t* emu, char* template, int suffixlen) sprintf(num, "%06d", rand()%999999); memcpy(fname+strlen(fname)-suffixlen-6, num, 6); } while(!FileExist(fname, -1)); - int ret = open64(fname, O_EXCL); + int ret = open(fname, O_EXCL); free(fname); return ret; } EXPORT int32_t my32_ftw(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd) { - return ftw64(pathname, findftwFct(B), nopenfd); + return ftw(pathname, findftwFct(B), nopenfd); } EXPORT int32_t my32_nftw(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd, int32_t flags) { - return nftw64(pathname, findnftwFct(B), nopenfd, flags); + return nftw(pathname, findnftwFct(B), nopenfd, flags); } EXPORT void* my32_ldiv(x64emu_t* emu, void* p, int32_t num, int32_t den) @@ -1752,7 +1752,7 @@ typedef struct my_glob_32_s ptr_t gl_lstat; //int (*gl_lstat) (const char *__restrict, struct stat *__restrict); ptr_t gl_stat; //int (*gl_stat) (const char *__restrict, struct stat *__restrict); } my_glob_32_t; -// glob64 is identical, except function are 64bits versions +// glob is identical, except function are 64bits versions static void convert_glob_to_32(void* d, void* s, int is64) { @@ -1783,54 +1783,54 @@ static void convert_glob_to_64(void* d, void* s, int is64) EXPORT int32_t my32_glob(x64emu_t *emu, void* pat, int32_t flags, void* errfnc, void* pglob) { - glob64_t glob_l = {0}; + glob_t glob_l = {0}; if(flags & GLOB_ALTDIRFUNC) printf_log(LOG_NONE, "Error: using unsupport GLOB_ALTDIRFUNC in glob\n"); if(flags&(1<<5)) // GLOB_APPEND is used, so convert also before convert_glob_to_64(&glob_l, pglob, 0); - int ret = glob64(pat, flags, findgloberrFct(errfnc), &glob_l); + int ret = glob(pat, flags, findgloberrFct(errfnc), &glob_l); convert_glob_to_32(pglob, &glob_l, 0); return ret; } EXPORT void my32_globfree(x64emu_t* emu, void* pglob) { - glob64_t glob_l = {0}; + glob_t glob_l = {0}; convert_glob_to_64(&glob_l, pglob, 0); - globfree64(&glob_l); + globfree(&glob_l); } #ifndef ANDROID EXPORT int32_t my32_glob64(x64emu_t *emu, void* pat, int32_t flags, void* errfnc, void* pglob) { - glob64_t glob_l = {0}; + glob_t glob_l = {0}; if(flags & GLOB_ALTDIRFUNC) printf_log(LOG_NONE, "Error: using unsupport GLOB_ALTDIRFUNC in glob64\n"); if(flags&(1<<5)) // GLOB_APPEND is used, so convert also before convert_glob_to_64(&glob_l, pglob, 1); - int ret = glob64(pat, flags, findgloberrFct(errfnc), &glob_l); + int ret = glob(pat, flags, findgloberrFct(errfnc), &glob_l); convert_glob_to_32(pglob, &glob_l, 1); return ret; } EXPORT void my32_globfree64(x64emu_t* emu, void* pglob) { - glob64_t glob_l = {0}; + glob_t glob_l = {0}; convert_glob_to_64(&glob_l, pglob, 1); - globfree64(&glob_l); + globfree(&glob_l); } #endif EXPORT int my32_scandir(x64emu_t *emu, void* dir, ptr_t* namelist, void* sel, void* comp) { - struct dirent64** list = NULL; - int ret = scandir64(dir, &list, findfilter_dirFct(sel), findcompare_dirFct(comp)); + struct dirent** list = NULL; + int ret = scandir(dir, &list, findfilter_dirFct(sel), findcompare_dirFct(comp)); *namelist = to_ptrv(list); if (ret>0) { // adjust the array of dirent... inplace adjust of listname and inplace of dirent too for(int i=0; id_ino ^ (dp64->d_ino >> 32); int32_t off32 = dp64->d_off; dp32->d_ino = ino32; dp32->d_off = off32; - dp32->d_reclen = dp64->d_reclen-(offsetof(struct dirent64, d_name)-offsetof(struct i386_dirent, d_name)); + dp32->d_reclen = dp64->d_reclen-(offsetof(struct dirent, d_name)-offsetof(struct i386_dirent, d_name)); dp32->d_type = dp64->d_type; memmove(dp32->d_name, dp64->d_name, dp32->d_reclen-offsetof(struct i386_dirent, d_name)); // inplace shrink pointer to @@ -1841,8 +1841,8 @@ EXPORT int my32_scandir(x64emu_t *emu, void* dir, ptr_t* namelist, void* sel, vo } EXPORT int my32_scandir64(x64emu_t *emu, void* dir, ptr_t* namelist, void* sel, void* comp) { - struct dirent64** list; - int ret = scandir64(dir, &list, findfilter64Fct(sel), findcompare64Fct(comp)); + struct dirent** list; + int ret = scandir(dir, &list, findfilter64Fct(sel), findcompare64Fct(comp)); if(ret>=0) *namelist = to_ptrv(list); if (ret>0) { @@ -1898,12 +1898,12 @@ EXPORT long my32_readv(x64emu_t* emu, int fd, struct i386_iovec* iov, int niov) EXPORT int my32_ftw64(x64emu_t* emu, void* filename, void* func, int descriptors) { - return ftw64(filename, findftw64Fct(func), descriptors); + return ftw(filename, findftw64Fct(func), descriptors); } EXPORT int32_t my32_nftw64(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd, int32_t flags) { - return nftw64(pathname, findnftw64Fct(B), nopenfd, flags); + return nftw(pathname, findnftw64Fct(B), nopenfd, flags); } EXPORT ptr_t my32_environ = 0; //char** @@ -2370,8 +2370,8 @@ EXPORT unsigned long int my32___fdelt_chk (unsigned long int d) EXPORT int my32_getrlimit(x64emu_t* emu, int what, uint32_t* pr) { - struct rlimit64 l = {0}; - int ret = getrlimit64(what, &l); + struct rlimit l = {0}; + int ret = getrlimit(what, &l); if(pr) { pr[0] = (l.rlim_cur<0x100000000LL)?l.rlim_cur:0xffffffff; pr[1] = (l.rlim_max<0x100000000LL)?l.rlim_max:0xffffffff; @@ -2380,10 +2380,10 @@ EXPORT int my32_getrlimit(x64emu_t* emu, int what, uint32_t* pr) } EXPORT int my32_setrlimit(x64emu_t* emu, int what, uint32_t* pr) { - struct rlimit64 l = {0}; + struct rlimit l = {0}; l.rlim_cur = (pr[0]!=0xffffffff)?pr[0]:0xffffffffffffffffLL; l.rlim_max = (pr[1]!=0xffffffff)?pr[1]:0xffffffffffffffffLL; - return setrlimit64(what, &l); + return setrlimit(what, &l); } EXPORT void* my32___localtime64(x64emu_t* emu, void* t) @@ -2788,13 +2788,13 @@ EXPORT int my32_getopt_long_only(int argc, char* const argv[], const char* optst EXPORT int my32_alphasort64(x64emu_t* emu, ptr_t* d1_, ptr_t* d2_) { - const struct dirent64* d1 = NULL; - const struct dirent64* d2 = NULL; - if(d1_) d1 = (struct dirent64*)from_ptrv(*d1_); - if(d2_) d2 = (struct dirent64*)from_ptrv(*d2_); - const struct dirent64** e1 = d1_?(&d1):NULL; - const struct dirent64** e2 = d2_?(&d2):NULL; - return alphasort64(e1, e2); + const struct dirent* d1 = NULL; + const struct dirent* d2 = NULL; + if(d1_) d1 = (struct dirent*)from_ptrv(*d1_); + if(d2_) d2 = (struct dirent*)from_ptrv(*d2_); + const struct dirent** e1 = d1_?(&d1):NULL; + const struct dirent** e2 = d2_?(&d2):NULL; + return alphasort(e1, e2); } #ifndef ANDROID @@ -3202,7 +3202,7 @@ static ssize_t my32_cookie_write(void *p, const char *buf, size_t size) my32_cookie_t* cookie = (my32_cookie_t*)p; return (ssize_t)RunFunction(my_context, cookie->w, 3, cookie->cookie, buf, size); } -static int my32_cookie_seek(void *p, off64_t *offset, int whence) +static int my32_cookie_seek(void *p, off_t *offset, int whence) { my32_cookie_t* cookie = (my32_cookie_t*)p; return RunFunction(my_context, cookie->s, 3, cookie->cookie, offset, whence); diff --git a/src/wrapped32/wrappedlibcups.c b/src/wrapped32/wrappedlibcups.c index 9ede52102..4b49afe71 100644 --- a/src/wrapped32/wrappedlibcups.c +++ b/src/wrapped32/wrappedlibcups.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibdl.c b/src/wrapped32/wrappedlibdl.c index 12039ad6f..379f588fc 100755 --- a/src/wrapped32/wrappedlibdl.c +++ b/src/wrapped32/wrappedlibdl.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped32/wrappedlibdrm.c b/src/wrapped32/wrappedlibdrm.c index d414763fe..55cb943d1 100644 --- a/src/wrapped32/wrappedlibdrm.c +++ b/src/wrapped32/wrappedlibdrm.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped32/wrappedlibegl.c b/src/wrapped32/wrappedlibegl.c index 3f72233ca..2e96e9027 100644 --- a/src/wrapped32/wrappedlibegl.c +++ b/src/wrapped32/wrappedlibegl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibgl.c b/src/wrapped32/wrappedlibgl.c index 06ad51e00..875c3a504 100644 --- a/src/wrapped32/wrappedlibgl.c +++ b/src/wrapped32/wrappedlibgl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibglu.c b/src/wrapped32/wrappedlibglu.c index 8558648d6..c8aa21eba 100644 --- a/src/wrapped32/wrappedlibglu.c +++ b/src/wrapped32/wrappedlibglu.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibglx.c b/src/wrapped32/wrappedlibglx.c index 305fd8478..76ce612cf 100644 --- a/src/wrapped32/wrappedlibglx.c +++ b/src/wrapped32/wrappedlibglx.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibglxnvidia.c b/src/wrapped32/wrappedlibglxnvidia.c index e5e8a23c1..b0543864b 100644 --- a/src/wrapped32/wrappedlibglxnvidia.c +++ b/src/wrapped32/wrappedlibglxnvidia.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibm.c b/src/wrapped32/wrappedlibm.c index dd0a6ab37..07bda89ab 100755 --- a/src/wrapped32/wrappedlibm.c +++ b/src/wrapped32/wrappedlibm.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped32/wrappedlibogg.c b/src/wrapped32/wrappedlibogg.c index 877b03853..1c32ebde5 100644 --- a/src/wrapped32/wrappedlibogg.c +++ b/src/wrapped32/wrappedlibogg.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibpthread.c b/src/wrapped32/wrappedlibpthread.c index 7c477c57a..1640580ad 100755 --- a/src/wrapped32/wrappedlibpthread.c +++ b/src/wrapped32/wrappedlibpthread.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped32/wrappedlibresolv.c b/src/wrapped32/wrappedlibresolv.c index cc0630564..0f4af9ebe 100644 --- a/src/wrapped32/wrappedlibresolv.c +++ b/src/wrapped32/wrappedlibresolv.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped32/wrappedlibrt.c b/src/wrapped32/wrappedlibrt.c index 0a72043d0..66e12e8d6 100755 --- a/src/wrapped32/wrappedlibrt.c +++ b/src/wrapped32/wrappedlibrt.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped32/wrappedlibuuid.c b/src/wrapped32/wrappedlibuuid.c index df5f67fa3..55c79094a 100644 --- a/src/wrapped32/wrappedlibuuid.c +++ b/src/wrapped32/wrappedlibuuid.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibvdpau.c b/src/wrapped32/wrappedlibvdpau.c index 5675e113d..da26c211e 100644 --- a/src/wrapped32/wrappedlibvdpau.c +++ b/src/wrapped32/wrappedlibvdpau.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibvorbis.c b/src/wrapped32/wrappedlibvorbis.c index e3d05c1b6..d86eaaeae 100644 --- a/src/wrapped32/wrappedlibvorbis.c +++ b/src/wrapped32/wrappedlibvorbis.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibx11.c b/src/wrapped32/wrappedlibx11.c index 34d5be1c9..71053b2ca 100644 --- a/src/wrapped32/wrappedlibx11.c +++ b/src/wrapped32/wrappedlibx11.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibx11xcb.c b/src/wrapped32/wrappedlibx11xcb.c index be3cfc4a3..e58f04462 100644 --- a/src/wrapped32/wrappedlibx11xcb.c +++ b/src/wrapped32/wrappedlibx11xcb.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxcb.c b/src/wrapped32/wrappedlibxcb.c index 4b676b7c8..d070f9020 100644 --- a/src/wrapped32/wrappedlibxcb.c +++ b/src/wrapped32/wrappedlibxcb.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxcbres.c b/src/wrapped32/wrappedlibxcbres.c index 8bffcf265..863702e25 100644 --- a/src/wrapped32/wrappedlibxcbres.c +++ b/src/wrapped32/wrappedlibxcbres.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxcomposite.c b/src/wrapped32/wrappedlibxcomposite.c index 38dd96035..eb5ca3411 100644 --- a/src/wrapped32/wrappedlibxcomposite.c +++ b/src/wrapped32/wrappedlibxcomposite.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxcursor.c b/src/wrapped32/wrappedlibxcursor.c index e0762b9ca..8f714a9c1 100644 --- a/src/wrapped32/wrappedlibxcursor.c +++ b/src/wrapped32/wrappedlibxcursor.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxdamage.c b/src/wrapped32/wrappedlibxdamage.c index 0b1520c60..98ce3fb8e 100644 --- a/src/wrapped32/wrappedlibxdamage.c +++ b/src/wrapped32/wrappedlibxdamage.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxext.c b/src/wrapped32/wrappedlibxext.c index e26b0cc08..a9c7d2a99 100644 --- a/src/wrapped32/wrappedlibxext.c +++ b/src/wrapped32/wrappedlibxext.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxfixes.c b/src/wrapped32/wrappedlibxfixes.c index 510482a9a..dfbb3a928 100644 --- a/src/wrapped32/wrappedlibxfixes.c +++ b/src/wrapped32/wrappedlibxfixes.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxi.c b/src/wrapped32/wrappedlibxi.c index 211f1fbeb..9dd4074bb 100644 --- a/src/wrapped32/wrappedlibxi.c +++ b/src/wrapped32/wrappedlibxi.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxrandr.c b/src/wrapped32/wrappedlibxrandr.c index 6ef7c7776..ea6f2a631 100644 --- a/src/wrapped32/wrappedlibxrandr.c +++ b/src/wrapped32/wrappedlibxrandr.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxrender.c b/src/wrapped32/wrappedlibxrender.c index 63702b647..c21fc5a9c 100644 --- a/src/wrapped32/wrappedlibxrender.c +++ b/src/wrapped32/wrappedlibxrender.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxss.c b/src/wrapped32/wrappedlibxss.c index 5598da659..db173c341 100644 --- a/src/wrapped32/wrappedlibxss.c +++ b/src/wrapped32/wrappedlibxss.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxxf86vm.c b/src/wrapped32/wrappedlibxxf86vm.c index d3d1ea498..dd1d60c08 100644 --- a/src/wrapped32/wrappedlibxxf86vm.c +++ b/src/wrapped32/wrappedlibxxf86vm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedmount.c b/src/wrapped32/wrappedmount.c index 7b70b1dd3..a530afa9a 100644 --- a/src/wrapped32/wrappedmount.c +++ b/src/wrapped32/wrappedmount.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappednsl.c b/src/wrapped32/wrappednsl.c index d410a31cc..fbe931cfb 100644 --- a/src/wrapped32/wrappednsl.c +++ b/src/wrapped32/wrappednsl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappednvml.c b/src/wrapped32/wrappednvml.c index e45ac7b88..b52cc178c 100644 --- a/src/wrapped32/wrappednvml.c +++ b/src/wrapped32/wrappednvml.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedopenal.c b/src/wrapped32/wrappedopenal.c index c3ae726e8..5cacb9655 100644 --- a/src/wrapped32/wrappedopenal.c +++ b/src/wrapped32/wrappedopenal.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedpulsesimple.c b/src/wrapped32/wrappedpulsesimple.c index bea4f1b7a..88015c1b2 100644 --- a/src/wrapped32/wrappedpulsesimple.c +++ b/src/wrapped32/wrappedpulsesimple.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedsdl1.c b/src/wrapped32/wrappedsdl1.c index 92f6fad54..399a593fe 100644 --- a/src/wrapped32/wrappedsdl1.c +++ b/src/wrapped32/wrappedsdl1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedsdl2.c b/src/wrapped32/wrappedsdl2.c index 842934f6c..55369dd6c 100644 --- a/src/wrapped32/wrappedsdl2.c +++ b/src/wrapped32/wrappedsdl2.c @@ -3,7 +3,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedsdl2image.c b/src/wrapped32/wrappedsdl2image.c index 3f07cf1bf..a9e20e064 100644 --- a/src/wrapped32/wrappedsdl2image.c +++ b/src/wrapped32/wrappedsdl2image.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedselinux.c b/src/wrapped32/wrappedselinux.c index b7a8d0bab..f6ce6b5a9 100644 --- a/src/wrapped32/wrappedselinux.c +++ b/src/wrapped32/wrappedselinux.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedtcmallocminimal.c b/src/wrapped32/wrappedtcmallocminimal.c index 154cdfcab..627603d34 100644 --- a/src/wrapped32/wrappedtcmallocminimal.c +++ b/src/wrapped32/wrappedtcmallocminimal.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedudev0.c b/src/wrapped32/wrappedudev0.c index 365756218..39caea560 100644 --- a/src/wrapped32/wrappedudev0.c +++ b/src/wrapped32/wrappedudev0.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped32/wrappedudev1.c b/src/wrapped32/wrappedudev1.c index bd0d602a8..0ccc7f097 100644 --- a/src/wrapped32/wrappedudev1.c +++ b/src/wrapped32/wrappedudev1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped32/wrappedxinerama.c b/src/wrapped32/wrappedxinerama.c index 534f55c23..61d340fd8 100644 --- a/src/wrapped32/wrappedxinerama.c +++ b/src/wrapped32/wrappedxinerama.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/tests/test17.c b/tests/test17.c index 9e5260fbf..19607d1f1 100644 --- a/tests/test17.c +++ b/tests/test17.c @@ -148,7 +148,7 @@ void print_64(v128 v) { #define print_128 print_64 void print_ps(v128 v) { for(int i=0; i<4; ++i) - if(isnanf(v.f32[i])) + if(isnan(v.f32[i])) printf("nan "); else printf("%g ", v.f32[i]); diff --git a/tests/test30.c b/tests/test30.c index e611306fd..21ec6c177 100644 --- a/tests/test30.c +++ b/tests/test30.c @@ -163,7 +163,7 @@ void print_64(v128 v) { #define print_128 print_64 void print_ps(v128 v) { for(int i=0; i<4; ++i) - if(isnanf(v.f32[i])) + if(isnan(v.f32[i])) printf("%cnan ", (v.u32[i]&0x80000000)?'-':'+'); else printf("%g ", v.f32[i]); diff --git a/tests32/test17.c b/tests32/test17.c index 04968b6f4..f4c7d6e1c 100644 --- a/tests32/test17.c +++ b/tests32/test17.c @@ -148,7 +148,7 @@ void print_64(v128 v) { #define print_128 print_64 void print_ps(v128 v) { for(int i=0; i<4; ++i) - if(isnanf(v.f32[i])) + if(isnan(v.f32[i])) printf("nan "); else printf("%g ", v.f32[i]); diff --git a/wrapperhelper/example-libc.h b/wrapperhelper/example-libc.h index 4ead3e38a..d65d4acc4 100644 --- a/wrapperhelper/example-libc.h +++ b/wrapperhelper/example-libc.h @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE 1 #define __USE_MISC 1 #define PORTMAP From c2b5bb536a272d115424f56c54111a44671d8e84 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 9 Nov 2026 16:47:00 +0800 Subject: [PATCH 155/156] [WRAPPER] Added wl_proxy_add_dispatcher to wayland-client (#4686) --- src/wrapped/generated/functions_list.txt | 2 ++ .../generated/wrappedwaylandclienttypes.h | 4 ++- src/wrapped/wrappedwaylandclient.c | 29 +++++++++++++++++++ src/wrapped/wrappedwaylandclient_private.h | 2 +- 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/wrapped/generated/functions_list.txt b/src/wrapped/generated/functions_list.txt index 1d5802a78..729135dc4 100644 --- a/src/wrapped/generated/functions_list.txt +++ b/src/wrapped/generated/functions_list.txt @@ -7743,6 +7743,8 @@ wrappedwaylandclient: - wl_log_set_handler_client - iFppp: - wl_proxy_add_listener +- iFpppp: + - wl_proxy_add_dispatcher wrappedwaylandcursor: wrappedwaylandegl: wrappedxinerama: diff --git a/src/wrapped/generated/wrappedwaylandclienttypes.h b/src/wrapped/generated/wrappedwaylandclienttypes.h index 0b22de652..5fc4a674f 100644 --- a/src/wrapped/generated/wrappedwaylandclienttypes.h +++ b/src/wrapped/generated/wrappedwaylandclienttypes.h @@ -14,9 +14,11 @@ typedef void (*vFp_t)(void*); typedef int32_t (*iFppp_t)(void*, void*, void*); +typedef int32_t (*iFpppp_t)(void*, void*, void*, void*); #define SUPER() ADDED_FUNCTIONS() \ GO(wl_log_set_handler_client, vFp_t) \ - GO(wl_proxy_add_listener, iFppp_t) + GO(wl_proxy_add_listener, iFppp_t) \ + GO(wl_proxy_add_dispatcher, iFpppp_t) #endif // __wrappedwaylandclientTYPES_H_ diff --git a/src/wrapped/wrappedwaylandclient.c b/src/wrapped/wrappedwaylandclient.c index c052e4707..1bf5f4185 100644 --- a/src/wrapped/wrappedwaylandclient.c +++ b/src/wrapped/wrappedwaylandclient.c @@ -74,6 +74,29 @@ static void* find_wl_log_func_t_Fct(void* fct) return NULL; } +//wl_dispatcher_func_t +#define GO(A) \ +static uintptr_t my_wl_dispatcher_func_t_fct_##A = 0; \ +static int my_wl_dispatcher_func_t_##A(const void* user_data, void* target, uint32_t opcode, const void* msg, void* args) \ +{ \ + return (int)RunFunctionFmt(my_wl_dispatcher_func_t_fct_##A, "ppupp", user_data, target, opcode, msg, args); \ +} +SUPER() +#undef GO +static void* find_wl_dispatcher_func_t_Fct(void* fct) +{ + if(!fct) return fct; + if(GetNativeFnc((uintptr_t)fct)) return GetNativeFnc((uintptr_t)fct); + #define GO(A) if(my_wl_dispatcher_func_t_fct_##A == (uintptr_t)fct) return my_wl_dispatcher_func_t_##A; + SUPER() + #undef GO + #define GO(A) if(my_wl_dispatcher_func_t_fct_##A == 0) {my_wl_dispatcher_func_t_fct_##A = (uintptr_t)fct; return my_wl_dispatcher_func_t_##A; } + SUPER() + #undef GO + printf_log(LOG_NONE, "Warning, no more slot for wayland-client wl_dispatcher_func_t callback\n"); + return NULL; +} + // wl_registry_listener ... typedef struct my_wl_registry_listener_s { uintptr_t global; //vFppupu @@ -1633,6 +1656,12 @@ static void* find_gtk_surface1_listener_Fct(void* fct) } #undef SUPER +EXPORT int my_wl_proxy_add_dispatcher(x64emu_t* emu, void* proxy, void* dispatcher_func, void* dispatcher_data, void* data) +{ + if (!proxy) return -1; + return my->wl_proxy_add_dispatcher(proxy, find_wl_dispatcher_func_t_Fct(dispatcher_func), dispatcher_data, data); +} + EXPORT int my_wl_proxy_add_listener(x64emu_t* emu, void* proxy, void** l, void* data) { if (!proxy) return -1; diff --git a/src/wrapped/wrappedwaylandclient_private.h b/src/wrapped/wrappedwaylandclient_private.h index 9a3b2a6fa..e02998cd1 100644 --- a/src/wrapped/wrappedwaylandclient_private.h +++ b/src/wrapped/wrappedwaylandclient_private.h @@ -45,7 +45,7 @@ GO(wl_list_remove, vFp) GOM(wl_log_set_handler_client, vFEp) DATA(wl_output_interface, 40) DATA(wl_pointer_interface, 40) -//GOM(wl_proxy_add_dispatcher, iFEpppp) +GOM(wl_proxy_add_dispatcher, iFEpppp) GOM(wl_proxy_add_listener, iFEppp) GO(wl_proxy_create, pFpp) GO(wl_proxy_create_wrapper, pFp) From 25d0e4c6c4868491f7d58b0484b7437fcdfcbe34 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 9 Nov 2026 17:46:34 +0800 Subject: [PATCH 156/156] [WRAPPER] Fixed my_execve path check for wrapped libc allocations (#4687) --- src/wrapped/wrappedlibc.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index 39f07fcae..e59bf76f4 100644 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -2161,6 +2161,17 @@ static long isProcMem(const char* path) } #define MAX_PATH_LENGTH 4096 +static int isPathPageReadable(uintptr_t page) +{ +#ifdef __NR_process_vm_readv + char c; + struct iovec local = { &c, 1 }; + struct iovec remote = { (void*)page, 1 }; + return syscall(__NR_process_vm_readv, getpid(), &local, 1, &remote, 1, 0) == 1; +#else + return 0; +#endif +} static int isPathValid(const char* path) { if(!path) @@ -2171,7 +2182,7 @@ static int isPathValid(const char* path) uintptr_t page = ALIGN_DOWN(p + i); if(page != cache_page) { cache_page = page; - if(!(getProtection_fast(cache_page) & PROT_READ)) + if(!(getProtection_fast(cache_page) & PROT_READ) && !isPathPageReadable(cache_page)) return 0; } if(!path[i])