[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 *
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

View File

@ -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<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.)
* 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>

View File

@ -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()

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_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;