mirror of
https://github.com/libretro/RetroArch
synced 2025-02-28 03:39:59 +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/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)
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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}; \
|
||||||
|
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");
|
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
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user