diff --git a/docs/USAGE.md b/docs/USAGE.md index 41b7e54b..c349d66c 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -169,15 +169,15 @@ Define Box64's Dynarec max allowed forward value when building Block. #### BOX64_DYNAREC_STRONGMEM * Enable/Disable simulation of Strong Memory model * 0 : Don't try anything special (Default.) -* 1 : Enable some memory barriers when writting to memory to simulate the Strong Memory Model in a limited way (Default when libmonobdwgc-2.0.so is loaded) +* 1 : Enable some memory barriers when writing to memory to simulate the Strong Memory Model in a limited way (Default when libmonobdwgc-2.0.so is loaded) * 2 : All 1. plus memory barriers on SIMD instructions * 3 : All 2. plus more memory barriers on a regular basis #### BOX64_DYNAREC_WEAKBARRIER * -Use weak memory barriers to reduce the performance impact by STRONGMEM +Tweaking the memory barriers to reduce the performance impact by STRONGMEM * 0 : Use regular safe barrier (Default.) * 1 : Use weak barriers to have more performance boost -* 2 : Disable the last write barriers to have even more performance boost +* 2 : All 1. Plus disabled the last write barriers #### BOX64_DYNAREC_X87DOUBLE * Force the use of Double for x87 emulation diff --git a/docs/box64.pod b/docs/box64.pod index 19f6e8a2..e1acdb2b 100644 --- a/docs/box64.pod +++ b/docs/box64.pod @@ -296,17 +296,17 @@ Define Box64's Dynarec max allowed forward value when building Block. Enable/Disable simulation of Strong Memory model * 0 : Don't try anything special (Default.) - * 1 : Enable some memory barriers when writting to memory to simulate the Strong Memory Model in a limited way (Default when libmonobdwgc-2.0.so is loaded) + * 1 : Enable some memory barriers when writing to memory to simulate the Strong Memory Model in a limited way (Default when libmonobdwgc-2.0.so is loaded) * 2 : All 1. plus memory barriers on SIMD instructions * 3 : All 2. plus more memory barriers on a regular basis =item B=I<0|1> -Use weak memory barriers to reduce the performance impact by STRONGMEM +Tweaking the memory barriers to reduce the performance impact by STRONGMEM * 0 : Use regular safe barrier (Default.) * 1 : Use weak barriers to have more performance boost - * 2 : Disable the last write barriers to have even more performance boost + * 2 : All 1. Plus disabled the last write barriers =item B=I<0|1> diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index aa06379f..1979c90e 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -53,10 +53,14 @@ * - SIMD operations (c2) * 4. After every third guest memory store in a SEQ (d) * - * STRONGMEM levels: - * LEVEL1: Includes a1, b1 - * LEVEL2: Includes LEVEL1, plus a2, b2, c1, c2 - * LEVEL3: Includes LEVEL2, plus d + * STRONGMEM levels (coarse-grained): + * 1: Includes a1, b1, c1 + * 2: Includes LEVEL1, plus a2, b2, c2 + * 3: Includes LEVEL2, plus d + * + * WEAKBARRIER levels (fine-grained): + * 1: Use dmb.ishld and dmb.ishst over dmb.ish for more performance + * 2. All 1. Plus disabled the last write barriers (c1, c2) */ #define STRONGMEM_SIMD_WRITE 2 // The level of SIMD memory writes will be tracked @@ -161,21 +165,22 @@ } while (0) // An opcode will write memory, this will be put before the STORE instruction automatically. -#define WILLWRITE() \ - do { \ - if (box64_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 (box64_dynarec_weakbarrier) \ - DMB_ISHST(); \ - else \ - DMB_ISH(); \ - } else if (box64_dynarec_strongmem >= STRONGMEM_LAST_WRITE && box64_dynarec_weakbarrier <= 1 && dyn->insts[ninst].last_write) { \ - /* Last write, put a barrier */ \ - if (box64_dynarec_weakbarrier) \ - DMB_ISHST(); \ - else \ - DMB_ISH(); \ - } \ +#define WILLWRITE() \ + do { \ + if (box64_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 (box64_dynarec_weakbarrier) \ + DMB_ISHLD(); \ + else \ + DMB_ISH(); \ + } else if (box64_dynarec_strongmem >= STRONGMEM_LAST_WRITE && box64_dynarec_weakbarrier != 2 \ + && dyn->insts[ninst].last_write) { \ + /* Last write, put a barrier */ \ + if (box64_dynarec_weakbarrier) \ + DMB_ISHST(); \ + else \ + DMB_ISH(); \ + } \ } while (0) // Similar to WILLWRITE, but checks lock. @@ -195,22 +200,19 @@ } while (0) // Will be put at the end of the SEQ -#define SMEND() \ - do { \ - if (box64_dynarec_strongmem) { \ - /* Check if there is any guest memory write. */ \ - int i = ninst; \ - while (i >= 0 && !dyn->insts[i].will_write) \ - --i; \ - if (i >= 0) { \ - /* It's a SEQ, put a barrier here. */ \ - if (box64_dynarec_weakbarrier) \ - DMB_ISHST(); \ - else \ - DMB_ISH(); \ - } \ - } \ - dyn->smwrite = 0; \ +#define SMEND() \ + do { \ + if (box64_dynarec_strongmem) { \ + /* It's a SEQ, put a barrier here. */ \ + if (dyn->smwrite) { \ + /* Check if the next instruction has a end loop mark */ \ + if (box64_dynarec_weakbarrier) \ + DMB_ISHST(); \ + else \ + DMB_ISH(); \ + } \ + } \ + dyn->smwrite = 0; \ } while (0) // The barrier. @@ -1283,9 +1285,9 @@ #define FTABLE64(A, V) #endif -#define ARCH_INIT() \ - dyn->smread = dyn->smwrite = 0; \ - dyn->doublepush = 0; \ +#define ARCH_INIT() \ + SMSTART(); \ + dyn->doublepush = 0; \ dyn->doublepop = 0; #define ARCH_RESET() diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h index 295574b8..297d9895 100644 --- a/src/dynarec/arm64/dynarec_arm64_private.h +++ b/src/dynarec/arm64/dynarec_arm64_private.h @@ -106,9 +106,9 @@ 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; - uint8_t last_write; - uint8_t lock; + 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 set_nat_flags; // 0 or combinaison of native flags define uint8_t use_nat_flags; // 0 or combinaison of native flags define uint8_t use_nat_flags_before; // 0 or combinaison of native flags define @@ -159,7 +159,6 @@ typedef struct dynarec_arm_s { int forward_ninst; // ninst at the forward point uint16_t ymm_zero; // bitmap of ymm to zero at purge uint8_t smwrite; // for strongmem model emulation - uint8_t smread; uint8_t doublepush; uint8_t doublepop; uint8_t always_test;