Message ID | 20241003182256.1765569-1-chenyangyu@isrc.iscas.ac.cn |
---|---|
State | New |
Headers | show |
Series | [v6] RISC-V: Implement __init_riscv_feature_bits, __riscv_feature_bits, and __riscv_vendor_feature_bits | expand |
Could you implement the latest API defined in the doc? struct { unsigned length; unsigned long long features[]; } __riscv_feature_bits; struct { unsigned length; unsigned long long features[]; } __riscv_vendor_feature_bits; struct { unsigned mvendorid; unsigned marchid; unsigned mimpid; } __riscv_cpu_model; On Fri, Oct 4, 2024 at 2:24 AM Yangyu Chen <chenyangyu@isrc.iscas.ac.cn> wrote: > > From: Kito Cheng <kito.cheng@sifive.com> > > This provides a common abstraction layer to probe the available extensions at > run-time. These functions can be used to implement function multi-versioning or > to detect available extensions. > > The advantages of providing this abstraction layer are: > - Easy to port to other new platforms. > - Easier to maintain in GCC for function multi-versioning. > - For example, maintaining platform-dependent code in C code/libgcc is much > easier than maintaining it in GCC by creating GIMPLEs... > > This API is intended to provide the capability to query minimal common available extensions on the system. > > Proposal in riscv-c-api-doc: https://github.com/riscv-non-isa/riscv-c-api-doc/pull/74 > > Full function multi-versioning implementation will come later. We are posting > this first because we intend to backport it to the GCC 14 branch to unblock > LLVM 19 to use this with GCC 14.2, rather than waiting for GCC 15. > > Changes since v5: > - Minor fixes on indentation. > > Changes since v4: > - Bump to newest riscv-c-api-doc with some new extensions like Zve*, Zc* > Zimop, Zcmop, Zawrs. > - Rename the return variable name of hwprobe syscall. > - Minor fixes on indentation. > > Changes since v3: > - Fix non-linux build. > - Let __init_riscv_feature_bits become constructor > > Changes since v2: > - Prevent it initialize more than once. > > Changes since v1: > - Fix the format. > - Prevented race conditions by introducing a local variable to avoid load/store > operations during the computation of the feature bit. > > libgcc/ChangeLog: > > * config/riscv/feature_bits.c: New. > * config/riscv/t-elf (LIB2ADD): Add feature_bits.c. > > Co-Developed-by: Yangyu Chen <chenyangyu@isrc.iscas.ac.cn> > Signed-off-by: Yangyu Chen <chenyangyu@isrc.iscas.ac.cn> > --- > libgcc/config/riscv/feature_bits.c | 364 +++++++++++++++++++++++++++++ > libgcc/config/riscv/t-elf | 1 + > 2 files changed, 365 insertions(+) > create mode 100644 libgcc/config/riscv/feature_bits.c > > diff --git a/libgcc/config/riscv/feature_bits.c b/libgcc/config/riscv/feature_bits.c > new file mode 100644 > index 00000000000..c5339f065c1 > --- /dev/null > +++ b/libgcc/config/riscv/feature_bits.c > @@ -0,0 +1,364 @@ > +/* Helper function for function multi-versioning for RISC-V. > + > + Copyright (C) 2024 Free Software Foundation, Inc. > + > +This file is part of GCC. > + > +GCC is free software; you can redistribute it and/or modify it under > +the terms of the GNU General Public License as published by the Free > +Software Foundation; either version 3, or (at your option) any later > +version. > + > +GCC is distributed in the hope that it will be useful, but WITHOUT ANY > +WARRANTY; without even the implied warranty of MERCHANTABILITY or > +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > +for more details. > + > +Under Section 7 of GPL version 3, you are granted additional > +permissions described in the GCC Runtime Library Exception, version > +3.1, as published by the Free Software Foundation. > + > +You should have received a copy of the GNU General Public License and > +a copy of the GCC Runtime Library Exception along with this program; > +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see > +<http://www.gnu.org/licenses/>. */ > + > +#define RISCV_FEATURE_BITS_LENGTH 2 > +struct { > + unsigned length; > + unsigned long long features[RISCV_FEATURE_BITS_LENGTH]; > +} __riscv_feature_bits __attribute__ ((visibility ("hidden"), nocommon)); > + > +#define RISCV_VENDOR_FEATURE_BITS_LENGTH 1 > + > +struct { > + unsigned vendorID; > + unsigned length; > + unsigned long long features[RISCV_VENDOR_FEATURE_BITS_LENGTH]; > +} __riscv_vendor_feature_bits __attribute__ ((visibility ("hidden"), nocommon)); > + > +#define A_GROUPID 0 > +#define A_BITMASK (1ULL << 0) > +#define C_GROUPID 0 > +#define C_BITMASK (1ULL << 2) > +#define D_GROUPID 0 > +#define D_BITMASK (1ULL << 3) > +#define F_GROUPID 0 > +#define F_BITMASK (1ULL << 5) > +#define I_GROUPID 0 > +#define I_BITMASK (1ULL << 8) > +#define M_GROUPID 0 > +#define M_BITMASK (1ULL << 12) > +#define V_GROUPID 0 > +#define V_BITMASK (1ULL << 21) > +#define ZACAS_GROUPID 0 > +#define ZACAS_BITMASK (1ULL << 26) > +#define ZBA_GROUPID 0 > +#define ZBA_BITMASK (1ULL << 27) > +#define ZBB_GROUPID 0 > +#define ZBB_BITMASK (1ULL << 28) > +#define ZBC_GROUPID 0 > +#define ZBC_BITMASK (1ULL << 29) > +#define ZBKB_GROUPID 0 > +#define ZBKB_BITMASK (1ULL << 30) > +#define ZBKC_GROUPID 0 > +#define ZBKC_BITMASK (1ULL << 31) > +#define ZBKX_GROUPID 0 > +#define ZBKX_BITMASK (1ULL << 32) > +#define ZBS_GROUPID 0 > +#define ZBS_BITMASK (1ULL << 33) > +#define ZFA_GROUPID 0 > +#define ZFA_BITMASK (1ULL << 34) > +#define ZFH_GROUPID 0 > +#define ZFH_BITMASK (1ULL << 35) > +#define ZFHMIN_GROUPID 0 > +#define ZFHMIN_BITMASK (1ULL << 36) > +#define ZICBOZ_GROUPID 0 > +#define ZICBOZ_BITMASK (1ULL << 37) > +#define ZICOND_GROUPID 0 > +#define ZICOND_BITMASK (1ULL << 38) > +#define ZIHINTNTL_GROUPID 0 > +#define ZIHINTNTL_BITMASK (1ULL << 39) > +#define ZIHINTPAUSE_GROUPID 0 > +#define ZIHINTPAUSE_BITMASK (1ULL << 40) > +#define ZKND_GROUPID 0 > +#define ZKND_BITMASK (1ULL << 41) > +#define ZKNE_GROUPID 0 > +#define ZKNE_BITMASK (1ULL << 42) > +#define ZKNH_GROUPID 0 > +#define ZKNH_BITMASK (1ULL << 43) > +#define ZKSED_GROUPID 0 > +#define ZKSED_BITMASK (1ULL << 44) > +#define ZKSH_GROUPID 0 > +#define ZKSH_BITMASK (1ULL << 45) > +#define ZKT_GROUPID 0 > +#define ZKT_BITMASK (1ULL << 46) > +#define ZTSO_GROUPID 0 > +#define ZTSO_BITMASK (1ULL << 47) > +#define ZVBB_GROUPID 0 > +#define ZVBB_BITMASK (1ULL << 48) > +#define ZVBC_GROUPID 0 > +#define ZVBC_BITMASK (1ULL << 49) > +#define ZVFH_GROUPID 0 > +#define ZVFH_BITMASK (1ULL << 50) > +#define ZVFHMIN_GROUPID 0 > +#define ZVFHMIN_BITMASK (1ULL << 51) > +#define ZVKB_GROUPID 0 > +#define ZVKB_BITMASK (1ULL << 52) > +#define ZVKG_GROUPID 0 > +#define ZVKG_BITMASK (1ULL << 53) > +#define ZVKNED_GROUPID 0 > +#define ZVKNED_BITMASK (1ULL << 54) > +#define ZVKNHA_GROUPID 0 > +#define ZVKNHA_BITMASK (1ULL << 55) > +#define ZVKNHB_GROUPID 0 > +#define ZVKNHB_BITMASK (1ULL << 56) > +#define ZVKSED_GROUPID 0 > +#define ZVKSED_BITMASK (1ULL << 57) > +#define ZVKSH_GROUPID 0 > +#define ZVKSH_BITMASK (1ULL << 58) > +#define ZVKT_GROUPID 0 > +#define ZVKT_BITMASK (1ULL << 59) > +#define ZVE32X_GROUPID 0 > +#define ZVE32X_BITMASK (1ULL << 60) > +#define ZVE32F_GROUPID 0 > +#define ZVE32F_BITMASK (1ULL << 61) > +#define ZVE64X_GROUPID 0 > +#define ZVE64X_BITMASK (1ULL << 62) > +#define ZVE64F_GROUPID 0 > +#define ZVE64F_BITMASK (1ULL << 63) > +#define ZVE64D_GROUPID 1 > +#define ZVE64D_BITMASK (1ULL << 0) > +#define ZIMOP_GROUPID 1 > +#define ZIMOP_BITMASK (1ULL << 1) > +#define ZCA_GROUPID 1 > +#define ZCA_BITMASK (1ULL << 2) > +#define ZCB_GROUPID 1 > +#define ZCB_BITMASK (1ULL << 3) > +#define ZCD_GROUPID 1 > +#define ZCD_BITMASK (1ULL << 4) > +#define ZCF_GROUPID 1 > +#define ZCF_BITMASK (1ULL << 5) > +#define ZCMOP_GROUPID 1 > +#define ZCMOP_BITMASK (1ULL << 6) > +#define ZAWRS_GROUPID 1 > +#define ZAWRS_BITMASK (1ULL << 7) > + > +#define SET_EXT(EXT) features[EXT##_GROUPID] |= EXT##_BITMASK > + > +#ifdef __linux > + > +#define __NR_riscv_hwprobe 258 > +#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_BASE_BEHAVIOR_IMA (1ULL << 0) > +#define RISCV_HWPROBE_KEY_IMA_EXT_0 4 > +#define RISCV_HWPROBE_IMA_FD (1ULL << 0) > +#define RISCV_HWPROBE_IMA_C (1ULL << 1) > +#define RISCV_HWPROBE_IMA_V (1ULL << 2) > +#define RISCV_HWPROBE_EXT_ZBA (1ULL << 3) > +#define RISCV_HWPROBE_EXT_ZBB (1ULL << 4) > +#define RISCV_HWPROBE_EXT_ZBS (1ULL << 5) > +#define RISCV_HWPROBE_EXT_ZICBOZ (1ULL << 6) > +#define RISCV_HWPROBE_EXT_ZBC (1ULL << 7) > +#define RISCV_HWPROBE_EXT_ZBKB (1ULL << 8) > +#define RISCV_HWPROBE_EXT_ZBKC (1ULL << 9) > +#define RISCV_HWPROBE_EXT_ZBKX (1ULL << 10) > +#define RISCV_HWPROBE_EXT_ZKND (1ULL << 11) > +#define RISCV_HWPROBE_EXT_ZKNE (1ULL << 12) > +#define RISCV_HWPROBE_EXT_ZKNH (1ULL << 13) > +#define RISCV_HWPROBE_EXT_ZKSED (1ULL << 14) > +#define RISCV_HWPROBE_EXT_ZKSH (1ULL << 15) > +#define RISCV_HWPROBE_EXT_ZKT (1ULL << 16) > +#define RISCV_HWPROBE_EXT_ZVBB (1ULL << 17) > +#define RISCV_HWPROBE_EXT_ZVBC (1ULL << 18) > +#define RISCV_HWPROBE_EXT_ZVKB (1ULL << 19) > +#define RISCV_HWPROBE_EXT_ZVKG (1ULL << 20) > +#define RISCV_HWPROBE_EXT_ZVKNED (1ULL << 21) > +#define RISCV_HWPROBE_EXT_ZVKNHA (1ULL << 22) > +#define RISCV_HWPROBE_EXT_ZVKNHB (1ULL << 23) > +#define RISCV_HWPROBE_EXT_ZVKSED (1ULL << 24) > +#define RISCV_HWPROBE_EXT_ZVKSH (1ULL << 25) > +#define RISCV_HWPROBE_EXT_ZVKT (1ULL << 26) > +#define RISCV_HWPROBE_EXT_ZFH (1ULL << 27) > +#define RISCV_HWPROBE_EXT_ZFHMIN (1ULL << 28) > +#define RISCV_HWPROBE_EXT_ZIHINTNTL (1ULL << 29) > +#define RISCV_HWPROBE_EXT_ZVFH (1ULL << 30) > +#define RISCV_HWPROBE_EXT_ZVFHMIN (1ULL << 31) > +#define RISCV_HWPROBE_EXT_ZFA (1ULL << 32) > +#define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33) > +#define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34) > +#define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35) > +#define RISCV_HWPROBE_EXT_ZIHINTPAUSE (1ULL << 36) > +#define RISCV_HWPROBE_EXT_ZVE32X (1ULL << 37) > +#define RISCV_HWPROBE_EXT_ZVE32F (1ULL << 38) > +#define RISCV_HWPROBE_EXT_ZVE64X (1ULL << 39) > +#define RISCV_HWPROBE_EXT_ZVE64F (1ULL << 40) > +#define RISCV_HWPROBE_EXT_ZVE64D (1ULL << 41) > +#define RISCV_HWPROBE_EXT_ZIMOP (1ULL << 42) > +#define RISCV_HWPROBE_EXT_ZCA (1ULL << 43) > +#define RISCV_HWPROBE_EXT_ZCB (1ULL << 44) > +#define RISCV_HWPROBE_EXT_ZCD (1ULL << 45) > +#define RISCV_HWPROBE_EXT_ZCF (1ULL << 46) > +#define RISCV_HWPROBE_EXT_ZCMOP (1ULL << 47) > +#define RISCV_HWPROBE_EXT_ZAWRS (1ULL << 48) > +#define RISCV_HWPROBE_KEY_CPUPERF_0 5 > +#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0) > +#define RISCV_HWPROBE_MISALIGNED_EMULATED (1ULL << 0) > +#define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0) > +#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0) > +#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0) > +#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0) > +#define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6 > + > +struct riscv_hwprobe { > + long long key; > + unsigned long long value; > +}; > + > +static long syscall_5_args (long number, long arg1, long arg2, long arg3, > + long arg4, long arg5) > +{ > + register long a7 __asm__ ("a7") = number; > + register long a0 __asm__ ("a0") = arg1; > + register long a1 __asm__ ("a1") = arg2; > + register long a2 __asm__ ("a2") = arg3; > + register long a3 __asm__ ("a3") = arg4; > + register long a4 __asm__ ("a4") = arg5; > + __asm__ __volatile__ ("ecall\n\t" > + : "=r"(a0) > + : "r"(a7), "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4) > + : "memory"); > + return a0; > +} > + > +#define SET_FROM_HWPROBE(HWPROBE_VAR, EXT) \ > + if (HWPROBE_VAR.value & RISCV_HWPROBE_EXT_##EXT) \ > + SET_EXT (EXT) > + > +#define SET_FROM_IMA_EXT(EXT) \ > + SET_FROM_HWPROBE (hwprobe_ima_ext, EXT) > + > +static void __init_riscv_features_bits_linux () > +{ > + struct riscv_hwprobe hwprobes[] = { > + {RISCV_HWPROBE_KEY_BASE_BEHAVIOR, 0}, > + {RISCV_HWPROBE_KEY_IMA_EXT_0, 0}, > + {RISCV_HWPROBE_KEY_MVENDORID, 0}, > + }; > + > + long res = syscall_5_args (__NR_riscv_hwprobe, (long)&hwprobes, > + sizeof (hwprobes) / sizeof (hwprobes[0]), 0, > + 0, 0); > + > + if (res) > + return; > + > + const struct riscv_hwprobe hwprobe_base_behavior = hwprobes[0]; > + unsigned long long features[RISCV_FEATURE_BITS_LENGTH]; > + int i; > + for (i = 0; i < RISCV_FEATURE_BITS_LENGTH; ++i) > + features[i] = 0; > + > + if (hwprobe_base_behavior.value & RISCV_HWPROBE_BASE_BEHAVIOR_IMA) > + { > + SET_EXT (I); > + SET_EXT (M); > + SET_EXT (A); > + } > + > + const struct riscv_hwprobe hwprobe_mvendorid = hwprobes[2]; > + > + __riscv_vendor_feature_bits.length = 0; > + __riscv_vendor_feature_bits.vendorID = hwprobe_mvendorid.value; > + > + const struct riscv_hwprobe hwprobe_ima_ext = hwprobes[1]; > + > + if (hwprobe_ima_ext.value & RISCV_HWPROBE_IMA_FD) > + { > + SET_EXT (F); > + SET_EXT (D); > + } > + > + if (hwprobe_ima_ext.value & RISCV_HWPROBE_IMA_C) > + SET_EXT (C); > + if (hwprobe_ima_ext.value & RISCV_HWPROBE_IMA_V) > + SET_EXT (V); > + > + SET_FROM_IMA_EXT (ZBA); > + SET_FROM_IMA_EXT (ZBB); > + SET_FROM_IMA_EXT (ZBS); > + SET_FROM_IMA_EXT (ZICBOZ); > + SET_FROM_IMA_EXT (ZBC); > + SET_FROM_IMA_EXT (ZBKB); > + SET_FROM_IMA_EXT (ZBKC); > + SET_FROM_IMA_EXT (ZBKX); > + SET_FROM_IMA_EXT (ZKND); > + SET_FROM_IMA_EXT (ZKNE); > + SET_FROM_IMA_EXT (ZKNH); > + SET_FROM_IMA_EXT (ZKSED); > + SET_FROM_IMA_EXT (ZKSH); > + SET_FROM_IMA_EXT (ZKT); > + SET_FROM_IMA_EXT (ZVBB); > + SET_FROM_IMA_EXT (ZVBC); > + SET_FROM_IMA_EXT (ZVKB); > + SET_FROM_IMA_EXT (ZVKG); > + SET_FROM_IMA_EXT (ZVKNED); > + SET_FROM_IMA_EXT (ZVKNHA); > + SET_FROM_IMA_EXT (ZVKNHB); > + SET_FROM_IMA_EXT (ZVKSED); > + SET_FROM_IMA_EXT (ZVKSH); > + SET_FROM_IMA_EXT (ZVKT); > + SET_FROM_IMA_EXT (ZFH); > + SET_FROM_IMA_EXT (ZFHMIN); > + SET_FROM_IMA_EXT (ZIHINTNTL); > + SET_FROM_IMA_EXT (ZIHINTPAUSE); > + SET_FROM_IMA_EXT (ZVFH); > + SET_FROM_IMA_EXT (ZVFHMIN); > + SET_FROM_IMA_EXT (ZFA); > + SET_FROM_IMA_EXT (ZTSO); > + SET_FROM_IMA_EXT (ZACAS); > + SET_FROM_IMA_EXT (ZICOND); > + SET_FROM_IMA_EXT (ZVE32X); > + SET_FROM_IMA_EXT (ZVE32F); > + SET_FROM_IMA_EXT (ZVE64X); > + SET_FROM_IMA_EXT (ZVE64F); > + SET_FROM_IMA_EXT (ZVE64D); > + SET_FROM_IMA_EXT (ZIMOP); > + SET_FROM_IMA_EXT (ZCA); > + SET_FROM_IMA_EXT (ZCB); > + SET_FROM_IMA_EXT (ZCD); > + SET_FROM_IMA_EXT (ZCF); > + SET_FROM_IMA_EXT (ZCMOP); > + SET_FROM_IMA_EXT (ZAWRS); > + > + for (i = 0; i < RISCV_FEATURE_BITS_LENGTH; ++i) > + __riscv_feature_bits.features[i] = features[i]; > + > + __riscv_feature_bits.length = RISCV_FEATURE_BITS_LENGTH; > +} > +#endif > + > + > +static int __init = 0; > + > +void > +__attribute__ ((constructor (101))) > +__init_riscv_feature_bits () > +{ > + if (__init) > + return; > + > +#ifdef __linux > + __init_riscv_features_bits_linux (); > +#else > + /* Unsupported, just initlizaed that into all zeros. */ > + __riscv_feature_bits.length = 0; > + __riscv_vendor_feature_bits.length = 0; > + __riscv_vendor_feature_bits.vendorID = 0; > +#endif > + > + __init = 1; > +} > diff --git a/libgcc/config/riscv/t-elf b/libgcc/config/riscv/t-elf > index 415e1fffbe7..acb5e280676 100644 > --- a/libgcc/config/riscv/t-elf > +++ b/libgcc/config/riscv/t-elf > @@ -3,6 +3,7 @@ LIB2ADD += $(srcdir)/config/riscv/save-restore.S \ > $(srcdir)/config/riscv/multi3.c \ > $(srcdir)/config/riscv/div.S \ > $(srcdir)/config/riscv/atomic.c \ > + $(srcdir)/config/riscv/feature_bits.c \ > > # Avoid the full unwinder being pulled along with the division libcalls. > LIB2_DIVMOD_EXCEPTION_FLAGS := -fasynchronous-unwind-tables > -- > 2.45.2 >
> On Oct 7, 2024, at 18:15, Kito Cheng <kito.cheng@gmail.com> wrote: > > Could you implement the latest API defined in the doc? > > struct { > unsigned length; > unsigned long long features[]; > } __riscv_feature_bits; > > struct { > unsigned length; > unsigned long long features[]; > } __riscv_vendor_feature_bits; > > struct { > unsigned mvendorid; > unsigned marchid; > unsigned mimpid; > } __riscv_cpu_model; > I doubt whether we should use unsigned instead of unsigned long for marchid and mimpid since they are XLEN-sized CSR: https://github.com/riscv-non-isa/riscv-c-api-doc/pull/74#discussion_r1798166307 I will submit another patch when this question has been resolved.
diff --git a/libgcc/config/riscv/feature_bits.c b/libgcc/config/riscv/feature_bits.c new file mode 100644 index 00000000000..c5339f065c1 --- /dev/null +++ b/libgcc/config/riscv/feature_bits.c @@ -0,0 +1,364 @@ +/* Helper function for function multi-versioning for RISC-V. + + Copyright (C) 2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +#define RISCV_FEATURE_BITS_LENGTH 2 +struct { + unsigned length; + unsigned long long features[RISCV_FEATURE_BITS_LENGTH]; +} __riscv_feature_bits __attribute__ ((visibility ("hidden"), nocommon)); + +#define RISCV_VENDOR_FEATURE_BITS_LENGTH 1 + +struct { + unsigned vendorID; + unsigned length; + unsigned long long features[RISCV_VENDOR_FEATURE_BITS_LENGTH]; +} __riscv_vendor_feature_bits __attribute__ ((visibility ("hidden"), nocommon)); + +#define A_GROUPID 0 +#define A_BITMASK (1ULL << 0) +#define C_GROUPID 0 +#define C_BITMASK (1ULL << 2) +#define D_GROUPID 0 +#define D_BITMASK (1ULL << 3) +#define F_GROUPID 0 +#define F_BITMASK (1ULL << 5) +#define I_GROUPID 0 +#define I_BITMASK (1ULL << 8) +#define M_GROUPID 0 +#define M_BITMASK (1ULL << 12) +#define V_GROUPID 0 +#define V_BITMASK (1ULL << 21) +#define ZACAS_GROUPID 0 +#define ZACAS_BITMASK (1ULL << 26) +#define ZBA_GROUPID 0 +#define ZBA_BITMASK (1ULL << 27) +#define ZBB_GROUPID 0 +#define ZBB_BITMASK (1ULL << 28) +#define ZBC_GROUPID 0 +#define ZBC_BITMASK (1ULL << 29) +#define ZBKB_GROUPID 0 +#define ZBKB_BITMASK (1ULL << 30) +#define ZBKC_GROUPID 0 +#define ZBKC_BITMASK (1ULL << 31) +#define ZBKX_GROUPID 0 +#define ZBKX_BITMASK (1ULL << 32) +#define ZBS_GROUPID 0 +#define ZBS_BITMASK (1ULL << 33) +#define ZFA_GROUPID 0 +#define ZFA_BITMASK (1ULL << 34) +#define ZFH_GROUPID 0 +#define ZFH_BITMASK (1ULL << 35) +#define ZFHMIN_GROUPID 0 +#define ZFHMIN_BITMASK (1ULL << 36) +#define ZICBOZ_GROUPID 0 +#define ZICBOZ_BITMASK (1ULL << 37) +#define ZICOND_GROUPID 0 +#define ZICOND_BITMASK (1ULL << 38) +#define ZIHINTNTL_GROUPID 0 +#define ZIHINTNTL_BITMASK (1ULL << 39) +#define ZIHINTPAUSE_GROUPID 0 +#define ZIHINTPAUSE_BITMASK (1ULL << 40) +#define ZKND_GROUPID 0 +#define ZKND_BITMASK (1ULL << 41) +#define ZKNE_GROUPID 0 +#define ZKNE_BITMASK (1ULL << 42) +#define ZKNH_GROUPID 0 +#define ZKNH_BITMASK (1ULL << 43) +#define ZKSED_GROUPID 0 +#define ZKSED_BITMASK (1ULL << 44) +#define ZKSH_GROUPID 0 +#define ZKSH_BITMASK (1ULL << 45) +#define ZKT_GROUPID 0 +#define ZKT_BITMASK (1ULL << 46) +#define ZTSO_GROUPID 0 +#define ZTSO_BITMASK (1ULL << 47) +#define ZVBB_GROUPID 0 +#define ZVBB_BITMASK (1ULL << 48) +#define ZVBC_GROUPID 0 +#define ZVBC_BITMASK (1ULL << 49) +#define ZVFH_GROUPID 0 +#define ZVFH_BITMASK (1ULL << 50) +#define ZVFHMIN_GROUPID 0 +#define ZVFHMIN_BITMASK (1ULL << 51) +#define ZVKB_GROUPID 0 +#define ZVKB_BITMASK (1ULL << 52) +#define ZVKG_GROUPID 0 +#define ZVKG_BITMASK (1ULL << 53) +#define ZVKNED_GROUPID 0 +#define ZVKNED_BITMASK (1ULL << 54) +#define ZVKNHA_GROUPID 0 +#define ZVKNHA_BITMASK (1ULL << 55) +#define ZVKNHB_GROUPID 0 +#define ZVKNHB_BITMASK (1ULL << 56) +#define ZVKSED_GROUPID 0 +#define ZVKSED_BITMASK (1ULL << 57) +#define ZVKSH_GROUPID 0 +#define ZVKSH_BITMASK (1ULL << 58) +#define ZVKT_GROUPID 0 +#define ZVKT_BITMASK (1ULL << 59) +#define ZVE32X_GROUPID 0 +#define ZVE32X_BITMASK (1ULL << 60) +#define ZVE32F_GROUPID 0 +#define ZVE32F_BITMASK (1ULL << 61) +#define ZVE64X_GROUPID 0 +#define ZVE64X_BITMASK (1ULL << 62) +#define ZVE64F_GROUPID 0 +#define ZVE64F_BITMASK (1ULL << 63) +#define ZVE64D_GROUPID 1 +#define ZVE64D_BITMASK (1ULL << 0) +#define ZIMOP_GROUPID 1 +#define ZIMOP_BITMASK (1ULL << 1) +#define ZCA_GROUPID 1 +#define ZCA_BITMASK (1ULL << 2) +#define ZCB_GROUPID 1 +#define ZCB_BITMASK (1ULL << 3) +#define ZCD_GROUPID 1 +#define ZCD_BITMASK (1ULL << 4) +#define ZCF_GROUPID 1 +#define ZCF_BITMASK (1ULL << 5) +#define ZCMOP_GROUPID 1 +#define ZCMOP_BITMASK (1ULL << 6) +#define ZAWRS_GROUPID 1 +#define ZAWRS_BITMASK (1ULL << 7) + +#define SET_EXT(EXT) features[EXT##_GROUPID] |= EXT##_BITMASK + +#ifdef __linux + +#define __NR_riscv_hwprobe 258 +#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_BASE_BEHAVIOR_IMA (1ULL << 0) +#define RISCV_HWPROBE_KEY_IMA_EXT_0 4 +#define RISCV_HWPROBE_IMA_FD (1ULL << 0) +#define RISCV_HWPROBE_IMA_C (1ULL << 1) +#define RISCV_HWPROBE_IMA_V (1ULL << 2) +#define RISCV_HWPROBE_EXT_ZBA (1ULL << 3) +#define RISCV_HWPROBE_EXT_ZBB (1ULL << 4) +#define RISCV_HWPROBE_EXT_ZBS (1ULL << 5) +#define RISCV_HWPROBE_EXT_ZICBOZ (1ULL << 6) +#define RISCV_HWPROBE_EXT_ZBC (1ULL << 7) +#define RISCV_HWPROBE_EXT_ZBKB (1ULL << 8) +#define RISCV_HWPROBE_EXT_ZBKC (1ULL << 9) +#define RISCV_HWPROBE_EXT_ZBKX (1ULL << 10) +#define RISCV_HWPROBE_EXT_ZKND (1ULL << 11) +#define RISCV_HWPROBE_EXT_ZKNE (1ULL << 12) +#define RISCV_HWPROBE_EXT_ZKNH (1ULL << 13) +#define RISCV_HWPROBE_EXT_ZKSED (1ULL << 14) +#define RISCV_HWPROBE_EXT_ZKSH (1ULL << 15) +#define RISCV_HWPROBE_EXT_ZKT (1ULL << 16) +#define RISCV_HWPROBE_EXT_ZVBB (1ULL << 17) +#define RISCV_HWPROBE_EXT_ZVBC (1ULL << 18) +#define RISCV_HWPROBE_EXT_ZVKB (1ULL << 19) +#define RISCV_HWPROBE_EXT_ZVKG (1ULL << 20) +#define RISCV_HWPROBE_EXT_ZVKNED (1ULL << 21) +#define RISCV_HWPROBE_EXT_ZVKNHA (1ULL << 22) +#define RISCV_HWPROBE_EXT_ZVKNHB (1ULL << 23) +#define RISCV_HWPROBE_EXT_ZVKSED (1ULL << 24) +#define RISCV_HWPROBE_EXT_ZVKSH (1ULL << 25) +#define RISCV_HWPROBE_EXT_ZVKT (1ULL << 26) +#define RISCV_HWPROBE_EXT_ZFH (1ULL << 27) +#define RISCV_HWPROBE_EXT_ZFHMIN (1ULL << 28) +#define RISCV_HWPROBE_EXT_ZIHINTNTL (1ULL << 29) +#define RISCV_HWPROBE_EXT_ZVFH (1ULL << 30) +#define RISCV_HWPROBE_EXT_ZVFHMIN (1ULL << 31) +#define RISCV_HWPROBE_EXT_ZFA (1ULL << 32) +#define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33) +#define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34) +#define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35) +#define RISCV_HWPROBE_EXT_ZIHINTPAUSE (1ULL << 36) +#define RISCV_HWPROBE_EXT_ZVE32X (1ULL << 37) +#define RISCV_HWPROBE_EXT_ZVE32F (1ULL << 38) +#define RISCV_HWPROBE_EXT_ZVE64X (1ULL << 39) +#define RISCV_HWPROBE_EXT_ZVE64F (1ULL << 40) +#define RISCV_HWPROBE_EXT_ZVE64D (1ULL << 41) +#define RISCV_HWPROBE_EXT_ZIMOP (1ULL << 42) +#define RISCV_HWPROBE_EXT_ZCA (1ULL << 43) +#define RISCV_HWPROBE_EXT_ZCB (1ULL << 44) +#define RISCV_HWPROBE_EXT_ZCD (1ULL << 45) +#define RISCV_HWPROBE_EXT_ZCF (1ULL << 46) +#define RISCV_HWPROBE_EXT_ZCMOP (1ULL << 47) +#define RISCV_HWPROBE_EXT_ZAWRS (1ULL << 48) +#define RISCV_HWPROBE_KEY_CPUPERF_0 5 +#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0) +#define RISCV_HWPROBE_MISALIGNED_EMULATED (1ULL << 0) +#define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0) +#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0) +#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0) +#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0) +#define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6 + +struct riscv_hwprobe { + long long key; + unsigned long long value; +}; + +static long syscall_5_args (long number, long arg1, long arg2, long arg3, + long arg4, long arg5) +{ + register long a7 __asm__ ("a7") = number; + register long a0 __asm__ ("a0") = arg1; + register long a1 __asm__ ("a1") = arg2; + register long a2 __asm__ ("a2") = arg3; + register long a3 __asm__ ("a3") = arg4; + register long a4 __asm__ ("a4") = arg5; + __asm__ __volatile__ ("ecall\n\t" + : "=r"(a0) + : "r"(a7), "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4) + : "memory"); + return a0; +} + +#define SET_FROM_HWPROBE(HWPROBE_VAR, EXT) \ + if (HWPROBE_VAR.value & RISCV_HWPROBE_EXT_##EXT) \ + SET_EXT (EXT) + +#define SET_FROM_IMA_EXT(EXT) \ + SET_FROM_HWPROBE (hwprobe_ima_ext, EXT) + +static void __init_riscv_features_bits_linux () +{ + struct riscv_hwprobe hwprobes[] = { + {RISCV_HWPROBE_KEY_BASE_BEHAVIOR, 0}, + {RISCV_HWPROBE_KEY_IMA_EXT_0, 0}, + {RISCV_HWPROBE_KEY_MVENDORID, 0}, + }; + + long res = syscall_5_args (__NR_riscv_hwprobe, (long)&hwprobes, + sizeof (hwprobes) / sizeof (hwprobes[0]), 0, + 0, 0); + + if (res) + return; + + const struct riscv_hwprobe hwprobe_base_behavior = hwprobes[0]; + unsigned long long features[RISCV_FEATURE_BITS_LENGTH]; + int i; + for (i = 0; i < RISCV_FEATURE_BITS_LENGTH; ++i) + features[i] = 0; + + if (hwprobe_base_behavior.value & RISCV_HWPROBE_BASE_BEHAVIOR_IMA) + { + SET_EXT (I); + SET_EXT (M); + SET_EXT (A); + } + + const struct riscv_hwprobe hwprobe_mvendorid = hwprobes[2]; + + __riscv_vendor_feature_bits.length = 0; + __riscv_vendor_feature_bits.vendorID = hwprobe_mvendorid.value; + + const struct riscv_hwprobe hwprobe_ima_ext = hwprobes[1]; + + if (hwprobe_ima_ext.value & RISCV_HWPROBE_IMA_FD) + { + SET_EXT (F); + SET_EXT (D); + } + + if (hwprobe_ima_ext.value & RISCV_HWPROBE_IMA_C) + SET_EXT (C); + if (hwprobe_ima_ext.value & RISCV_HWPROBE_IMA_V) + SET_EXT (V); + + SET_FROM_IMA_EXT (ZBA); + SET_FROM_IMA_EXT (ZBB); + SET_FROM_IMA_EXT (ZBS); + SET_FROM_IMA_EXT (ZICBOZ); + SET_FROM_IMA_EXT (ZBC); + SET_FROM_IMA_EXT (ZBKB); + SET_FROM_IMA_EXT (ZBKC); + SET_FROM_IMA_EXT (ZBKX); + SET_FROM_IMA_EXT (ZKND); + SET_FROM_IMA_EXT (ZKNE); + SET_FROM_IMA_EXT (ZKNH); + SET_FROM_IMA_EXT (ZKSED); + SET_FROM_IMA_EXT (ZKSH); + SET_FROM_IMA_EXT (ZKT); + SET_FROM_IMA_EXT (ZVBB); + SET_FROM_IMA_EXT (ZVBC); + SET_FROM_IMA_EXT (ZVKB); + SET_FROM_IMA_EXT (ZVKG); + SET_FROM_IMA_EXT (ZVKNED); + SET_FROM_IMA_EXT (ZVKNHA); + SET_FROM_IMA_EXT (ZVKNHB); + SET_FROM_IMA_EXT (ZVKSED); + SET_FROM_IMA_EXT (ZVKSH); + SET_FROM_IMA_EXT (ZVKT); + SET_FROM_IMA_EXT (ZFH); + SET_FROM_IMA_EXT (ZFHMIN); + SET_FROM_IMA_EXT (ZIHINTNTL); + SET_FROM_IMA_EXT (ZIHINTPAUSE); + SET_FROM_IMA_EXT (ZVFH); + SET_FROM_IMA_EXT (ZVFHMIN); + SET_FROM_IMA_EXT (ZFA); + SET_FROM_IMA_EXT (ZTSO); + SET_FROM_IMA_EXT (ZACAS); + SET_FROM_IMA_EXT (ZICOND); + SET_FROM_IMA_EXT (ZVE32X); + SET_FROM_IMA_EXT (ZVE32F); + SET_FROM_IMA_EXT (ZVE64X); + SET_FROM_IMA_EXT (ZVE64F); + SET_FROM_IMA_EXT (ZVE64D); + SET_FROM_IMA_EXT (ZIMOP); + SET_FROM_IMA_EXT (ZCA); + SET_FROM_IMA_EXT (ZCB); + SET_FROM_IMA_EXT (ZCD); + SET_FROM_IMA_EXT (ZCF); + SET_FROM_IMA_EXT (ZCMOP); + SET_FROM_IMA_EXT (ZAWRS); + + for (i = 0; i < RISCV_FEATURE_BITS_LENGTH; ++i) + __riscv_feature_bits.features[i] = features[i]; + + __riscv_feature_bits.length = RISCV_FEATURE_BITS_LENGTH; +} +#endif + + +static int __init = 0; + +void +__attribute__ ((constructor (101))) +__init_riscv_feature_bits () +{ + if (__init) + return; + +#ifdef __linux + __init_riscv_features_bits_linux (); +#else + /* Unsupported, just initlizaed that into all zeros. */ + __riscv_feature_bits.length = 0; + __riscv_vendor_feature_bits.length = 0; + __riscv_vendor_feature_bits.vendorID = 0; +#endif + + __init = 1; +} diff --git a/libgcc/config/riscv/t-elf b/libgcc/config/riscv/t-elf index 415e1fffbe7..acb5e280676 100644 --- a/libgcc/config/riscv/t-elf +++ b/libgcc/config/riscv/t-elf @@ -3,6 +3,7 @@ LIB2ADD += $(srcdir)/config/riscv/save-restore.S \ $(srcdir)/config/riscv/multi3.c \ $(srcdir)/config/riscv/div.S \ $(srcdir)/config/riscv/atomic.c \ + $(srcdir)/config/riscv/feature_bits.c \ # Avoid the full unwinder being pulled along with the division libcalls. LIB2_DIVMOD_EXCEPTION_FLAGS := -fasynchronous-unwind-tables