41 #include <stdatomic.h>
43 #if HAVE_SYS_HWPROBE_H
44 #include <sys/hwprobe.h>
45 #elif HAVE_ASM_HWPROBE_H
46 #include <asm/hwprobe.h>
47 #include <asm/unistd.h>
48 #include <sys/syscall.h>
51static int __riscv_hwprobe(
struct riscv_hwprobe *pairs,
size_t pair_count,
55 return syscall(__NR_riscv_hwprobe, pairs, pair_count,
cpu_count, cpus,
59 #if HAVE_GETAUXVAL || HAVE_ELF_AUX_INFO
61 #define HWCAP_RV(letter) (1ul << ((letter) - 'A'))
64int checkasm_get_cpuids(uint32_t *vendor, uintptr_t *arch, uintptr_t *imp)
66#if HAVE_SYS_HWPROBE_H || HAVE_ASM_HWPROBE_H
67 struct riscv_hwprobe pairs[] = {
68 { RISCV_HWPROBE_KEY_MVENDORID, 0 },
69 { RISCV_HWPROBE_KEY_MARCHID, 0 },
70 { RISCV_HWPROBE_KEY_MIMPID, 0 },
74 *vendor = (uint32_t)pairs[0].
value;
75 *arch = (uintptr_t)pairs[1].
value;
76 *imp = (uintptr_t)pairs[2].
value;
83const char *checkasm_get_riscv_vendor_name(uint32_t vendorid)
86 unsigned bank = vendorid >> 7,
offset = vendorid & 0x7f;
94const char *checkasm_get_riscv_arch_name(
char *buf,
size_t buflen,
95 uint32_t vendor, uintptr_t arch)
97 if (arch & INTPTR_MIN) {
99 snprintf(buf, buflen,
"vendor arch 0x%"PRIXPTR, arch);
104 case 0:
return "Unspecified";
105 case 5:
return "Spike";
106 case 42:
return "QEMU";
108 snprintf(buf, buflen,
"open arch %"PRIuPTR, arch);
115#define RISCV_FLOAT (1 << 0)
116#define RISCV_VECTOR (1 << 1)
118static int checkasm_hwprobe(
void)
121#if HAVE_SYS_HWPROBE_H || HAVE_ASM_HWPROBE_H
122 struct riscv_hwprobe pairs[] = {
123 { RISCV_HWPROBE_KEY_IMA_EXT_0, 0 },
127 if (pairs[0].
value & RISCV_HWPROBE_IMA_FD)
128 flags |= RISCV_FLOAT;
129#ifdef RISCV_HWPROBE_EXT_ZVE32X
130 if (pairs[0].
value & RISCV_HWPROBE_EXT_ZVE32X)
131 flags |= RISCV_VECTOR;
133#ifdef RISCV_HWPROBE_IMA_V
135 if (pairs[0].
value & RISCV_HWPROBE_IMA_V)
136 flags |= RISCV_VECTOR;
144#elif HAVE_GETAUXVAL || HAVE_ELF_AUX_INFO
148 if (hwcap & HWCAP_RV(
'F'))
149 flags |= RISCV_FLOAT;
150 if (hwcap & HWCAP_RV(
'V'))
151 flags |= RISCV_VECTOR;
155 flags |= RISCV_FLOAT;
158 flags |= RISCV_VECTOR;
163static int checkasm_cpu_flags(
void)
169 flags = checkasm_hwprobe();
176int checkasm_has_float(
void)
178 return (checkasm_cpu_flags() & RISCV_FLOAT) != 0;
181int checkasm_has_vector(
void)
183 return (checkasm_cpu_flags() & RISCV_VECTOR) != 0;
188 void *checked_call =
NULL;
189 int flags = checkasm_cpu_flags();
192#ifdef __riscv_float_abi_soft
194 checked_call = checkasm_checked_call_i;
197 checked_call = checkasm_checked_call_iv;
201 checked_call = checkasm_checked_call_if;
203 case RISCV_FLOAT | RISCV_VECTOR:
204 checked_call = checkasm_checked_call_ifv;
207 assert(checked_call !=
NULL);
#define flags(name, subs,...)
#define atomic_load_explicit(object, order)
#define atomic_store_explicit(object, desired, order)
static atomic_int cpu_flags
static atomic_int cpu_count
COLD unsigned long checkasm_getauxval(unsigned long type)
COLD const char * checkasm_get_jedec_vendor_name(unsigned bank, unsigned offset)