diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2024-11-25 18:28:19 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-11-25 11:28:19 +0100 |
| commit | 84608fc581546076d6a34ae18c864eb8cde6ddae (patch) | |
| tree | c746c42a1af7b04b3ac0d0988297661aef9d0b77 /src | |
| parent | c30a392fe863aca59a6be34c03c0fa226b576de8 (diff) | |
| download | box64-84608fc581546076d6a34ae18c864eb8cde6ddae.tar.gz box64-84608fc581546076d6a34ae18c864eb8cde6ddae.zip | |
[ARM64_DYNAREC] Added DYNAREC_PAUSE option for hint instructions (#2070)
* [ARM64_DYNAREC] Added DYNAREC_PAUSE option for hint instructions * Use sevl for wfe * Add docs * Fix typo * use switch case
Diffstat (limited to 'src')
| -rw-r--r-- | src/core.c | 13 | ||||
| -rw-r--r-- | src/dynarec/arm64/arm64_emitter.h | 1 | ||||
| -rw-r--r-- | src/dynarec/arm64/arm64_printer.c | 4 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_00.c | 15 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_0f.c | 2 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_67.c | 8 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_67_32.c | 8 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.h | 2 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_private.h | 1 | ||||
| -rw-r--r-- | src/include/debug.h | 1 | ||||
| -rw-r--r-- | src/tools/rcfile.c | 4 |
11 files changed, 51 insertions, 8 deletions
diff --git a/src/core.c b/src/core.c index 5060823f..e5aab281 100644 --- a/src/core.c +++ b/src/core.c @@ -80,6 +80,7 @@ int box64_dynarec_bigblock = 1; int box64_dynarec_forward = 128; int box64_dynarec_strongmem = 0; int box64_dynarec_weakbarrier = 0; +int box64_dynarec_pause = 0; int box64_dynarec_x87double = 0; int box64_dynarec_div0 = 0; int box64_dynarec_fastnan = 1; @@ -787,6 +788,18 @@ void LoadLogEnv() if (box64_dynarec_weakbarrier) printf_log(LOG_INFO, "Dynarec will try to use weaker memory barriers to reduce the performance loss introduce by strong memory emulation\n"); } +#ifdef ARM64 + p = getenv("BOX64_DYNAREC_PAUSE"); + if (p) { + if (strlen(p) == 1) { + if (p[0] >= '0' && p[0] <= '3') + box64_dynarec_pause = p[0] - '0'; + } + if (box64_dynarec_pause) + printf_log(LOG_INFO, "Dynarec will use %s to emulate pause instruction\n", + box64_dynarec_pause == 1 ? "yield" : (box64_dynarec_pause == 2 ? "wfi" : "wfe")); + } +#endif p = getenv("BOX64_DYNAREC_X87DOUBLE"); if(p) { if(strlen(p)==1) { diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h index 168f26e0..0ad26893 100644 --- a/src/dynarec/arm64/arm64_emitter.h +++ b/src/dynarec/arm64/arm64_emitter.h @@ -543,6 +543,7 @@ int convert_bitmask(uint64_t bitmask); #define WFE EMIT(0b11010101000000110010000001011111) #define WFI EMIT(0b11010101000000110010000001111111) #define YIELD EMIT(0b11010101000000110010000000111111) +#define SEVL EMIT(0b11010101000000110010000010111111) #define CSINC_gen(sf, Rm, cond, Rn, Rd) ((sf)<<31 | 0b11010100<<21 | (Rm)<<16 | (cond)<<12 | 1<<10 | (Rn)<<5 | (Rd)) #define CSINCx(Rd, Rn, Rm, cond) EMIT(CSINC_gen(1, Rm, cond, Rn, Rd)) diff --git a/src/dynarec/arm64/arm64_printer.c b/src/dynarec/arm64/arm64_printer.c index 4b797a3c..b7f269fd 100644 --- a/src/dynarec/arm64/arm64_printer.c +++ b/src/dynarec/arm64/arm64_printer.c @@ -136,6 +136,10 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) snprintf(buff, sizeof(buff), "YIELD"); return buff; } + if(isMask(opcode, "11010101000000110010000010111111", &a)) { + snprintf(buff, sizeof(buff), "SEVL"); + return buff; + } // --- LDR / STR if(isMask(opcode, "f010100011iiiiiii22222nnnnnttttt", &a)) { int offset = signExtend(imm, 7)<<(2+sf); diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 5141a598..450cb1b9 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -986,11 +986,13 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin /* inside the block, cache transform */ \ CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \ i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size);\ + SKIP_SEVL(i32); \ B(i32); \ } \ } else { \ /* inside the block, no cache change */ \ i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \ + SKIP_SEVL(i32); \ Bcond(YES, i32); \ } @@ -1427,7 +1429,15 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(gd==xRAX) { if (rep == 2) { INST_NAME("PAUSE"); - YIELD; + switch (box64_dynarec_pause) { + case 1: YIELD; break; + case 2: WFI; break; + case 3: + dyn->insts[ninst].wfe = 1; + SEVL; + WFE; + break; + } } else { INST_NAME("NOP"); } @@ -2950,11 +2960,13 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else { \ CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \ i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \ + SKIP_SEVL(i32); \ Bcond(c__, i32); \ } \ } else { \ /* inside the block */ \ i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \ + SKIP_SEVL(i32); \ if(Z) {CBZz(xRCX, i32);} else {CBNZz(xRCX, i32);}; \ } case 0xE0: @@ -3161,6 +3173,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin // inside the block CacheTransform(dyn, ninst, CHECK_CACHE(), x1, x2, x3); tmp = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); + SKIP_SEVL(tmp); if(tmp==4) { NOP; } else { diff --git a/src/dynarec/arm64/dynarec_arm64_0f.c b/src/dynarec/arm64/dynarec_arm64_0f.c index edd85a4e..3d488876 100644 --- a/src/dynarec/arm64/dynarec_arm64_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_0f.c @@ -1577,11 +1577,13 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else { \ CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \ i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \ + SKIP_SEVL(i32); \ B(i32); \ } \ } else { \ /* inside the block */ \ i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \ + SKIP_SEVL(i32); \ Bcond(YES, i32); \ } diff --git a/src/dynarec/arm64/dynarec_arm64_67.c b/src/dynarec/arm64/dynarec_arm64_67.c index 9d6059a1..5dc4043a 100644 --- a/src/dynarec/arm64/dynarec_arm64_67.c +++ b/src/dynarec/arm64/dynarec_arm64_67.c @@ -1380,12 +1380,14 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else { \ CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \ i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size);\ + SKIP_SEVL(i32); \ B(i32); \ } \ - } else { \ - /* inside the block */ \ + } else { \ + /* inside the block */ \ i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \ - Bcond(YES, i32); \ + SKIP_SEVL(i32); \ + Bcond(YES, i32); \ } case 0xE0: INST_NAME("LOOPNZ (32bits)"); diff --git a/src/dynarec/arm64/dynarec_arm64_67_32.c b/src/dynarec/arm64/dynarec_arm64_67_32.c index 6a1e1d7e..4b247fd0 100644 --- a/src/dynarec/arm64/dynarec_arm64_67_32.c +++ b/src/dynarec/arm64/dynarec_arm64_67_32.c @@ -80,12 +80,14 @@ uintptr_t dynarec64_67_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int } else { \ CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \ i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size);\ + SKIP_SEVL(i32); \ B(i32); \ } \ - } else { \ - /* inside the block */ \ + } else { \ + /* inside the block */ \ i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \ - Bcond(YES, i32); \ + SKIP_SEVL(i32); \ + Bcond(YES, i32); \ } case 0xE0: INST_NAME("LOOPNZ (16bits)"); diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index c07ba709..267d873b 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -1140,6 +1140,8 @@ #endif #define CLEARIP() dyn->last_ip=0 +#define SKIP_SEVL(val) if (dyn->insts[dyn->insts[ninst].x64.jmp_insts].wfe) val += 4; + #if STEP < 2 #define PASS2IF(A, B) if(A) #elif STEP == 2 diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h index 297d9895..113e4341 100644 --- a/src/dynarec/arm64/dynarec_arm64_private.h +++ b/src/dynarec/arm64/dynarec_arm64_private.h @@ -109,6 +109,7 @@ typedef struct instruction_arm64_s { 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 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 uint8_t use_nat_flags_before; // 0 or combinaison of native flags define diff --git a/src/include/debug.h b/src/include/debug.h index be8e0110..cbaab9db 100644 --- a/src/include/debug.h +++ b/src/include/debug.h @@ -28,6 +28,7 @@ extern int box64_dynarec_bigblock; extern int box64_dynarec_forward; extern int box64_dynarec_strongmem; extern int box64_dynarec_weakbarrier; +extern int box64_dynarec_pause; extern int box64_dynarec_fastnan; extern int box64_dynarec_fastround; extern int box64_dynarec_x87double; diff --git a/src/tools/rcfile.c b/src/tools/rcfile.c index 5a022d7d..1bb9695e 100644 --- a/src/tools/rcfile.c +++ b/src/tools/rcfile.c @@ -155,8 +155,9 @@ ENTRYINT(BOX64_DYNAREC_DUMP, box64_dynarec_dump, 0, 2, 2) \ ENTRYINT(BOX64_DYNAREC_LOG, box64_dynarec_log, 0, 3, 2) \ ENTRYINT(BOX64_DYNAREC_BIGBLOCK, box64_dynarec_bigblock, 0, 3, 2) \ ENTRYSTRING_(BOX64_DYNAREC_FORWARD, box64_dynarec_forward) \ -ENTRYINT(BOX64_DYNAREC_STRONGMEM, box64_dynarec_strongmem, 0, 4, 3) \ +ENTRYINT(BOX64_DYNAREC_STRONGMEM, box64_dynarec_strongmem, 0, 3, 2) \ ENTRYINT(BOX64_DYNAREC_WEAKBARRIER, box64_dynarec_weakbarrier, 0, 2, 2) \ +ENTRYINT(BOX64_DYNAREC_PAUSE, box64_dynarec_pause, 0, 3, 2) \ ENTRYBOOL(BOX64_DYNAREC_X87DOUBLE, box64_dynarec_x87double) \ ENTRYBOOL(BOX64_DYNAREC_DIV0, box64_dynarec_div0) \ ENTRYBOOL(BOX64_DYNAREC_FASTNAN, box64_dynarec_fastnan) \ @@ -184,6 +185,7 @@ IGNORE(BOX64_DYNAREC_BIGBLOCK) \ IGNORE(BOX64_DYNAREC_FORWARD) \ IGNORE(BOX64_DYNAREC_STRONGMEM) \ IGNORE(BOX64_DYNAREC_WEAKBARRIER) \ +IGNORE(BOX64_DYNAREC_PAUSE) \ IGNORE(BOX64_DYNAREC_X87DOUBLE) \ IGNORE(BOX64_DYNAREC_DIV0) \ IGNORE(BOX64_DYNAREC_FASTNAN) \ |