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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
#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(*vFiip_t)(int, int, void*);
static void detect_sigill(int sig)
{
siglongjmp(sigbuf, 1);
}
static int Check(void* block)
{
static uint64_t buf[2] = {0};
// 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;
}
((vFiip_t)block)(0, 1, buf);
// 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
// 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
block = (uint32_t*)my_block;
BCLR(A0, A0, A1);
BR(xRA);
rv64_zbs = Check(my_block);
// THead vendor extensions
// Test XTheadBa with TH_ADDSL
block = (uint32_t*)my_block;
TH_ADDSL(A0, A0, A1, 1);
BR(xRA);
rv64_xtheadba = Check(my_block);
// Test XTheadBb with TH_SRRI
block = (uint32_t*)my_block;
TH_SRRI(A0, A1, 1);
BR(xRA);
rv64_xtheadbb = Check(my_block);
// Test XTheadBs with TH_TST
block = (uint32_t*)my_block;
TH_TST(A0, A1, 1);
BR(xRA);
rv64_xtheadbs = Check(my_block);
// Test XTheadCondMov with TH_MVEQZ
block = (uint32_t*)my_block;
TH_MVEQZ(A0, A0, A1);
BR(xRA);
rv64_xtheadcondmov = Check(my_block);
// Test XTheadMemIdx with TH_LBIA
block = (uint32_t*)my_block;
TH_LBIA(A0, A2, 1, 1);
BR(xRA);
rv64_xtheadmemidx = Check(my_block);
// Test XTheadMemPair with TH_LDD
block = (uint32_t*)my_block;
TH_LDD(A0, A1, A2, 0);
BR(xRA);
rv64_xtheadmempair = Check(my_block);
// Test XTheadFMemIdx with TH_FLRD
block = (uint32_t*)my_block;
TH_FLRD(A0, A2, xZR, 0);
BR(xRA);
rv64_xtheadfmemidx = Check(my_block);
// Test XTheadMac with TH_MULA
block = (uint32_t*)my_block;
TH_MULA(A0, A0, A1);
BR(xRA);
rv64_xtheadmac = Check(my_block);
// Test XTheadFmv with TH_FMV_X_HW
block = (uint32_t*)my_block;
TH_FMV_X_HW(A0, A1);
BR(xRA);
rv64_xtheadfmv = Check(my_block);
// Finish
// Free the memory my_block
munmap(my_block, box64_pagesize);
}
|