about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2025-05-20 15:24:09 +0800
committerYang Liu <liuyang22@iscas.ac.cn>2025-05-20 15:24:09 +0800
commit5b8a71d720bb8a4be2a9a67f8c6d1392a48f6e36 (patch)
tree7f1dcf02668dc988929bc8f8b4955a7f89c725c0 /src
parent58021bbf42c3e5a5b1eddba0e5d649b1d91a8189 (diff)
downloadbox64-5b8a71d720bb8a4be2a9a67f8c6d1392a48f6e36.tar.gz
box64-5b8a71d720bb8a4be2a9a67f8c6d1392a48f6e36.zip
[RV64] Improved vendor extension detection to avoid conflicts (for #2645)
Diffstat (limited to 'src')
-rw-r--r--src/rv64detect.c88
1 files changed, 51 insertions, 37 deletions
diff --git a/src/rv64detect.c b/src/rv64detect.c
index ec41b482..8ef0ad82 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(*vFiip_t)(int, int, void*);
+typedef int (*iFiip_t)(int, int, void*);
 static void detect_sigill(int sig)
 {
     siglongjmp(sigbuf, 1);
@@ -29,7 +29,12 @@ static int Check(void* block)
         signal(SIGILL, old);
         return 0;
     }
-    ((vFiip_t)block)(0, 1, buf);
+    int result = ((iFiip_t)block)(0, 1, buf);
+    if (result != 42) {
+        // wrong result, extension not present
+        signal(SIGILL, old);
+        return 0;
+    }
     // done...
     signal(SIGILL, old);
     return 1;
@@ -45,37 +50,62 @@ 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);
-    BR(xRA);
-    rv64_zba = Check(my_block);
-    // Test Zbb with ANDN
-    block = (uint32_t*)my_block;
-    ANDN(A0, A0, A1);
-    BR(xRA);
-    rv64_zbb = Check(my_block);
-    // Test Zbc with CLMUL
-    block = (uint32_t*)my_block;
-    CLMUL(A0, A0, A1);
-    BR(xRA);
-    rv64_zbc = Check(my_block);
-    // Test Zbs with BCLR
+    // THead vendor extensions
     block = (uint32_t*)my_block;
-    BCLR(A0, A0, A1);
+    ADDI(A0, xZR, 40);
+    ADDI(A1, xZR, 1);
+    TH_ADDSL(A0, A0, A1, 1);
     BR(xRA);
-    rv64_zbs = Check(my_block);
+    rv64_xtheadba
+        = rv64_xtheadbb
+        = rv64_xtheadbs
+        = rv64_xtheadcondmov
+        = rv64_xtheadmemidx
+        = rv64_xtheadmempair
+        = rv64_xtheadfmemidx
+        = rv64_xtheadmac
+        = rv64_xtheadfmv = Check(my_block);
+
+    // Official extensions
+
+    if (!rv64_xtheadba) {
+        // Test Zba with ADDUW
+        block = (uint32_t*)my_block;
+        ADDUW(A0, A0, A1);
+        ADDI(A0, xZR, 42);
+        BR(xRA);
+        rv64_zba = Check(my_block);
+        // Test Zbb with ANDN
+        block = (uint32_t*)my_block;
+        ANDN(A0, A0, A1);
+        ADDI(A0, xZR, 42);
+        BR(xRA);
+        rv64_zbb = Check(my_block);
+        // Test Zbc with CLMUL
+        block = (uint32_t*)my_block;
+        CLMUL(A0, A0, A1);
+        ADDI(A0, xZR, 42);
+        BR(xRA);
+        rv64_zbc = Check(my_block);
+        // Test Zbs with BCLR
+        block = (uint32_t*)my_block;
+        BCLR(A0, A0, A1);
+        ADDI(A0, xZR, 42);
+        BR(xRA);
+        rv64_zbs = Check(my_block);
+    }
 
     block = (uint32_t*)my_block;
     CSRRS(xZR, xZR, 0xc22 /* vlenb */);
+    ADDI(A0, xZR, 42);
     BR(xRA);
     rv64_vector = Check(my_block);
 
     if (rv64_vector) {
         block = (uint32_t*)my_block;
         CSRRS(xZR, xZR, 0x00f /* vcsr */); // vcsr does not exists in xtheadvector
+        ADDI(A0, xZR, 42);
         BR(xRA);
         rv64_xtheadvector = !Check(my_block);
     }
@@ -90,22 +120,6 @@ void RV64_Detect_Function()
         }
     }
 
-    // THead vendor extensions
-    if (!rv64_zba) {
-        block = (uint32_t*)my_block;
-        TH_ADDSL(A0, A0, A1, 1);
-        BR(xRA);
-        rv64_xtheadba
-            = rv64_xtheadbb
-            = rv64_xtheadbs
-            = rv64_xtheadcondmov
-            = rv64_xtheadmemidx
-            = rv64_xtheadmempair
-            = rv64_xtheadfmemidx
-            = rv64_xtheadmac
-            = rv64_xtheadfmv = Check(my_block);
-    }
-
     // Finish
     // Free the memory my_block
     munmap(my_block, box64_pagesize);