riscv(support): add extension detection

This commit is contained in:
gns 2024-03-06 09:27:26 +08:00 committed by gns
parent 9eb94f1afc
commit e1ce400d1f
2 changed files with 134 additions and 0 deletions

View File

@ -631,6 +631,111 @@ JIT_PARAMDEF(JIT_PARAMINIT)
#include <sys/utsname.h>
#endif
#if LJ_TARGET_RISCV64 && LJ_TARGET_POSIX
#include <setjmp.h>
#include <signal.h>
static sigjmp_buf sigbuf = {0};
static void detect_sigill(int sig)
{
siglongjmp(sigbuf, 1);
}
static int riscv_compressed()
{
#if defined(__riscv_c) || defined(__riscv_compressed)
/* Don't bother checking for RVC -- would crash before getting here. */
return 1;
#elif defined(__GNUC__)
/* c.nop; c.nop; */
__asm__(".4byte 0x00010001");
return 1;
#else
return 0;
#endif
}
static int riscv_zba()
{
#if defined(__riscv_b) || defined(__riscv_zba)
/* Don't bother checking for Zba -- would crash before getting here. */
return 1;
#elif defined(__GNUC__)
/* Don't bother verifying the result, just check if the instruction exists. */
/* add.uw zero, zero, zero */
__asm__(".4byte 0x0800003b");
return 1;
#else
return 0;
#endif
}
static int riscv_zbb()
{
#if defined(__riscv_b) || defined(__riscv_zbb)
/* Don't bother checking for Zbb -- would crash before getting here. */
return 1;
#elif defined(__GNUC__)
register int t asm ("a0");
/* addi a0, zero, 255; sext.b a0, a0; */
__asm__("addi a0, zero, 255\n\t.4byte 0x60451513");
return t < 0;
#else
return 0;
#endif
}
static int riscv_zicond()
{
#if defined(__riscv_zicond)
/* Don't bother checking for Zicond -- would crash before getting here. */
return 1;
#elif defined(__GNUC__)
/* czero.eqz zero, zero, zero; */
__asm__(".4byte 0x0e005033");
return 1;
#else
return 0;
#endif
}
static int riscv_zfa()
{
#if defined(__riscv_zfa)
/* Don't bother checking for Zfa -- would crash before getting here. */
return 1;
#else
return 0;
#endif
}
static int riscv_xthead()
{
#if (defined(__riscv_xtheadba) \
&& defined(__riscv_xtheadbb) \
&& defined(__riscv_xtheadcondmov) \
&& defined(__riscv_xtheadmac))
/* Don't bother checking for XThead -- would crash before getting here. */
return 1;
#elif defined(__GNUC__)
register int t asm ("a0");
/* C906 & C910 & C908 all have "xtheadc", XTheadBb subset "xtheadc". */
/* Therefore assume XThead* are present if XTheadBb is present. */
/* addi a0, zero, 255; th.ext a0, a0, 7, 0; */
__asm__("addi a0, zero, 255\n\t.4byte 0x1c05250b");
return t == -1; /* In case of collision with other vendor extensions. */
#else
return 0;
#endif
}
static uint32_t riscv_probe(int (*func)(void), uint32_t flag)
{
if (sigsetjmp(sigbuf, 1) == 0) {
return func() ? flag : 0;
} else return 0;
}
#endif
/* Arch-dependent CPU feature detection. */
static uint32_t jit_cpudetect(void)
{
@ -702,6 +807,24 @@ static uint32_t jit_cpudetect(void)
}
#endif
#elif LJ_TARGET_RISCV64
#if LJ_HASJIT
/* SIGILL-based detection of RVC, Zba, Zbb and XThead. Welcome to the future. */
struct sigaction old = {0}, act = {0};
act.sa_handler = detect_sigill;
sigaction(SIGILL, &act, &old);
flags |= riscv_probe(riscv_compressed, JIT_F_RVC);
flags |= riscv_probe(riscv_zba, JIT_F_RVZba);
flags |= riscv_probe(riscv_zbb, JIT_F_RVZbb);
flags |= riscv_probe(riscv_zicond, JIT_F_RVZicond);
flags |= riscv_probe(riscv_zfa, JIT_F_RVZfa);
flags |= riscv_probe(riscv_xthead, JIT_F_RVXThead);
sigaction(SIGILL, &old, NULL);
/* Detect V/P? */
/* V have no hardware available, P not ratified yet. */
#endif
#else
#error "Missing CPU detection for this architecture"
#endif

View File

@ -67,6 +67,17 @@
#endif
#endif
#elif LJ_TARGET_RISCV64
#define JIT_F_RVC (JIT_F_CPU << 0)
#define JIT_F_RVZba (JIT_F_CPU << 1)
#define JIT_F_RVZbb (JIT_F_CPU << 2)
#define JIT_F_RVZicond (JIT_F_CPU << 3)
#define JIT_F_RVZfa (JIT_F_CPU << 4)
#define JIT_F_RVXThead (JIT_F_CPU << 5)
#define JIT_F_CPUSTRING "\003RVC\003Zba\003Zbb\006Zicond\003Zfa\006XThead"
#else
#define JIT_F_CPUSTRING ""