diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-09-11 13:17:01 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-11 13:17:01 +0200 |
| commit | 0913c94e46a138edb906bf4cb1e109519aff3bfe (patch) | |
| tree | 26d05296f6fa4d5f1a320a41ca03c553b9436bad /src | |
| parent | 5e52c735a67f4b40c38c6d8d2c00d104c31677fc (diff) | |
| parent | 910a0ef8e1b98e5d20fdec7bae01a37d8ea25b1e (diff) | |
| download | box64-0913c94e46a138edb906bf4cb1e109519aff3bfe.tar.gz box64-0913c94e46a138edb906bf4cb1e109519aff3bfe.zip | |
Merge pull request #969 from ksco/thead
[RV64_DYNAREC] Added thead vendor extension detection
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/rv64_emitter.h | 153 | ||||
| -rw-r--r-- | src/include/debug.h | 13 | ||||
| -rw-r--r-- | src/main.c | 35 | ||||
| -rw-r--r-- | src/rv64detect.c | 66 |
4 files changed, 254 insertions, 13 deletions
diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index f23c6716..6457ad59 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -650,5 +650,158 @@ f28–31 ft8–11 FP temporaries Caller // Single-bit Set (Immediate) #define BSETI(rd, rs1, imm) EMIT(R_type(0b0010100, imm, rs1, 0b001, rd, 0b0010011)) +/// THead vendor extension +/// https://github.com/T-head-Semi/thead-extension-spec/releases + +// XTheadBa - Address calculation instructions + +// Add a shifted operand to a second operand. +// reg[rd] := reg[rs1] + (reg[rs2] << imm2) +#define TH_ADDSL(rd, rs1, rs2, imm2) EMIT(R_type(imm2&0b11, rs2, rs1, 0b001, rd, 0b0001011)) + +// XTheadBb - Basic bit-manipulation + +// Perform a cyclic right shift. +// reg[rd] := (reg[rs1] >> imm6) | (reg[rs1] << (xlen - imm6)) +#define TH_SRRI(rd, rs1, imm6) EMIT(I_type(0b000100000000|(imm6&0x3f), rs1, 0b001, rd, 0b0001011)) + +// TODO +// th.srriw rd, rs1, imm5 Cyclic right shift on word operand +// th.ext rd, rs1, imm1, imm2 Extract and sign-extend bits +// th.extu rd, rs1, imm1, imm2 Extract and zero-extend bits +// th.ff0 rd, rs1 Find first '0'-bit +// th.ff1 rd, rs1 Find first '1'-bit +// th.rev rd, rs1 Reverse byte order +// th.revw rd, rs1 Reverse byte order of word operand +// th.tstnbz rd, rs1 Test for NUL bytes + +// XTheadBs - Single-bit instructions + +// Tests if a single bit is set. +// if (reg[rs1] & (1 << imm6)) +// rd := 1 +// else +// rd := 0 +#define TH_TST(rd, rs1, imm6) EMIT(I_type(0b100010000000|(imm6&0x3f), rs1, 0b001, rd, 0b0001011)) + + +// XTheadCondMov - Conditional move + +// Move if equal zero. +// if (reg[rs2] == 0x0) +// reg[rd] := reg[rs1] +#define TH_MVEQZ(rd, rs1, rs2) EMIT(R_type(0b0100000, rs2, rs1, 0b001, rd, 0b0001011)) + +// Move if not equal zero. +// if (reg[rs2] != 0x0) +// reg[rd] := reg[rs1] +#define TH_MVNEZ(rd, rs1, rs2) EMIT(R_type(0b0100001, rs2, rs1, 0b001, rd, 0b0001011)) + +// XTheadMemIdx - Indexed memory operations + +// Load indexed byte, increment address after loading. +// rd := sign_extend(mem[rs1]) +// rs1 := rs1 + (sign_extend(imm5) << imm2) +#define TH_LBIA(rd, rs1, imm5, imm2) EMIT(I_type(0b000110000000|((imm2&0b11)<<5)|(imm5&0x1f), rs1, 0b100, rd, 0b0001011)) + +// TODO +// th.lbib rd, (rs1), imm5, imm2 Load indexed byte +// th.lbuia rd, (rs1), imm5, imm2 Load indexed unsigned byte +// th.lbuib rd, (rs1), imm5, imm2 Load indexed unsigned byte +// th.lhia rd, (rs1), imm5, imm2 Load indexed half-word +// th.lhib rd, (rs1), imm5, imm2 Load indexed half-word +// th.lhuia rd, (rs1), imm5, imm2 Load indexed unsigned half-word +// th.lhuib rd, (rs1), imm5, imm2 Load indexed unsigned half-word +// th.lwia rd, (rs1), imm5, imm2 Load indexed word +// th.lwib rd, (rs1), imm5, imm2 Load indexed word +// th.lwuia rd, (rs1), imm5, imm2 Load indexed unsigned word +// th.lwuib rd, (rs1), imm5, imm2 Load indexed unsigned word +// th.ldia rd, (rs1), imm5, imm2 Load indexed double-word +// th.ldib rd, (rs1), imm5, imm2 Load indexed double-word +// th.sbia rd, (rs1), imm5, imm2 Store indexed byte +// th.sbib rd, (rs1), imm5, imm2 Store indexed byte +// th.shia rd, (rs1), imm5, imm2 Store indexed half-word +// th.shib rd, (rs1), imm5, imm2 Store indexed half-word +// th.swia rd, (rs1), imm5, imm2 Store indexed word +// th.swib rd, (rs1), imm5, imm2 Store indexed word +// th.sdia rd, (rs1), imm5, imm2 Store indexed double-word +// th.sdib rd, (rs1), imm5, imm2 Store indexed double-word +// th.lrb rd, rs1, rs2, imm2 Load indexed byte +// th.lrbu rd, rs1, rs2, imm2 Load indexed unsigned byte +// th.lrh rd, rs1, rs2, imm2 Load indexed half-word +// th.lrhu rd, rs1, rs2, imm2 Load indexed unsigned half-word +// th.lrw rd, rs1, rs2, imm2 Load indexed word +// th.lrwu rd, rs1, rs2, imm2 Load indexed unsigned word +// th.lrd rd, rs1, rs2, imm2 Load indexed double-word +// th.srb rd, rs1, rs2, imm2 Store indexed byte +// th.srh rd, rs1, rs2, imm2 Store indexed half-word +// th.srw rd, rs1, rs2, imm2 Store indexed word +// th.srd rd, rs1, rs2, imm2 Store indexed double-word +// th.lurb rd, rs1, rs2, imm2 Load unsigned indexed byte +// th.lurbu rd, rs1, rs2, imm2 Load unsigned indexed unsigned byte +// th.lurh rd, rs1, rs2, imm2 Load unsigned indexed half-word +// th.lurhu rd, rs1, rs2, imm2 Load unsigned indexed unsigned half-word +// th.lurw rd, rs1, rs2, imm2 Load unsigned indexed word +// th.lurwu rd, rs1, rs2, imm2 Load unsigned indexed unsigned word +// th.lurd rd, rs1, rs2, imm2 Load unsigned indexed double-word +// th.surb rd, rs1, rs2, imm2 Store unsigned indexed byte +// th.surh rd, rs1, rs2, imm2 Store unsigned indexed half-word +// th.surw rd, rs1, rs2, imm2 Store unsigned indexed word +// th.surd rd, rs1, rs2, imm2 Store unsigned indexed double-word + +// XTheadMemPair - Two-GPR memory operations + + +// Load two 64-bit values from memory into two GPRs. +// addr := rs1 + (zero_extend(imm2) << 4) +// rd1 := mem[addr+7:addr] +// rd2 := mem[addr+15:addr+8] +#define TH_LDD(rd1, rd2, rs1, imm2) EMIT(R_type(0b1111100|(imm2&0b11), rd2, rs1, 0b100, rd1, 0b0001011)) + +// TODO +// th.lwd rd1, rd2, (rs1), imm2, 3 Load two signed 32-bit values +// th.lwud rd1, rd2, (rs1), imm2, 3 Load two unsigned 32-bit values +// th.sdd rd1, rd2, (rs1), imm2, 4 Store two 64-bit values +// th.swd rd1, rd2, (rs1), imm2, 3 Store two 32-bit values + +// XTheadFMemIdx - Indexed memory operations for floating-point registers + +// Load indexed double-precision floating point value. +// addr := rs1 + (rs2 << imm2) +// rd := fmem[addr+7:addr] +#define TH_FLRD(rd, rs1, rs2, imm2) EMIT(R_type(0b0110000|(imm2&0b11), rs2, rs1, 0b110, rd, 0b0001011)) + +// TODO +// th.flrw rd, rs1, rs2, imm2 Load indexed float +// th.flurd rd, rs1, rs2, imm2 Load unsigned indexed double +// th.flurw rd, rs1, rs2, imm2 Load unsigned indexed float +// th.fsrd rd, rs1, rs2, imm2 Store indexed double +// th.fsrw rd, rs1, rs2, imm2 Load indexed float +// th.fsurd rd, rs1, rs2, imm2 Store unsigned indexed double +// th.fsurw rd, rs1, rs2, imm2 Load unsigned indexed float + +// XTheadMac - Multiply-accumulate instructions + +// Compute multiply-add result of double-word operands. +// M := reg[rs1] * reg[rs2] +// reg[rd] := reg[rd] + M +#define TH_MULA(rd, rs1, rs2) EMIT(R_type(0b0010000, rs2, rs1, 0b001, rd, 0b0001011)) + +// TODO +// th.mulah rd, rs1, rs2 Multiply-add half-words +// th.mulaw rd, rs1, rs2 Multiply-add words +// th.muls rd, rs1, rs2 Multiply-subtract double-words +// th.mulsh rd, rs1, rs2 Multiply-subtract half-words +// th.mulsw rd, rs1, rs2 Multiply-subtract words + +// XTheadFmv - Double-precision floating-point high-bit data transmission instructions + +// Read double-precision floating-point high-bit data +// rd := fs1[63:32] +#define TH_FMV_X_HW(rd, fs1) EMIT(R_type(0b1100000, 0, fs1, 0b001, rd, 0b0001011)) + +// Write double-precision floating-point high-bit data +// fs1[63:32] := rd +#define TH_FMV_HW_X(rd, fs1) EMIT(R_type(0b1010000, 0, fs1, 0b001, rd, 0b0001011)) #endif //__RV64_EMITTER_H__ diff --git a/src/include/debug.h b/src/include/debug.h index 9bfc5c89..acd842c2 100644 --- a/src/include/debug.h +++ b/src/include/debug.h @@ -40,6 +40,15 @@ extern int rv64_zba; extern int rv64_zbb; extern int rv64_zbc; extern int rv64_zbs; +extern int rv64_xtheadba; +extern int rv64_xtheadbb; +extern int rv64_xtheadbs; +extern int rv64_xtheadcondmov; +extern int rv64_xtheadmemidx; +extern int rv64_xtheadmempair; +extern int rv64_xtheadfmemidx; +extern int rv64_xtheadmac; +extern int rv64_xtheadfmv; #endif #endif extern int box64_libcef; @@ -100,7 +109,7 @@ void printf_ftrace(const char* fmt, ...); #ifdef BUILD_DYNAMIC #define EXPORTDYN __attribute__((visibility("default"))) #else -#define EXPORTDYN +#define EXPORTDYN #endif void init_malloc_hook(void); @@ -123,7 +132,7 @@ extern void* __libc_memalign(size_t, size_t); #define box_realloc __libc_realloc #define box_calloc __libc_calloc #define box_free __libc_free -#define box_memalign __libc_memalign +#define box_memalign __libc_memalign extern char* box_strdup(const char* s); extern char* box_realpath(const char* path, char* ret); diff --git a/src/main.c b/src/main.c index e8ebe74d..377eea1f 100644 --- a/src/main.c +++ b/src/main.c @@ -79,6 +79,15 @@ int rv64_zba = 0; int rv64_zbb = 0; int rv64_zbc = 0; int rv64_zbs = 0; +int rv64_xtheadba = 0; +int rv64_xtheadbb = 0; +int rv64_xtheadbs = 0; +int rv64_xtheadcondmov = 0; +int rv64_xtheadmemidx = 0; +int rv64_xtheadmempair = 0; +int rv64_xtheadfmemidx = 0; +int rv64_xtheadmac = 0; +int rv64_xtheadfmv = 0; #endif #else //DYNAREC int box64_dynarec = 0; @@ -208,7 +217,7 @@ void my_child_fork() { if(ftrace_has_pid) { // open a new ftrace... - if(!ftrace_name) + if(!ftrace_name) fclose(ftrace); openFTrace(NULL); } @@ -372,6 +381,16 @@ HWCAP2_ECV if(rv64_zbb) printf_log(LOG_INFO, " Zbb"); if(rv64_zbc) printf_log(LOG_INFO, " Zbc"); if(rv64_zbs) printf_log(LOG_INFO, " Zbs"); + if(rv64_xtheadba) printf_log(LOG_INFO, " XTheadBa"); + if(rv64_xtheadbb) printf_log(LOG_INFO, " XTheadBb"); + if(rv64_xtheadbs) printf_log(LOG_INFO, " XTheadBs"); + if(rv64_xtheadcondmov) printf_log(LOG_INFO, " XTheadCondMov"); + if(rv64_xtheadmemidx) printf_log(LOG_INFO, " XTheadMemIdx"); + if(rv64_xtheadmempair) printf_log(LOG_INFO, " XTheadMemPair"); + if(rv64_xtheadfmemidx) printf_log(LOG_INFO, " XTheadFMemIdx"); + if(rv64_xtheadmac) printf_log(LOG_INFO, " XTheadMac"); + if(rv64_xtheadfmv) printf_log(LOG_INFO, " XTheadFmv"); + printf_log(LOG_INFO, " PageSize:%zd ", box64_pagesize); #else #error Unsupported architecture @@ -888,7 +907,7 @@ int GatherEnv(char*** dest, char** env, char* prog) { // Add all but BOX64_* environnement // but add 2 for default BOX64_PATH and BOX64_LD_LIBRARY_PATH - char** p = env; + char** p = env; int idx = 0; int path = 0; int ld_path = 0; @@ -1200,7 +1219,7 @@ void endBox64() { if(!my_context || box64_quit) return; - + endMallocHook(); x64emu_t* emu = thread_get_emu(); // atexit first @@ -1323,7 +1342,7 @@ int main(int argc, const char **argv, char **env) { } } } - + const char* prog = argv[1]; int nextarg = 1; // check if some options are passed @@ -1351,7 +1370,7 @@ int main(int argc, const char **argv, char **env) { if(!box64_nobanner) PrintBox64Version(); // precheck, for win-preload - if(strstr(prog, "wine-preloader")==(prog+strlen(prog)-strlen("wine-preloader")) + if(strstr(prog, "wine-preloader")==(prog+strlen(prog)-strlen("wine-preloader")) || strstr(prog, "wine64-preloader")==(prog+strlen(prog)-strlen("wine64-preloader"))) { // wine-preloader detecter, skipping it if next arg exist and is an x86 binary int x64 = (nextarg<argc)?FileIsX64ELF(argv[nextarg]):0; @@ -1372,8 +1391,8 @@ int main(int argc, const char **argv, char **env) { int ld_libs_args = -1; // check if this is wine if(!strcmp(prog, "wine64") - || !strcmp(prog, "wine64-development") - || !strcmp(prog, "wine") + || !strcmp(prog, "wine64-development") + || !strcmp(prog, "wine") || (strlen(prog)>5 && !strcmp(prog+strlen(prog)-strlen("/wine"), "/wine")) || (strlen(prog)>7 && !strcmp(prog+strlen(prog)-strlen("/wine64"), "/wine64"))) { const char* prereserve = getenv("WINEPRELOADRESERVE"); @@ -1391,7 +1410,7 @@ int main(int argc, const char **argv, char **env) { } } box64_wine = 1; - } else + } else // check if ld-musl-x86_64.so.1 is used if(strstr(prog, "ld-musl-x86_64.so.1")) { printf_log(LOG_INFO, "BOX64: ld-musl detected, trying to workaround and use system ld-linux\n"); diff --git a/src/rv64detect.c b/src/rv64detect.c index 9976d1d7..e1b3b40a 100644 --- a/src/rv64detect.c +++ b/src/rv64detect.c @@ -11,7 +11,7 @@ // Detect RV64 extensions, by executing on of the opcode with a SIGILL signal handler static sigjmp_buf sigbuf = {0}; -typedef void(*vFii_t)(int, int); +typedef void(*vFiip_t)(int, int, void*); static void detect_sigill(int sig) { siglongjmp(sigbuf, 1); @@ -19,6 +19,7 @@ static void detect_sigill(int sig) static int Check(void* block) { + static uint64_t buf[2] = {0}; // Clear instruction cache __clear_cache(block, block+box64_pagesize); // Setup SIGILL signal handler @@ -28,7 +29,7 @@ static int Check(void* block) signal(SIGILL, old); return 0; } - ((vFii_t)block)(0, 1); + ((vFiip_t)block)(0, 1, buf); // done... signal(SIGILL, old); return 1; @@ -43,6 +44,9 @@ void RV64_Detect_Function() } uint32_t* block; #define EMIT(A) *block = (A); ++block + + // Official extensions + // Test Zba with ADDUW block = (uint32_t*)my_block; ADDUW(A0, A0, A1); @@ -64,7 +68,63 @@ void RV64_Detect_Function() BR(xRA); rv64_zbs = Check(my_block); + // THead vendor extensions + + // Test XTheadBa with TH_ADDSL + block = (uint32_t*)my_block; + TH_ADDSL(A0, A0, A1, 1); + BR(xRA); + rv64_xtheadba = Check(my_block); + + // Test XTheadBb with TH_SRRI + block = (uint32_t*)my_block; + TH_SRRI(A0, A1, 1); + BR(xRA); + rv64_xtheadbb = Check(my_block); + + // Test XTheadBs with TH_TST + block = (uint32_t*)my_block; + TH_TST(A0, A1, 1); + BR(xRA); + rv64_xtheadbs = Check(my_block); + + // Test XTheadCondMov with TH_MVEQZ + block = (uint32_t*)my_block; + TH_MVEQZ(A0, A0, A1); + BR(xRA); + rv64_xtheadcondmov = Check(my_block); + + // Test XTheadMemIdx with TH_LBIA + block = (uint32_t*)my_block; + TH_LBIA(A0, A2, 1, 1); + BR(xRA); + rv64_xtheadmemidx = Check(my_block); + + // Test XTheadMemPair with TH_LDD + block = (uint32_t*)my_block; + TH_LDD(A0, A1, A2, 0); + BR(xRA); + rv64_xtheadmempair = Check(my_block); + + // Test XTheadFMemIdx with TH_FLRD + block = (uint32_t*)my_block; + TH_FLRD(A0, A2, xZR, 0); + BR(xRA); + rv64_xtheadfmemidx = Check(my_block); + + // Test XTheadMac with TH_MULA + block = (uint32_t*)my_block; + TH_MULA(A0, A0, A1); + BR(xRA); + rv64_xtheadmac = Check(my_block); + + // Test XTheadFmv with TH_FMV_X_HW + block = (uint32_t*)my_block; + TH_FMV_X_HW(A0, A1); + BR(xRA); + rv64_xtheadfmv = Check(my_block); + // Finish // Free the memory my_block munmap(my_block, box64_pagesize); -} \ No newline at end of file +} |