xref: /linux/arch/riscv/include/asm/cpufeature-macros.h (revision 7f71507851fc7764b36a3221839607d3a45c2025)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright 2022-2024 Rivos, Inc
4  */
5 
6 #ifndef _ASM_CPUFEATURE_MACROS_H
7 #define _ASM_CPUFEATURE_MACROS_H
8 
9 #include <asm/hwcap.h>
10 #include <asm/alternative-macros.h>
11 
12 #define STANDARD_EXT		0
13 
14 bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, unsigned int bit);
15 #define riscv_isa_extension_available(isa_bitmap, ext)	\
16 	__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
17 
18 static __always_inline bool __riscv_has_extension_likely(const unsigned long vendor,
19 							 const unsigned long ext)
20 {
21 	asm goto(ALTERNATIVE("j	%l[l_no]", "nop", %[vendor], %[ext], 1)
22 	:
23 	: [vendor] "i" (vendor), [ext] "i" (ext)
24 	:
25 	: l_no);
26 
27 	return true;
28 l_no:
29 	return false;
30 }
31 
32 static __always_inline bool __riscv_has_extension_unlikely(const unsigned long vendor,
33 							   const unsigned long ext)
34 {
35 	asm goto(ALTERNATIVE("nop", "j	%l[l_yes]", %[vendor], %[ext], 1)
36 	:
37 	: [vendor] "i" (vendor), [ext] "i" (ext)
38 	:
39 	: l_yes);
40 
41 	return false;
42 l_yes:
43 	return true;
44 }
45 
46 static __always_inline bool riscv_has_extension_unlikely(const unsigned long ext)
47 {
48 	compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX");
49 
50 	if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE))
51 		return __riscv_has_extension_unlikely(STANDARD_EXT, ext);
52 
53 	return __riscv_isa_extension_available(NULL, ext);
54 }
55 
56 static __always_inline bool riscv_has_extension_likely(const unsigned long ext)
57 {
58 	compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX");
59 
60 	if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE))
61 		return __riscv_has_extension_likely(STANDARD_EXT, ext);
62 
63 	return __riscv_isa_extension_available(NULL, ext);
64 }
65 
66 #endif /* _ASM_CPUFEATURE_MACROS_H */
67