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/pixconv.o \
gfx/scaler/scaler_int.o \
gfx/scaler/filter.o
gfx/scaler/filter.o \
performance.o
JOYCONFIG_OBJ = tools/retroarch-joyconfig.o \
conf/config_file.o \
@ -56,7 +57,7 @@ endif
ifneq ($(findstring Linux,$(OS)),)
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
endif
@ -143,7 +144,6 @@ endif
ifeq ($(PERF_TEST), 1)
DEFINES += -DPERF_TEST
OBJ += performance.o
endif
ifeq ($(HAVE_SDL), 1)

View File

@ -16,6 +16,8 @@
#include "performance.h"
#ifdef PERF_TEST
#if defined(__CELLOS_LV2__) || defined(GEKKO)
#ifndef _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_perf_tick_t rarch_get_perf_counter(void)
{
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)
#if defined(__i386__) || defined(__i486__)
#if defined(__i386__) || defined(__i486__) || defined(__i686__)
asm volatile ("rdtsc" : "=A" (time));
#elif defined(__x86_64__)
unsigned a, d;
@ -85,3 +85,57 @@ rarch_perf_tick_t rarch_get_perf_counter(void)
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"
#endif
#ifdef __linux
#include "performance/performance_linux.h"
#endif
#include <stdint.h>
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_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
#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");
}
// 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[])
{
init_state();
@ -2550,7 +2574,6 @@ int rarch_main_init(int argc, char *argv[])
return sjlj_ret;
}
g_extern.error_in_init = true;
parse_input(argc, argv);
if (g_extern.verbose)
@ -2560,6 +2583,7 @@ int rarch_main_init(int argc, char *argv[])
RARCH_LOG_OUTPUT("=================================================\n");
}
validate_cpu_features();
config_load();
init_libretro_sym();
@ -2792,9 +2816,6 @@ int rarch_main(int argc, char *argv[])
// Consoles use the higher level API.
int main(int argc, char *argv[])
{
#if 0
rarch_perf_get_cpu_features();
#endif
return rarch_main(argc, argv);
}
#endif

View File

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