diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2025-06-20 17:26:21 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-20 11:26:21 +0200 |
| commit | f1e884103040ef5d304de5d4f10aac3915f92451 (patch) | |
| tree | 77fc740002fa46971c0108046be177d0c1d0e7df /src | |
| parent | cfdc733e2f6c25901cc72e774bcbcdecceb3d9de (diff) | |
| download | box64-f1e884103040ef5d304de5d4f10aac3915f92451.tar.gz box64-f1e884103040ef5d304de5d4f10aac3915f92451.zip | |
[DYNACACHE][RV64] Enabled dynacache for RV64 (#2762)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_3.c | 42 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.c | 25 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 15 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_pass2.h | 32 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_pass3.h | 33 | ||||
| -rw-r--r-- | src/dynarec/rv64/rv64_emitter.h | 30 | ||||
| -rw-r--r-- | src/tools/env.c | 2 |
7 files changed, 119 insertions, 60 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 5eb2196e..924f3e36 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -460,7 +460,7 @@ 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) { - call_n(dyn, ninst, *(void**)(addr + 8), tmp); + call_n(dyn, ninst, (void*)(addr + 8), tmp); addr += 8 + 8; } else { GETIP(ip + 1, x7); // read the 0xCC @@ -964,7 +964,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int #endif } #if STEP < 2 - if (!rex.is32bits && IsNativeCall(addr + i32, rex.is32bits, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn)) + if (!rex.is32bits && !dyn->need_reloc && IsNativeCall(addr + i32, rex.is32bits, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn)) tmp = dyn->insts[ninst].pass2choice = 3; else tmp = dyn->insts[ninst].pass2choice = i32 ? 0 : 1; @@ -978,8 +978,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int BARRIER(BARRIER_FULL); if (dyn->last_ip && (addr - dyn->last_ip < 0x800)) { ADDI(x2, xRIP, addr - dyn->last_ip); + } else if (dyn->last_ip && (dyn->last_ip - addr < 0x800)) { + SUBI(x2, xRIP, dyn->last_ip - addr); } else { - MOV64x(x2, addr); + if (dyn->need_reloc) { + TABLE64(x2, addr); + } else { + MOV64x(x2, addr); + } } PUSH1(x2); MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall - 1)), dyn->insts[ninst].retn); @@ -996,7 +1002,7 @@ 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) { - call_n(dyn, ninst, *(void**)(dyn->insts[ninst].natcall + 2 + 8), tmp); + call_n(dyn, ninst, (void*)(dyn->insts[ninst].natcall + 2 + 8), tmp); POP1(xRIP); // pop the return address dyn->last_ip = addr; } else { @@ -1026,7 +1032,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 1: // this is call to next step, so just push the return address to the stack - MOV64x(x2, addr); + if (dyn->need_reloc) { + TABLE64(x2, addr); + } else { + MOV64x(x2, addr); + } PUSH1z(x2); break; default: @@ -1036,15 +1046,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags to "dont'care" state } // regular call - /*if(BOX64DRENV(dynarec_callret) && BOX64DRENV(dynarec_bigblock)>1) { - BARRIER(BARRIER_FULL); + if (dyn->need_reloc) { + TABLE64(x2, addr); } else { - BARRIER(BARRIER_FLOAT); - *need_epilog = 0; - *ok = 0; - }*/ - - MOV64x(x2, addr); + MOV64x(x2, addr); + } fpu_purgecache(dyn, ninst, 1, x1, x3, x4); PUSH1z(x2); if (BOX64DRENV(dynarec_callret)) { @@ -1072,7 +1078,12 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) { // jumps out of current dynablock... j64 = getJumpTableAddress64(addr); - MOV64x(x4, j64); + if (dyn->need_reloc) { + AddRelocTable64JmpTbl(dyn, ninst, addr, STEP); + TABLE64_(x4, j64); + } else { + MOV64x(x4, j64); + } LD(x4, x4, 0); BR(x4); } @@ -1562,7 +1573,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) { // jumps out of current dynablock... j64 = getJumpTableAddress64(addr); - TABLE64(x4, j64); + if (dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); + TABLE64_(x4, j64); LD(x4, x4, 0); BR(x4); } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 9f2645b5..0b597163 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -118,7 +118,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, GETIP(addr + delta, scratch); ADDI(ret, xRIP, tmp); SCRATCH_USAGE(1); - } else if (tmp + addr + delta < 0x100000000LL) { + } else if (tmp + addr + delta < 0x80000000LL && !dyn->need_reloc) { MOV64x(ret, tmp + addr + delta); } else { if (adj) { @@ -591,7 +591,11 @@ static int indirect_lookup(dynarec_rv64_t* dyn, int ninst, int is32bits, int s1, if (!is32bits) { SRLI(s1, xRIP, 48); BNEZ_safe(s1, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block); - MOV64x(s2, getConst(const_jmptbl48)); + if (dyn->need_reloc) { + TABLE64C(s2, const_jmptbl48); + } else { + MOV64x(s2, getConst(const_jmptbl48)); + } TH_EXTU(s1, xRIP, JMPTABL_START2 + JMPTABL_SHIFT2 - 1, JMPTABL_START2); TH_LRD(s2, s2, s1, 3); } else { @@ -649,7 +653,8 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 uintptr_t p = getJumpTableAddress64(ip); MAYUSE(p); GETIP_(ip, x3); - TABLE64(x3, p); + if (dyn->need_reloc) AddRelocTable64JmpTbl(dyn, ninst, ip, STEP); + TABLE64_(x3, p); LD(x2, x3, 0); dest = x2; } @@ -755,7 +760,11 @@ void iret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is64bits) // set new RSP MV(xRSP, x3); // Ret.... - MOV64x(x2, getConst(const_epilog)); // epilog on purpose, CS might have changed! + // epilog on purpose, CS might have changed! + if (dyn->need_reloc) + TABLE64C(x2, const_epilog); + else + MOV64x(x2, getConst(const_epilog)); SMEND(); BR(x2); CLEARIP(); @@ -841,7 +850,13 @@ void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w) } } // native call - TABLE64(x3, (uintptr_t)fnc); + if (dyn->need_reloc) { + // fnc is indirect, to help with relocation (but PltResolver might be an issue here) + TABLE64(x3, (uintptr_t)fnc); + LD(x3, x3, 0); + } else { + TABLE64_(x3, *(uintptr_t*)fnc); // using x16 as scratch regs for call address + } JALR(xRA, x3); // put return value in x64 regs if (w > 0) { diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 361e104f..939e3c37 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1152,6 +1152,9 @@ #ifndef TABLE64C #define TABLE64C(A, V) #endif +#ifndef TABLE64_ +#define TABLE64_(A, V) +#endif #define ARCH_INIT() \ SMSTART(); \ @@ -1168,7 +1171,11 @@ do { \ ssize_t _delta_ip = (ssize_t)(A) - (ssize_t)dyn->last_ip; \ if (!dyn->last_ip) { \ - MOV64x(xRIP, A); \ + if (dyn->need_reloc) { \ + TABLE64(xRIP, (A)); \ + } else { \ + MOV64x(xRIP, (A)); \ + } \ } else if (_delta_ip == 0) { \ } else if (_delta_ip >= -2048 && _delta_ip < 2048) { \ ADDI(xRIP, xRIP, _delta_ip); \ @@ -1179,7 +1186,11 @@ MOV32w(scratch, _delta_ip); \ ADD(xRIP, xRIP, scratch); \ } else { \ - MOV64x(xRIP, (A)); \ + if (dyn->need_reloc) { \ + TABLE64(xRIP, (A)); \ + } else { \ + MOV64x(xRIP, (A)); \ + } \ } \ } while (0) #define GETIP(A, scratch) \ diff --git a/src/dynarec/rv64/dynarec_rv64_pass2.h b/src/dynarec/rv64/dynarec_rv64_pass2.h index 7466f426..d6bb4934 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass2.h +++ b/src/dynarec/rv64/dynarec_rv64_pass2.h @@ -25,22 +25,32 @@ } #define INST_EPILOG dyn->insts[ninst].epilog = dyn->native_size; #define INST_NAME(name) -#define TABLE64(A, V) \ - { \ +#define TABLE64(A, V) \ + do { \ + if (dyn->need_reloc && !isTable64(dyn, (V))) \ + AddRelocTable64Addr(dyn, ninst, (V), 2); \ + Table64(dyn, (V), 2); \ + EMIT(0); \ + EMIT(0); \ + } while (0) +#define TABLE64_(A, V) \ + do { \ Table64(dyn, (V), 2); \ EMIT(0); \ EMIT(0); \ - } + } while (0) #define FTABLE64(A, V) \ - { \ + do { \ mmx87_regs_t v = { .d = V }; \ Table64(dyn, v.q, 2); \ EMIT(0); \ EMIT(0); \ - } -#define TABLE64C(A, V) \ - { \ - Table64(dyn, getConst(V), 2); \ - EMIT(0); \ - EMIT(0); \ - } + } while (0) +#define TABLE64C(A, V) \ + do { \ + if (dyn->need_reloc && !isTable64(dyn, getConst(V))) \ + AddRelocTable64Const(dyn, ninst, (V), 2); \ + Table64(dyn, getConst(V), 2); \ + EMIT(0); \ + EMIT(0); \ + } while (0) diff --git a/src/dynarec/rv64/dynarec_rv64_pass3.h b/src/dynarec/rv64/dynarec_rv64_pass3.h index 9a08a57e..1938eccc 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass3.h +++ b/src/dynarec/rv64/dynarec_rv64_pass3.h @@ -30,27 +30,38 @@ #define INST_NAME(name) inst_name_pass3(dyn, ninst, name, rex) #define TABLE64(A, V) \ - { \ + do { \ + if (dyn->need_reloc && !isTable64(dyn, (V))) \ + AddRelocTable64Addr(dyn, ninst, (V), 3); \ int val64offset = Table64(dyn, (V), 3); \ MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); \ AUIPC(A, SPLIT20(val64offset)); \ LD(A, A, SPLIT12(val64offset)); \ - } + } while (0) +#define TABLE64_(A, V) \ + do { \ + int val64offset = Table64(dyn, (V), 3); \ + MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); \ + AUIPC(A, SPLIT20(val64offset)); \ + LD(A, A, SPLIT12(val64offset)); \ + } while (0) #define FTABLE64(A, V) \ - { \ + do { \ mmx87_regs_t v = { .d = V }; \ int val64offset = Table64(dyn, v.q, 3); \ MESSAGE(LOG_DUMP, " FTable64: %g\n", v.d); \ AUIPC(x1, SPLIT20(val64offset)); \ FLD(A, x1, SPLIT12(val64offset)); \ - } -#define TABLE64C(A, V) \ - { \ - int val64offset = Table64(dyn, getConst(V), 3); \ - MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); \ - AUIPC(A, SPLIT20(val64offset)); \ - LD(A, A, SPLIT12(val64offset)); \ - } + } while (0) +#define TABLE64C(A, V) \ + do { \ + if (dyn->need_reloc && !isTable64(dyn, getConst(V))) \ + AddRelocTable64Const(dyn, ninst, (V), 3); \ + int val64offset = Table64(dyn, getConst(V), 3); \ + MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); \ + AUIPC(A, SPLIT20(val64offset)); \ + LD(A, A, SPLIT12(val64offset)); \ + } while (0) #define DEFAULT_VECTOR \ if (BOX64ENV(dynarec_log) >= LOG_INFO || dyn->need_dump || BOX64ENV(dynarec_missing) == 2) { \ diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index cb91b7e6..f5ad2530 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -948,21 +948,21 @@ // Count trailing zero bits // BEWARE: You should take care of the all zeros situation yourself, // and clear the high 32bit when x is 1. -#define CTZxw(rd, rs, x, s1, s2) \ - if (cpuext.zbb) { \ - if (x) \ - CTZ(rd, rs); \ - else \ - CTZW(rd, rs); \ - } else { \ - NEG(s2, rs); \ - AND(s2, s2, rs); \ - TABLE64(s1, 0x03f79d71b4ca8b09ULL); \ - MUL(s2, s2, s1); \ - SRLI(s2, s2, 64 - 6); \ - TABLE64C(s1, const_deBruijn64tab); \ - ADD(s1, s1, s2); \ - LBU(rd, s1, 0); \ +#define CTZxw(rd, rs, x, s1, s2) \ + if (cpuext.zbb) { \ + if (x) \ + CTZ(rd, rs); \ + else \ + CTZW(rd, rs); \ + } else { \ + NEG(s2, rs); \ + AND(s2, s2, rs); \ + TABLE64_(s1, 0x03f79d71b4ca8b09ULL); \ + MUL(s2, s2, s1); \ + SRLI(s2, s2, 64 - 6); \ + TABLE64C(s1, const_deBruijn64tab); \ + ADD(s1, s1, s2); \ + LBU(rd, s1, 0); \ } // Count set bits diff --git a/src/tools/env.c b/src/tools/env.c index 3a22855c..fce6cdaa 100644 --- a/src/tools/env.c +++ b/src/tools/env.c @@ -806,7 +806,7 @@ done: #ifdef ARM64 #define ARCH_VERSION SET_VERSION(0, 0, 1) #elif defined(RV64) -#define ARCH_VERSION SET_VERSION(0, 0, 0) +#define ARCH_VERSION SET_VERSION(0, 0, 1) #elif defined(LA64) #define ARCH_VERSION SET_VERSION(0, 0, 0) #else |