about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/dynarec/arm64/arm64_epilog.S2
-rw-r--r--src/dynarec/arm64/arm64_next.S34
-rw-r--r--src/dynarec/dynarec.c11
-rw-r--r--src/dynarec/dynarec_next.h6
-rw-r--r--src/dynarec/la64/la64_next.S59
-rw-r--r--src/dynarec/rv64/rv64_next.S69
6 files changed, 120 insertions, 61 deletions
diff --git a/src/dynarec/arm64/arm64_epilog.S b/src/dynarec/arm64/arm64_epilog.S
index 57f23200..62e75590 100644
--- a/src/dynarec/arm64/arm64_epilog.S
+++ b/src/dynarec/arm64/arm64_epilog.S
@@ -7,6 +7,7 @@
 .align 4
 
 .global arm64_epilog
+.global arm64_epilog_fast
 arm64_epilog:
     //update register -> emu
     stp     x10, x11, [x0, (8 *  0)]
@@ -18,6 +19,7 @@ arm64_epilog:
     stp     x22, x23, [x0, (8 * 12)]
     stp     x24, x25, [x0, (8 * 14)]
     stp     x26, x27, [x0, (8 * 16)] // put back reg value in emu, including EIP (so x27 must be EIP now)
+arm64_epilog_fast:
     //restore all used register
     add     sp, x28, 0
     //vpop     {d8-d15}
diff --git a/src/dynarec/arm64/arm64_next.S b/src/dynarec/arm64/arm64_next.S
index e900fbec..b9b0f2fd 100644
--- a/src/dynarec/arm64/arm64_next.S
+++ b/src/dynarec/arm64/arm64_next.S
@@ -14,28 +14,36 @@
 arm64_next:
     // emu is r0
     // IP address is r1
-    sub     sp,  sp,  (8 * 12)
+    sub     sp,  sp,  (8 * 2)
     stp     x0,  x1,  [sp, (8 *  0)]
-    stp     x10, x11, [sp, (8 *  2)]
-    stp     x12, x13, [sp, (8 *  4)]
-    stp     x14, x15, [sp, (8 *  6)]
-    stp     x16, x17, [sp, (8 *  8)]
-    stp     x18, x27, [sp, (8 * 10)]    // also save x27(rip) to allow change in LinkNext
+    stp     x10, x11, [x0, (8 *  0)]
+    stp     x12, x13, [x0, (8 *  2)]
+    stp     x14, x15, [x0, (8 *  4)]
+    stp     x16, x17, [x0, (8 *  6)]
+    stp     x18, x19, [x0, (8 *  8)]
+    stp     x20, x21, [x0, (8 * 10)]
+    stp     x22, x23, [x0, (8 * 12)]
+    stp     x24, x25, [x0, (8 * 14)]
+    stp     x26, x27, [x0, (8 * 16)] 
 
     mov     x2, x30      // "from" is in lr, so put in x2
-    add     x3, sp, 8*11    // x3 is address to change rip
+
     // call the function
     bl      LinkNext
     // preserve return value
     mov     x3, x0
     // pop regs
     ldp     x0, x1,   [sp, (8 *  0)]
-    ldp     x10, x11, [sp, (8 *  2)]
-    ldp     x12, x13, [sp, (8 *  4)]
-    ldp     x14, x15, [sp, (8 *  6)]
-    ldp     x16, x17, [sp, (8 *  8)]
-    ldp     x18, x27, [sp, (8 * 10)]
-    add     sp,  sp, (8 * 12)
+    ldp     x10, x11, [x0, (8 *  0)]
+    ldp     x12, x13, [x0, (8 *  2)]
+    ldp     x14, x15, [x0, (8 *  4)]
+    ldp     x16, x17, [x0, (8 *  6)]
+    ldp     x18, x19, [x0, (8 *  8)]
+    ldp     x20, x21, [x0, (8 * 10)]
+    ldp     x22, x23, [x0, (8 * 12)]
+    ldp     x24, x25, [x0, (8 * 14)]
+    ldp     x26, x27, [x0, (8 * 16)]
+    add     sp,  sp, (8 * 2)
     // return offset is jump address
     br      x3
 
diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c
index 5dddc23b..3675d5c9 100644
--- a/src/dynarec/dynarec.c
+++ b/src/dynarec/dynarec.c
@@ -28,7 +28,7 @@
 #ifdef DYNAREC
 uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr);
 
-void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
+void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
 {
     int is32bits = (R_CS == 0x23);
     #ifdef HAVE_TRACE
@@ -53,7 +53,6 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
         uintptr_t old_addr = addr;
         addr = (uintptr_t)getAlternate((void*)addr);    // set new address
         R_RIP = addr;   // but also new RIP!
-        *x3 = addr; // and the RIP in x27 register
         printf_log(LOG_DEBUG, " -> %p\n", (void*)addr);
         block = DBAlternateBlock(emu, old_addr, addr, is32bits);
     } else
@@ -66,12 +65,12 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
             } else {
                 dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
                 elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2-4);
-                dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s), RIP=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)", (void*)*x3);
+                dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s), RIP=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)", R_RIP);
             }
         }
         #endif
         //tableupdate(native_epilog, addr, table);
-        return native_epilog;
+        return native_epilog_fast;
     }
     if(!block->done) {
         // not finished yet... leave linker
@@ -81,11 +80,11 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
             printf_log(LOG_NONE, "Warning, NULL block at %p from %p (db=%p, x64addr=%p/%s)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, db?getAddrFunctionName(getX64Address(db, (uintptr_t)x2-4)):"(nil)");
         }
         #endif
-        return native_epilog;
+        return native_epilog_fast;
     }
     if(!(jblock=block->block)) {
         // null block, but done: go to epilog, no linker here
-        return native_epilog;
+        return native_epilog_fast;
     }
     //dynablock_t *father = block->father?block->father:block;
     return jblock;
diff --git a/src/dynarec/dynarec_next.h b/src/dynarec/dynarec_next.h
index 9c3411d1..f95421eb 100644
--- a/src/dynarec/dynarec_next.h
+++ b/src/dynarec/dynarec_next.h
@@ -5,23 +5,29 @@
 void arm64_next(void) EXPORTDYN;
 void arm64_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
 void arm64_epilog(void) EXPORTDYN;
+void arm64_epilog_fast(void) EXPORTDYN;
 #define native_next         arm64_next
 #define native_prolog       arm64_prolog
 #define native_epilog       arm64_epilog
+#define native_epilog_fast  arm64_epilog_fast
 #elif defined(LA64)
 void la64_next(void) EXPORTDYN;
 void la64_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
 void la64_epilog(void) EXPORTDYN;
+void la64_epilog_fast(void) EXPORTDYN;
 #define native_next         la64_next
 #define native_prolog       la64_prolog
 #define native_epilog       la64_epilog
+#define native_epilog_fast  la64_epilog_fast
 #elif defined(RV64)
 void rv64_next(void) EXPORTDYN;
 void rv64_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
 void rv64_epilog(void) EXPORTDYN;
+void rv64_epilog_fast(void) EXPORTDYN;
 #define native_next         rv64_next
 #define native_prolog       rv64_prolog
 #define native_epilog       rv64_epilog
+#define native_epilog_fast  rv64_epilog_fast
 #else
 #error Unsupported architecture
 #endif
diff --git a/src/dynarec/la64/la64_next.S b/src/dynarec/la64/la64_next.S
index f98558b0..ec502ac9 100644
--- a/src/dynarec/la64/la64_next.S
+++ b/src/dynarec/la64/la64_next.S
@@ -14,22 +14,27 @@
 la64_next:
     // emu is a0
     // IP address is a1
-    addi.d $sp, $sp, -(8 * 12)
+    addi.d $sp, $sp, -(8 * 2)
     st.d   $a0, $sp, 0
     st.d   $a1, $sp, 8
-    st.d   $r11, $sp, 16
-    st.d   $r12, $sp, 24
-    st.d   $r13, $sp, 32
-    st.d   $r14, $sp, 40
-    st.d   $r15, $sp, 48
-    st.d   $r16, $sp, 56
-    st.d   $r17, $sp, 64
-    st.d   $r18, $sp, 72
-    st.d   $r19, $sp, 80
-    st.d   $r20, $sp, 88 // also save r20(rip) to allow change in LinkNext
+    st.d   $r12, $a0, (8 * 0)
+    st.d   $r13, $a0, (8 * 1)
+    st.d   $r14, $a0, (8 * 2)
+    st.d   $r15, $a0, (8 * 3)
+    st.d   $r16, $a0, (8 * 4)
+    st.d   $r17, $a0, (8 * 5)
+    st.d   $r18, $a0, (8 * 6)
+    st.d   $r19, $a0, (8 * 7)
+    st.d   $r23, $a0, (8 * 8)
+    st.d   $r24, $a0, (8 * 9)
+    st.d   $r25, $a0, (8 * 10)
+    st.d   $r26, $a0, (8 * 11)
+    st.d   $r27, $a0, (8 * 12)
+    st.d   $r28, $a0, (8 * 13)
+    st.d   $r29, $a0, (8 * 14)
+    st.d   $r30, $a0, (8 * 15)
 
     move   $a2, $ra      // "from" is in ra, so put in a2
-    addi.d $a3, $sp, 88  // a3 is address to change rip
     // call the function
     bl LinkNext
     // preserve return value
@@ -37,16 +42,24 @@ la64_next:
     // pop regs
     ld.d   $a0, $sp, 0
     ld.d   $a1, $sp, 8
-    ld.d   $r11, $sp, 16
-    ld.d   $r12, $sp, 24
-    ld.d   $r13, $sp, 32
-    ld.d   $r14, $sp, 40
-    ld.d   $r15, $sp, 48
-    ld.d   $r16, $sp, 56
-    ld.d   $r17, $sp, 64
-    ld.d   $r18, $sp, 72
-    ld.d   $r19, $sp, 80
-    ld.d   $r20, $sp, 88
-    addi.d $sp,  $sp, (8 * 12)
+    ld.d   $r12, $a0, (8 * 0)
+    ld.d   $r13, $a0, (8 * 1)
+    ld.d   $r14, $a0, (8 * 2)
+    ld.d   $r15, $a0, (8 * 3)
+    ld.d   $r16, $a0, (8 * 4)
+    ld.d   $r17, $a0, (8 * 5)
+    ld.d   $r18, $a0, (8 * 6)
+    ld.d   $r19, $a0, (8 * 7)
+    ld.d   $r23, $a0, (8 * 8)
+    ld.d   $r24, $a0, (8 * 9)
+    ld.d   $r25, $a0, (8 * 10)
+    ld.d   $r26, $a0, (8 * 11)
+    ld.d   $r27, $a0, (8 * 12)
+    ld.d   $r28, $a0, (8 * 13)
+    ld.d   $r29, $a0, (8 * 14)
+    ld.d   $r30, $a0, (8 * 15)
+    ld.d   $r31, $a0, (8 * 16)  // xFlags
+    ld.d   $r20, $a0, (8 * 17)  // xRIP
+    addi.d $sp,  $sp, (8 * 2)
     // return offset is jump address
     jr     $a3
\ No newline at end of file
diff --git a/src/dynarec/rv64/rv64_next.S b/src/dynarec/rv64/rv64_next.S
index ce34bb7f..bb6f3901 100644
--- a/src/dynarec/rv64/rv64_next.S
+++ b/src/dynarec/rv64/rv64_next.S
@@ -14,20 +14,36 @@
 rv64_next:
     // emu is a0
     // IP address is a1
-    addi    sp,  sp,  -(8 * 10)
+    addi    sp,  sp,  -(8 * 2)
     sd      a0, (sp)
     sd      a1, 8(sp)
-    sd      x5, 16(sp)
-    sd      x7, 24(sp)
-    sd      x16, 32(sp)
-    sd      x17, 40(sp)
-    sd      x28, 48(sp)
-    sd      x29, 56(sp)
-    sd      x30, 64(sp)
-    sd      x31, 72(sp)
+    sd      x16, (a0)
+    sd      x17, 8(a0)
+    sd      x18, 16(a0)
+    sd      x19, 24(a0)
+    sd      x20, 32(a0)
+    sd      x21, 40(a0)
+    sd      x22, 48(a0)
+    sd      x23, 56(a0)
+    sd      x24, 64(a0)
+    sd      x25, 72(a0)
+    sd      x26, 80(a0)
+    sd      x27, 88(a0)
+    sd      x28, 96(a0)
+    sd      x29, 104(a0)
+    sd      x30, 112(a0)
+    sd      x31, 120(a0)
+    // adjust flags bit 5 -> bit 11
+    li      x5, ~(1<<11)
+    and     x8, x8, x5
+    andi    x5, x8, 1<<5
+    slli    x5, x5, 11-5
+    or      x8, x8, x5
+    sd      x8, 128(a0)     //xFlags
+    sd      x7, 136(a0)     // put back reg value in emu, including EIP (so x7 must be EIP now)
 
     mv      a2, ra      // "from" is in ra, so put in a2
-    addi    a3, sp, 24   // a3 is address to change rip
+
     // call the function
 1:
     auipc   a4, %pcrel_hi(LinkNext)
@@ -37,15 +53,30 @@ rv64_next:
     // pop regs
     ld      a0, (sp)
     ld      a1, 8(sp)
-    ld      x5, 16(sp)
-    ld      x7, 24(sp)
-    ld      x16, 32(sp)
-    ld      x17, 40(sp)
-    ld      x28, 48(sp)
-    ld      x29, 56(sp)
-    ld      x30, 64(sp)
-    ld      x31, 72(sp)
-    addi    sp,  sp,  (8 * 10)
+    ld      x16, (a0)
+    ld      x17, 8(a0)
+    ld      x18, 16(a0)
+    ld      x19, 24(a0)
+    ld      x20, 32(a0)
+    ld      x21, 40(a0)
+    ld      x22, 48(a0)
+    ld      x23, 56(a0)
+    ld      x24, 64(a0)
+    ld      x25, 72(a0)
+    ld      x26, 80(a0)
+    ld      x27, 88(a0)
+    ld      x28, 96(a0)
+    ld      x29, 104(a0)
+    ld      x30, 112(a0)
+    ld      x31, 120(a0)
+    ld      x8, 128(a0)     //xFlags
+    ld      x7, 136(a0)     // xRIP
+    // // adjust flags bit 11 -> bit 5
+    andi    x8, x8, ~(1<<5)    // probably not usefull?
+    srli    x5, x8, 11-5
+    andi    x5, x5, 1<<5
+    or      x8, x8, x5
+    addi    sp,  sp,  (8 * 2)
     // return offset is jump address
     jr      a3