diff options
author | David Schleef <ds@schleef.org> | 2005-03-25 04:57:36 +0000 |
---|---|---|
committer | David Schleef <ds@schleef.org> | 2005-03-25 04:57:36 +0000 |
commit | 1aa4c1ea4b660e4f6cd885d98385f6799a1c3ed8 (patch) | |
tree | 2b167f1dc3643c0009aa413c756bb2c108d02baa | |
parent | 32d77a38dc0d84656d961c3ffbe4c11b9d2fa738 (diff) | |
download | liboil-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-- | ChangeLog | 8 | ||||
-rw-r--r-- | liboil/liboilcpu.c | 100 | ||||
-rw-r--r-- | liboil/liboilfunction.h | 1 |
3 files changed, 103 insertions, 6 deletions
@@ -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) |