riscv64: Add RISC-V target
[platform/upstream/openblas.git] / cpuid_zarch.h
1 #include <stdlib.h>
2
3 #define CPU_GENERIC     0
4 #define CPU_Z13         1
5 #define CPU_Z14         2
6 #define CPU_Z15         3
7
8 static char *cpuname[] = {
9   "ZARCH_GENERIC",
10   "Z13",
11   "Z14",
12   "Z15"
13 };
14
15 static char *cpuname_lower[] = {
16   "zarch_generic",
17   "z13",
18   "z14",
19   "z15"
20 };
21
22 // Guard the use of getauxval() on glibc version >= 2.16
23 #ifdef __GLIBC__
24 #include <features.h>
25 #if __GLIBC_PREREQ(2, 16)
26 #include <sys/auxv.h>
27 #define HAVE_GETAUXVAL 1
28
29 static unsigned long get_hwcap(void)
30 {
31         unsigned long hwcap = getauxval(AT_HWCAP);
32         char *maskenv;
33
34         // honor requests for not using specific CPU features in LD_HWCAP_MASK
35         maskenv = getenv("LD_HWCAP_MASK");
36         if (maskenv)
37                 hwcap &= strtoul(maskenv, NULL, 0);
38
39         return hwcap;
40         // note that a missing auxval is interpreted as no capabilities
41         // available, which is safe.
42 }
43
44 #else // __GLIBC_PREREQ(2, 16)
45 #warn "Cannot detect SIMD support in Z13 or newer architectures since glibc is older than 2.16"
46
47 static unsigned long get_hwcap(void) {
48         // treat missing support for getauxval() as no capabilities available,
49         // which is safe.
50         return 0;
51 }
52 #endif // __GLIBC_PREREQ(2, 16)
53 #endif // __GLIBC
54
55 static int detect(void)
56 {
57         unsigned long hwcap = get_hwcap();
58
59         // Choose the architecture level for optimized kernels based on hardware
60         // capability bits (just like glibc chooses optimized implementations).
61         //
62         // The hardware capability bits that are used here indicate both
63         // hardware support for a particular ISA extension and the presence of
64         // software support to enable its use. For example, when HWCAP_S390_VX
65         // is set then both the CPU can execute SIMD instructions and the Linux
66         // kernel can manage applications using the vector registers and SIMD
67         // instructions.
68         //
69         // See glibc's sysdeps/s390/dl-procinfo.h for an overview (also in
70         // sysdeps/unix/sysv/linux/s390/bits/hwcap.h) of the defined hardware
71         // capability bits. They are derived from the information that the
72         // "store facility list (extended)" instructions provide.
73         // (https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=sysdeps/s390/dl-procinfo.h;hb=HEAD)
74         //
75         // currently used:
76         // HWCAP_S390_VX - vector facility for z/Architecture (introduced with
77         //                 IBM z13), enables level CPU_Z13 (SIMD)
78         // HWCAP_S390_VXE - vector enhancements facility 1 (introduced with IBM
79         //                  z14), together with VX enables level CPU_Z14
80         //                  (single-precision SIMD instructions)
81         //
82         // When you add optimized kernels that make use of other ISA extensions
83         // (e.g., for exploiting the vector-enhancements facility 2 that was introduced
84         // with IBM z15), then add a new architecture level (e.g., CPU_Z15) and gate
85         // it on the hwcap that represents it here (e.g., HWCAP_S390_VXRS_EXT2
86         // for the z15 vector enhancements).
87         //
88         // To learn the value of hwcaps on a given system, set the environment
89         // variable LD_SHOW_AUXV and let ld.so dump it (e.g., by running
90         // LD_SHOW_AUXV=1 /bin/true).
91         // Also, the init function for dynamic arch support will print hwcaps
92         // when OPENBLAS_VERBOSE is set to 2 or higher.
93         if ((hwcap & HWCAP_S390_VX) && (hwcap & HWCAP_S390_VXE))
94                 return CPU_Z14;
95
96         if (hwcap & HWCAP_S390_VX)
97                 return CPU_Z13;
98
99         return CPU_GENERIC;
100 }
101