From 2a08026fa6c50b554160b86b10f0678c12a2dadd Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 26 Dec 2024 19:21:24 +0800 Subject: [PATCH 1/2] [LA64_DYNAREC] Added hardware wall-clock support --- src/core.c | 2 +- src/dynarec/la64/dynarec_la64_0f.c | 7 ++++-- src/dynarec/la64/la64_emitter.h | 2 ++ src/emu/x64emu.c | 35 ++++++++++++++++++++++++++++-- src/tools/my_cpuid.c | 4 ++-- 5 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/core.c b/src/core.c index aa9def4ee4..c7e6bd2c34 100644 --- a/src/core.c +++ b/src/core.c @@ -593,7 +593,7 @@ void computeRDTSC() { int hardware = 0; box64_rdtsc_shift = 0; - #if defined(ARM64) || defined(RV64) + #if defined(ARM64) || defined(RV64) || defined(LA64) hardware = 1; box64_rdtsc = 0; // allow hardware counter #else diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c index 4e80972f7f..d1a6c396ce 100644 --- a/src/dynarec/la64/dynarec_la64_0f.c +++ b/src/dynarec/la64/dynarec_la64_0f.c @@ -338,8 +338,11 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0x31: INST_NAME("RDTSC"); NOTEST(x1); - // TODO: how to read the wall-clock real time on LoongArch? - CALL(ReadTSC, x3); // will return the u64 in x3 + if (box64_rdtsc) { + CALL(ReadTSC, x3); // will return the u64 in x3 + } else { + RDTIME_D(x3, xZR); + } if (box64_rdtsc_shift) { SRLI_D(x3, x3, box64_rdtsc_shift); } diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h index cddcb1c17e..8af62ce1d3 100644 --- a/src/dynarec/la64/la64_emitter.h +++ b/src/dynarec/la64/la64_emitter.h @@ -950,6 +950,8 @@ f24-f31 fs0-fs7 Static registers Callee #define FCMP_D(cd, fj, fk, cond) EMIT(type_4R(0b000011000010, cond, fk, fj, cd & 0b111)) #define FSEL(fd, fj, fk, ca) EMIT(type_4R(0b000011010000, ca & 0b111, fk, fj, fd)) +#define RDTIME_D(rd, rj) EMIT(type_2R(0b11010, rj, rd)) + //////////////////////////////////////////////////////////////////////////////// // (undocumented) LSX/LASX extension instructions diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c index e63f46ddc5..e35f260834 100644 --- a/src/emu/x64emu.c +++ b/src/emu/x64emu.c @@ -702,6 +702,37 @@ static inline uint64_t readFreq() : "=r"(val)); return val; } +#elif defined(LA64) +static inline uint64_t readCycleCounter() +{ + uint64_t val; + asm volatile("rdtime.d %0, %1" + : "=r"(val) : "r"(0)); + return val; +} + +static inline uint64_t readFreq() +{ + static size_t val = -1; + + FILE* f = popen("cat /proc/cpuinfo | grep -i \"CPU MHz\" | head -n 1 | sed -r 's/CPU MHz.+:\\s{1,}//g'", "r"); + if(f) { + char tmp[200] = ""; + ssize_t s = fread(tmp, 1, 200, f); + pclose(f); + if (s > 0) return (uint64_t)atof(tmp) * 1e6; + } + + // fallback to rdtime + sleep + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 50000000; // 50 milliseconds + uint64_t cycles = readCycleCounter(); + nanosleep(&ts, NULL); + // round to MHz + val = (size_t)round(((double)(readCycleCounter() - cycles) * 20) / 1e6) * 1e6; + return (uint64_t)val; +} #endif uint64_t ReadTSC(x64emu_t* emu) @@ -709,7 +740,7 @@ uint64_t ReadTSC(x64emu_t* emu) (void)emu; // Hardware counter, per architecture -#if defined(ARM64) || defined(RV64) +#if defined(ARM64) || defined(RV64) || defined(LA64) if (!box64_rdtsc) return readCycleCounter(); #endif // fall back to gettime... @@ -728,7 +759,7 @@ uint64_t ReadTSCFrequency(x64emu_t* emu) { (void)emu; // Hardware counter, per architecture -#if defined(ARM64) || defined(RV64) +#if defined(ARM64) || defined(RV64) || defined(LA64) if (!box64_rdtsc) return readFreq(); #endif // fall back to get time diff --git a/src/tools/my_cpuid.c b/src/tools/my_cpuid.c index b30466f3a3..cb3860b34f 100644 --- a/src/tools/my_cpuid.c +++ b/src/tools/my_cpuid.c @@ -134,7 +134,7 @@ const char* getCpuName() } setenv("BOX64_CPUNAME", name, 1); // temporary set #ifndef STATICBUILD - FILE* f = popen("lscpu | grep \"Model name:\" | sed -r 's/Model name:\\s{1,}//g'", "r"); + FILE* f = popen("lscpu | grep -i \"model name:\\|型号名称:\" | sed -r 's/(Model name:|型号名称:)\\s{1,}//g'", "r"); if(f) { char tmp[200] = ""; ssize_t s = fread(tmp, 1, 200, f); @@ -155,7 +155,7 @@ const char* getCpuName() } } // failled, try to get architecture at least - f = popen("lscpu | grep \"Architecture:\" | sed -r 's/Architecture:\\s{1,}//g'", "r"); + f = popen("lscpu | grep -i \"architecture:\\|架构:\" | sed -r 's/(architecture:|架构:)\\s{1,}//g'", "r"); if(f) { char tmp[200] = ""; ssize_t s = fread(tmp, 1, 200, f); From b9d30ed1ed9207a07fbe45a907c00b163c762567 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 26 Dec 2024 20:36:00 +0800 Subject: [PATCH 2/2] Refined multi-language support --- src/tools/my_cpuid.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/tools/my_cpuid.c b/src/tools/my_cpuid.c index cb3860b34f..b201bd7148 100644 --- a/src/tools/my_cpuid.c +++ b/src/tools/my_cpuid.c @@ -134,7 +134,7 @@ const char* getCpuName() } setenv("BOX64_CPUNAME", name, 1); // temporary set #ifndef STATICBUILD - FILE* f = popen("lscpu | grep -i \"model name:\\|型号名称:\" | sed -r 's/(Model name:|型号名称:)\\s{1,}//g'", "r"); + FILE* f = popen("LC_ALL=C lscpu | grep -i \"model name:\" | head -n 1 | sed -r 's/(model name:)\\s{1,}//gi'", "r"); if(f) { char tmp[200] = ""; ssize_t s = fread(tmp, 1, 200, f); @@ -145,9 +145,6 @@ const char* getCpuName() // trim ending while(strlen(tmp) && tmp[strlen(tmp)-1]=='\n') tmp[strlen(tmp)-1] = 0; - // incase multiple cpu type are present, there will be multiple lines - while(strchr(tmp, '\n')) - *strchr(tmp,'\n') = ' '; strncpy(name, tmp, 199); } setenv("BOX64_CPUNAME", name, 1); @@ -155,7 +152,7 @@ const char* getCpuName() } } // failled, try to get architecture at least - f = popen("lscpu | grep -i \"architecture:\\|架构:\" | sed -r 's/(architecture:|架构:)\\s{1,}//g'", "r"); + f = popen("LC_ALL=C lscpu | grep -i \"architecture:\" | head -n 1 | sed -r 's/(architecture:)\\s{1,}//gi'", "r"); if(f) { char tmp[200] = ""; ssize_t s = fread(tmp, 1, 200, f); @@ -165,9 +162,6 @@ const char* getCpuName() // trim ending while(strlen(tmp) && tmp[strlen(tmp)-1]=='\n') tmp[strlen(tmp)-1] = 0; - // incase multiple cpu type are present, there will be multiple lines - while(strchr(tmp, '\n')) - *strchr(tmp,'\n') = ' '; snprintf(name, 199, "unknown %s cpu", tmp); setenv("BOX64_CPUNAME", name, 1); return name;