asm volatile(".inst 0x658aa000" : : : "z0");
}
+static void hbc_sigill(void)
+{
+ /* BC.EQ +4 */
+ asm volatile("cmp xzr, xzr\n"
+ ".inst 0x54000030" : : : "cc");
+}
+
+ static void uscat_sigbus(void)
+ {
+ /* unaligned atomic access */
+ asm volatile("ADD x1, sp, #2" : : : );
+ /* STADD W0, [X1] */
+ asm volatile(".inst 0xb820003f" : : : );
+ }
+
static const struct hwcap_data {
const char *name;
unsigned long at_hwcap;
.hwcap_bit = HWCAP2_SVE_EBF16,
.cpuinfo = "sveebf16",
},
+ {
+ .name = "HBC",
+ .at_hwcap = AT_HWCAP2,
+ .hwcap_bit = HWCAP2_HBC,
+ .cpuinfo = "hbc",
+ .sigill_fn = hbc_sigill,
+ .sigill_reliable = true,
+ },
};
- static bool seen_sigill;
-
- static void handle_sigill(int sig, siginfo_t *info, void *context)
- {
- ucontext_t *uc = context;
-
- seen_sigill = true;
-
- /* Skip over the offending instruction */
- uc->uc_mcontext.pc += 4;
+ typedef void (*sighandler_fn)(int, siginfo_t *, void *);
+
+ #define DEF_SIGHANDLER_FUNC(SIG, NUM) \
+ static bool seen_##SIG; \
+ static void handle_##SIG(int sig, siginfo_t *info, void *context) \
+ { \
+ ucontext_t *uc = context; \
+ \
+ seen_##SIG = true; \
+ /* Skip over the offending instruction */ \
+ uc->uc_mcontext.pc += 4; \
}
+ DEF_SIGHANDLER_FUNC(sigill, SIGILL);
+ DEF_SIGHANDLER_FUNC(sigbus, SIGBUS);
+
bool cpuinfo_present(const char *name)
{
FILE *f;