about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2024-11-25 18:28:19 +0800
committerGitHub <noreply@github.com>2024-11-25 11:28:19 +0100
commit84608fc581546076d6a34ae18c864eb8cde6ddae (patch)
treec746c42a1af7b04b3ac0d0988297661aef9d0b77 /src
parentc30a392fe863aca59a6be34c03c0fa226b576de8 (diff)
downloadbox64-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.c13
-rw-r--r--src/dynarec/arm64/arm64_emitter.h1
-rw-r--r--src/dynarec/arm64/arm64_printer.c4
-rw-r--r--src/dynarec/arm64/dynarec_arm64_00.c15
-rw-r--r--src/dynarec/arm64/dynarec_arm64_0f.c2
-rw-r--r--src/dynarec/arm64/dynarec_arm64_67.c8
-rw-r--r--src/dynarec/arm64/dynarec_arm64_67_32.c8
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h2
-rw-r--r--src/dynarec/arm64/dynarec_arm64_private.h1
-rw-r--r--src/include/debug.h1
-rw-r--r--src/tools/rcfile.c4
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)                                       \