16 #include "alfstream.h"
24 #if defined(HAVE_GCC_GET_CPUID) \
25 && (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64))
26 using reg_type
= unsigned int;
27 inline void get_cpuid(unsigned int f
, reg_type
*regs
)
28 { __get_cpuid(f
, ®s
[0], ®s
[1], ®s
[2], ®s
[3]); }
30 #elif defined(HAVE_CPUID_INTRINSIC) \
31 && (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64))
33 inline void get_cpuid(unsigned int f
, reg_type
*regs
)
34 { (__cpuid
)(regs
, f
); }
41 void FillCPUCaps(int capfilter
)
45 /* FIXME: We really should get this for all available CPUs in case different
46 * CPUs have different caps (is that possible on one machine?).
51 char str
[sizeof(reg_type
[4])];
54 get_cpuid(0, cpuinf
[0].regs
);
55 if(cpuinf
[0].regs
[0] == 0)
56 ERR("Failed to get CPUID\n");
59 const reg_type maxfunc
{cpuinf
[0].regs
[0]};
61 get_cpuid(0x80000000, cpuinf
[0].regs
);
62 const reg_type maxextfunc
{cpuinf
[0].regs
[0]};
64 TRACE("Detected max CPUID function: 0x%x (ext. 0x%x)\n", maxfunc
, maxextfunc
);
66 TRACE("Vendor ID: \"%.4s%.4s%.4s\"\n", cpuinf
[0].str
+4, cpuinf
[0].str
+12, cpuinf
[0].str
+8);
67 if(maxextfunc
>= 0x80000004)
69 get_cpuid(0x80000002, cpuinf
[0].regs
);
70 get_cpuid(0x80000003, cpuinf
[1].regs
);
71 get_cpuid(0x80000004, cpuinf
[2].regs
);
72 TRACE("Name: \"%.16s%.16s%.16s\"\n", cpuinf
[0].str
, cpuinf
[1].str
, cpuinf
[2].str
);
77 get_cpuid(1, cpuinf
[0].regs
);
78 if((cpuinf
[0].regs
[3]&(1<<25)))
80 if((caps
&CPU_CAP_SSE
) && (cpuinf
[0].regs
[3]&(1<<26)))
82 if((caps
&CPU_CAP_SSE2
) && (cpuinf
[0].regs
[2]&(1<<0)))
84 if((caps
&CPU_CAP_SSE3
) && (cpuinf
[0].regs
[2]&(1<<19)))
85 caps
|= CPU_CAP_SSE4_1
;
89 /* Assume support for whatever's supported if we can't check for it */
90 #if defined(HAVE_SSE4_1)
91 #warning "Assuming SSE 4.1 run-time support!"
92 caps
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
93 #elif defined(HAVE_SSE3)
94 #warning "Assuming SSE 3 run-time support!"
95 caps
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
96 #elif defined(HAVE_SSE2)
97 #warning "Assuming SSE 2 run-time support!"
98 caps
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
99 #elif defined(HAVE_SSE)
100 #warning "Assuming SSE run-time support!"
107 caps
|= CPU_CAP_NEON
;
109 al::ifstream file
{"/proc/cpuinfo"};
111 ERR("Failed to open /proc/cpuinfo, cannot check for NEON support\n");
114 std::string features
;
116 auto getline
= [](std::istream
&f
, std::string
&output
) -> bool
118 while(f
.good() && f
.peek() == '\n')
120 return std::getline(f
, output
) && !output
.empty();
122 while(getline(file
, features
))
124 if(features
.compare(0, 10, "Features\t:", 10) == 0)
130 while((extpos
=features
.find("neon", extpos
+1)) != std::string::npos
)
132 if(std::isspace(features
[extpos
-1])
133 && (extpos
+4 == features
.length() || std::isspace(features
[extpos
+4])))
135 caps
|= CPU_CAP_NEON
;
139 if(!(caps
&CPU_CAP_NEON
))
142 while((extpos
=features
.find("asimd", extpos
+1)) != std::string::npos
)
144 if(std::isspace(features
[extpos
-1])
145 && (extpos
+5 == features
.length() || std::isspace(features
[extpos
+5])))
147 caps
|= CPU_CAP_NEON
;
156 TRACE("Extensions:%s%s%s%s%s%s\n",
157 ((capfilter
&CPU_CAP_SSE
) ? ((caps
&CPU_CAP_SSE
) ? " +SSE" : " -SSE") : ""),
158 ((capfilter
&CPU_CAP_SSE2
) ? ((caps
&CPU_CAP_SSE2
) ? " +SSE2" : " -SSE2") : ""),
159 ((capfilter
&CPU_CAP_SSE3
) ? ((caps
&CPU_CAP_SSE3
) ? " +SSE3" : " -SSE3") : ""),
160 ((capfilter
&CPU_CAP_SSE4_1
) ? ((caps
&CPU_CAP_SSE4_1
) ? " +SSE4.1" : " -SSE4.1") : ""),
161 ((capfilter
&CPU_CAP_NEON
) ? ((caps
&CPU_CAP_NEON
) ? " +NEON" : " -NEON") : ""),
162 ((!capfilter
) ? " -none-" : "")
164 CPUCapFlags
= caps
& capfilter
;