#include <stdint.h>
#include <stdio.h>
#if defined(_MSC_VER)
#include <intrin.h>
#else
#include <cpuid.h>
#endif
enum {
CPU_NO_X86_SIMD = 0x000000 ,
CPU_SSE2_SUPPORT = 0x000001 ,
CPU_SSE3_SUPPORT = 0x000002 ,
CPU_SSSE3_SUPPORT = 0x000004 ,
CPU_SSE4_1_SUPPORT = 0x000008 ,
CPU_SSE4_2_SUPPORT = 0x000010 ,
CPU_SSE4_A_SUPPORT = 0x000020 ,
CPU_FMA4_SUPPORT = 0x000040 ,
CPU_FMA3_SUPPORT = 0x000080 ,
CPU_AVX_SUPPORT = 0x000100 ,
CPU_AVX2_SUPPORT = 0x000200 ,
CPU_AVX512F_SUPPORT = 0x000400 ,
CPU_AVX512DQ_SUPPORT = 0x000800 ,
CPU_AVX512IFMA52_SUPPORT = 0x001000 ,
CPU_AVX512PF_SUPPORT = 0x002000 ,
CPU_AVX512ER_SUPPORT = 0x004000 ,
CPU_AVX512CD_SUPPORT = 0x008000 ,
CPU_AVX512BW_SUPPORT = 0x010000 ,
CPU_AVX512VL_SUPPORT = 0x020000 ,
CPU_AVX512VBMI_SUPPORT = 0x040000 ,
} ;
static inline void get_cpuid( int * array, int info_type)
{
#if defined(_MSC_VER)
__cpuid( array, info_type) ;
#else
__cpuid( info_type, array[ 0 ] , array[ 1 ] , array[ 2 ] , array[ 3 ] ) ;
#endif
}
static inline void get_cpuid2( int * array, int info_type, int ecx)
{
#if defined(_MSC_VER)
__cpuidex( array, info_type, ecx) ;
#else
__cpuid_count( info_type, ecx, array[ 0 ] , array[ 1 ] , array[ 2 ] , array[ 3 ] ) ;
#endif
}
static inline int is_bit_set( int bitfield, int bit)
{
return bitfield & ( 1 << bit) ;
}
static uint32_t get_simd_support_info( void )
{
uint32_t ret = 0 ;
int regs[ 4 ] ;
get_cpuid( regs, 0x00000001 ) ;
if ( is_bit_set( regs[ 3 ] , 26 ) ) {
ret |= CPU_SSE2_SUPPORT;
}
if ( is_bit_set( regs[ 2 ] , 0 ) ) {
ret |= CPU_SSE3_SUPPORT;
}
if ( is_bit_set( regs[ 2 ] , 9 ) ) {
ret |= CPU_SSSE3_SUPPORT;
}
if ( is_bit_set( regs[ 2 ] , 19 ) ) {
ret |= CPU_SSE4_1_SUPPORT;
}
if ( is_bit_set( regs[ 2 ] , 26 ) ) {
ret |= CPU_SSE4_2_SUPPORT;
}
if ( is_bit_set( regs[ 2 ] , 27 ) ) {
if ( is_bit_set( regs[ 2 ] , 28 ) ) {
ret |= CPU_AVX_SUPPORT;
}
if ( is_bit_set( regs[ 2 ] , 12 ) ) {
ret |= CPU_FMA3_SUPPORT;
}
}
get_cpuid( regs, 0x80000001 ) ;
if ( is_bit_set( regs[ 3 ] , 6 ) ) {
ret |= CPU_SSE4_A_SUPPORT;
}
if ( is_bit_set( regs[ 3 ] , 16 ) ) {
ret |= CPU_FMA4_SUPPORT;
}
get_cpuid( regs, 0x00000000 ) ;
if ( regs[ 0 ] < 7 ) {
return ret;
}
get_cpuid2( regs, 0x00000007 , 0 ) ;
if ( is_bit_set( regs[ 1 ] , 5 ) ) {
ret |= CPU_AVX2_SUPPORT;
}
if ( ! is_bit_set( regs[ 1 ] , 16 ) ) {
return ret;
}
ret |= CPU_AVX512F_SUPPORT;
if ( is_bit_set( regs[ 1 ] , 17 ) ) {
ret |= CPU_AVX512DQ_SUPPORT;
}
if ( is_bit_set( regs[ 1 ] , 21 ) ) {
ret |= CPU_AVX512IFMA52_SUPPORT;
}
if ( is_bit_set( regs[ 1 ] , 26 ) ) {
ret |= CPU_AVX512PF_SUPPORT;
}
if ( is_bit_set( regs[ 1 ] , 27 ) ) {
ret |= CPU_AVX512ER_SUPPORT;
}
if ( is_bit_set( regs[ 1 ] , 28 ) ) {
ret |= CPU_AVX512CD_SUPPORT;
}
if ( is_bit_set( regs[ 1 ] , 30 ) ) {
ret |= CPU_AVX512BW_SUPPORT;
}
if ( is_bit_set( regs[ 1 ] , 31 ) ) {
ret |= CPU_AVX512VL_SUPPORT;
}
if ( is_bit_set( regs[ 2 ] , 1 ) ) {
ret |= CPU_AVX512VBMI_SUPPORT;
}
return ret;
}
static void get_vendor_name( char * buff)
{
int32_t regs[ 4 ] ;
int32_t * temp = ( int32_t * ) buff;
get_cpuid( regs, 0 ) ;
temp[ 0 ] = regs[ 1 ] ;
temp[ 1 ] = regs[ 3 ] ;
temp[ 2 ] = regs[ 2 ] ;
}
static void get_brand_string( char * buff)
{
int32_t regs[ 4 ] ;
int32_t * temp = ( int32_t * ) buff;
for ( int i = 0 ; i < 3 ; i++ ) {
get_cpuid( regs, 0x80000002 + i) ;
for ( int j = 0 ; j < 4 ; j++ ) {
temp[ i * 4 + j] = regs[ j] ;
}
}
}
int main( void )
{
char str[ 64 ] = { 0 } ;
get_vendor_name( str) ;
get_brand_string( str) ;
uint32_t cpu = get_simd_support_info( ) ;
const struct {
int flag;
const char * name;
} table[ ] = {
{ CPU_SSE2_SUPPORT , "SSE2" } ,
{ CPU_SSE3_SUPPORT , "SSE3" } ,
{ CPU_SSSE3_SUPPORT , "SSSE3" } ,
{ CPU_SSE4_1_SUPPORT , "SSE4.1" } ,
{ CPU_SSE4_2_SUPPORT , "SSE4.2" } ,
{ CPU_SSE4_A_SUPPORT , "SSE4a" } ,
{ CPU_FMA4_SUPPORT , "FMA4" } ,
{ CPU_FMA3_SUPPORT , "FMA3" } ,
{ CPU_AVX_SUPPORT , "AVX" } ,
{ CPU_AVX2_SUPPORT , "AVX2" } ,
{ CPU_AVX512F_SUPPORT , "AVX512F" } ,
{ CPU_AVX512DQ_SUPPORT , "AVX512DQ" } ,
{ CPU_AVX512IFMA52_SUPPORT, "AVX512IFMA" } ,
{ CPU_AVX512PF_SUPPORT , "AVX512PF" } ,
{ CPU_AVX512ER_SUPPORT , "AVX512ER" } ,
{ CPU_AVX512CD_SUPPORT , "AVX512CD" } ,
{ CPU_AVX512BW_SUPPORT , "AVX512BW" } ,
{ CPU_AVX512VL_SUPPORT , "AVX512VL" } ,
{ CPU_AVX512VBMI_SUPPORT , "AVX512VBMI" } ,
{ - 1 , NULL}
} ;
if ( cpu == CPU_NO_X86_SIMD) {
printf ( "this cpu is too old.\n " ) ; return 0 ;
}
for ( int i = 0 ; table[ i] .name != NULL; i++ ) {
if ( cpu & table[ i] .flag ) {
printf ( "%s is supported.\n " , table
[ i
] .
name ) ; }
}
return 0 ;
}
I2luY2x1ZGUgPHN0ZGludC5oPgojaW5jbHVkZSA8c3RkaW8uaD4KCiNpZiBkZWZpbmVkKF9NU0NfVkVSKQojaW5jbHVkZSA8aW50cmluLmg+CiNlbHNlCiNpbmNsdWRlIDxjcHVpZC5oPgojZW5kaWYKCmVudW0gewogICAgQ1BVX05PX1g4Nl9TSU1EICAgICAgICAgID0gMHgwMDAwMDAsCiAgICBDUFVfU1NFMl9TVVBQT1JUICAgICAgICAgPSAweDAwMDAwMSwKICAgIENQVV9TU0UzX1NVUFBPUlQgICAgICAgICA9IDB4MDAwMDAyLAogICAgQ1BVX1NTU0UzX1NVUFBPUlQgICAgICAgID0gMHgwMDAwMDQsCiAgICBDUFVfU1NFNF8xX1NVUFBPUlQgICAgICAgPSAweDAwMDAwOCwKICAgIENQVV9TU0U0XzJfU1VQUE9SVCAgICAgICA9IDB4MDAwMDEwLAogICAgQ1BVX1NTRTRfQV9TVVBQT1JUICAgICAgID0gMHgwMDAwMjAsCiAgICBDUFVfRk1BNF9TVVBQT1JUICAgICAgICAgPSAweDAwMDA0MCwKICAgIENQVV9GTUEzX1NVUFBPUlQgICAgICAgICA9IDB4MDAwMDgwLAogICAgQ1BVX0FWWF9TVVBQT1JUICAgICAgICAgID0gMHgwMDAxMDAsCiAgICBDUFVfQVZYMl9TVVBQT1JUICAgICAgICAgPSAweDAwMDIwMCwKICAgIENQVV9BVlg1MTJGX1NVUFBPUlQgICAgICA9IDB4MDAwNDAwLAogICAgQ1BVX0FWWDUxMkRRX1NVUFBPUlQgICAgID0gMHgwMDA4MDAsCiAgICBDUFVfQVZYNTEySUZNQTUyX1NVUFBPUlQgPSAweDAwMTAwMCwKICAgIENQVV9BVlg1MTJQRl9TVVBQT1JUICAgICA9IDB4MDAyMDAwLAogICAgQ1BVX0FWWDUxMkVSX1NVUFBPUlQgICAgID0gMHgwMDQwMDAsCiAgICBDUFVfQVZYNTEyQ0RfU1VQUE9SVCAgICAgPSAweDAwODAwMCwKICAgIENQVV9BVlg1MTJCV19TVVBQT1JUICAgICA9IDB4MDEwMDAwLAogICAgQ1BVX0FWWDUxMlZMX1NVUFBPUlQgICAgID0gMHgwMjAwMDAsCiAgICBDUFVfQVZYNTEyVkJNSV9TVVBQT1JUICAgPSAweDA0MDAwMCwKfTsKCnN0YXRpYyBpbmxpbmUgdm9pZCBnZXRfY3B1aWQoaW50ICphcnJheSwgaW50IGluZm9fdHlwZSkKewojaWYgZGVmaW5lZChfTVNDX1ZFUikKICAgIF9fY3B1aWQoYXJyYXksIGluZm9fdHlwZSk7CiNlbHNlCiAgICBfX2NwdWlkKGluZm9fdHlwZSwgYXJyYXlbMF0sIGFycmF5WzFdLCBhcnJheVsyXSwgYXJyYXlbM10pOwojZW5kaWYKfQoKc3RhdGljIGlubGluZSB2b2lkIGdldF9jcHVpZDIoaW50ICphcnJheSwgaW50IGluZm9fdHlwZSwgaW50IGVjeCkKewojaWYgZGVmaW5lZChfTVNDX1ZFUikKICAgIF9fY3B1aWRleChhcnJheSwgaW5mb190eXBlLCBlY3gpOwojZWxzZQogICAgX19jcHVpZF9jb3VudChpbmZvX3R5cGUsIGVjeCwgYXJyYXlbMF0sIGFycmF5WzFdLCBhcnJheVsyXSwgYXJyYXlbM10pOwojZW5kaWYKfQoKc3RhdGljIGlubGluZSBpbnQgaXNfYml0X3NldChpbnQgYml0ZmllbGQsIGludCBiaXQpCnsKICAgIHJldHVybiBiaXRmaWVsZCAmICgxIDw8IGJpdCk7Cn0KCnN0YXRpYyB1aW50MzJfdCBnZXRfc2ltZF9zdXBwb3J0X2luZm8odm9pZCkKewogICAgdWludDMyX3QgcmV0ID0gMDsKICAgIGludCByZWdzWzRdOwoKICAgIGdldF9jcHVpZChyZWdzLCAweDAwMDAwMDAxKTsKICAgIGlmIChpc19iaXRfc2V0KHJlZ3NbM10sIDI2KSkgewogICAgICAgIHJldCB8PSBDUFVfU1NFMl9TVVBQT1JUOwogICAgfQogICAgaWYgKGlzX2JpdF9zZXQocmVnc1syXSwgMCkpIHsKICAgICAgICByZXQgfD0gQ1BVX1NTRTNfU1VQUE9SVDsKICAgIH0KICAgIGlmIChpc19iaXRfc2V0KHJlZ3NbMl0sIDkpKSB7CiAgICAgICAgcmV0IHw9IENQVV9TU1NFM19TVVBQT1JUOwogICAgfQogICAgaWYgKGlzX2JpdF9zZXQocmVnc1syXSwgMTkpKSB7CiAgICAgICAgcmV0IHw9IENQVV9TU0U0XzFfU1VQUE9SVDsKICAgIH0KICAgIGlmIChpc19iaXRfc2V0KHJlZ3NbMl0sIDI2KSkgewogICAgICAgIHJldCB8PSBDUFVfU1NFNF8yX1NVUFBPUlQ7CiAgICB9CiAgICBpZiAoaXNfYml0X3NldChyZWdzWzJdLCAyNykpIHsKICAgICAgICBpZiAoaXNfYml0X3NldChyZWdzWzJdLCAyOCkpIHsKICAgICAgICAgICAgcmV0IHw9IENQVV9BVlhfU1VQUE9SVDsKICAgICAgICB9CiAgICAgICAgaWYgKGlzX2JpdF9zZXQocmVnc1syXSwgMTIpKSB7CiAgICAgICAgICAgIHJldCB8PSBDUFVfRk1BM19TVVBQT1JUOwogICAgICAgIH0KICAgIH0KCiAgICBnZXRfY3B1aWQocmVncywgMHg4MDAwMDAwMSk7CiAgICBpZiAoaXNfYml0X3NldChyZWdzWzNdLCA2KSkgewogICAgICAgIHJldCB8PSBDUFVfU1NFNF9BX1NVUFBPUlQ7CiAgICB9CiAgICBpZiAoaXNfYml0X3NldChyZWdzWzNdLCAxNikpIHsKICAgICAgICByZXQgfD0gQ1BVX0ZNQTRfU1VQUE9SVDsKICAgIH0KCiAgICBnZXRfY3B1aWQocmVncywgMHgwMDAwMDAwMCk7CiAgICBpZiAocmVnc1swXSA8IDcpIHsKICAgICAgICByZXR1cm4gcmV0OwogICAgfQoKICAgIGdldF9jcHVpZDIocmVncywgMHgwMDAwMDAwNywgMCk7CiAgICBpZiAoaXNfYml0X3NldChyZWdzWzFdLCA1KSkgewogICAgICAgIHJldCB8PSBDUFVfQVZYMl9TVVBQT1JUOwogICAgfQogICAgaWYgKCFpc19iaXRfc2V0KHJlZ3NbMV0sIDE2KSkgewogICAgICAgIHJldHVybiByZXQ7CiAgICB9CgogICAgcmV0IHw9IENQVV9BVlg1MTJGX1NVUFBPUlQ7CiAgICBpZiAoaXNfYml0X3NldChyZWdzWzFdLCAxNykpIHsKICAgICAgICByZXQgfD0gQ1BVX0FWWDUxMkRRX1NVUFBPUlQ7CiAgICB9CiAgICBpZiAoaXNfYml0X3NldChyZWdzWzFdLCAyMSkpIHsKICAgICAgICByZXQgfD0gQ1BVX0FWWDUxMklGTUE1Ml9TVVBQT1JUOwogICAgfQogICAgaWYgKGlzX2JpdF9zZXQocmVnc1sxXSwgMjYpKSB7CiAgICAgICAgcmV0IHw9IENQVV9BVlg1MTJQRl9TVVBQT1JUOwogICAgfQogICAgaWYgKGlzX2JpdF9zZXQocmVnc1sxXSwgMjcpKSB7CiAgICAgICAgcmV0IHw9IENQVV9BVlg1MTJFUl9TVVBQT1JUOwogICAgfQogICAgaWYgKGlzX2JpdF9zZXQocmVnc1sxXSwgMjgpKSB7CiAgICAgICAgcmV0IHw9IENQVV9BVlg1MTJDRF9TVVBQT1JUOwogICAgfQogICAgaWYgKGlzX2JpdF9zZXQocmVnc1sxXSwgMzApKSB7CiAgICAgICAgcmV0IHw9IENQVV9BVlg1MTJCV19TVVBQT1JUOwogICAgfQogICAgaWYgKGlzX2JpdF9zZXQocmVnc1sxXSwgMzEpKSB7CiAgICAgICAgcmV0IHw9IENQVV9BVlg1MTJWTF9TVVBQT1JUOwogICAgfQogICAgaWYgKGlzX2JpdF9zZXQocmVnc1syXSwgMSkpIHsKICAgICAgICByZXQgfD0gQ1BVX0FWWDUxMlZCTUlfU1VQUE9SVDsKICAgIH0KCiAgICByZXR1cm4gcmV0Owp9CgpzdGF0aWMgdm9pZCBnZXRfdmVuZG9yX25hbWUoY2hhciAqYnVmZikKewogICAgaW50MzJfdCByZWdzWzRdOwogICAgaW50MzJfdCAqdGVtcCA9IChpbnQzMl90ICopYnVmZjsKICAgIGdldF9jcHVpZChyZWdzLCAwKTsKICAgIHRlbXBbMF0gPSByZWdzWzFdOwogICAgdGVtcFsxXSA9IHJlZ3NbM107CiAgICB0ZW1wWzJdID0gcmVnc1syXTsKfQoKc3RhdGljIHZvaWQgZ2V0X2JyYW5kX3N0cmluZyhjaGFyICpidWZmKQp7CiAgICBpbnQzMl90IHJlZ3NbNF07CiAgICBpbnQzMl90ICp0ZW1wID0gKGludDMyX3QgKilidWZmOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCAzOyBpKyspIHsKICAgICAgICBnZXRfY3B1aWQocmVncywgMHg4MDAwMDAwMiArIGkpOwogICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgNDsgaisrKSB7CiAgICAgICAgICAgIHRlbXBbaSAqIDQgKyBqXSA9IHJlZ3Nbal07CiAgICAgICAgfQogICAgfQp9CgppbnQgbWFpbih2b2lkKQp7CiAgICBjaGFyIHN0cls2NF0gPSB7MH07CgogICAgZ2V0X3ZlbmRvcl9uYW1lKHN0cik7CiAgICBwcmludGYoInZlbmRvcjogJXNcbiIsIHN0cik7CiAgICBnZXRfYnJhbmRfc3RyaW5nKHN0cik7CiAgICBwcmludGYoImJyYW5kOiAlc1xuIiwgc3RyKTsKCiAgICB1aW50MzJfdCBjcHUgPSBnZXRfc2ltZF9zdXBwb3J0X2luZm8oKTsKICAgIAogICAgY29uc3Qgc3RydWN0IHsKICAgICAgICBpbnQgZmxhZzsKICAgICAgICBjb25zdCBjaGFyICpuYW1lOwogICAgfSB0YWJsZVtdID0gewogICAgICAgIHtDUFVfU1NFMl9TVVBQT1JUICAgICAgICAsICJTU0UyIiAgICAgIH0sCiAgICAgICAge0NQVV9TU0UzX1NVUFBPUlQgICAgICAgICwgIlNTRTMiICAgICAgfSwKICAgICAgICB7Q1BVX1NTU0UzX1NVUFBPUlQgICAgICAgLCAiU1NTRTMiICAgICB9LAogICAgICAgIHtDUFVfU1NFNF8xX1NVUFBPUlQgICAgICAsICJTU0U0LjEiICAgIH0sCiAgICAgICAge0NQVV9TU0U0XzJfU1VQUE9SVCAgICAgICwgIlNTRTQuMiIgICAgfSwKICAgICAgICB7Q1BVX1NTRTRfQV9TVVBQT1JUICAgICAgLCAiU1NFNGEiICAgICB9LAogICAgICAgIHtDUFVfRk1BNF9TVVBQT1JUICAgICAgICAsICJGTUE0IiAgICAgIH0sCiAgICAgICAge0NQVV9GTUEzX1NVUFBPUlQgICAgICAgICwgIkZNQTMiICAgICAgfSwKICAgICAgICB7Q1BVX0FWWF9TVVBQT1JUICAgICAgICAgLCAiQVZYIiAgICAgICB9LAogICAgICAgIHtDUFVfQVZYMl9TVVBQT1JUICAgICAgICAsICJBVlgyIiAgICAgIH0sCiAgICAgICAge0NQVV9BVlg1MTJGX1NVUFBPUlQgICAgICwgIkFWWDUxMkYiICAgfSwKICAgICAgICB7Q1BVX0FWWDUxMkRRX1NVUFBPUlQgICAgLCAiQVZYNTEyRFEiICB9LAogICAgICAgIHtDUFVfQVZYNTEySUZNQTUyX1NVUFBPUlQsICJBVlg1MTJJRk1BIn0sCiAgICAgICAge0NQVV9BVlg1MTJQRl9TVVBQT1JUICAgICwgIkFWWDUxMlBGIiAgfSwKICAgICAgICB7Q1BVX0FWWDUxMkVSX1NVUFBPUlQgICAgLCAiQVZYNTEyRVIiICB9LAogICAgICAgIHtDUFVfQVZYNTEyQ0RfU1VQUE9SVCAgICAsICJBVlg1MTJDRCIgIH0sCiAgICAgICAge0NQVV9BVlg1MTJCV19TVVBQT1JUICAgICwgIkFWWDUxMkJXIiAgfSwKICAgICAgICB7Q1BVX0FWWDUxMlZMX1NVUFBPUlQgICAgLCAiQVZYNTEyVkwiICB9LAogICAgICAgIHtDUFVfQVZYNTEyVkJNSV9TVVBQT1JUICAsICJBVlg1MTJWQk1JIn0sCiAgICAgICAgey0xLCBOVUxMfQogICAgfTsKCiAgICBpZiAoY3B1ID09IENQVV9OT19YODZfU0lNRCkgewogICAgICAgIHByaW50ZigidGhpcyBjcHUgaXMgdG9vIG9sZC5cbiIpOwogICAgICAgIHJldHVybiAwOwogICAgfQoKICAgIGZvciAoaW50IGkgPSAwOyB0YWJsZVtpXS5uYW1lICE9IE5VTEw7IGkrKykgewogICAgICAgIGlmIChjcHUgJiB0YWJsZVtpXS5mbGFnKSB7CiAgICAgICAgICAgIHByaW50ZigiJXMgaXMgc3VwcG9ydGVkLlxuIiwgdGFibGVbaV0ubmFtZSk7CiAgICAgICAgfQogICAgfQoKICAgIHJldHVybiAwOwp9Cg==