PageRenderTime 26ms CodeModel.GetById 11ms app.highlight 13ms RepoModel.GetById 0ms app.codeStats 0ms

/cpucheck.c

https://bitbucket.org/cesbo/astra
C | 157 lines | 123 code | 16 blank | 18 comment | 33 complexity | e14094e5cadb2e252370a43434a30540 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0
  1/*
  2 * This file is part of Astra. For more information, visit
  3 * https://cesbo.com
  4 *
  5 * Copyright (C) 2011, Andrey Dyldin <and@cesbo.com>
  6 */
  7
  8#if defined(__i386__) || defined(__x86_64__)
  9
 10#include <stdio.h>
 11
 12#define GCC_VERSION (__GNUC__ * 10000 + (__GNUC_MINOR__ * 100) + __GNUC_PATCHLEVEL__)
 13
 14typedef struct
 15{
 16    const char *arch;
 17    int curr[2]; // cpu { family, model }
 18    int next[2]; // check next { family, model } if arch==NULL or gcc not support curr
 19} cpu_arch_t;
 20
 21static cpu_arch_t intel_list[] =
 22{ /* from the begin to the end */
 23    // Sandy Bridge
 24    { "corei7-avx", {6,42}, {6,15} }
 25    // Core i7,i5,i3, Xeon 55xx
 26        , { NULL, {6,44}, {6,26} }, { NULL, {6,37}, {6,26} }, { NULL, {6,46}, {6,26} }
 27        , { NULL, {6,47}, {6,26} }, { NULL, {6,29}, {6,26} }, { NULL, {6,30}, {6,26} }
 28    , { "corei7", {6,26}, {6,15} }
 29    // Atom
 30    , { "atom", {6,28}, {6,15} }
 31    // Pentium 4, Pentium D, Celeron D
 32        , { NULL, {15,4}, {15,3} }, { NULL, {15,6}, {15,3} }
 33#if defined(__i386__)
 34    , { "prescott", {15,3}, {6,9} }
 35#elif defined(__x86_64__)
 36    , { "nocona", {15,3}, {6,9} }
 37#endif
 38    // Pentium 4
 39        , { NULL, {15,1}, {15,0} }, { NULL, {15,2}, {15,0} }
 40    , { "pentium4", {15,0}, {5,1} }
 41    // Core 2 Duo/Quad, Xeon 51xx/53xx/54xx/3360
 42        , { NULL, {6,23}, {6,15} }
 43    , { "core2", {6,15}, {6,14} }
 44    // Core Solo/Duo
 45        , { NULL, {6,22}, {6,14} }
 46    , { "prescott", {6,14}, {6,9} }
 47        , { NULL, {6,13}, {6,9} }
 48    , { "pentium-m", {6,9}, {6,7} }
 49        , { NULL, {6,11}, {6,7} }, { NULL, {6,10}, {6,7} }, { NULL, {6,8}, {6,7} }
 50    , { "pentium3", {6,7}, {6,1} }
 51        , { NULL, {6,5}, {6,3} }, { NULL, {6,6}, {6,3} }
 52    , { "pentium2", {6,3}, {6,1} }
 53    , { "pentiumpro", {6,1}, {5,5} }
 54    , { "pentium-mmx", {5,4}, {5,1} }
 55        , { NULL, {5,2}, {5,1} }, { NULL, {5,3}, {5,1} }
 56    , { "pentium", {5,1}, {0,0} }
 57    , { "i486", {4,0}, {0,0} }
 58    , { "i386", {3,0}, {0,0} }
 59    , { NULL, {0,0}, {0,0} }
 60};
 61
 62static cpu_arch_t amd_list[] =
 63{
 64      { "k6-2", {5,8}, {0,0} } // my first x86 pc :)
 65    , { NULL, 0, 0, 0 }
 66};
 67
 68const char * cpu_arch_get(cpu_arch_t *list, int family, int model)
 69{
 70    char cmd[64];
 71    while(list->curr[0])
 72    {
 73        if(list->curr[0] == family && list->curr[1] == model)
 74        {
 75            sprintf(cmd, "gcc -march=%s -E -xc /dev/null 1>/dev/null 2>/dev/null", list->arch);
 76            if(system(cmd) == 0)
 77                return list->arch;
 78            else
 79                return cpu_arch_get(list, list->next[0], list->next[1]);
 80        }
 81        ++list;
 82    }
 83}
 84
 85typedef struct { unsigned int eax, ebx, ecx, edx; } regs_t;
 86static inline cpuid(regs_t *regs, unsigned int op)
 87{
 88    __asm__ __volatile__ (  "cpuid"
 89                          : "=a" (regs->eax)
 90                          , "=b" (regs->ebx)
 91                          , "=c" (regs->ecx)
 92                          , "=d" (regs->edx)
 93                          : "a"  (op));
 94}
 95
 96int main()
 97{
 98    regs_t vr, ir;
 99    cpuid(&vr, 0);
100    cpuid(&ir, 1);
101
102    // TODO: get CPU cores -DCPU_CORES=%d
103//    unsigned int logical = (ir.ebx >> 24) & 0xff;
104//    printf("test:%d\n", logical);
105
106#if GCC_VERSION >= 40203
107    printf(" -march=native");
108#else
109    int cpu_family = (ir.eax & 0x00000F00) >> 8;
110    int cpu_model = (ir.eax & 0x000000F0) >> 4;
111    if(vr.ebx == 0x756e6547
112       && vr.edx == 0x49656e69
113       && vr.ecx == 0x6c65746e)
114    {
115        /* GenuineIntel */
116        cpu_family += ((ir.eax & 0x0FF00000) >> 20);
117        cpu_model += ((ir.eax & 0x000F0000) >> 12 /* (>>16)<<4 */ );
118        const char *march = cpu_arch_get(intel_list, cpu_family, cpu_model);
119        if(march)
120            printf(" -march=%s", march);
121    }
122    else if(vr.ebx == 0x68747541
123            && vr.edx == 0x69746E65
124            && vr.ecx == 0x444D4163)
125    {
126        /* AuthenticAMD */
127        if(cpu_family == 0xF)
128        {
129            cpu_family += ((ir.eax & 0x0FF00000) >> 20);
130            cpu_model += ((ir.eax & 0x000F0000) >> 12 /* (>>16)<<4 */ );
131        }
132        const char *march = cpu_arch_get(amd_list, cpu_family, cpu_model);
133        if(march)
134            printf(" -march=%s", march);
135    }
136#endif
137
138    if(ir.ecx & (0x00080000 /* 4.1 */ | 0x00100000 /* 4.2 */ ))
139        printf(" -msse4");
140    else if(ir.ecx & 0x00000001)
141        printf(" -msse3");
142    else if(ir.edx & 0x04000000)
143        printf(" -msse2");
144    else if(ir.edx & 0x02000000)
145        printf(" -msse");
146    else if(ir.edx & 0x00800000)
147        printf(" -mmmx");
148    putchar('\n');
149
150    return 0;
151}
152
153#else
154
155int main() { return 0; }
156
157#endif