Updated to compile:
- KdTree+Octree: max_depth changed to static const (this should be configured at compile time)
- wget tool replaced by curl, which is now more widespread
- added CMakeLists (to eventually replace SCons)
- various fixes
/*
* cpuflags
*
* Simple tool which detects CPU capabilities
* and outputs appropriate compiler flags.
*
* Usage:
* cpuflags [gcc version] [intelc version]
*
* Returns:
* [arch]
* [gcc flags]
* [intelc flags]
*
* The gcc/intelc version must be passed as floating point value,
* e.g. 4.23
*
* Copyright (C) 2008 Radek Brich <radek@brich.org>
*
* Based on x86cpucaps
* by Osamu Kayasono <jacobi@jcom.home.ne.jp>
* http://members.jcom.home.ne.jp/jacobi/linux/softwares.html
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN_VENDORNAME 13
#define VENDOR_INTEL 1
#define VENDOR_AMD 2
#define VENDOR_CYRIX 3
#define VENDOR_CENTAUR 4
#define VENDOR_TRANSMETA 5
#define VENDOR_OTHERS 0
struct simdcaps
{
unsigned int has_mmx;
unsigned int has_sse;
unsigned int has_sse2;
unsigned int has_sse3;
unsigned int has_ssse3;
unsigned int has_sse41;
unsigned int has_sse42;
unsigned int has_mmxext;
unsigned int has_3dnowext;
unsigned int has_3dnow;
};
/* CPU caps */
#define FLAG_MMX (1<<23)
#define FLAG_SSE (1<<25)
#define FLAG_SSE2 (1<<26)
/* CPU caps 2 */
#define FLAG_SSE3 (1<<0)
#define FLAG_SSSE3 (1<<9)
#define FLAG_SSE41 (1<<19)
#define FLAG_SSE42 (1<<20)
/* AMD CPU caps */
#define FLAG_MMXEXT (1<<22)
#define FLAG_3DNOWEXT (1<<30)
#define FLAG_3DNOW (1<<31)
/* cpuid, from kernel source ( linux/include/asm-i386/processor.h ) */
void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx)
{
__asm__("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "a" (op));
}
/*
* check SIMD capabilities
*/
int x86cpucaps_simd(struct simdcaps *simd)
{
int ex[4];
memset(&(*simd),0,sizeof(struct simdcaps));
/* check CPU has CPUID */
cpuid(0,&ex[0],&ex[1],&ex[2],&ex[3]);
if ( ex[0] < 1) return 1;
cpuid(0x80000001,&ex[0],&ex[1],&ex[2],&ex[3]);
if ( (ex[3] & FLAG_MMXEXT ) == FLAG_MMXEXT) simd->has_mmxext = 1;
if ( (ex[3] & FLAG_3DNOW ) == FLAG_3DNOW) simd->has_3dnow = 1;
if ( (ex[3] & FLAG_3DNOWEXT ) == FLAG_3DNOWEXT) simd->has_3dnowext = 1;
cpuid(1,&ex[0],&ex[1],&ex[2],&ex[3]);
if ( (ex[3] & FLAG_MMX ) == FLAG_MMX ) simd->has_mmx = 1;
if ( (ex[3] & FLAG_SSE ) == FLAG_SSE ) simd->has_sse = 1;
if ( (ex[3] & FLAG_SSE2 ) == FLAG_SSE2) simd->has_sse2 = 1;
if ( (ex[2] & FLAG_SSE3 ) == FLAG_SSE3 ) simd->has_sse3 = 1;
if ( (ex[2] & FLAG_SSSE3 ) == FLAG_SSSE3 ) simd->has_ssse3 = 1;
if ( (ex[2] & FLAG_SSE41 ) == FLAG_SSE41 ) simd->has_sse41 = 1;
if ( (ex[2] & FLAG_SSE42 ) == FLAG_SSE42 ) simd->has_sse42 = 1;
/* SSE CPU supports mmxext too */
if (simd->has_sse == 1) simd->has_mmxext = 1;
return 0;
}
/*
* check CPU Family-Model-Stepping
*/
int x86cpucaps_cpumodel()
{
int ex[4];
int f = 0;
/* check CPU has CPUID */
cpuid(0,&ex[0],&ex[1],&ex[2],&ex[3]);
if ( ex[0] < 1) return f;
cpuid(1,&ex[0],&ex[1],&ex[2],&ex[3]);
f = ex[0] & 0x0fff;
return f;
}
/*
* check CPU Vendor
*/
int x86cpucaps_vendor(char *vendorname)
{
int ex[4];
int f = 0;
char vendorstr[LEN_VENDORNAME];
/* check CPU has CPUID */
cpuid(0,&ex[0],&ex[1],&ex[2],&ex[3]);
if ( ex[0] < 1) return f;
/* read Vendor Strings */
vendorstr[0] = ex[1] & 0xff;
vendorstr[1] = (ex[1] >> 8) & 0xff;
vendorstr[2] = (ex[1] >> 16) & 0xff;
vendorstr[3] = (ex[1] >> 24) & 0xff;
vendorstr[4] = ex[3] & 0xff;
vendorstr[5] = (ex[3] >> 8) & 0xff;
vendorstr[6] = (ex[3] >> 16) & 0xff;
vendorstr[7] = (ex[3] >> 24) & 0xff;
vendorstr[8] = ex[2] & 0xff;
vendorstr[9] = (ex[2] >> 8) & 0xff;
vendorstr[10]= (ex[2] >> 16) & 0xff;
vendorstr[11]= (ex[2] >> 24) & 0xff;
vendorstr[12]= '\0';
if ( strcmp(vendorstr, "GenuineIntel") == 0 )
f = VENDOR_INTEL;
else if ( strcmp(vendorstr, "AuthenticAMD") == 0 )
f = VENDOR_AMD;
else if ( strcmp(vendorstr, "CyrixInstead") == 0 )
f = VENDOR_CYRIX;
else if ( strcmp(vendorstr, "CentaurHauls") == 0 )
f = VENDOR_CENTAUR;
else if ( strcmp(vendorstr, "GenuineTMx86") == 0 )
f = VENDOR_TRANSMETA;
strncpy(vendorname, vendorstr, LEN_VENDORNAME);
return f;
}
int main(int argc, char **argv)
{
int family, model, stepping;
char *arch, *gccarch, *gccsimd, *iccarch, *icctune, *iccsimd;
int cpu_id = x86cpucaps_cpumodel();
char vendorname[LEN_VENDORNAME];
int vendor_id = x86cpucaps_vendor(vendorname);
struct simdcaps simd;
float gccver = 999.;
float iccver = 999.;
if (argc > 1)
gccver = atof(argv[1]);
if (argc > 2)
iccver = atof(argv[2]);
family = (cpu_id & 0xf00) >> 8;
model = (cpu_id & 0x0f0) >> 4;
stepping = cpu_id & 0x00f;
switch (vendor_id)
{
case VENDOR_INTEL:
if (family == 4)
{
arch = "i486";
}
else if (family == 5)
{
if (model < 4) arch = "pentium";
else arch = "pentium-mmx";
}
else if (family == 6)
{
if (model <= 1) arch = "pentiumpro";
else if (model < 7) arch = "pentium2";
else if (model < 12) arch = "pentium3";
else if (model < 14) arch = "pentium-m";
else if (model == 14) arch = "prescott"; // core
else if (model == 15) arch = "core2";
}
else if (family > 6)
{ /* family == 15 */
arch = "pentium4";
}
else
{
arch = "i386";
}
break;
case VENDOR_AMD:
if (family == 4)
{
if (model <= 9) arch = "i486";
else arch = "i586";
}
else if (family == 5)
{
if (model <= 3) arch = "i586";
else if (model <= 7) arch = "k6";
else if (model == 8) arch = "k6-2";
else arch = "k6-3";
}
else if (family == 6)
{
if (model <= 3) arch = "athlon";
else if (model == 4) arch = "athlon-tbird";
else arch = "athlon-xp";
}
else if (family > 6)
{
arch = "k8";
}
else
{
arch = "unknown";
}
break;
case VENDOR_CYRIX:
if (family == 4) arch = "i586";
else if (family == 5) arch = "i586";
else if (family == 6) arch = "i686";
else arch = "unknown";
break;
case VENDOR_CENTAUR:
if (family == 5) arch = "i586";
else arch = "unknown";
break;
case VENDOR_TRANSMETA:
arch = "i686";
break;
default:
arch = "unknown";
break;
}
/* some targets not supported by older gcc */
gccarch = arch;
if (gccver < (float)4.3)
{
if (!strcmp(gccarch, "core2")) gccarch = "pentium-m";
}
if (gccver < (float)3.41)
{
if (!strcmp(gccarch, "prescott")) gccarch = "pentium4";
if (!strcmp(gccarch, "pentium-m")) gccarch = "pentium4";
}
if (gccver < (float)3.4)
{
if (!strcmp(gccarch, "k8")) gccarch = "athlon-xp";
}
if (gccver < (float)3.1)
{
if (strstr(gccarch, "athlon-") != NULL)
gccarch = "athlon";
else if (strstr(gccarch, "k6-") != NULL)
gccarch = "k6";
else if (!strcmp(gccarch, "pentium-mmx"))
gccarch = "pentium";
else if (!strcmp(gccarch, "pentium2")
|| !strcmp(gccarch, "pentium3")
|| !strcmp(gccarch, "pentium4"))
gccarch = "pentiumpro";
}
if (gccver < (float)3.0)
{
if (!strcmp(gccarch, "athlon"))
gccarch = "pentiumpro";
else if (!strcmp(gccarch, "k6"))
gccarch = "pentium";
}
if (gccver < (float)2.95)
{
if (!strcmp(gccarch, "pentiumpro"))
gccarch = "i686";
else if (!strcmp(gccarch, "pentium"))
gccarch = "i586";
}
/* SIMD options */
x86cpucaps_simd(&simd);
gccsimd = "";
if (gccver >= 3.1) {
if ( simd.has_3dnow || simd.has_3dnowext )
gccsimd = "-m3dnow";
else
{
if (gccver >= 4.3)
{
if (simd.has_sse41 || simd.has_sse42) gccsimd = "-msse4 -mfpmath=sse";
else if (simd.has_ssse3) gccsimd = "-mssse3 -mfpmath=sse";
}
else if ( gccver >= 3.4 && simd.has_sse3 ) gccsimd = "-msse3 -mfpmath=sse";
else if ( simd.has_sse2 ) gccsimd = "-msse2 -mfpmath=sse";
else if ( simd.has_sse ) gccsimd = "-msse";
else if ( simd.has_mmx ) gccsimd = "-mmmx";
}
}
/* IntelC options */
iccarch = arch;
icctune = arch;
iccsimd = "";
if (simd.has_sse41 || simd.has_sse42) iccsimd = "-xS";
else if (simd.has_ssse3) iccsimd = "-xT";
else if (simd.has_sse3) iccsimd = "-msse3 -xP";
else if (simd.has_sse2) iccsimd = "-msse2";
printf("%s\n", arch);
/* GCC flags */
if (gccver >= 4.2) gccarch = "native";
#ifdef __x86_64__
/* do not output i386 flags on x86_64 */
if (strcmp(gccarch, "core2") != 0 && strcmp(gccarch, "native") != 0)
printf("%s\n", gccsimd);
else
#endif
printf("-march=%s %s\n", gccarch, gccsimd);
/* IntelC flags */
printf("-march=%s -mtune=%s %s\n", iccarch, icctune, iccsimd);
return 0;
}