
/** 
 * This code was auto-generated by write_check.py. Do not edit here!
 * 
 * Utilities for checking the CPU instruction set
 *
 * https://en.wikipedia.org/wiki/CPUID
 *
 */

#include <stdio.h>

#ifdef _MSC_VER
    #include <intrin.h>
#else
    #include <cpuid.h>
#endif
#include "cImageD11.h"
#include "check_cpu_auto.h"

/* DO NOT Use static globals here 
 * Results of calls to cpuid 
 * Stuff to look for : EAX call, A|B|C|D, bit position 
 *  0  : {B,D,C} = name, A = maxcall
 *  1  :  4A, 5B, 6C, 7D
 *      A = Processor information
 *      B = Additional information
 *      C = Features
 *      D = Features
 *  2  : Cache and TLB Descriptor information
 *  3  : Processor Serial Number
 * EAX=4 and EAX=Bh: Intel thread/core and cache topology
 * EAX=7, ECX=0: Extended Features
 * EAX=80000000h: Get Highest Extended Function Implemented : 
 *                The highest calling parameter is returned in EAX.
 * EAX=80000001h: Extended Processor Info and Feature Bits
 * EAX=80000002h,80000003h,80000004h: Processor Brand String
 * EAX=80000005h: L1 Cache and TLB Identifiers
 * EAX=80000006h: Extended L2 Cache Features
 * EAX=80000007h: Advanced Power Management Information
 * EAX=80000008h: Virtual and Physical address Sizes
 * EAX=8FFFFFFFh: AMD Easter Egg
 */


/**
 * Calls cpuid and stores results of eax,ebx,ecx,edx in idBits[op*4:op*4+4]
 * __cpuid_count needed for > XXX
 */
void readcpuid( unsigned int leaf, unsigned int subleaf, unsigned int idBits[4] ) {
  int j;
  // MSVC and gcc both provide a __cpuid function
  for(j=0;j<4;j++) idBits[j]=0;
  #if defined(__GNUC__)
   __cpuid_count( leaf, subleaf, idBits[0], idBits[1], idBits[2], idBits[3]);
  #elif defined(_WIN32)
  __cpuidex( &idBits[0], leaf, subleaf );
  #endif
}


/**
 * Retrieve the processor name.
 * \param name Preallocated string containing at least room for 13 characters. Will
 *             contain the name of the processor.
 */
void cpuidProcessorName( char* name ){
  unsigned int idBits[4];
  readcpuid( 0, 0, idBits );
  name[0]  = (idBits[1]    ) & 0xFF;
  name[1]  = (idBits[1]>> 8) & 0xFF;
  name[2]  = (idBits[1]>>16) & 0xFF;
  name[3]  = (idBits[1]>>24) & 0xFF;
  name[4]  = (idBits[3]    ) & 0xFF;
  name[5]  = (idBits[3]>> 8) & 0xFF;
  name[6]  = (idBits[3]>>16) & 0xFF;
  name[7]  = (idBits[3]>>24) & 0xFF;
  name[8]  = (idBits[2]    ) & 0xFF;
  name[9]  = (idBits[2]>> 8) & 0xFF;
  name[10] = (idBits[2]>>16) & 0xFF;
  name[11] = (idBits[2]>>24) & 0xFF;
  name[12] = 0;
}



int flag_SSE(){
 unsigned int idBits[4];
 readcpuid( 1 , 0, idBits );
 return (idBits[3] & ( 1 << 25))>0;
}
int flag_SSE2(){
 unsigned int idBits[4];
 readcpuid( 1 , 0, idBits );
 return (idBits[3] & ( 1 << 26))>0;
}
int flag_SSE3(){
 unsigned int idBits[4];
 readcpuid( 1 , 0, idBits );
 return (idBits[2] & ( 1 << 0))>0;
}
int flag_FMA3(){
 unsigned int idBits[4];
 readcpuid( 1 , 0, idBits );
 return (idBits[2] & ( 1 << 12))>0;
}
int flag_SSE41(){
 unsigned int idBits[4];
 readcpuid( 1 , 0, idBits );
 return (idBits[2] & ( 1 << 19))>0;
}
int flag_SSE42(){
 unsigned int idBits[4];
 readcpuid( 1 , 0, idBits );
 return (idBits[2] & ( 1 << 20))>0;
}
int flag_MOVBE(){
 unsigned int idBits[4];
 readcpuid( 1 , 0, idBits );
 return (idBits[2] & ( 1 << 22))>0;
}
int flag_XSAVE(){
 unsigned int idBits[4];
 readcpuid( 1 , 0, idBits );
 return (idBits[2] & ( 1 << 26))>0;
}
int flag_OSXSAVE(){
 unsigned int idBits[4];
 readcpuid( 1 , 0, idBits );
 return (idBits[2] & ( 1 << 27))>0;
}
int flag_AVX(){
 unsigned int idBits[4];
 readcpuid( 1 , 0, idBits );
 return (idBits[2] & ( 1 << 28))>0;
}
int flag_AVX2(){
 unsigned int idBits[4];
 readcpuid( 7 , 0, idBits );
 return (idBits[1] & ( 1 << 5))>0;
}
int flag_AVX512F(){
 unsigned int idBits[4];
 readcpuid( 7 , 0, idBits );
 return (idBits[1] & ( 1 << 16))>0;
}

int i_have_SSE2(){
  return (flag_SSE2()>0);
}
int i_have_SSE42(){
  return (flag_SSE42()>0);
}
int i_have_AVX(){
    return (flag_XSAVE()>0)&(flag_OSXSAVE()>0)&(flag_AVX()>0);
}
int i_have_AVX2(){
    return (flag_AVX()>0)&(flag_MOVBE()>0)&(flag_FMA3()>0)&(flag_AVX2()>0);
}
int i_have_AVX512F(){
    return (flag_OSXSAVE()>0)&(flag_AVX512F()>0);
}

