diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2025-05-07 22:50:37 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-07 16:50:37 +0200 |
| commit | 5d14413b89d7bb78023307fc59d2d9da182554a4 (patch) | |
| tree | 3822c9835ff42632837da6dde40a292e7048247f /src/dynarec | |
| parent | ec549690944d2768b811340bc999abdfbc60ca2c (diff) | |
| download | box64-5d14413b89d7bb78023307fc59d2d9da182554a4.tar.gz box64-5d14413b89d7bb78023307fc59d2d9da182554a4.zip | |
[DYNAREC] Use PE volatile metadata in dynarec (#2610)
Diffstat (limited to 'src/dynarec')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_00.c | 6 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.c | 11 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.h | 6 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_private.h | 8 | ||||
| -rw-r--r-- | src/dynarec/dynarec_helper.h | 102 | ||||
| -rw-r--r-- | src/dynarec/dynarec_native_pass.c | 23 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_00.c | 6 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.c | 10 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.h | 6 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_private.h | 8 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_3.c | 6 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.c | 10 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 6 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_private.h | 8 |
14 files changed, 132 insertions, 84 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 34913701..351e1e0a 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -2387,7 +2387,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next i32 = F16; - retn_to_epilog(dyn, ninst, rex, i32); + retn_to_epilog(dyn, ip, ninst, rex, i32); *need_epilog = 0; *ok = 0; break; @@ -2398,7 +2398,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin READFLAGS(X_PEND); // so instead, force the deferred flags, so it's not too slow, and flags are not lost } fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next - ret_to_epilog(dyn, ninst, rex); + ret_to_epilog(dyn, ip, ninst, rex); *need_epilog = 0; *ok = 0; break; @@ -2724,7 +2724,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin INST_NAME("IRET"); SETFLAGS(X_ALL, SF_SET_NODF); // Not a hack, EFLAGS are restored BARRIER(BARRIER_FLOAT); - iret_to_epilog(dyn, ninst, rex.is32bits, rex.w); + iret_to_epilog(dyn, ip, ninst, rex.is32bits, rex.w); *need_epilog = 0; *ok = 0; break; diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index 51f619b2..32f03214 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -30,7 +30,10 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u { MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta); - if(l==LOCK_LOCK) { /*SMDMB();*/DMB_ISH(); } + if (l == LOCK_LOCK) { + dyn->insts[ninst].lock_prefixed = 1; + DMB_ISH(); + } if(rex.is32bits) return geted_32(dyn, addr, ninst, nextop, ed, hint, fixaddress, unscaled, absmax, mask, l, s); @@ -617,7 +620,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32 #endif } -void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex) +void ret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex) { MAYUSE(dyn); MAYUSE(ninst); MESSAGE(LOG_DUMP, "Ret to epilog\n"); @@ -658,7 +661,7 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex) CLEARIP(); } -void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n) +void retn_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n) { MAYUSE(dyn); MAYUSE(ninst); MESSAGE(LOG_DUMP, "Retn to epilog\n"); @@ -705,7 +708,7 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n) CLEARIP(); } -void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is32bits, int is64bits) +void iret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, int is64bits) { int64_t j64; //#warning TODO: is64bits diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index fa3cff10..f36601e6 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -1479,9 +1479,9 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, // generic x64 helper void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst); void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32bits); -void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex); -void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n); -void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is32bits, int is64bits); +void ret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex); +void retn_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n); +void iret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, int is64bits); void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg); void call_i(dynarec_arm_t* dyn, int ninst, void* fnc); void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w); diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h index ae615571..60c24aa2 100644 --- a/src/dynarec/arm64/dynarec_arm64_private.h +++ b/src/dynarec/arm64/dynarec_arm64_private.h @@ -109,9 +109,11 @@ typedef struct instruction_arm64_s { uint16_t ymm0_out; // the ymm0 at th end of the opcode uint16_t ymm0_pass2, ymm0_pass3; uint8_t barrier_maybe; - uint8_t will_write:2; // [strongmem] will write to memory - uint8_t last_write:1; // [strongmem] the last write in a SEQ - uint8_t lock:1; // [strongmem] lock semantic + uint8_t will_write:2; // [strongmem] will write to memory + uint8_t will_read:1; // [strongmem] will read from memory + uint8_t last_write:1; // [strongmem] the last write in a SEQ + uint8_t lock:1; // [strongmem] lock semantic + uint8_t lock_prefixed:1; // [strongmem] the opcode is lock prefixed uint8_t wfe:1; // opcode uses sevl + wfe uint8_t set_nat_flags; // 0 or combinaison of native flags define uint8_t use_nat_flags; // 0 or combinaison of native flags define diff --git a/src/dynarec/dynarec_helper.h b/src/dynarec/dynarec_helper.h index d8b0eb52..f5fbfeee 100644 --- a/src/dynarec/dynarec_helper.h +++ b/src/dynarec/dynarec_helper.h @@ -1,6 +1,10 @@ #ifndef __DYNAREC_HELPER__H_ #define __DYNAREC_HELPER__H_ +#include "env.h" +#include "pe_tools.h" +#include "debug.h" + /* Box64 Strong Memory Model Emulation * * Definition of a SEQ: @@ -32,6 +36,8 @@ #define STRONGMEM_LAST_WRITE 1 // The level of a barrier before the last guest memory store will be put #define STRONGMEM_SEQ_WRITE 3 // The level of a barrier at every third memory store will be put +#define STRONGMEM_LEVEL() (box64_wine && VolatileRangesContains(ip) ? 0 : BOX64DRENV(dynarec_strongmem)) + #if STEP == 1 #define SMWRITE() \ @@ -49,15 +55,20 @@ SMWRITE(); \ } while (0) -#define SMWRITE2() \ - do { \ - if (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_SIMD_WRITE) { \ - dyn->smwrite = 1; \ - dyn->insts[ninst].will_write = 2; \ - } \ +#define SMWRITE2() \ + do { \ + if (STRONGMEM_LEVEL() >= STRONGMEM_SIMD_WRITE) { \ + dyn->smwrite = 1; \ + dyn->insts[ninst].will_write = 2; \ + } \ + } while (0) + +#define SMREAD() \ + do { \ + /* Mark that current opcode read from guest memory. */ \ + dyn->insts[ninst].will_read = 1; \ } while (0) -#define SMREAD() #define SMREADLOCK(lock) #define WILLWRITE() #define WILLWRITELOCK(lock) @@ -71,7 +82,7 @@ #define SMEND() \ do { \ /* If there is any guest memory write, which is a SEQ, then compute the last_write. */ \ - if (dyn->smwrite && (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_LAST_WRITE)) { \ + if (dyn->smwrite && (STRONGMEM_LEVEL() >= STRONGMEM_LAST_WRITE)) { \ int i = ninst; \ while (i >= 0 && !dyn->insts[i].will_write) \ --i; \ @@ -85,22 +96,23 @@ #else // An opcode writes guest memory, this need to be put after the STORE instruction manually. It will also end the SEQ automaticaly on last_write immediatly -#define SMWRITE() \ - do { \ - if(dyn->insts[ninst].last_write) { \ - dyn->smwrite = 1; \ - SMEND(); \ - } else { \ - /* Put a barrier at every third memory write. */ \ - if (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_SEQ_WRITE) { \ - if (++dyn->smwrite >= 3 /* Every third memory write */) { \ - DMB_ISH(); \ - dyn->smwrite = 1; \ - } \ - } else { \ - /* Mark that current sequence writes to guest memory. */ \ - dyn->smwrite = 1; \ - } } \ +#define SMWRITE() \ + do { \ + if (dyn->insts[ninst].last_write) { \ + dyn->smwrite = 1; \ + SMEND(); \ + } else { \ + /* Put a barrier at every third memory write. */ \ + if (STRONGMEM_LEVEL() >= STRONGMEM_SEQ_WRITE) { \ + if (++dyn->smwrite >= 3 /* Every third memory write */) { \ + DMB_ISH(); \ + dyn->smwrite = 1; \ + } \ + } else { \ + /* Mark that current sequence writes to guest memory. */ \ + dyn->smwrite = 1; \ + } \ + } \ } while (0) // Similar to SMWRITE, but checks lock. @@ -114,10 +126,10 @@ } while (0) // Similar to SMWRITE, but for SIMD instructions. -#define SMWRITE2() \ - do { \ - if (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_SIMD_WRITE) \ - SMWRITE(); \ +#define SMWRITE2() \ + do { \ + if (STRONGMEM_LEVEL() >= STRONGMEM_SIMD_WRITE) \ + SMWRITE(); \ } while (0) // An opcode reads guest memory, this need to be put before the LOAD instruction manually. @@ -134,22 +146,22 @@ } while (0) // An opcode will write memory, this will be put before the STORE instruction automatically. -#define WILLWRITE() \ - do { \ - if (BOX64DRENV(dynarec_strongmem) >= dyn->insts[ninst].will_write && dyn->smwrite == 0) { \ - /* Will write but never written, this is the start of a SEQ, put a barrier. */ \ - if (BOX64ENV(dynarec_weakbarrier)) \ - DMB_ISHLD(); \ - else \ - DMB_ISH(); \ - } else if (BOX64DRENV(dynarec_strongmem) >= 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(); \ - } \ +#define WILLWRITE() \ + do { \ + if (STRONGMEM_LEVEL() >= dyn->insts[ninst].will_write && dyn->smwrite == 0) { \ + /* Will write but never written, this is the start of a SEQ, put a barrier. */ \ + if (BOX64ENV(dynarec_weakbarrier)) \ + DMB_ISHLD(); \ + else \ + DMB_ISH(); \ + } 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(); \ + } \ } while (0) // Similar to WILLWRITE, but checks lock. @@ -171,7 +183,7 @@ // Will be put at the end of the SEQ #define SMEND() \ do { \ - if (BOX64DRENV(dynarec_strongmem)) { \ + if (STRONGMEM_LEVEL()) { \ /* It's a SEQ, put a barrier here. */ \ if (dyn->smwrite) { \ /* Check if the next instruction has a end loop mark */ \ diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index 1f55ada4..eab3e10b 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -18,6 +18,7 @@ #include "dynablock_private.h" #include "custommem.h" #include "x64test.h" +#include "pe_tools.h" #include "dynarec_arch.h" #include "dynarec_helper.h" @@ -132,6 +133,14 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int } else if (dyn->insts[ninst].will_write) { WILLWRITE(); } + + int is_opcode_volatile = box64_wine && VolatileRangesContains(ip); + if (is_opcode_volatile && !dyn->insts[ninst].lock_prefixed) { + if (dyn->insts[ninst].will_write) + DMB_ISH(); + else if (dyn->insts[ninst].will_read) + DMB_ISHLD(); + } #endif if((dyn->insts[ninst].x64.need_before&~X_PEND) && !ninst) { READFLAGS(dyn->insts[ninst].x64.need_before&~X_PEND); @@ -149,7 +158,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int 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); } -#ifdef HAVE_TRACE + #ifdef HAVE_TRACE else if(my_context->dec && BOX64ENV(dynarec_trace)) { if((trace_end == 0) || ((ip >= trace_start) && (ip < trace_end))) { @@ -160,7 +169,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int MESSAGE(LOG_DUMP, "----------\n"); } } -#endif + #endif rep = 0; uint8_t pk = PK(0); @@ -187,6 +196,16 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int if(dyn->abort) return ip; INST_EPILOG; + + #if STEP > 1 + if (is_opcode_volatile && !dyn->insts[ninst].lock_prefixed) { + if (dyn->insts[ninst].will_write) + DMB_ISHST(); + else if (dyn->insts[ninst].will_read) + DMB_ISHLD(); + } + #endif + fpu_reset_scratch(dyn); int next = ninst+1; #if STEP > 0 diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c index b44b3e75..4811bbac 100644 --- a/src/dynarec/la64/dynarec_la64_00.c +++ b/src/dynarec/la64/dynarec_la64_00.c @@ -1854,7 +1854,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next i32 = F16; - retn_to_epilog(dyn, ninst, rex, i32); + retn_to_epilog(dyn, ip, ninst, rex, i32); *need_epilog = 0; *ok = 0; break; @@ -1864,7 +1864,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni READFLAGS(X_PEND); // so instead, force the deferred flags, so it's not too slow, and flags are not lost } fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next - ret_to_epilog(dyn, ninst, rex); + ret_to_epilog(dyn, ip, ninst, rex); *need_epilog = 0; *ok = 0; break; @@ -2032,7 +2032,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("IRET"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Not a hack, EFLAGS are restored BARRIER(BARRIER_FLOAT); - iret_to_epilog(dyn, ninst, rex.w); + iret_to_epilog(dyn, ip, ninst, rex.w); *need_epilog = 0; *ok = 0; break; diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c index c76690d9..b6fc31c2 100644 --- a/src/dynarec/la64/dynarec_la64_helper.c +++ b/src/dynarec/la64/dynarec_la64_helper.c @@ -35,6 +35,10 @@ uintptr_t geted(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, MAYUSE(ninst); MAYUSE(delta); + if (l == LOCK_LOCK) { + dyn->insts[ninst].lock_prefixed = 1; + } + if (rex.is32bits) return geted_32(dyn, addr, ninst, nextop, ed, hint, scratch, fixaddress, l, i12); @@ -572,7 +576,7 @@ void jump_to_next(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 JIRL((dyn->insts[ninst].x64.has_callret ? xRA : xZR), x2, 0x0); // save LR... } -void ret_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex) +void ret_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex) { MAYUSE(dyn); MAYUSE(ninst); @@ -611,7 +615,7 @@ void ret_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex) CLEARIP(); } -void retn_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex, int n) +void retn_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n) { MAYUSE(dyn); MAYUSE(ninst); @@ -656,7 +660,7 @@ void retn_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex, int n) CLEARIP(); } -void iret_to_epilog(dynarec_la64_t* dyn, int ninst, int is64bits) +void iret_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, int is64bits) { // #warning TODO: is64bits MAYUSE(ninst); diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index 7d472bf6..8dfa9970 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -1011,9 +1011,9 @@ uintptr_t geted32(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop void jump_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst); void jump_to_epilog_fast(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst); void jump_to_next(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst, int is32bits); -void ret_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex); -void retn_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex, int n); -void iret_to_epilog(dynarec_la64_t* dyn, int ninst, int is64bits); +void ret_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex); +void retn_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n); +void iret_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, int is64bits); void call_c(dynarec_la64_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg); void grab_segdata(dynarec_la64_t* dyn, uintptr_t addr, int ninst, int reg, int segment, int modreg); void emit_cmp8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5, int s6); diff --git a/src/dynarec/la64/dynarec_la64_private.h b/src/dynarec/la64/dynarec_la64_private.h index 2244b122..4bc621bd 100644 --- a/src/dynarec/la64/dynarec_la64_private.h +++ b/src/dynarec/la64/dynarec_la64_private.h @@ -93,9 +93,11 @@ typedef struct instruction_la64_s { uint16_t ymm0_out; // the ymm0 at th end of the opcode uint16_t ymm0_pass2, ymm0_pass3; uint8_t barrier_maybe; - uint8_t will_write; - uint8_t last_write; - uint8_t lock; + uint8_t will_write:2; // [strongmem] will write to memory + uint8_t will_read:1; // [strongmem] will read from memory + uint8_t last_write:1; // [strongmem] the last write in a SEQ + uint8_t lock:1; // [strongmem] lock semantic + uint8_t lock_prefixed:1; // [strongmem] the opcode is lock prefixed uint8_t df_notneeded; uint8_t nat_flags_fusion:1; uint8_t nat_flags_nofusion:1; diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 2dfa119e..c10742db 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -285,7 +285,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next i32 = F16; - retn_to_epilog(dyn, ninst, rex, i32); + retn_to_epilog(dyn, ip, ninst, rex, i32); *need_epilog = 0; *ok = 0; break; @@ -296,7 +296,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 } fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next - ret_to_epilog(dyn, ninst, rex); + ret_to_epilog(dyn, ip, ninst, rex); *need_epilog = 0; *ok = 0; break; @@ -553,7 +553,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("IRET"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Not a hack, EFLAGS are restored BARRIER(BARRIER_FLOAT); - iret_to_epilog(dyn, ninst, rex.w); + iret_to_epilog(dyn, ip, ninst, rex.w); *need_epilog = 0; *ok = 0; break; diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index f436ea18..4d584d35 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -34,6 +34,10 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, MAYUSE(ninst); MAYUSE(delta); + if (l == LOCK_LOCK) { + dyn->insts[ninst].lock_prefixed = 1; + } + if (rex.is32bits) return geted_32(dyn, addr, ninst, nextop, ed, hint, scratch, fixaddress, l, i12); @@ -601,7 +605,7 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 #endif } -void ret_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex) +void ret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex) { MAYUSE(dyn); MAYUSE(ninst); @@ -664,7 +668,7 @@ void ret_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex) CLEARIP(); } -void retn_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex, int n) +void retn_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n) { MAYUSE(dyn); MAYUSE(ninst); @@ -732,7 +736,7 @@ void retn_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex, int n) CLEARIP(); } -void iret_to_epilog(dynarec_rv64_t* dyn, int ninst, int is64bits) +void iret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is64bits) { // #warning TODO: is64bits MAYUSE(ninst); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 48886fbd..900245fb 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1434,9 +1434,9 @@ uintptr_t geted32(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop void jump_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst); void jump_to_epilog_fast(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst); void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is32bits); -void ret_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex); -void retn_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex, int n); -void iret_to_epilog(dynarec_rv64_t* dyn, int ninst, int is64bits); +void ret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex); +void retn_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n); +void iret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is64bits); void call_c(dynarec_rv64_t* dyn, int ninst, void* 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); void grab_segdata(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, int reg, int segment, int modreg); diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index 80507b49..16ea574f 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -125,9 +125,11 @@ typedef struct instruction_rv64_s { uint16_t ymm0_out; // the ymm0 at th end of the opcode uint16_t ymm0_pass2, ymm0_pass3; int barrier_maybe; - uint8_t will_write; - uint8_t last_write; - uint8_t lock; + uint8_t will_write:2; // [strongmem] will write to memory + uint8_t will_read:1; // [strongmem] will read from memory + uint8_t last_write:1; // [strongmem] the last write in a SEQ + uint8_t lock:1; // [strongmem] lock semantic + uint8_t lock_prefixed:1; // [strongmem] the opcode is lock prefixed uint8_t df_notneeded; uint8_t nat_flags_fusion:1; uint8_t nat_flags_nofusion:1; |