#include <stdint.h>
#include <stdio.h>
#include <immintrin.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 ;
}
I2luY2x1ZGUgPHN0ZGludC5oPgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPGltbWludHJpbi5oPgoKI2lmIGRlZmluZWQoX01TQ19WRVIpCiNpbmNsdWRlIDxpbnRyaW4uaD4KI2Vsc2UKI2luY2x1ZGUgPGNwdWlkLmg+CiNlbmRpZgoKZW51bSB7CiAgICBDUFVfTk9fWDg2X1NJTUQgICAgICAgICAgPSAweDAwMDAwMCwKICAgIENQVV9TU0UyX1NVUFBPUlQgICAgICAgICA9IDB4MDAwMDAxLAogICAgQ1BVX1NTRTNfU1VQUE9SVCAgICAgICAgID0gMHgwMDAwMDIsCiAgICBDUFVfU1NTRTNfU1VQUE9SVCAgICAgICAgPSAweDAwMDAwNCwKICAgIENQVV9TU0U0XzFfU1VQUE9SVCAgICAgICA9IDB4MDAwMDA4LAogICAgQ1BVX1NTRTRfMl9TVVBQT1JUICAgICAgID0gMHgwMDAwMTAsCiAgICBDUFVfU1NFNF9BX1NVUFBPUlQgICAgICAgPSAweDAwMDAyMCwKICAgIENQVV9GTUE0X1NVUFBPUlQgICAgICAgICA9IDB4MDAwMDQwLAogICAgQ1BVX0ZNQTNfU1VQUE9SVCAgICAgICAgID0gMHgwMDAwODAsCiAgICBDUFVfQVZYX1NVUFBPUlQgICAgICAgICAgPSAweDAwMDEwMCwKICAgIENQVV9BVlgyX1NVUFBPUlQgICAgICAgICA9IDB4MDAwMjAwLAogICAgQ1BVX0FWWDUxMkZfU1VQUE9SVCAgICAgID0gMHgwMDA0MDAsCiAgICBDUFVfQVZYNTEyRFFfU1VQUE9SVCAgICAgPSAweDAwMDgwMCwKICAgIENQVV9BVlg1MTJJRk1BNTJfU1VQUE9SVCA9IDB4MDAxMDAwLAogICAgQ1BVX0FWWDUxMlBGX1NVUFBPUlQgICAgID0gMHgwMDIwMDAsCiAgICBDUFVfQVZYNTEyRVJfU1VQUE9SVCAgICAgPSAweDAwNDAwMCwKICAgIENQVV9BVlg1MTJDRF9TVVBQT1JUICAgICA9IDB4MDA4MDAwLAogICAgQ1BVX0FWWDUxMkJXX1NVUFBPUlQgICAgID0gMHgwMTAwMDAsCiAgICBDUFVfQVZYNTEyVkxfU1VQUE9SVCAgICAgPSAweDAyMDAwMCwKICAgIENQVV9BVlg1MTJWQk1JX1NVUFBPUlQgICA9IDB4MDQwMDAwLAp9OwoKc3RhdGljIGlubGluZSB2b2lkIGdldF9jcHVpZChpbnQgKmFycmF5LCBpbnQgaW5mb190eXBlKQp7CiNpZiBkZWZpbmVkKF9NU0NfVkVSKQogICAgX19jcHVpZChhcnJheSwgaW5mb190eXBlKTsKI2Vsc2UKICAgIF9fY3B1aWQoaW5mb190eXBlLCBhcnJheVswXSwgYXJyYXlbMV0sIGFycmF5WzJdLCBhcnJheVszXSk7CiNlbmRpZgp9CgpzdGF0aWMgaW5saW5lIHZvaWQgZ2V0X2NwdWlkMihpbnQgKmFycmF5LCBpbnQgaW5mb190eXBlLCBpbnQgZWN4KQp7CiNpZiBkZWZpbmVkKF9NU0NfVkVSKQogICAgX19jcHVpZGV4KGFycmF5LCBpbmZvX3R5cGUsIGVjeCk7CiNlbHNlCiAgICBfX2NwdWlkX2NvdW50KGluZm9fdHlwZSwgZWN4LCBhcnJheVswXSwgYXJyYXlbMV0sIGFycmF5WzJdLCBhcnJheVszXSk7CiNlbmRpZgp9CgpzdGF0aWMgaW5saW5lIGludCBpc19iaXRfc2V0KGludCBiaXRmaWVsZCwgaW50IGJpdCkKewogICAgcmV0dXJuIGJpdGZpZWxkICYgKDEgPDwgYml0KTsKfQoKc3RhdGljIHVpbnQzMl90IGdldF9zaW1kX3N1cHBvcnRfaW5mbyh2b2lkKQp7CiAgICB1aW50MzJfdCByZXQgPSAwOwogICAgaW50IHJlZ3NbNF07CgogICAgZ2V0X2NwdWlkKHJlZ3MsIDB4MDAwMDAwMDEpOwogICAgaWYgKGlzX2JpdF9zZXQocmVnc1szXSwgMjYpKSB7CiAgICAgICAgcmV0IHw9IENQVV9TU0UyX1NVUFBPUlQ7CiAgICB9CiAgICBpZiAoaXNfYml0X3NldChyZWdzWzJdLCAwKSkgewogICAgICAgIHJldCB8PSBDUFVfU1NFM19TVVBQT1JUOwogICAgfQogICAgaWYgKGlzX2JpdF9zZXQocmVnc1syXSwgOSkpIHsKICAgICAgICByZXQgfD0gQ1BVX1NTU0UzX1NVUFBPUlQ7CiAgICB9CiAgICBpZiAoaXNfYml0X3NldChyZWdzWzJdLCAxOSkpIHsKICAgICAgICByZXQgfD0gQ1BVX1NTRTRfMV9TVVBQT1JUOwogICAgfQogICAgaWYgKGlzX2JpdF9zZXQocmVnc1syXSwgMjYpKSB7CiAgICAgICAgcmV0IHw9IENQVV9TU0U0XzJfU1VQUE9SVDsKICAgIH0KICAgIGlmIChpc19iaXRfc2V0KHJlZ3NbMl0sIDI3KSkgewogICAgICAgIGlmIChpc19iaXRfc2V0KHJlZ3NbMl0sIDI4KSkgewogICAgICAgICAgICByZXQgfD0gQ1BVX0FWWF9TVVBQT1JUOwogICAgICAgIH0KICAgICAgICBpZiAoaXNfYml0X3NldChyZWdzWzJdLCAxMikpIHsKICAgICAgICAgICAgcmV0IHw9IENQVV9GTUEzX1NVUFBPUlQ7CiAgICAgICAgfQogICAgfQoKICAgIGdldF9jcHVpZChyZWdzLCAweDgwMDAwMDAxKTsKICAgIGlmIChpc19iaXRfc2V0KHJlZ3NbM10sIDYpKSB7CiAgICAgICAgcmV0IHw9IENQVV9TU0U0X0FfU1VQUE9SVDsKICAgIH0KICAgIGlmIChpc19iaXRfc2V0KHJlZ3NbM10sIDE2KSkgewogICAgICAgIHJldCB8PSBDUFVfRk1BNF9TVVBQT1JUOwogICAgfQoKICAgIGdldF9jcHVpZChyZWdzLCAweDAwMDAwMDAwKTsKICAgIGlmIChyZWdzWzBdIDwgNykgewogICAgICAgIHJldHVybiByZXQ7CiAgICB9CgogICAgZ2V0X2NwdWlkMihyZWdzLCAweDAwMDAwMDA3LCAwKTsKICAgIGlmIChpc19iaXRfc2V0KHJlZ3NbMV0sIDUpKSB7CiAgICAgICAgcmV0IHw9IENQVV9BVlgyX1NVUFBPUlQ7CiAgICB9CiAgICBpZiAoIWlzX2JpdF9zZXQocmVnc1sxXSwgMTYpKSB7CiAgICAgICAgcmV0dXJuIHJldDsKICAgIH0KCiAgICByZXQgfD0gQ1BVX0FWWDUxMkZfU1VQUE9SVDsKICAgIGlmIChpc19iaXRfc2V0KHJlZ3NbMV0sIDE3KSkgewogICAgICAgIHJldCB8PSBDUFVfQVZYNTEyRFFfU1VQUE9SVDsKICAgIH0KICAgIGlmIChpc19iaXRfc2V0KHJlZ3NbMV0sIDIxKSkgewogICAgICAgIHJldCB8PSBDUFVfQVZYNTEySUZNQTUyX1NVUFBPUlQ7CiAgICB9CiAgICBpZiAoaXNfYml0X3NldChyZWdzWzFdLCAyNikpIHsKICAgICAgICByZXQgfD0gQ1BVX0FWWDUxMlBGX1NVUFBPUlQ7CiAgICB9CiAgICBpZiAoaXNfYml0X3NldChyZWdzWzFdLCAyNykpIHsKICAgICAgICByZXQgfD0gQ1BVX0FWWDUxMkVSX1NVUFBPUlQ7CiAgICB9CiAgICBpZiAoaXNfYml0X3NldChyZWdzWzFdLCAyOCkpIHsKICAgICAgICByZXQgfD0gQ1BVX0FWWDUxMkNEX1NVUFBPUlQ7CiAgICB9CiAgICBpZiAoaXNfYml0X3NldChyZWdzWzFdLCAzMCkpIHsKICAgICAgICByZXQgfD0gQ1BVX0FWWDUxMkJXX1NVUFBPUlQ7CiAgICB9CiAgICBpZiAoaXNfYml0X3NldChyZWdzWzFdLCAzMSkpIHsKICAgICAgICByZXQgfD0gQ1BVX0FWWDUxMlZMX1NVUFBPUlQ7CiAgICB9CiAgICBpZiAoaXNfYml0X3NldChyZWdzWzJdLCAxKSkgewogICAgICAgIHJldCB8PSBDUFVfQVZYNTEyVkJNSV9TVVBQT1JUOwogICAgfQoKICAgIHJldHVybiByZXQ7Cn0KCnN0YXRpYyB2b2lkIGdldF92ZW5kb3JfbmFtZShjaGFyICpidWZmKQp7CiAgICBpbnQzMl90IHJlZ3NbNF07CiAgICBpbnQzMl90ICp0ZW1wID0gKGludDMyX3QgKilidWZmOwogICAgZ2V0X2NwdWlkKHJlZ3MsIDApOwogICAgdGVtcFswXSA9IHJlZ3NbMV07CiAgICB0ZW1wWzFdID0gcmVnc1szXTsKICAgIHRlbXBbMl0gPSByZWdzWzJdOwp9CgpzdGF0aWMgdm9pZCBnZXRfYnJhbmRfc3RyaW5nKGNoYXIgKmJ1ZmYpCnsKICAgIGludDMyX3QgcmVnc1s0XTsKICAgIGludDMyX3QgKnRlbXAgPSAoaW50MzJfdCAqKWJ1ZmY7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IDM7IGkrKykgewogICAgICAgIGdldF9jcHVpZChyZWdzLCAweDgwMDAwMDAyICsgaSk7CiAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCA0OyBqKyspIHsKICAgICAgICAgICAgdGVtcFtpICogNCArIGpdID0gcmVnc1tqXTsKICAgICAgICB9CiAgICB9Cn0KCmludCBtYWluKHZvaWQpCnsKICAgIGNoYXIgc3RyWzY0XSA9IHswfTsKCiAgICBnZXRfdmVuZG9yX25hbWUoc3RyKTsKICAgIHByaW50ZigidmVuZG9yOiAlc1xuIiwgc3RyKTsKICAgIGdldF9icmFuZF9zdHJpbmcoc3RyKTsKICAgIHByaW50ZigiYnJhbmQ6ICVzXG4iLCBzdHIpOwoKICAgIHVpbnQzMl90IGNwdSA9IGdldF9zaW1kX3N1cHBvcnRfaW5mbygpOwogICAgCiAgICBjb25zdCBzdHJ1Y3QgewogICAgICAgIGludCBmbGFnOwogICAgICAgIGNvbnN0IGNoYXIgKm5hbWU7CiAgICB9IHRhYmxlW10gPSB7CiAgICAgICAge0NQVV9TU0UyX1NVUFBPUlQgICAgICAgICwgIlNTRTIiICAgICAgfSwKICAgICAgICB7Q1BVX1NTRTNfU1VQUE9SVCAgICAgICAgLCAiU1NFMyIgICAgICB9LAogICAgICAgIHtDUFVfU1NTRTNfU1VQUE9SVCAgICAgICAsICJTU1NFMyIgICAgIH0sCiAgICAgICAge0NQVV9TU0U0XzFfU1VQUE9SVCAgICAgICwgIlNTRTQuMSIgICAgfSwKICAgICAgICB7Q1BVX1NTRTRfMl9TVVBQT1JUICAgICAgLCAiU1NFNC4yIiAgICB9LAogICAgICAgIHtDUFVfU1NFNF9BX1NVUFBPUlQgICAgICAsICJTU0U0YSIgICAgIH0sCiAgICAgICAge0NQVV9GTUE0X1NVUFBPUlQgICAgICAgICwgIkZNQTQiICAgICAgfSwKICAgICAgICB7Q1BVX0ZNQTNfU1VQUE9SVCAgICAgICAgLCAiRk1BMyIgICAgICB9LAogICAgICAgIHtDUFVfQVZYX1NVUFBPUlQgICAgICAgICAsICJBVlgiICAgICAgIH0sCiAgICAgICAge0NQVV9BVlgyX1NVUFBPUlQgICAgICAgICwgIkFWWDIiICAgICAgfSwKICAgICAgICB7Q1BVX0FWWDUxMkZfU1VQUE9SVCAgICAgLCAiQVZYNTEyRiIgICB9LAogICAgICAgIHtDUFVfQVZYNTEyRFFfU1VQUE9SVCAgICAsICJBVlg1MTJEUSIgIH0sCiAgICAgICAge0NQVV9BVlg1MTJJRk1BNTJfU1VQUE9SVCwgIkFWWDUxMklGTUEifSwKICAgICAgICB7Q1BVX0FWWDUxMlBGX1NVUFBPUlQgICAgLCAiQVZYNTEyUEYiICB9LAogICAgICAgIHtDUFVfQVZYNTEyRVJfU1VQUE9SVCAgICAsICJBVlg1MTJFUiIgIH0sCiAgICAgICAge0NQVV9BVlg1MTJDRF9TVVBQT1JUICAgICwgIkFWWDUxMkNEIiAgfSwKICAgICAgICB7Q1BVX0FWWDUxMkJXX1NVUFBPUlQgICAgLCAiQVZYNTEyQlciICB9LAogICAgICAgIHtDUFVfQVZYNTEyVkxfU1VQUE9SVCAgICAsICJBVlg1MTJWTCIgIH0sCiAgICAgICAge0NQVV9BVlg1MTJWQk1JX1NVUFBPUlQgICwgIkFWWDUxMlZCTUkifSwKICAgICAgICB7LTEsIE5VTEx9CiAgICB9OwoKICAgIGlmIChjcHUgPT0gQ1BVX05PX1g4Nl9TSU1EKSB7CiAgICAgICAgcHJpbnRmKCJ0aGlzIGNwdSBpcyB0b28gb2xkLlxuIik7CiAgICAgICAgcmV0dXJuIDA7CiAgICB9CgogICAgZm9yIChpbnQgaSA9IDA7IHRhYmxlW2ldLm5hbWUgIT0gTlVMTDsgaSsrKSB7CiAgICAgICAgaWYgKGNwdSAmIHRhYmxlW2ldLmZsYWcpIHsKICAgICAgICAgICAgcHJpbnRmKCIlcyBpcyBzdXBwb3J0ZWQuXG4iLCB0YWJsZVtpXS5uYW1lKTsKICAgICAgICB9CiAgICB9CgogICAgcmV0dXJuIDA7Cn0K