riscv(support): add extension detection
This commit is contained in:
parent
23d49c6973
commit
89e0d60ad0
120
src/lib_jit.c
120
src/lib_jit.c
@ -647,6 +647,104 @@ JIT_PARAMDEF(JIT_PARAMINIT)
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
#if LJ_TARGET_RISCV64 && LJ_TARGET_POSIX
|
||||
|
||||
#if LJ_TARGET_LINUX
|
||||
#include <unistd.h>
|
||||
|
||||
struct riscv_hwprobe hwprobe_requests[] = {
|
||||
{RISCV_HWPROBE_KEY_IMA_EXT_0}
|
||||
};
|
||||
|
||||
const uint64_t *hwprobe_ext = &hwprobe_requests[0].value;
|
||||
|
||||
int hwprobe_ret = 0;
|
||||
#endif
|
||||
|
||||
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 LJ_TARGET_LINUX
|
||||
return (hwprobe_ret == 0 && ((*hwprobe_ext) & RISCV_HWPROBE_IMA_C)) ? 1 : 0;
|
||||
#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 LJ_TARGET_LINUX
|
||||
return (hwprobe_ret == 0 && ((*hwprobe_ext) & RISCV_HWPROBE_EXT_ZBA)) ? 1 : 0;
|
||||
#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 LJ_TARGET_LINUX
|
||||
return (hwprobe_ret == 0 && ((*hwprobe_ext) & RISCV_HWPROBE_EXT_ZBB)) ? 1 : 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 LJ_TARGET_LINUX
|
||||
return (hwprobe_ret == 0 && ((*hwprobe_ext) & RISCV_HWPROBE_EXT_ZICOND)) ? 1 : 0;
|
||||
#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;
|
||||
#elif LJ_TARGET_LINUX
|
||||
return (hwprobe_ret == 0 && ((*hwprobe_ext) & RISCV_HWPROBE_EXT_ZFA)) ? 1 : 0;
|
||||
#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;
|
||||
#else
|
||||
/*
|
||||
** Hardcoded as there's no easy way of detection:
|
||||
** - SIGILL have some trouble with libluajit as we speak
|
||||
** - Checking mvendorid looks good, but might not be reliable.
|
||||
*/
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t riscv_probe(int (*func)(void), uint32_t flag)
|
||||
{
|
||||
return func() ? flag : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Arch-dependent CPU feature detection. */
|
||||
static uint32_t jit_cpudetect(void)
|
||||
{
|
||||
@ -724,6 +822,28 @@ static uint32_t jit_cpudetect(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#elif LJ_TARGET_RISCV64
|
||||
#if LJ_HASJIT
|
||||
|
||||
#if LJ_TARGET_LINUX
|
||||
/* HWPROBE-based detection of RVC, Zba, Zbb and Zicond. */
|
||||
hwprobe_ret = syscall(__NR_riscv_hwprobe, &hwprobe_requests,
|
||||
sizeof(hwprobe_requests) / sizeof(struct riscv_hwprobe), 0,
|
||||
NULL, 0);
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
||||
/* Detect V/P? */
|
||||
/* V have no hardware available, P not ratified yet. */
|
||||
#endif
|
||||
|
||||
#else
|
||||
#error "Missing CPU detection for this architecture"
|
||||
#endif
|
||||
|
||||
40
src/lj_jit.h
40
src/lj_jit.h
@ -67,6 +67,46 @@
|
||||
#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"
|
||||
|
||||
#if LJ_TARGET_LINUX
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#ifndef __NR_riscv_hwprobe
|
||||
#ifndef __NR_arch_specific_syscall
|
||||
#define __NR_arch_specific_syscall 244
|
||||
#endif
|
||||
#define __NR_riscv_hwprobe (__NR_arch_specific_syscall + 14)
|
||||
#endif
|
||||
|
||||
struct riscv_hwprobe {
|
||||
int64_t key;
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
#define RISCV_HWPROBE_KEY_MVENDORID 0
|
||||
#define RISCV_HWPROBE_KEY_MARCHID 1
|
||||
#define RISCV_HWPROBE_KEY_MIMPID 2
|
||||
#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3
|
||||
#define RISCV_HWPROBE_KEY_IMA_EXT_0 4
|
||||
|
||||
#define RISCV_HWPROBE_IMA_C (1 << 1)
|
||||
#define RISCV_HWPROBE_EXT_ZBA (1 << 3)
|
||||
#define RISCV_HWPROBE_EXT_ZBB (1 << 4)
|
||||
#define RISCV_HWPROBE_EXT_ZFA (1ULL << 32)
|
||||
#define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35)
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define JIT_F_CPUSTRING ""
|
||||
|
||||
Loading…
Reference in New Issue
Block a user