about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core.c2
-rw-r--r--src/dynarec/la64/dynarec_la64_0f.c7
-rw-r--r--src/dynarec/la64/la64_emitter.h2
-rw-r--r--src/emu/x64emu.c35
-rw-r--r--src/tools/my_cpuid.c10
5 files changed, 43 insertions, 13 deletions
diff --git a/src/core.c b/src/core.c
index aa9def4e..c7e6bd2c 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 4e80972f..d1a6c396 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 9290869b..6d8e507f 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 e63f46dd..e35f2608 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 b30466f3..b201bd71 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("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 \"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;