Commit a999325a authored by Doug Nazar's avatar Doug Nazar

powerpc: Fix cpu feature detection

Fix meson cpu family detection.
Actually call cpu detection from progam init.
Add VSX & v2.07 checks for linux with options to diable.
Add display of target flags & cache sizes.
parent 00dc4a44
......@@ -89,7 +89,7 @@ endif
if cpu_family.startswith('x86')
orc_sources += ['orccpu-x86.c']
elif cpu_family == 'powerpc'
elif cpu_family == 'ppc' or cpu_family == 'ppc64'
orc_sources += ['orccpu-powerpc.c']
elif cpu_family == 'arm'
orc_sources += ['orccpu-arm.c']
......
......@@ -29,6 +29,7 @@
#include "config.h"
#endif
#include <orc/orc.h>
#include <orc/orcinternal.h>
#if defined(__linux__)
#include <linux/auxvec.h>
......@@ -43,6 +44,14 @@
#define PPC_FEATURE_HAS_ALTIVEC 0x10000000
#endif
#ifndef PPC_FEATURE_HAS_VSX
#define PPC_FEATURE_HAS_VSX 0x00000080
#endif
#ifndef PPC_FEATURE2_ARCH_2_07
#define PPC_FEATURE2_ARCH_2_07 0x80000000
#endif
#endif
#if defined(__FreeBSD__) || defined(__APPLE__)
......@@ -57,6 +66,7 @@
#endif
/***** powerpc *****/
int orc_powerpc_cpu_flags;
#if 0
static unsigned long
......@@ -83,28 +93,24 @@ test_altivec (void * ignored)
#define SYSCTL "hw.altivec"
#endif
static unsigned long
orc_check_altivec_sysctl_bsd (void)
static void
orc_check_powerpc_sysctl_bsd (void)
{
unsigned long cpu_flags = 0;
int ret, vu;
size_t len;
len = sizeof(vu);
ret = sysctlbyname(SYSCTL, &vu, &len, NULL, 0);
if (!ret && vu) {
cpu_flags |= ORC_TARGET_ALTIVEC_ALTIVEC;
orc_powerpc_cpu_flags |= ORC_TARGET_POWERPC_ALTIVEC;
}
return cpu_flags;
}
#endif
#if defined(__OpenBSD__)
static unsigned long
orc_check_altivec_sysctl_openbsd (void)
static void
orc_check_powerpc_sysctl_openbsd (void)
{
unsigned long cpu_flags = 0;
int mib[2], ret, vu;
size_t len;
......@@ -114,94 +120,106 @@ orc_check_altivec_sysctl_openbsd (void)
len = sizeof(vu);
ret = sysctl(mib, 2, &vu, &len, NULL, 0);
if (!ret && vu) {
cpu_flags |= ORC_TARGET_ALTIVEC_ALTIVEC;
orc_powerpc_cpu_flags |= ORC_TARGET_POWERPC_ALTIVEC;
}
return cpu_flags;
}
#endif
#if defined(__linux__)
static unsigned long
orc_check_altivec_proc_auxv (void)
static void
orc_check_powerpc_proc_auxv (void)
{
unsigned long cpu_flags = 0;
static int available = -1;
int new_avail = 0;
unsigned long buf[64];
ssize_t count;
int fd, i;
/* Flags already set */
if (available != -1) {
return 0;
}
int fd, i, found = 0;
fd = open("/proc/self/auxv", O_RDONLY);
if (fd < 0) {
goto out;
}
more:
count = read(fd, buf, sizeof(buf));
if (count < 0) {
goto out_close;
}
for (i=0; i < (count / sizeof(unsigned long)); i += 2) {
if (buf[i] == AT_HWCAP) {
new_avail = !!(buf[i+1] & PPC_FEATURE_HAS_ALTIVEC);
goto out_close;
} else if (buf[i] == AT_NULL) {
goto out_close;
if (fd < 0)
return;
while (1) {
count = read(fd, buf, sizeof(buf));
if (count <= 0)
break;
for (i=0; i < (count / sizeof(unsigned long)); i += 2) {
if (buf[i] == AT_NULL)
break;
if (buf[i] == AT_HWCAP) {
if (buf[i + 1] & PPC_FEATURE_HAS_ALTIVEC)
orc_powerpc_cpu_flags |= ORC_TARGET_POWERPC_ALTIVEC;
if (buf[i + 1] & PPC_FEATURE_HAS_VSX)
orc_powerpc_cpu_flags |= ORC_TARGET_POWERPC_VSX;
found++;
}
if (buf[i] == AT_HWCAP2) {
if (buf[i + 1] & PPC_FEATURE2_ARCH_2_07)
orc_powerpc_cpu_flags |= ORC_TARGET_POWERPC_V207;
found++;
}
if (buf[i] == AT_PLATFORM) {
_orc_cpu_name = (char*)buf[i + 1];
found++;
}
if (buf[i] == AT_L1D_CACHESIZE) {
_orc_data_cache_size_level1 = buf[i + 1];
found++;
}
if (buf[i] == AT_L2_CACHESIZE) {
_orc_data_cache_size_level2 = buf[i + 1];
found++;
}
if (buf[i] == AT_L3_CACHESIZE) {
_orc_data_cache_size_level3 = buf[i + 1];
found++;
}
if (found == 6)
break;
}
}
if (count == sizeof(buf)) {
goto more;
}
out_close:
close(fd);
out:
available = new_avail;
if (available) {
cpu_flags |= ORC_TARGET_ALTIVEC_ALTIVEC;
}
return cpu_flags;
}
#endif
#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && !defined(__OpenBSD__) && !defined(__APPLE__) && !defined(__linux__)
static void
orc_check_altivec_fault (void)
orc_check_powerpc_fault (void)
{
orc_fault_check_enable ();
if (orc_fault_check_try(test_altivec, NULL)) {
ORC_DEBUG ("cpu flag altivec");
orc_cpu_flags |= ORC_IMPL_FLAG_ALTIVEC;
orc_powerpc_cpu_flags |= ORC_TARGET_POWERPC_ALTIVEC;
}
orc_fault_check_disable ();
}
#endif
void
orc_cpu_detect_arch(void)
powerpc_detect_cpu_flags (void)
{
static int inited = 0;
if (inited) return;
inited = 1;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
orc_check_altivec_sysctl_bsd();
orc_check_powerpc_sysctl_bsd();
#elif defined(__OpenBSD__)
orc_check_altivec_sysctl_openbsd();
orc_check_powerpc_sysctl_openbsd();
#elif defined(__linux__)
orc_check_altivec_proc_auxv();
orc_check_powerpc_proc_auxv();
#else
orc_check_altivec_fault();
orc_check_powerpc_fault();
#endif
/* _orc_profile_stamp = orc_profile_stamp_tb; */
if (orc_compiler_flag_check("-altivec")) {
orc_powerpc_cpu_flags &= ~ORC_TARGET_POWERPC_ALTIVEC;
}
if (orc_compiler_flag_check("-vsx")) {
orc_powerpc_cpu_flags &= ~ORC_TARGET_POWERPC_VSX;
}
if (orc_compiler_flag_check("-v207")) {
orc_powerpc_cpu_flags &= ~ORC_TARGET_POWERPC_V207;
}
}
......@@ -6,11 +6,6 @@
ORC_BEGIN_DECLS
typedef enum {
ORC_TARGET_POWERPC_64BIT = (1<<0),
ORC_TARGET_POWERPC_LE = (1<<1)
} OrcTargetPowerPCFlags;
#ifdef ORC_ENABLE_UNSTABLE_API
......@@ -94,6 +89,9 @@ enum {
POWERPC_V31
};
extern int orc_powerpc_cpu_flags;
void powerpc_detect_cpu_flags (void);
const char * powerpc_get_regname(int i);
int powerpc_regnum (int i);
......
......@@ -17,6 +17,7 @@ void orc_compiler_powerpc_register_rules (OrcTarget *target);
static void orc_compiler_powerpc_init (OrcCompiler *compiler);
static unsigned int orc_compiler_powerpc_get_default_flags (void);
static void orc_compiler_powerpc_assemble (OrcCompiler *compiler);
static const char* powerpc_get_flag_name (int shift);
static void
......@@ -79,7 +80,7 @@ static OrcTarget altivec_target = {
0,
NULL,
NULL,
NULL,
powerpc_get_flag_name,
orc_powerpc_flush_cache
};
......@@ -87,6 +88,14 @@ static OrcTarget altivec_target = {
void
orc_powerpc_init (void)
{
#ifdef HAVE_POWERPC
powerpc_detect_cpu_flags ();
if (!(orc_powerpc_cpu_flags & ORC_TARGET_POWERPC_ALTIVEC)) {
altivec_target.executable = FALSE;
}
#endif
orc_target_register (&altivec_target);
orc_compiler_powerpc_register_rules (&altivec_target);
......@@ -104,9 +113,31 @@ orc_compiler_powerpc_get_default_flags (void)
flags |= ORC_TARGET_POWERPC_LE;
#endif
#ifdef HAVE_POWERPC
flags |= orc_powerpc_cpu_flags;
#else
flags |= ORC_TARGET_POWERPC_ALTIVEC;
flags |= ORC_TARGET_POWERPC_VSX;
flags |= ORC_TARGET_POWERPC_V207;
#endif
return flags;
}
static const char *
powerpc_get_flag_name (int shift)
{
static const char *flags[] = {
"64bit", "le", "altivec", "vsx", "v2.07"
};
if (shift >= 0 && shift < sizeof(flags)/sizeof(flags[0])) {
return flags[shift];
}
return NULL;
}
static void
orc_compiler_powerpc_init (OrcCompiler *compiler)
{
......
......@@ -20,8 +20,12 @@ enum {
};
enum {
ORC_TARGET_ALTIVEC_ALTIVEC = (1<<0)
};
ORC_TARGET_POWERPC_64BIT = (1<<0),
ORC_TARGET_POWERPC_LE = (1<<1),
ORC_TARGET_POWERPC_ALTIVEC = (1<<2),
ORC_TARGET_POWERPC_VSX = (1<<3),
ORC_TARGET_POWERPC_V207 = (1<<4)
} OrcTargetPowerPCFlags;
enum {
ORC_TARGET_NEON_CLEAN_COMPILE = (1<<0),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment