This page describes how to find out what features a CPU supports. There are two different use cases for needing this information. The first is casual probing via the command line. The other is when making decisions at runtime in your source code.
Generic Approaches To Feature Determination
$ cat /proc/cpuinfo | grep "^Features" Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls
You can also do it programmatically. The code below dumps the value of AT_HWCAP. You can decode this value using asm/hwcap.h
/**
* This program is derived from information in:
* http://articles.manugarg.com/aboutelfauxiliaryvectors.html
*/
#include <stdio.h>
#include <elf.h>
int main(int argc, char *argv[], char *envp[])
{
Elf32_auxv_t *auxv;
while(*envp++ != NULL); /*auxv follows envp*/
auxv = (Elf32_auxv_t*)envp;
while (auxv && auxv->a_type != AT_HWCAP)
auxv++;
if (auxv)
printf("hwcaps: %u\n", auxv->a_un.a_val);
return 0;
}
Determining Neon Support
$ cat /proc/cpuinfo | grep "^Features.*neon" Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls3
This can also be done in code with something like:
/**
* This program is derived from information in:
* http://articles.manugarg.com/aboutelfauxiliaryvectors.html
*/
#include <stdio.h>
#include <elf.h>
#include <asm/hwcap.h>
int main(int argc, char *argv[], char *envp[])
{
Elf32_auxv_t *auxv;
while(*envp++ != NULL); /*auxv follows envp*/
auxv = (Elf32_auxv_t*)envp;
while (auxv && auxv->a_type != AT_HWCAP)
auxv++;
if( auxv && auxv->a_un.a_val & HWCAP_NEON )
printf("NEON capable!\n");
return 0;
}
Determining Neon Support In A Library
The approach from a library is a little different as the auxv must be obtained via a different method. In these examples ElfW is used which is 32/64 bit independent.
volatile ElfW(auxv_t) *auxv = NULL;
LOCAL(ElfW(auxv_t) *)get_auxv(void)
{
FILE *auxv_f;
ElfW(auxv_t) auxv_struct;
int i = 0;
if(auxv == NULL) {
auxv_f = fopen("/proc/self/auxv", "r");
if(auxv_f == 0) {
perror("Error opening file for reading");
return 0;
}
auxv =(ElfW(auxv_t) *)malloc(getpagesize());
do
{
fread(&auxv_struct, sizeof(ElfW(auxv_t)), 1, auxv_f);
auxv[i] = auxv_struct;
i++;
} while(auxv_struct.a_type != AT_NULL);
}
return auxv;
}With the auxv in hand one can use code like the following to determine if HWCAP_NEON is present and set in this case a global simd_support variable.
void
init_simd (void)
{
char *env=NULL;
ElfW(auxv_t) *tauxv=(ElfW(auxv_t) *)auxv;
while (tauxv && tauxv->a_type != AT_HWCAP)
tauxv++;
if( tauxv && tauxv->a_un.a_val & HWCAP_NEON )
simd_support = 1;
}Resources/HowTo/DeterminingCPUFeatures (last modified 2011-09-29 23:22:48)