1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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
__sighandler_t old = signal(SIGILL, detect_sigill);
if(sigsetjmp(sigbuf, 1)) {
// didn't work, extension not present
signal(SIGILL, old);
return 0;
}
((vFii_t)block)(0, 1);
// done...
signal(SIGILL, old);
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);
}
|