diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-11-03 19:16:35 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-11-03 19:16:35 +0100 |
| commit | 52a05c9f67aa61215cae13a61c94347de4b58e07 (patch) | |
| tree | bfca6825d3054c481848590823c6529ae4944ff6 /src | |
| parent | ba5aa0c83b60ea14d5923da397b7ec192dd1be68 (diff) | |
| download | box64-52a05c9f67aa61215cae13a61c94347de4b58e07.tar.gz box64-52a05c9f67aa61215cae13a61c94347de4b58e07.zip | |
[DYNAREC] Make sure the emu structure is up-to-date each time LinkNext is called
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/arm64_epilog.S | 2 | ||||
| -rw-r--r-- | src/dynarec/arm64/arm64_next.S | 34 | ||||
| -rw-r--r-- | src/dynarec/dynarec.c | 11 | ||||
| -rw-r--r-- | src/dynarec/dynarec_next.h | 6 | ||||
| -rw-r--r-- | src/dynarec/la64/la64_next.S | 59 | ||||
| -rw-r--r-- | src/dynarec/rv64/rv64_next.S | 69 |
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 |