1
/* The GIMP -- an image manipulation program
2
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
* x86 bits Copyright (C) Manish Singh <yosh@gimp.org>
24
* PPC CPU acceleration detection was taken from DirectFB but seems to be
25
* originating from mpeg2dec with the following copyright:
27
* Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
38
#include "cpu-accel.h"
40
#if defined(ARCH_X86) && defined(USE_MMX) && defined(__GNUC__)
47
ARCH_X86_VENDOR_INTEL,
49
ARCH_X86_VENDOR_CENTAUR,
50
ARCH_X86_VENDOR_CYRIX,
52
ARCH_X86_VENDOR_TRANSMETA,
53
ARCH_X86_VENDOR_NEXGEN,
57
ARCH_X86_VENDOR_UNKNOWN = 0xff
62
ARCH_X86_INTEL_FEATURE_MMX = 1 << 23,
63
ARCH_X86_INTEL_FEATURE_XMM = 1 << 25,
64
ARCH_X86_INTEL_FEATURE_XMM2 = 1 << 26,
66
ARCH_X86_AMD_FEATURE_MMXEXT = 1 << 22,
67
ARCH_X86_AMD_FEATURE_3DNOW = 1 << 31,
69
ARCH_X86_CENTAUR_FEATURE_MMX = 1 << 23,
70
ARCH_X86_CENTAUR_FEATURE_MMXEXT = 1 << 24,
71
ARCH_X86_CENTAUR_FEATURE_3DNOW = 1 << 31,
73
ARCH_X86_CYRIX_FEATURE_MMX = 1 << 23,
74
ARCH_X86_CYRIX_FEATURE_MMXEXT = 1 << 24
77
#if !defined(ARCH_X86_64) && (defined(PIC) || defined(__PIC__))
78
#define cpuid(op,eax,ebx,ecx,edx) \
79
__asm__ ("movl %%ebx, %%esi\n\t" \
88
#define cpuid(op,eax,ebx,ecx,edx) \
99
arch_get_vendor (void)
101
guint32 eax, ebx, ecx, edx;
105
/* Only need to check this on ia32 */
106
__asm__ ("pushfl\n\t"
110
"xorl $0x200000,%0\n\t"
122
return ARCH_X86_VENDOR_NONE;
125
cpuid (0, eax, ebx, ecx, edx);
128
return ARCH_X86_VENDOR_NONE;
130
*(int *)&id[0] = ebx;
131
*(int *)&id[4] = edx;
132
*(int *)&id[8] = ecx;
137
if (strcmp (id, "AuthenticAMD") == 0)
138
return ARCH_X86_VENDOR_AMD;
139
else if (strcmp (id, "GenuineIntel") == 0)
140
return ARCH_X86_VENDOR_INTEL;
142
if (strcmp (id, "GenuineIntel") == 0)
143
return ARCH_X86_VENDOR_INTEL;
144
else if (strcmp (id, "AuthenticAMD") == 0)
145
return ARCH_X86_VENDOR_AMD;
146
else if (strcmp (id, "CentaurHauls") == 0)
147
return ARCH_X86_VENDOR_CENTAUR;
148
else if (strcmp (id, "CyrixInstead") == 0)
149
return ARCH_X86_VENDOR_CYRIX;
150
else if (strcmp (id, "Geode by NSC") == 0)
151
return ARCH_X86_VENDOR_NSC;
152
else if (strcmp (id, "GenuineTMx86") == 0 ||
153
strcmp (id, "TransmetaCPU") == 0)
154
return ARCH_X86_VENDOR_TRANSMETA;
155
else if (strcmp (id, "NexGenDriven") == 0)
156
return ARCH_X86_VENDOR_NEXGEN;
157
else if (strcmp (id, "RiseRiseRise") == 0)
158
return ARCH_X86_VENDOR_RISE;
159
else if (strcmp (id, "UMC UMC UMC ") == 0)
160
return ARCH_X86_VENDOR_UMC;
161
else if (strcmp (id, "SiS SiS SiS ") == 0)
162
return ARCH_X86_VENDOR_SIS;
165
return ARCH_X86_VENDOR_UNKNOWN;
169
arch_accel_intel (void)
175
guint32 eax, ebx, ecx, edx;
177
cpuid (1, eax, ebx, ecx, edx);
179
if ((edx & ARCH_X86_INTEL_FEATURE_MMX) == 0)
182
caps = CPU_ACCEL_X86_MMX;
185
if (edx & ARCH_X86_INTEL_FEATURE_XMM)
186
caps |= CPU_ACCEL_X86_SSE | CPU_ACCEL_X86_MMXEXT;
188
if (edx & ARCH_X86_INTEL_FEATURE_XMM2)
189
caps |= CPU_ACCEL_X86_SSE2;
198
arch_accel_amd (void)
202
caps = arch_accel_intel ();
206
guint32 eax, ebx, ecx, edx;
208
cpuid (0x80000000, eax, ebx, ecx, edx);
210
if (eax < 0x80000001)
214
cpuid (0x80000001, eax, ebx, ecx, edx);
216
if (edx & ARCH_X86_AMD_FEATURE_3DNOW)
217
caps |= CPU_ACCEL_X86_3DNOW;
219
if (edx & ARCH_X86_AMD_FEATURE_MMXEXT)
220
caps |= CPU_ACCEL_X86_MMXEXT;
229
arch_accel_centaur (void)
233
caps = arch_accel_intel ();
237
guint32 eax, ebx, ecx, edx;
239
cpuid (0x80000000, eax, ebx, ecx, edx);
241
if (eax < 0x80000001)
244
cpuid (0x80000001, eax, ebx, ecx, edx);
246
if (edx & ARCH_X86_CENTAUR_FEATURE_MMX)
247
caps |= CPU_ACCEL_X86_MMX;
250
if (edx & ARCH_X86_CENTAUR_FEATURE_3DNOW)
251
caps |= CPU_ACCEL_X86_3DNOW;
253
if (edx & ARCH_X86_CENTAUR_FEATURE_MMXEXT)
254
caps |= CPU_ACCEL_X86_MMXEXT;
263
arch_accel_cyrix (void)
267
caps = arch_accel_intel ();
271
guint32 eax, ebx, ecx, edx;
273
cpuid (0, eax, ebx, ecx, edx);
278
cpuid (0x80000001, eax, ebx, ecx, edx);
280
if (edx & ARCH_X86_CYRIX_FEATURE_MMX)
281
caps |= CPU_ACCEL_X86_MMX;
284
if (edx & ARCH_X86_CYRIX_FEATURE_MMXEXT)
285
caps |= CPU_ACCEL_X86_MMXEXT;
294
static jmp_buf sigill_return;
297
sigill_handler (gint n)
299
longjmp (sigill_return, 1);
303
arch_accel_sse_os_support (void)
305
if (setjmp (sigill_return))
311
signal (SIGILL, sigill_handler);
312
__asm__ __volatile__ ("xorps %xmm0, %xmm0");
313
signal (SIGILL, SIG_DFL);
326
vendor = arch_get_vendor ();
330
case ARCH_X86_VENDOR_NONE:
334
case ARCH_X86_VENDOR_AMD:
335
caps = arch_accel_amd ();
338
case ARCH_X86_VENDOR_CENTAUR:
339
caps = arch_accel_centaur ();
342
case ARCH_X86_VENDOR_CYRIX:
343
case ARCH_X86_VENDOR_NSC:
344
caps = arch_accel_cyrix ();
347
/* check for what Intel speced, even if UNKNOWN */
349
caps = arch_accel_intel ();
354
if ((caps & CPU_ACCEL_X86_SSE) && !arch_accel_sse_os_support ())
355
caps &= ~(CPU_ACCEL_X86_SSE | CPU_ACCEL_X86_SSE2);
361
#endif /* ARCH_X86 && USE_MMX && __GNUC__ */
364
#if defined (ARCH_PPC) && defined (USE_ALTIVEC) && defined(__GNUC__)
368
static sigjmp_buf jmpbuf;
369
static volatile sig_atomic_t canjump = 0;
372
sigill_handler (gint sig)
376
signal (sig, SIG_DFL);
381
siglongjmp (jmpbuf, 1);
387
signal (SIGILL, sigill_handler);
389
if (sigsetjmp (jmpbuf, 1))
391
signal (SIGILL, SIG_DFL);
397
asm volatile ("mtspr 256, %0\n\t"
398
"vand %%v0, %%v0, %%v0"
402
signal (SIGILL, SIG_DFL);
404
return CPU_ACCEL_PPC_ALTIVEC;
407
#endif /* ARCH_PPC && USE_ALTIVEC && __GNUC__ */
414
static guint32 accel = ~0U;
419
accel = arch_accel ();
423
#else /* !HAVE_ACCEL */
429
cpu_accel_print_results (void)
431
g_printerr ("Testing CPU features...\n");
434
g_printerr (" mmx : %s\n",
435
(cpu_accel() & CPU_ACCEL_X86_MMX) ? "yes" : "no");
436
g_printerr (" 3dnow : %s\n",
437
(cpu_accel() & CPU_ACCEL_X86_3DNOW) ? "yes" : "no");
438
g_printerr (" mmxext : %s\n",
439
(cpu_accel() & CPU_ACCEL_X86_MMXEXT) ? "yes" : "no");
440
g_printerr (" sse : %s\n",
441
(cpu_accel() & CPU_ACCEL_X86_SSE) ? "yes" : "no");
442
g_printerr (" sse2 : %s\n",
443
(cpu_accel() & CPU_ACCEL_X86_SSE2) ? "yes" : "no");
446
g_printerr (" altivec : %s\n",
447
(cpu_accel() & CPU_ACCEL_PPC_ALTIVEC) ? "yes" : "no");