summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2005-03-25 04:57:36 +0000
committerDavid Schleef <ds@schleef.org>2005-03-25 04:57:36 +0000
commit1aa4c1ea4b660e4f6cd885d98385f6799a1c3ed8 (patch)
tree2b167f1dc3643c0009aa413c756bb2c108d02baa
parent32d77a38dc0d84656d961c3ffbe4c11b9d2fa738 (diff)
downloadliboil-1aa4c1ea4b660e4f6cd885d98385f6799a1c3ed8.tar.gz
* liboil/liboilcpu.c: (get_proc_cpuinfo),
(oil_cpu_i386_getflags_cpuinfo), (get_cpuid), (oil_cpu_i386_getflags_cpuid), (oil_cpu_i386_getflags): Add support for getting flags from cpuid instruction directly. * liboil/liboilfunction.h: Add SSE3
-rw-r--r--ChangeLog8
-rw-r--r--liboil/liboilcpu.c100
-rw-r--r--liboil/liboilfunction.h1
3 files changed, 103 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index c7ffeb1..d820689 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2005-03-24 David Schleef <ds@schleef.org>
+
+ * liboil/liboilcpu.c: (get_proc_cpuinfo),
+ (oil_cpu_i386_getflags_cpuinfo), (get_cpuid),
+ (oil_cpu_i386_getflags_cpuid), (oil_cpu_i386_getflags): Add
+ support for getting flags from cpuid instruction directly.
+ * liboil/liboilfunction.h: Add SSE3
+
2005-03-17 David Schleef <ds@schleef.org>
* configure.ac: bump version
diff --git a/liboil/liboilcpu.c b/liboil/liboilcpu.c
index 1dcb308..ddf4962 100644
--- a/liboil/liboilcpu.c
+++ b/liboil/liboilcpu.c
@@ -50,7 +50,7 @@ static unsigned long oil_cpu_flags;
#if defined(__i386__)
static char *
-get_cpuinfo (void)
+get_proc_cpuinfo (void)
{
char *cpuinfo;
int fd;
@@ -71,16 +71,12 @@ get_cpuinfo (void)
#ifdef __i386__
static void
-oil_cpu_i386_getflags(void)
+oil_cpu_i386_getflags_cpuinfo (char *cpuinfo)
{
- char *cpuinfo;
char *cpuinfo_flags;
char **flags;
char **f;
- cpuinfo = get_cpuinfo();
- if (cpuinfo == NULL) return;
-
cpuinfo_flags = get_cpuinfo_flags_string(cpuinfo);
if (cpuinfo_flags == NULL) {
free (cpuinfo);
@@ -124,6 +120,98 @@ oil_cpu_i386_getflags(void)
free (cpuinfo);
free (cpuinfo_flags);
}
+
+static void
+get_cpuid (uint32_t op, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
+{
+ __asm__ (
+ " pushl %%ebx\n"
+ " cpuid\n"
+ " mov %%ebx, %%esi\n"
+ " popl %%ebx\n"
+ : "=a" (*a), "=S" (*b), "=c" (*c), "=d" (*d)
+ : "0" (op));
+}
+
+static void
+test_cpuid (void)
+{
+ uint32_t eax, ebx, ecx, edx;
+
+ get_cpuid (0x00000000, &eax, &ebx, &ecx, &edx);
+}
+
+static void
+oil_cpu_i386_getflags_cpuid (void)
+{
+ uint32_t eax, ebx, ecx, edx;
+ int level;
+ char vendor[13];
+
+ oil_cpu_fault_check_enable ();
+ if (!oil_cpu_fault_check_try(test_cpuid, NULL)) {
+ /* CPU thinks cpuid is an illegal instruction. */
+ return;
+ }
+ oil_cpu_fault_check_disable ();
+
+ get_cpuid (0x00000000, &level, (uint32_t *)(vendor+0),
+ (uint32_t *)(vendor+8), (uint32_t *)(vendor+4));
+
+ OIL_DEBUG("cpuid %d %s", level, vendor);
+
+ if (level < 1) {
+ return;
+ }
+
+ get_cpuid (0x00000001, &eax, &ebx, &ecx, &edx);
+
+ /* Intel flags */
+ if (edx & (1<<15)) {
+ oil_cpu_flags |= OIL_IMPL_FLAG_CMOV;
+ }
+ if (edx & (1<<23)) {
+ oil_cpu_flags |= OIL_IMPL_FLAG_MMX;
+ }
+ if (edx & (1<<25)) {
+ oil_cpu_flags |= OIL_IMPL_FLAG_SSE;
+ }
+ if (edx & (1<<26)) {
+ oil_cpu_flags |= OIL_IMPL_FLAG_SSE2;
+ }
+ if (ecx & (1<<0)) {
+ oil_cpu_flags |= OIL_IMPL_FLAG_SSE3;
+ }
+
+ if (memcmp (vendor, "AuthenticAMD", 12) == 0) {
+ get_cpuid (0x80000001, &eax, &ebx, &ecx, &edx);
+
+ /* AMD flags */
+ if (edx & (1<<22)) {
+ oil_cpu_flags |= OIL_IMPL_FLAG_MMXEXT;
+ }
+ if (edx & (1<<31)) {
+ oil_cpu_flags |= OIL_IMPL_FLAG_3DNOW;
+ }
+ if (edx & (1<<30)) {
+ oil_cpu_flags |= OIL_IMPL_FLAG_3DNOWEXT;
+ }
+ }
+}
+
+static void
+oil_cpu_i386_getflags(void)
+{
+ char *cpuinfo;
+
+ cpuinfo = get_proc_cpuinfo();
+ if (cpuinfo) {
+ oil_cpu_i386_getflags_cpuinfo(cpuinfo);
+ } else {
+ oil_cpu_i386_getflags_cpuid();
+ }
+}
+
#endif
#ifdef __powerpc__
diff --git a/liboil/liboilfunction.h b/liboil/liboilfunction.h
index 797bfa6..6baacbe 100644
--- a/liboil/liboilfunction.h
+++ b/liboil/liboilfunction.h
@@ -91,6 +91,7 @@ struct _OilFunctionImpl {
#define OIL_IMPL_FLAG_SSE2 (1<<20)
#define OIL_IMPL_FLAG_3DNOW (1<<21)
#define OIL_IMPL_FLAG_3DNOWEXT (1<<22)
+#define OIL_IMPL_FLAG_SSE3 (1<<23)
/* powerpc */
#define OIL_IMPL_FLAG_ALTIVEC (1<<16)