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 <sys/syscall.h>
50 static int __riscv_hwprobe(
struct riscv_hwprobe *pairs,
size_t pair_count,
54 return syscall(__NR_riscv_hwprobe, pairs, pair_count,
cpu_count, cpus,
58 #if HAVE_GETAUXVAL || HAVE_ELF_AUX_INFO
60 #define HWCAP_RV(letter) (1ul << ((letter) - 'A'))
63 int checkasm_get_cpuids(uint32_t *vendor, uintptr_t *arch, uintptr_t *imp)
65 #if HAVE_SYS_HWPROBE_H || HAVE_ASM_HWPROBE_H
66 struct riscv_hwprobe pairs[] = {
67 { RISCV_HWPROBE_KEY_MVENDORID, 0 },
68 { RISCV_HWPROBE_KEY_MARCHID, 0 },
69 { RISCV_HWPROBE_KEY_MIMPID, 0 },
73 *vendor = (uint32_t)pairs[0].
value;
74 *arch = (uintptr_t)pairs[1].
value;
75 *imp = (uintptr_t)pairs[2].
value;
82 const char *checkasm_get_riscv_vendor_name(uint32_t vendorid)
85 unsigned bank = vendorid >> 7,
offset = vendorid & 0x7f;
93 const char *checkasm_get_riscv_arch_name(
char *buf,
size_t buflen,
94 uint32_t vendor, uintptr_t arch)
96 if (arch & INTPTR_MIN) {
98 snprintf(buf, buflen,
"vendor arch 0x%"PRIXPTR, arch);
103 case 0:
return "Unspecified";
104 case 5:
return "Spike";
105 case 42:
return "QEMU";
107 snprintf(buf, buflen,
"open arch %"PRIuPTR, arch);
114 #define RISCV_FLOAT (1 << 0)
115 #define RISCV_VECTOR (1 << 1)
117 static int checkasm_hwprobe(
void)
120 #if HAVE_SYS_HWPROBE_H || HAVE_ASM_HWPROBE_H
121 struct riscv_hwprobe pairs[] = {
122 { RISCV_HWPROBE_KEY_IMA_EXT_0, 0 },
126 if (pairs[0].
value & RISCV_HWPROBE_IMA_FD)
127 flags |= RISCV_FLOAT;
128 #ifdef RISCV_HWPROBE_EXT_ZVE32X
129 if (pairs[0].
value & RISCV_HWPROBE_EXT_ZVE32X)
130 flags |= RISCV_VECTOR;
132 #ifdef RISCV_HWPROBE_IMA_V
134 if (pairs[0].
value & RISCV_HWPROBE_IMA_V)
135 flags |= RISCV_VECTOR;
143 #elif HAVE_GETAUXVAL || HAVE_ELF_AUX_INFO
147 if (hwcap & HWCAP_RV(
'F'))
148 flags |= RISCV_FLOAT;
149 if (hwcap & HWCAP_RV(
'V'))
150 flags |= RISCV_VECTOR;
154 flags |= RISCV_FLOAT;
156 #ifdef __riscv_vector
157 flags |= RISCV_VECTOR;
162 static int checkasm_cpu_flags(
void)
168 flags = checkasm_hwprobe();
175 int checkasm_has_float(
void)
177 return (checkasm_cpu_flags() & RISCV_FLOAT) != 0;
180 int checkasm_has_vector(
void)
182 return (checkasm_cpu_flags() & RISCV_VECTOR) != 0;
187 void *checked_call =
NULL;
188 int flags = checkasm_cpu_flags();
191 #ifdef __riscv_float_abi_soft
193 checked_call = checkasm_checked_call_i;
196 checked_call = checkasm_checked_call_iv;
200 checked_call = checkasm_checked_call_if;
202 case RISCV_FLOAT | RISCV_VECTOR:
203 checked_call = checkasm_checked_call_ifv;
206 assert(checked_call !=
NULL);