mirror of
https://github.com/libretro/RetroArch.git
synced 2025-01-21 08:26:17 +00:00
Add CPU feature detection for X86.
This commit is contained in:
parent
2d5d1295cd
commit
c6b50d2645
6
Makefile
6
Makefile
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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}; \
|
||||
|
29
retroarch.c
29
retroarch.c
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user