[ARM64_DYNAREC] More optimizations on strongmem emulation (#2051)

This commit is contained in:
Yang Liu 2024-11-21 01:59:20 +08:00 committed by GitHub
parent 5422b108af
commit 9757d1b67a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 49 additions and 48 deletions

View File

@ -169,15 +169,15 @@ Define Box64's Dynarec max allowed forward value when building Block.
#### BOX64_DYNAREC_STRONGMEM * #### BOX64_DYNAREC_STRONGMEM *
Enable/Disable simulation of Strong Memory model Enable/Disable simulation of Strong Memory model
* 0 : Don't try anything special (Default.) * 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 * 2 : All 1. plus memory barriers on SIMD instructions
* 3 : All 2. plus more memory barriers on a regular basis * 3 : All 2. plus more memory barriers on a regular basis
#### BOX64_DYNAREC_WEAKBARRIER * #### 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.) * 0 : Use regular safe barrier (Default.)
* 1 : Use weak barriers to have more performance boost * 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 * #### BOX64_DYNAREC_X87DOUBLE *
Force the use of Double for x87 emulation Force the use of Double for x87 emulation

View File

@ -296,17 +296,17 @@ Define Box64's Dynarec max allowed forward value when building Block.
Enable/Disable simulation of Strong Memory model Enable/Disable simulation of Strong Memory model
* 0 : Don't try anything special (Default.) * 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 * 2 : All 1. plus memory barriers on SIMD instructions
* 3 : All 2. plus more memory barriers on a regular basis * 3 : All 2. plus more memory barriers on a regular basis
=item B<BOX64_DYNAREC_WEAKBARRIER>=I<0|1> =item B<BOX64_DYNAREC_WEAKBARRIER>=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.) * 0 : Use regular safe barrier (Default.)
* 1 : Use weak barriers to have more performance boost * 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<BOX64_DYNAREC_X87DOUBLE>=I<0|1> =item B<BOX64_DYNAREC_X87DOUBLE>=I<0|1>

View File

@ -53,10 +53,14 @@
* - SIMD operations (c2) * - SIMD operations (c2)
* 4. After every third guest memory store in a SEQ (d) * 4. After every third guest memory store in a SEQ (d)
* *
* STRONGMEM levels: * STRONGMEM levels (coarse-grained):
* LEVEL1: Includes a1, b1 * 1: Includes a1, b1, c1
* LEVEL2: Includes LEVEL1, plus a2, b2, c1, c2 * 2: Includes LEVEL1, plus a2, b2, c2
* LEVEL3: Includes LEVEL2, plus d * 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 #define STRONGMEM_SIMD_WRITE 2 // The level of SIMD memory writes will be tracked
@ -161,21 +165,22 @@
} while (0) } while (0)
// An opcode will write memory, this will be put before the STORE instruction automatically. // An opcode will write memory, this will be put before the STORE instruction automatically.
#define WILLWRITE() \ #define WILLWRITE() \
do { \ do { \
if (box64_dynarec_strongmem >= dyn->insts[ninst].will_write && dyn->smwrite == 0) { \ 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. */ \ /* Will write but never written, this is the start of a SEQ, put a barrier. */ \
if (box64_dynarec_weakbarrier) \ if (box64_dynarec_weakbarrier) \
DMB_ISHST(); \ DMB_ISHLD(); \
else \ else \
DMB_ISH(); \ DMB_ISH(); \
} else if (box64_dynarec_strongmem >= STRONGMEM_LAST_WRITE && box64_dynarec_weakbarrier <= 1 && dyn->insts[ninst].last_write) { \ } else if (box64_dynarec_strongmem >= STRONGMEM_LAST_WRITE && box64_dynarec_weakbarrier != 2 \
/* Last write, put a barrier */ \ && dyn->insts[ninst].last_write) { \
if (box64_dynarec_weakbarrier) \ /* Last write, put a barrier */ \
DMB_ISHST(); \ if (box64_dynarec_weakbarrier) \
else \ DMB_ISHST(); \
DMB_ISH(); \ else \
} \ DMB_ISH(); \
} \
} while (0) } while (0)
// Similar to WILLWRITE, but checks lock. // Similar to WILLWRITE, but checks lock.
@ -195,22 +200,19 @@
} while (0) } while (0)
// Will be put at the end of the SEQ // Will be put at the end of the SEQ
#define SMEND() \ #define SMEND() \
do { \ do { \
if (box64_dynarec_strongmem) { \ if (box64_dynarec_strongmem) { \
/* Check if there is any guest memory write. */ \ /* It's a SEQ, put a barrier here. */ \
int i = ninst; \ if (dyn->smwrite) { \
while (i >= 0 && !dyn->insts[i].will_write) \ /* Check if the next instruction has a end loop mark */ \
--i; \ if (box64_dynarec_weakbarrier) \
if (i >= 0) { \ DMB_ISHST(); \
/* It's a SEQ, put a barrier here. */ \ else \
if (box64_dynarec_weakbarrier) \ DMB_ISH(); \
DMB_ISHST(); \ } \
else \ } \
DMB_ISH(); \ dyn->smwrite = 0; \
} \
} \
dyn->smwrite = 0; \
} while (0) } while (0)
// The barrier. // The barrier.
@ -1283,9 +1285,9 @@
#define FTABLE64(A, V) #define FTABLE64(A, V)
#endif #endif
#define ARCH_INIT() \ #define ARCH_INIT() \
dyn->smread = dyn->smwrite = 0; \ SMSTART(); \
dyn->doublepush = 0; \ dyn->doublepush = 0; \
dyn->doublepop = 0; dyn->doublepop = 0;
#define ARCH_RESET() #define ARCH_RESET()

View File

@ -106,9 +106,9 @@ typedef struct instruction_arm64_s {
uint16_t ymm0_out; // the ymm0 at th end of the opcode uint16_t ymm0_out; // the ymm0 at th end of the opcode
uint16_t ymm0_pass2, ymm0_pass3; uint16_t ymm0_pass2, ymm0_pass3;
uint8_t barrier_maybe; uint8_t barrier_maybe;
uint8_t will_write; uint8_t will_write:2; // [strongmem] will write to memory
uint8_t last_write; uint8_t last_write:1; // [strongmem] the last write in a SEQ
uint8_t lock; uint8_t lock:1; // [strongmem] lock semantic
uint8_t set_nat_flags; // 0 or combinaison of native flags define 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; // 0 or combinaison of native flags define
uint8_t use_nat_flags_before; // 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 int forward_ninst; // ninst at the forward point
uint16_t ymm_zero; // bitmap of ymm to zero at purge uint16_t ymm_zero; // bitmap of ymm to zero at purge
uint8_t smwrite; // for strongmem model emulation uint8_t smwrite; // for strongmem model emulation
uint8_t smread;
uint8_t doublepush; uint8_t doublepush;
uint8_t doublepop; uint8_t doublepop;
uint8_t always_test; uint8_t always_test;