about summary refs log tree commit diff stats
path: root/src/rv64detect.c
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-05-01 10:24:46 +0000
committerptitSeb <sebastien.chev@gmail.com>2023-05-01 10:24:46 +0000
commitaac1663d7579cb9e821d342dda9f999623d20b62 (patch)
treec9a273241ff52100d9a79dec64d0d3002bdaee24 /src/rv64detect.c
parent5b9d963d314aa99302fa5cddb459e34e408d47b2 (diff)
downloadbox64-aac1663d7579cb9e821d342dda9f999623d20b62.tar.gz
box64-aac1663d7579cb9e821d342dda9f999623d20b62.zip
[RV64_DYNAREC] Add detection of Zba, Zbb, Zbc and Zbs CPU extensions
Diffstat (limited to 'src/rv64detect.c')
-rw-r--r--src/rv64detect.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/rv64detect.c b/src/rv64detect.c
new file mode 100644
index 00000000..5e84423b
--- /dev/null
+++ b/src/rv64detect.c
@@ -0,0 +1,70 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <setjmp.h>
+
+#include "debug.h"
+#include "dynarec/rv64/rv64_emitter.h"
+
+// 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);
+static void detect_sigill(int sig)
+{
+    siglongjmp(sigbuf, 1);
+}
+
+static int Check(void* block)
+{
+    // Clear instruction cache
+    __clear_cache(block, block+box64_pagesize);
+    // Setup SIGILL signal handler
+    signal(SIGILL, detect_sigill);
+    if(sigsetjmp(sigbuf, 1)) {
+        // didn't work, extension not present
+        signal(SIGILL, SIG_DFL);
+        return 0;
+    }
+    ((vFii_t)block)(0, 1);
+    // done...
+    signal(SIGILL, SIG_DFL);
+    return 1;
+}
+
+void RV64_Detect_Function()
+{
+    // Alloc memory to execute stuffs
+    void* my_block = mmap(NULL, box64_pagesize, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+    if(my_block==(void*)-1) {
+        return;
+    }
+    uint32_t* block;
+    #define EMIT(A) *block = (A); ++block
+    // 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
+    block = (uint32_t*)my_block;
+    BCLR(A0, A0, A1);
+    BR(xRA);
+    rv64_zbs = Check(my_block);
+
+    // Finish
+    // Free the memory my_block
+    munmap(my_block, box64_pagesize);
+}
\ No newline at end of file