diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2025-01-25 04:35:47 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-24 21:35:47 +0100 |
| commit | 6f8f37e8ffc61a496c9e533fdca83d14adc5ee28 (patch) | |
| tree | f32277bcd71887a69168d7653100029d7cf54bbb /src | |
| parent | 3ec950726b61eb427cb4250a28125a2a791e3a6a (diff) | |
| download | box64-6f8f37e8ffc61a496c9e533fdca83d14adc5ee28.tar.gz box64-6f8f37e8ffc61a496c9e533fdca83d14adc5ee28.zip | |
[RV64_DYNAREC] Optimized GETIP (#2294)
Co-authored-by: xctan <xctan@cirno.icu>
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_1.c | 4 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_3.c | 36 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_0f.c | 6 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_66.c | 4 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.c | 14 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 43 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_private.h | 2 |
7 files changed, 55 insertions, 54 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_1.c b/src/dynarec/rv64/dynarec_rv64_00_1.c index f532218e..88dd813f 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_1.c +++ b/src/dynarec/rv64/dynarec_rv64_00_1.c @@ -290,7 +290,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } else { SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state } - GETIP(ip); + GETIP(ip, x7); STORE_XEMU_CALL(x3); CALL(native_priv, -1, 0, 0); LOAD_XEMU_CALL(); @@ -306,7 +306,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } else { SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state } - GETIP(ip); + GETIP(ip, x7); STORE_XEMU_CALL(x3); CALL(native_priv, -1, 0, 0); LOAD_XEMU_CALL(); diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 6777c7ac..0764618e 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -438,8 +438,6 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if ((PK64(0) == 0)) { addr += 8; MESSAGE(LOG_DEBUG, "Exit x64 Emu\n"); - // GETIP(ip+1+2); // no use - // STORE_XEMU_REGS(xRIP); // no need, done in epilog MOV64x(x1, 1); SW(x1, xEmu, offsetof(x64emu_t, quit)); *ok = 0; @@ -457,11 +455,10 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (tmp < 0 || (tmp & 15) > 1) tmp = 0; // TODO: removed when FP is in place if ((BOX64ENV(log) < 2 && !BOX64ENV(rolling_log)) && tmp) { - // GETIP(ip+3+8+8); // read the 0xCC call_n(dyn, ninst, *(void**)(addr + 8), tmp); addr += 8 + 8; } else { - GETIP(ip + 1); // read the 0xCC + GETIP(ip + 1, x7); // read the 0xCC STORE_XEMU_CALL(x3); ADDI(x3, xRIP, 8 + 8); // expected return address ADDI(x1, xEmu, (uint32_t)offsetof(x64emu_t, ip)); // setup addr as &emu->ip @@ -484,7 +481,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ADD(x2, x2, x1); LD(x3, x2, 0); BEQZ_MARK(x3); - GETIP(addr); + GETIP(addr, x7); STORE_XEMU_CALL(x3); CALL(native_int3, -1, 0, 0); LOAD_XEMU_CALL(); @@ -502,7 +499,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("INT 29/2c/2d"); // lets do nothing MESSAGE(LOG_INFO, "INT 29/2c/2d Windows interruption\n"); - GETIP(ip); // priviledged instruction, IP not updated + GETIP(ip, x7); // priviledged instruction, IP not updated STORE_XEMU_CALL(x3); MOV32w(x1, u8); CALL(native_int, -1, x1, 0); @@ -511,7 +508,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("32bits SYSCALL"); NOTEST(x1); SMEND(); - GETIP(addr); + GETIP(addr, x7); STORE_XEMU_CALL(x3); CALL_S(x86Syscall, -1, 0); LOAD_XEMU_CALL(); @@ -529,7 +526,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } else { SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state } - GETIP(addr); + GETIP(addr, x7); STORE_XEMU_CALL(x3); CALL(native_int3, -1, 0, 0); LOAD_XEMU_CALL(); @@ -543,7 +540,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } else { SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state } - GETIP(ip); // priviledged instruction, IP not updated + GETIP(ip, x7); // priviledged instruction, IP not updated STORE_XEMU_CALL(x3); CALL(native_priv, -1, 0, 0); LOAD_XEMU_CALL(); @@ -964,12 +961,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int // return value will be on the stack, so the stack depth needs to be updated x87_purgecache(dyn, ninst, 0, x3, x1, x4); if ((BOX64ENV(log) < 2 && !BOX64ENV(rolling_log)) && dyn->insts[ninst].natcall && tmp) { - // GETIP(ip+3+8+8); // read the 0xCC call_n(dyn, ninst, *(void**)(dyn->insts[ninst].natcall + 2 + 8), tmp); POP1(xRIP); // pop the return address dyn->last_ip = addr; } else { - GETIP_(dyn->insts[ninst].natcall); // read the 0xCC already + GETIP_(dyn->insts[ninst].natcall, x7); // read the 0xCC already STORE_XEMU_CALL(x3); ADDI(x1, xEmu, (uint32_t)offsetof(x64emu_t, ip)); // setup addr as &emu->ip CALL_S(x64Int3, -1, x1); @@ -1091,7 +1087,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int else INST_NAME("OUT DX, EAX"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state - GETIP(ip); + GETIP(ip, x7); STORE_XEMU_CALL(xRIP); CALL(native_priv, -1, 0, 0); LOAD_XEMU_CALL(); @@ -1285,14 +1281,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int && *(uint32_t*)(dyn->insts[ninst - 1].x64.addr + 1) == 0) { // hack for some protection that check a divide by zero actually trigger a divide by zero exception MESSAGE(LOG_INFO, "Divide by 0 hack\n"); - GETIP(ip); + GETIP(ip, x7); STORE_XEMU_CALL(x3); CALL(native_div0, -1, 0, 0); LOAD_XEMU_CALL(); } else { if (BOX64ENV(dynarec_div0)) { BNE_MARK3(ed, xZR); - GETIP_(ip); + GETIP_(ip, x7); STORE_XEMU_CALL(x3); CALL(native_div0, -1, 0, 0); CLEARIP(); @@ -1320,7 +1316,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETED(0); if (BOX64ENV(dynarec_div0)) { BNE_MARK3(ed, xZR); - GETIP_(ip); + GETIP_(ip, x7); STORE_XEMU_CALL(x3); CALL(native_div0, -1, 0, 0); CLEARIP(); @@ -1335,7 +1331,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETEDH(x1, 0); // get edd changed addr, so cannot be called 2 times for same op... if (BOX64ENV(dynarec_div0)) { BNE_MARK3(ed, xZR); - GETIP_(ip); + GETIP_(ip, x7); STORE_XEMU_CALL(x3); CALL(native_div0, -1, 0, 0); CLEARIP(); @@ -1362,7 +1358,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETSED(0); if (BOX64ENV(dynarec_div0)) { BNE_MARK3(ed, xZR); - GETIP_(ip); + GETIP_(ip, x7); STORE_XEMU_CALL(x3); CALL(native_div0, -1, 0, 0); CLEARIP(); @@ -1385,7 +1381,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETED(0); if (BOX64ENV(dynarec_div0)) { BNE_MARK3(ed, xZR); - GETIP_(ip); + GETIP_(ip, x7); STORE_XEMU_CALL(x3); CALL(native_div0, -1, 0, 0); CLEARIP(); @@ -1400,7 +1396,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETEDH(x1, 0); // get edd changed addr, so cannot be called 2 times for same op... if (BOX64ENV(dynarec_div0)) { BNE_MARK3(ed, xZR); - GETIP_(ip); + GETIP_(ip, x7); STORE_XEMU_CALL(x3); CALL(native_div0, -1, 0, 0); CLEARIP(); @@ -1504,7 +1500,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int *need_epilog = 0; *ok = 0; } - GETIP_(addr); + GETIP_(addr, x7); if (BOX64DRENV(dynarec_callret)) { SET_HASCALLRET(); j64 = (dyn->insts) ? (GETMARK - (dyn->native_size)) : 0; diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index 8d760708..35441901 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -116,7 +116,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("SYSCALL"); NOTEST(x1); SMEND(); - GETIP(addr); + GETIP(addr, x7); STORE_XEMU_CALL(x3); CALL_S(x64Syscall, -1, 0); LOAD_XEMU_CALL(); @@ -136,7 +136,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } else { SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state } - GETIP(ip); + GETIP(ip, x7); STORE_XEMU_CALL(x3); CALL(native_ud, -1, 0, 0); LOAD_XEMU_CALL(); @@ -152,7 +152,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } else { SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state } - GETIP(ip); + GETIP(ip, x7); STORE_XEMU_CALL(x3); CALL(native_ud, -1, 0, 0); LOAD_XEMU_CALL(); diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index fc939557..3bffea83 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -1403,7 +1403,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni OR(x2, x2, x7); if (BOX64ENV(dynarec_div0)) { BNE_MARK3(ed, xZR); - GETIP_(ip); + GETIP_(ip, x7); STORE_XEMU_CALL(x6); CALL(native_div0, -1, 0, 0); CLEARIP(); @@ -1424,7 +1424,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETSEW(x1, 0); if (BOX64ENV(dynarec_div0)) { BNE_MARK3(ed, xZR); - GETIP_(ip); + GETIP_(ip, x7); STORE_XEMU_CALL(x6); CALL(native_div0, -1, 0, 0); CLEARIP(); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 8f53ceb3..1a7d0f97 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -90,13 +90,13 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, ret = xRIP; *fixaddress = tmp + adj; } else if (i12 && (tmp >= -2048) && (tmp <= maxval)) { - GETIP(addr + delta); + GETIP(addr + delta, scratch); ret = xRIP; *fixaddress = tmp; } else if (adj && (tmp + adj >= -2048) && (tmp + adj <= maxval)) { ADDI(ret, xRIP, tmp + adj); } else if ((tmp >= -2048) && (tmp <= maxval)) { - GETIP(addr + delta); + GETIP(addr + delta, scratch); ADDI(ret, xRIP, tmp); } else if (tmp + addr + delta < 0x100000000LL) { MOV64x(ret, tmp + addr + delta); @@ -105,7 +105,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, MOV64x(ret, tmp + adj); } else { MOV64x(ret, tmp); - GETIP(addr + delta); + GETIP(addr + delta, scratch); } ADD(ret, ret, xRIP); } @@ -390,7 +390,7 @@ uintptr_t geted32(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop uint32_t tmp = F32; // no need to zero up, as we did it below rv64_move32(dyn, ninst, ret, tmp, 0); - GETIP(addr + delta); + GETIP(addr + delta, scratch); ADDW(ret, ret, xRIP); ZEROUP(ret); switch (lock) { @@ -490,7 +490,7 @@ void jump_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst) MV(xRIP, reg); } } else { - GETIP_(ip); + GETIP_(ip, x2); } TABLE64(x2, (uintptr_t)rv64_epilog); SMEND(); @@ -509,7 +509,7 @@ void jump_to_epilog_fast(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst) MV(xRIP, reg); } } else { - GETIP_(ip); + GETIP_(ip, x2); } TABLE64(x2, (uintptr_t)rv64_epilog_fast); SMEND(); @@ -590,8 +590,8 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 } else { uintptr_t p = getJumpTableAddress64(ip); MAYUSE(p); + GETIP_(ip, x3); TABLE64(x3, p); - GETIP_(ip); LD(x2, x3, 0); } CLEARIP(); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 2b8a6d42..5669406f 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1107,26 +1107,31 @@ dyn->vector_sew = VECTOR_SEWNA; #if STEP < 2 -#define GETIP(A) MOV64x(xRIP, A) -#define GETIP_(A) MOV64x(xRIP, A) +#define GETIP(A, scratch) +#define GETIP_(A, scratch) #else -// put value in the Table64 even if not using it for now to avoid difference between Step2 and Step3. Needs to be optimized later... -#define GETIP(A) \ - if (dyn->last_ip && ((A) - dyn->last_ip) < 2048) { \ - uint64_t _delta_ip = (A) - dyn->last_ip; \ - dyn->last_ip += _delta_ip; \ - if (_delta_ip) ADDI(xRIP, xRIP, _delta_ip); \ - } else { \ - dyn->last_ip = (A); \ - MOV64x(xRIP, (A)); \ - } -#define GETIP_(A) \ - if (dyn->last_ip && ((A) - dyn->last_ip) < 2048) { \ - int64_t _delta_ip = (A) - dyn->last_ip; \ - if (_delta_ip) ADDI(xRIP, xRIP, _delta_ip); \ - } else { \ - MOV64x(xRIP, (A)); \ - } +#define GETIP_(A, scratch) \ + do { \ + ssize_t _delta_ip = (ssize_t)(A) - (ssize_t)dyn->last_ip; \ + if (!dyn->last_ip) { \ + MOV64x(xRIP, A); \ + } else if (_delta_ip == 0) { \ + } else if (_delta_ip >= -2048 && _delta_ip < 2048) { \ + ADDI(xRIP, xRIP, _delta_ip); \ + } else if (_delta_ip < 0 && _delta_ip >= -0xffffffff) { \ + MOV32w(scratch, -_delta_ip); \ + SUB(xRIP, xRIP, scratch); \ + } else if (_delta_ip > 0 && _delta_ip <= 0xffffffff) { \ + MOV32w(scratch, _delta_ip); \ + ADD(xRIP, xRIP, scratch); \ + } else { \ + MOV64x(xRIP, (A)); \ + } \ + } while (0) +#define GETIP(A, scratch) \ + GETIP_(A, scratch); \ + dyn->last_ip = (A); + #endif #define CLEARIP() dyn->last_ip = 0 diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index b39a589b..99281462 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -204,7 +204,7 @@ int Table64(dynarec_rv64_t *dyn, uint64_t val, int pass); // add a value to tab void CreateJmpNext(void* addr, void* next); #define GO_TRACE(A, B, s0) \ - GETIP(addr); \ + GETIP(addr, s0); \ MV(x1, xRIP); \ STORE_XEMU_CALL(s0); \ MOV64x(x2, B); \ |