Add CPU feature detection for X86.

This commit is contained in:
Themaister 2012-11-01 22:31:24 +01:00
parent 2d5d1295cd
commit c6b50d2645
5 changed files with 97 additions and 15 deletions

View File

@ -23,7 +23,8 @@ OBJ = retroarch.o \
gfx/scaler/scaler.o \ gfx/scaler/scaler.o \
gfx/scaler/pixconv.o \ gfx/scaler/pixconv.o \
gfx/scaler/scaler_int.o \ gfx/scaler/scaler_int.o \
gfx/scaler/filter.o gfx/scaler/filter.o \
performance.o
JOYCONFIG_OBJ = tools/retroarch-joyconfig.o \ JOYCONFIG_OBJ = tools/retroarch-joyconfig.o \
conf/config_file.o \ conf/config_file.o \
@ -56,7 +57,7 @@ endif
ifneq ($(findstring Linux,$(OS)),) ifneq ($(findstring Linux,$(OS)),)
LIBS += -lrt LIBS += -lrt
OBJ += input/linuxraw_input.o input/linuxraw_joypad.o performance/performance_linux.o OBJ += input/linuxraw_input.o input/linuxraw_joypad.o
JOYCONFIG_OBJ += input/linuxraw_joypad.o JOYCONFIG_OBJ += input/linuxraw_joypad.o
endif endif
@ -143,7 +144,6 @@ endif
ifeq ($(PERF_TEST), 1) ifeq ($(PERF_TEST), 1)
DEFINES += -DPERF_TEST DEFINES += -DPERF_TEST
OBJ += performance.o
endif endif
ifeq ($(HAVE_SDL), 1) ifeq ($(HAVE_SDL), 1)

View File

@ -16,6 +16,8 @@
#include "performance.h" #include "performance.h"
#ifdef PERF_TEST
#if defined(__CELLOS_LV2__) || defined(GEKKO) #if defined(__CELLOS_LV2__) || defined(GEKKO)
#ifndef _PPU_INTRINSICS_H #ifndef _PPU_INTRINSICS_H
#include <ppu_intrinsics.h> #include <ppu_intrinsics.h>
@ -46,8 +48,6 @@ void rarch_perf_log(void)
RARCH_PERFORMANCE_LOG(perf_counters[i]->ident, *perf_counters[i]); RARCH_PERFORMANCE_LOG(perf_counters[i]->ident, *perf_counters[i]);
} }
rarch_perf_tick_t rarch_get_perf_counter(void) rarch_perf_tick_t rarch_get_perf_counter(void)
{ {
rarch_perf_tick_t time = 0; rarch_perf_tick_t time = 0;
@ -69,7 +69,7 @@ rarch_perf_tick_t rarch_get_perf_counter(void)
#elif defined(__GNUC__) && !defined(RARCH_CONSOLE) #elif defined(__GNUC__) && !defined(RARCH_CONSOLE)
#if defined(__i386__) || defined(__i486__) #if defined(__i386__) || defined(__i486__) || defined(__i686__)
asm volatile ("rdtsc" : "=A" (time)); asm volatile ("rdtsc" : "=A" (time));
#elif defined(__x86_64__) #elif defined(__x86_64__)
unsigned a, d; unsigned a, d;
@ -85,3 +85,57 @@ rarch_perf_tick_t rarch_get_perf_counter(void)
return time; return time;
} }
#endif
#if defined(__x86_64__) || defined(__i386__) || defined(__i486__) || defined(__i686__)
#define CPU_X86
#endif
#ifdef _MSC_VER
#include <intrin.h>
#endif
#ifdef CPU_X86
static void x86_cpuid(int func, int flags[4])
{
#ifdef __GNUC__
asm volatile("cpuid\n" :
"=a"(flags[0]),
"=b"(flags[1]),
"=c"(flags[2]),
"=d"(flags[3]) : "a"(func));
#elif defined(_MSC_VER)
__cpuid(flags, func);
#endif
}
#endif
void rarch_get_cpu_features(struct rarch_cpu_features *cpu)
{
memset(cpu, 0, sizeof(*cpu));
#ifdef CPU_X86
int flags[4];
x86_cpuid(0, flags);
char vendor[13] = {0};
const int vendor_shuffle[3] = { flags[1], flags[3], flags[2] };
memcpy(vendor, vendor_shuffle, sizeof(vendor_shuffle));
RARCH_LOG("[CPUID]: Vendor: %s\n", vendor);
if (flags[0] < 1) // Does CPUID not support func = 1? (unlikely ...)
return;
x86_cpuid(1, flags);
cpu->sse = flags[3] & (1 << 25);
cpu->sse2 = flags[3] & (1 << 26);
int avx_flags = (1 << 27) | (1 << 28);
cpu->avx = (flags[2] & avx_flags) == avx_flags; // Is this enough?
RARCH_LOG("[CPUID]: SSE: %d\n", cpu->sse);
RARCH_LOG("[CPUID]: SSE2: %d\n", cpu->sse2);
RARCH_LOG("[CPUID]: AVX: %d\n", cpu->avx);
#endif
}

View File

@ -23,10 +23,6 @@
#include "config.h" #include "config.h"
#endif #endif
#ifdef __linux
#include "performance/performance_linux.h"
#endif
#include <stdint.h> #include <stdint.h>
typedef unsigned long long rarch_perf_tick_t; typedef unsigned long long rarch_perf_tick_t;
@ -44,6 +40,17 @@ rarch_perf_tick_t rarch_get_perf_counter(void);
void rarch_perf_register(struct rarch_perf_counter *perf); void rarch_perf_register(struct rarch_perf_counter *perf);
void rarch_perf_log(void); void rarch_perf_log(void);
struct rarch_cpu_features
{
bool sse;
bool sse2;
bool vmx;
bool avx;
bool neon;
};
void rarch_get_cpu_features(struct rarch_cpu_features *cpu);
#ifdef PERF_TEST #ifdef PERF_TEST
#define RARCH_PERFORMANCE_INIT(X) static rarch_perf_counter_t X = {#X}; \ #define RARCH_PERFORMANCE_INIT(X) static rarch_perf_counter_t X = {#X}; \

View File

@ -2539,6 +2539,30 @@ static void verify_api_version(void)
RARCH_WARN("RetroArch is compiled against a different version of libretro than this libretro implementation.\n"); RARCH_WARN("RetroArch is compiled against a different version of libretro than this libretro implementation.\n");
} }
// Make sure we haven't compiled for something we cannot run.
// Ideally, code would get swapped out depending on CPU support, but this will do for now.
static void validate_cpu_features(void)
{
struct rarch_cpu_features cpu;
rarch_get_cpu_features(&cpu);
#ifdef __SSE2__
if (!cpu.sse2)
{
RARCH_ERR("SSE2 code is compiled in, but CPU does not support this feature. Cannot continue.\n");
rarch_fail(1, "validate_cpu_features()");
}
#endif
#ifdef __AVX__
if (!cpu.avx)
{
RARCH_ERR("AVX code is compiled in, but CPU does not support this feature. Cannot continue.\n");
rarch_fail(1, "validate_cpu_features()");
}
#endif
}
int rarch_main_init(int argc, char *argv[]) int rarch_main_init(int argc, char *argv[])
{ {
init_state(); init_state();
@ -2550,7 +2574,6 @@ int rarch_main_init(int argc, char *argv[])
return sjlj_ret; return sjlj_ret;
} }
g_extern.error_in_init = true; g_extern.error_in_init = true;
parse_input(argc, argv); parse_input(argc, argv);
if (g_extern.verbose) if (g_extern.verbose)
@ -2560,6 +2583,7 @@ int rarch_main_init(int argc, char *argv[])
RARCH_LOG_OUTPUT("=================================================\n"); RARCH_LOG_OUTPUT("=================================================\n");
} }
validate_cpu_features();
config_load(); config_load();
init_libretro_sym(); init_libretro_sym();
@ -2792,9 +2816,6 @@ int rarch_main(int argc, char *argv[])
// Consoles use the higher level API. // Consoles use the higher level API.
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
#if 0
rarch_perf_get_cpu_features();
#endif
return rarch_main(argc, argv); return rarch_main(argc, argv);
} }
#endif #endif

View File

@ -56,7 +56,7 @@
#define RARCH_LOG_OUTPUT(...) do { \ #define RARCH_LOG_OUTPUT(...) do { \
if (g_extern.verbose) \ if (g_extern.verbose) \
{ \ { \
fprintf(stderr, "stderr: " __VA_ARGS__); \ fprintf(stderr, __VA_ARGS__); \
fflush(stderr); \ fflush(stderr); \
} \ } \
} while (0) } while (0)