Move processor capability information to utils-cpuinfo.[ch]hpp. Add new

utils-sentinel.hpp for helper functions to be called at program initialization
and termination.
This commit is contained in:
gbeauche 2006-07-16 12:28:01 +00:00
parent 9bc307c3fd
commit 7cfee5a2be
3 changed files with 229 additions and 0 deletions

View File

@ -0,0 +1,137 @@
/*
* utils-cpuinfo.cpp - Processor capability information
*
* Kheperix (C) 2003-2005 Gwenole Beauchesne
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "sysdeps.h"
#include "utils/utils-cpuinfo.hpp"
#include "utils/utils-sentinel.hpp"
// x86 CPU features
static uint32 x86_cpu_features = 0;
enum {
HWCAP_I386_CMOV = 1 << 15,
HWCAP_I386_MMX = 1 << 23,
HWCAP_I386_SSE = 1 << 25,
HWCAP_I386_SSE2 = 1 << 26,
HWCAP_I386_EDX_FLAGS = (HWCAP_I386_CMOV|HWCAP_I386_MMX|HWCAP_I386_SSE|HWCAP_I386_SSE2),
HWCAP_I386_SSE3 = 1 << 0,
HWCAP_I386_SSE4 = 1 << 9,
HWCAP_I386_ECX_FLAGS = (HWCAP_I386_SSE3|HWCAP_I386_SSE4),
};
// Determine x86 CPU features
DEFINE_INIT_SENTINEL(init_x86_cpu_features);
static void init_x86_cpu_features(void)
{
#if defined(__i386__) || defined(__x86_64__)
unsigned int fl1, fl2;
#ifndef __x86_64__
/* See if we can use cpuid. On AMD64 we always can. */
__asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
"pushl %0; popfl; pushfl; popl %0; popfl"
: "=&r" (fl1), "=&r" (fl2)
: "i" (0x00200000));
if (((fl1 ^ fl2) & 0x00200000) == 0)
return;
#endif
/* Host supports cpuid. See if cpuid gives capabilities, try
CPUID(0). Preserve %ebx and %ecx; cpuid insn clobbers these, we
don't need their CPUID values here, and %ebx may be the PIC
register. */
#ifdef __x86_64__
__asm__ ("pushq %%rcx; pushq %%rbx; cpuid; popq %%rbx; popq %%rcx"
: "=a" (fl1) : "0" (0) : "rdx", "cc");
#else
__asm__ ("push %%ecx ; push %%ebx ; cpuid ; pop %%ebx ; pop %%ecx"
: "=a" (fl1) : "0" (0) : "edx", "cc");
#endif
if (fl1 == 0)
return;
/* Invoke CPUID(1), return %edx; caller can examine bits to
determine what's supported. */
#ifdef __x86_64__
__asm__ ("push %%rbx ; cpuid ; pop %%rbx" : "=c" (fl1), "=d" (fl2) : "a" (1) : "cc");
#else
__asm__ ("push %%ebx ; cpuid ; pop %%ebx" : "=c" (fl1), "=d" (fl2) : "a" (1) : "cc");
#endif
x86_cpu_features = (fl1 & HWCAP_I386_ECX_FLAGS) | (fl2 & HWCAP_I386_EDX_FLAGS);
#endif
}
// Check for x86 feature CMOV
bool cpuinfo_check_cmov(void)
{
return x86_cpu_features & HWCAP_I386_CMOV;
}
// Check for x86 feature MMX
bool cpuinfo_check_mmx(void)
{
return x86_cpu_features & HWCAP_I386_MMX;
}
// Check for x86 feature SSE
bool cpuinfo_check_sse(void)
{
return x86_cpu_features & HWCAP_I386_SSE;
}
// Check for x86 feature SSE2
bool cpuinfo_check_sse2(void)
{
return x86_cpu_features & HWCAP_I386_SSE2;
}
// Check for x86 feature SSE3
bool cpuinfo_check_sse3(void)
{
return x86_cpu_features & HWCAP_I386_SSE3;
}
// Check for x86 feature SSE4
bool cpuinfo_check_sse4(void)
{
return x86_cpu_features & HWCAP_I386_SSE4;
}
// PowerPC CPU features
static uint32 ppc_cpu_features = 0;
enum {
HWCAP_PPC_ALTIVEC = 1 << 0
};
// Determine PowerPC CPU features
DEFINE_INIT_SENTINEL(init_ppc_cpu_features);
static void init_ppc_cpu_features(void)
{
}
// Check for ppc feature VMX (Altivec)
bool cpuinfo_check_altivec(void)
{
return ppc_cpu_features & HWCAP_PPC_ALTIVEC;
}

View File

@ -0,0 +1,45 @@
/*
* utils-cpuinfo.hpp - Processor capability information
*
* Kheperix (C) 2003-2005 Gwenole Beauchesne
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef UTILS_CPUINFO_H
#define UTILS_CPUINFO_H
// Check for x86 feature CMOV
extern bool cpuinfo_check_cmov(void);
// Check for x86 feature MMX
extern bool cpuinfo_check_mmx(void);
// Check for x86 feature SSE
extern bool cpuinfo_check_sse(void);
// Check for x86 feature SSE2
extern bool cpuinfo_check_sse2(void);
// Check for x86 feature SSE3
extern bool cpuinfo_check_sse3(void);
// Check for x86 feature SSE4
extern bool cpuinfo_check_sse4(void);
// Check for ppc feature VMX (Altivec)
extern bool cpuinfo_check_altivec(void);
#endif /* UTILS_CPUINFO_H */

View File

@ -0,0 +1,47 @@
/*
* utils-sentinel.hpp - Helper functions for program initialization and termination
*
* Kheperix (C) 2003-2005 Gwenole Beauchesne
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef UTILS_SENTINEL_H
#define UTILS_SENTINEL_H
class program_sentinel {
void (*fini)(void);
public:
program_sentinel(void (*init_func)(void) = 0, void (*exit_func)(void) = 0)
: fini(exit_func)
{ if (init_func) init_func(); }
~program_sentinel()
{ if (fini) fini(); }
};
#define DEFINE_INIT_SENTINEL(FUNCTION) \
static void FUNCTION(void); \
static program_sentinel g_program_init_sentinel__##FUNCTION(FUNCTION)
#define DEFINE_EXIT_SENTINEL(FUNCTION) \
static void FUNCTION(void); \
static program_sentinel g_program_exit_sentinel__##FUNCTION(0, FUNCTION)
#define DEFINE_PROG_SENTINEL(FUNCTION) \
static void init_##FUNCTION(void); \
static void exit_##FUNCTION(void); \
static program_sentinel g_program_sentinel_##FUNCTION(init_##FUNCTION, exit_##FUNCTION)
#endif /* UTILS_SENTINEL_H */