redone target platform detection and MMX assembly checks. Basically copied

2003-07-04  Sven Neumann  <sven@gimp.org>

	* configure.in: redone target platform detection and MMX assembly
	checks. Basically copied from DirectFB.

	* app/Makefile.am
	* app/arch/i386/mmx/detect_mmx.S
	* app/arch/i386/mmx/paint_funcs_mmx.S
	* app/paint-funcs/Makefile.am
	* app/paint-funcs/paint-funcs-mmx.h
	* app/paint-funcs/paint-funcs-simd.S: removed the old MMX routines.
	New ones will come instead.

	* app/base/Makefile.am
	* app/base/detect-mmx.[Sh]: removed these two files...

	* app/base/cpu-accel.[ch]: ... and added new ones that do more
	fine-grained cpu acceleration detection. Again taken from DirectFB
	but the code is originally from mpeg2dec.

	* app/base/base.c: print results from cpu feature tests.
This commit is contained in:
Sven Neumann 2003-07-04 00:31:05 +00:00 committed by Sven Neumann
parent 6bbec4dd45
commit 54adf6ffac
16 changed files with 611 additions and 1881 deletions

View File

@ -1,3 +1,25 @@
2003-07-04 Sven Neumann <sven@gimp.org>
* configure.in: redone target platform detection and MMX assembly
checks. Basically copied from DirectFB.
* app/Makefile.am
* app/arch/i386/mmx/detect_mmx.S
* app/arch/i386/mmx/paint_funcs_mmx.S
* app/paint-funcs/Makefile.am
* app/paint-funcs/paint-funcs-mmx.h
* app/paint-funcs/paint-funcs-simd.S: removed the old MMX routines.
New ones will come instead.
* app/base/Makefile.am
* app/base/detect-mmx.[Sh]: removed these two files...
* app/base/cpu-accel.[ch]: ... and added new ones that do more
fine-grained cpu acceleration detection. Again taken from DirectFB
but the code is originally from mpeg2dec.
* app/base/base.c: print results from cpu feature tests.
2003-07-04 Dave Neary <bolsh@gimp.org>
* app/core/gimpdrawable-bucket-fill.c: Add alpha channel

View File

@ -26,24 +26,22 @@ scriptdata =
bin_PROGRAMS = gimp-1.3
gimp_1_3_SOURCES = \
appenv.h \
app_procs.c \
app_procs.h \
main.c \
batch.c \
batch.h \
errors.c \
errors.h \
gimp-intl.h \
libgimp_glue.c \
appenv.h \
app_procs.c \
app_procs.h \
main.c \
batch.c \
batch.h \
errors.c \
errors.h \
gimp-intl.h \
libgimp_glue.c \
libgimp_glue.h
EXTRA_DIST = \
makefile.msc \
gimp.rc \
wilber.ico \
arch/i386/mmx/detect_mmx.S \
arch/i386/mmx/paint_funcs_mmx.S
makefile.msc \
gimp.rc \
wilber.ico
if HAVE_GLIBC_REGEX
REGEXREPL =

View File

@ -1,63 +0,0 @@
.data
cpu_flags: .long 0
.text
.align 4
#ifndef __MINGW32__
.globl intel_cpu_features
.type intel_cpu_features,@function
intel_cpu_features:
#else
.globl _intel_cpu_features
_intel_cpu_features:
#endif
pushl %ebx
pushfl
popl %eax
movl %eax,%ecx
xorl $0x040000,%eax
pushl %eax
popfl
pushfl
popl %eax
xorl %ecx,%eax
jz .intel_cpu_features_end # Processor is 386
pushl %ecx
popfl
movl %ecx,%eax
xorl $0x200000,%eax
pushl %eax
popfl
pushfl
popl %eax
xorl %ecx,%eax
je .intel_cpu_features_end
pushal
movl $1,%eax
cpuid
movl %edx,cpu_flags
popal
movl cpu_flags,%eax
.intel_cpu_features_end:
popl %ebx
ret

File diff suppressed because it is too large Load Diff

View File

@ -2,12 +2,6 @@
noinst_LIBRARIES = libappbase.a
if HAVE_ASM_MMX
mmx_sources = detect-mmx.S
else
mmx_sources =
endif
libappbase_a_SOURCES = \
base.c \
base.h \
@ -24,8 +18,8 @@ libappbase_a_SOURCES = \
colorize.h \
curves.c \
curves.h \
$(mmx_sources) \
detect-mmx.h \
cpu-accel.c \
cpu-accel.h \
gimphistogram.c \
gimphistogram.h \
gimplut.c \

View File

@ -41,7 +41,7 @@
#include "paint-funcs/paint-funcs.h"
#include "base.h"
#include "detect-mmx.h"
#include "cpu-accel.h"
#include "temp-buf.h"
#include "tile-cache.h"
#include "tile-swap.h"
@ -71,11 +71,24 @@ base_init (GimpBaseConfig *config,
base_config = config;
#ifdef ENABLE_MMX
#ifdef HAVE_ASM_MMX
use_mmx = use_mmx && (intel_cpu_features() & (1 << 23)) ? 1 : 0;
g_print ("using MMX: %s\n", use_mmx ? "yes" : "no");
#ifdef USE_MMX
if (use_mmx)
{
#ifdef ARCH_X86
g_printerr ("Testing CPU features...\n");
g_printerr (" mmx : %s\n",
(cpu_accel() & CPU_ACCEL_X86_MMX) ? "yes" : "no");
g_printerr (" 3dnow : %s\n",
(cpu_accel() & CPU_ACCEL_X86_3DNOW) ? "yes" : "no");
g_printerr (" mmxext : %s\n",
(cpu_accel() & CPU_ACCEL_X86_MMXEXT) ? "yes" : "no");
g_printerr (" sse : %s\n",
(cpu_accel() & CPU_ACCEL_X86_SSE) ? "yes" : "no");
g_printerr (" sse2 : %s\n",
(cpu_accel() & CPU_ACCEL_X86_SSE2) ? "yes" : "no");
g_printerr ("\n");
#endif
}
#endif
tile_cache_init (config->tile_cache_size);

203
app/base/cpu-accel.c Normal file
View File

@ -0,0 +1,203 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* CPU acceleration detection was taken from DirectFB but seems to be
* originating from mpeg2dec with the following copyright:
*
* Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
*/
#include "config.h"
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <glib.h>
#include "cpu-accel.h"
#ifdef ARCH_X86
static guint32
arch_accel (void)
{
guint32 eax, ebx, ecx, edx;
gint AMD;
guint32 caps = 0;
#define cpuid(op,eax,ebx,ecx,edx) \
asm ("pushl %%ebx\n\t" \
"cpuid\n\t" \
"movl %%ebx,%1\n\t" \
"popl %%ebx" \
: "=a" (eax), \
"=r" (ebx), \
"=c" (ecx), \
"=d" (edx) \
: "a" (op) \
: "cc")
asm ("pushfl\n\t"
"pushfl\n\t"
"popl %0\n\t"
"movl %0,%1\n\t"
"xorl $0x200000,%0\n\t"
"pushl %0\n\t"
"popfl\n\t"
"pushfl\n\t"
"popl %0\n\t"
"popfl"
: "=r" (eax),
"=r" (ebx)
:
: "cc");
if (eax == ebx) /* no cpuid */
return 0;
cpuid (0x00000000, eax, ebx, ecx, edx);
if (!eax) /* vendor string only */
return 0;
AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
cpuid (0x00000001, eax, ebx, ecx, edx);
if (! (edx & 0x00800000)) /* no MMX */
return 0;
#ifdef USE_MMX
caps = CPU_ACCEL_X86_MMX;
#ifdef USE_SSE
if (edx & 0x02000000) /* SSE - identical to AMD MMX extensions */
caps |= CPU_ACCEL_X86_SSE | CPU_ACCEL_X86_MMXEXT;
if (edx & 0x04000000) /* SSE2 */
caps |= CPU_ACCEL_X86_SSE2;
cpuid (0x80000000, eax, ebx, ecx, edx);
if (eax < 0x80000001) /* no extended capabilities */
return caps;
cpuid (0x80000001, eax, ebx, ecx, edx);
if (edx & 0x80000000)
caps |= CPU_ACCEL_X86_3DNOW;
if (AMD && (edx & 0x00400000)) /* AMD MMX extensions */
caps |= CPU_ACCEL_X86_MMXEXT;
#endif /* USE_SSE */
#endif /* USE_MMX */
return caps;
}
static jmp_buf sigill_return;
static void
sigill_handler (gint n)
{
g_printerr ("OS lacks support for SSE instructions.\n");
longjmp(sigill_return, 1);
}
#endif /* ARCH_X86 */
#if defined (ARCH_PPC) && defined (ENABLE_ALTIVEC)
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjump = 0;
static void
sigill_handler (gint sig)
{
if (!canjump)
{
signal (sig, SIG_DFL);
raise (sig);
}
canjump = 0;
siglongjmp (jmpbuf, 1);
}
static guint32 arch_accel (void)
{
signal (SIGILL, sigill_handler);
if (sigsetjmp (jmpbuf, 1))
{
signal (SIGILL, SIG_DFL);
return 0;
}
canjump = 1;
asm volatile ("mtspr 256, %0\n\t"
"vand %%v0, %%v0, %%v0"
:
: "r" (-1));
signal (SIGILL, SIG_DFL);
return CPU_ACCEL_PPC_ALTIVEC;
}
#endif /* ARCH_PPC */
guint32
cpu_accel (void)
{
#if defined (ARCH_X86) || (defined (ARCH_PPC) && defined (ENABLE_ALTIVEC))
static guint32 accel = ~0U;
if (accel != ~0U)
return accel;
accel = arch_accel ();
#ifdef USE_SSE
/* test OS support for SSE */
if (accel & CPU_ACCEL_X86_SSE)
{
if (setjmp (sigill_return))
{
accel &= ~(CPU_ACCEL_X86_SSE | CPU_ACCEL_X86_SSE2);
}
else
{
signal (SIGILL, sigill_handler);
__asm __volatile ("xorps %xmm0, %xmm0");
signal (SIGILL, SIG_DFL);
}
}
#endif /* USE_SSE */
return accel;
#else /* !ARCH_X86 && !ARCH_PPC/ENABLE_ALTIVEC */
#ifdef HAVE_MLIB
return CPU_ACCEL_MLIB;
#else
return 0;
#endif
#endif /* !ARCH_X86 && !ARCH_PPC/ENABLE_ALTIVEC */
}

View File

@ -16,13 +16,33 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __DETECT_MMX_H__
#define __DETECT_MMX_H__
/*
* CPU acceleration detection was taken from DirectFB but seems to be
* originating from mpeg2dec with the following copyright:
*
* Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
*/
#ifndef __CPU_ACCEL_H__
#define __CPU_ACCEL_H__
#ifdef HAVE_ASM_MMX
gulong intel_cpu_features (void);
#endif
/* generic accelerations */
#define CPU_ACCEL_MLIB 0x00000001
/* x86 accelerations */
#define CPU_ACCEL_X86_MMX 0x80000000
#define CPU_ACCEL_X86_3DNOW 0x40000000
#define CPU_ACCEL_X86_MMXEXT 0x20000000
#define CPU_ACCEL_X86_SSE 0x10000000
#define CPU_ACCEL_X86_SSE2 0x08000000
/* powerpc accelerations */
#define CPU_ACCEL_PPC_ALTIVEC 0x04000000
#endif /* __DETECT_MMX__ */
guint32 cpu_accel (void) G_GNUC_CONST;
#endif /* __CPU_ACCEL_H__ */

View File

@ -1,5 +0,0 @@
#include "config.h"
#ifdef HAVE_ASM_MMX
#include "arch/i386/mmx/detect_mmx.S"
#endif

View File

@ -2,19 +2,11 @@
noinst_LIBRARIES = libapppaint-funcs.a
if HAVE_ASM_MMX
mmx_sources = paint-funcs-simd.S
else
mmx_sources =
endif
libapppaint_funcs_a_SOURCES = \
paint-funcs-types.h \
paint-funcs.c \
paint-funcs.h \
paint-funcs-generic.h \
paint-funcs-mmx.h \
$(mmx_sources)
paint-funcs-generic.h
INCLUDES = \
-I$(top_srcdir) \

View File

@ -1,137 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* This file is supposed to contain the MMX implementation of the
* pixelfiddeling paint-functions.
*/
#ifndef __PAINT_FUNCS_MMX_H__
#define __PAINT_FUNCS_MMX_H__
/* FIXME: Needs a bigger overhaul. Maybe inline assembly would be better?
* 'bigger overhaul' indeed, but let's not talk about assembly language now (Nov-03-2002)
* This code is being disabled to address Bug #86290; point your favorite browser to
* http://bugzilla.gnome.org/show_bug.cgi?id=86290 for the reason this is being done.
* Presuming you've read the "Additional Comments" there, and really, really, think that
* Gimp ought to have this MMX code, RIGHT NOW (!) then this is what I believe you have to do:
* 1. Be aware that the MMX code is incomplete; the macro USE_MMX_PIXEL_OP_3A_1A has been
* written the way it has so that the MMX code is invoked only on region depths it knows
* how to handle. In that case, the MMX code executes and the macro performs a return to
* caller. Otherwise, it DOES NOT DO ANYTHING, and the macro ought to be followed by
* code that had better do something. Check out an archival app/paint_funcs/paint_funcs.c
* say, CVS version 1.98 (Nov 2, 2001) and study how USE_MMX_PIXEL_OP_3A_1A was used there;
* you'll discover that it must have some kind of alternate code following in case program
* flow does not return to the caller inside the macro.
* 2a. For this reason, you have to pretty much undo the separation of 'generic C' and 'mmx' code at
* at the heart of Nov-18-2001, Nov-19-2001 check-ins (See Daniel Egger's comments in
* ChangeLog). That, or replicate the 'generic C' in the various *_mmx functions implemented
* in this header file, below. Not only would that make the separation effort rather pointless, but
* the replication of functionality creates a maintenance problem.
* 2b. Alternatively, you can finish the MMX code so that it handles all cases that the generic
* C does. This is ideal, and makes sensible the separation effort, for then USE_MMX_PIXEL_OP_3A_1A
* need not have any additional implementation following. For that matter, you'd likely not
* even need the macro. You'd also be a better man than I am, Gunga Din.
* Whatever you do, proceed carefully and keep fresh batteries in your electric torch: there be monsters here.
* grosgood@rcn.com
*/
#ifdef HAVE_ASM_MMX
#if GIMP_ENABLE_MMX
#define MMX_PIXEL_OP(x) \
void \
x( \
const guchar *src1, \
const guchar *src2, \
guint count, \
guchar *dst) __attribute((regparm(3)));
#define MMX_PIXEL_OP_3A_1A(op) \
MMX_PIXEL_OP(op##_pixels_3a_3a) \
MMX_PIXEL_OP(op##_pixels_1a_1a)
#define USE_MMX_PIXEL_OP_3A_1A(op) \
if (HAS_ALPHA (alms->bytes1) && HAS_ALPHA (alms->bytes2)) \
{ \
if (alms->bytes1==2 && alms->bytes2==2) \
return op##_pixels_1a_1a(alms->src1, alms->src2, alms->length, *(alms->dest)); \
if (alms->bytes1==4 && alms->bytes2==4) \
return op##_pixels_3a_3a(alms->src1, alms->src2, alms->length, *(alms->dest)); \
}
MMX_PIXEL_OP_3A_1A(multiply);
static void
layer_multiply_mode_mmx (struct apply_layer_mode_struct *alms)
{
USE_MMX_PIXEL_OP_3A_1A(multiply);
}
MMX_PIXEL_OP_3A_1A(screen);
static void
layer_screen_mode_mmx (struct apply_layer_mode_struct *alms)
{
USE_MMX_PIXEL_OP_3A_1A(screen);
}
MMX_PIXEL_OP_3A_1A(overlay);
static void
layer_overlay_mode_mmx (struct apply_layer_mode_struct *alms)
{
USE_MMX_PIXEL_OP_3A_1A(overlay);
}
MMX_PIXEL_OP_3A_1A(difference);
static void
layer_difference_mode_mmx (struct apply_layer_mode_struct *alms)
{
USE_MMX_PIXEL_OP_3A_1A(difference);
}
MMX_PIXEL_OP_3A_1A(add);
static void
layer_addition_mode_mmx (struct apply_layer_mode_struct *alms)
{
USE_MMX_PIXEL_OP_3A_1A(add);
}
MMX_PIXEL_OP_3A_1A(substract);
static void
layer_subtract_mode_mmx (struct apply_layer_mode_struct *alms)
{
USE_MMX_PIXEL_OP_3A_1A(substract);
}
MMX_PIXEL_OP_3A_1A(darken);
static void
layer_darken_only_mode_mmx (struct apply_layer_mode_struct *alms)
{
USE_MMX_PIXEL_OP_3A_1A(darken);
}
MMX_PIXEL_OP_3A_1A(lighten);
static void
layer_lighten_only_mode_mmx (struct apply_layer_mode_struct *alms)
{
USE_MMX_PIXEL_OP_3A_1A(lighten);
}
#endif /* GIMP_ENABLE_MMX */
#endif /* HAVE_ASM_MMX */
#endif /* __PAINT_FUNCS_MMX_H__ */

View File

@ -1,5 +0,0 @@
#include "config.h"
#ifdef HAVE_ASM_MMX
#include "arch/i386/mmx/paint_funcs_mmx.S"
#endif

View File

@ -36,7 +36,6 @@
#include "paint-funcs.h"
#include "paint-funcs-generic.h"
#include "paint-funcs-mmx.h"
#define RANDOM_SEED 314159265
#define EPSILON 0.0001
@ -447,26 +446,6 @@ paint_funcs_setup (gboolean use_mmx)
for (i = 256; i <= 510; i++)
add_lut[i] = 255;
/* *_mmx functions are problematical. See "Additional Comments: Bug #86290"
* http://bugzilla.gnome.org/show_bug.cgi?id=86290 grosgood@rcn.com Nov-03-2002
*/
#ifdef HAVE_ASM_MMX
#if GIMP_ENABLE_MMX
if (use_mmx)
{
layer_mode_funcs[GIMP_DIFFERENCE_MODE] = layer_difference_mode_mmx;
layer_mode_funcs[GIMP_ADDITION_MODE] = layer_addition_mode_mmx;
layer_mode_funcs[GIMP_SUBTRACT_MODE] = layer_subtract_mode_mmx;
layer_mode_funcs[GIMP_OVERLAY_MODE] = layer_overlay_mode_mmx;
layer_mode_funcs[GIMP_SCREEN_MODE] = layer_screen_mode_mmx;
layer_mode_funcs[GIMP_MULTIPLY_MODE] = layer_multiply_mode_mmx;
layer_mode_funcs[GIMP_DARKEN_ONLY_MODE] = layer_darken_only_mode_mmx;
layer_mode_funcs[GIMP_LIGHTEN_ONLY_MODE] = layer_lighten_only_mode_mmx;
}
#endif /* GIMP_ENABLE_MMX */
#endif /* HAVE_ASM_MMX */
g_rand_free (gr);
}

View File

@ -92,13 +92,40 @@ AC_LIBTOOL_WIN32_DLL
AC_PROG_LIBTOOL
###########################
# Check target architecture
###########################
AC_MSG_CHECKING([for target architecture])
case x"$target" in
xNONE | x)
target_or_host="$host" ;;
*)
target_or_host="$target" ;;
esac
AC_MSG_RESULT([$target_or_host])
case "$target_or_host" in
i*86-*-*)
have_x86=yes
AC_DEFINE(ARCH_X86, 1, [Define to 1 if you are compiling for ix86.])
;;
ppc-*-linux* | powerpc-*)
have_ppc=yes
AC_DEFINE(ARCH_PPC, 1, [Define to 1 if you are compiling for PowerPC.])
;;
*)
;;
esac
#################
# Check for Win32
#################
AC_MSG_CHECKING([for some Win32 platform])
case "$host" in
*-*-mingw*|*-*-cygwin*)
case "$target_or_host" in
*-*-mingw* | *-*-cygwin*)
platform_win32=yes
;;
*)
@ -109,7 +136,7 @@ AC_MSG_RESULT([$platform_win32])
AM_CONDITIONAL(PLATFORM_WIN32, test "$platform_win32" = "yes")
AC_MSG_CHECKING([for native Win32])
case "$host" in
case "$target_or_host" in
*-*-mingw*)
os_win32=yes
PATHSEP=';'
@ -368,50 +395,61 @@ AC_SUBST(SOCKET_LIBS)
# Check for MMX assembly
########################
have_asm_mmx=false
AC_MSG_CHECKING([for Intel Pentium architecture (IA32)])
if test "$host_cpu" = "i386" -o "$host_cpu" = "i486"\
-o "$host_cpu" = "i586" -o "$host_cpu" = "i586"\
-o "$host_cpu" = "i686" -o "$host_cpu" = "i786" ;
then
AC_MSG_RESULT(yes)
AC_MSG_CHECKING([for support for gcc-style register parameters on Intel])
AC_TRY_COMPILE([],
[extern void x(
const unsigned char *src1,
const unsigned char *src2,
unsigned count,
unsigned char *dst) __attribute((regparm(3)));],
AC_ARG_ENABLE(mmx,
[ --enable-mmx enable MMX support (default=auto)],,
enable_mmx=$have_x86)
[AC_MSG_RESULT(yes)
AC_ARG_ENABLE(sse,
[ --enable-sse enable SSE support (default=auto)],,
enable_sse=$have_x86)
AC_MSG_CHECKING([for support for MMX in assembly code])
cat > conftest.S <<EOF
.text
if test "x$enable_mmx" = xyes; then
psubusb %mm3, %mm4
EOF
dnl Necessary for assembler sources
save_ac_ext="$ac_ext"
ac_ext=S
if $CC -c conftest.S ; then
AC_MSG_CHECKING(whether the binutils support MMX)
echo " movq 0, %mm0" > conftest.S
if AC_TRY_EVAL(ac_compile); then
AC_DEFINE(USE_MMX, 1, [Define to 1 if MMX assembly is available.])
AC_MSG_RESULT(yes)
AC_MSG_CHECKING(whether the binutils support SSE)
echo " movntps %xmm0, 0" > conftest.S
if AC_TRY_EVAL(ac_compile); then
AC_DEFINE(USE_SSE, 1, [Define to 1 if SSE assembly is available.])
AC_MSG_RESULT(yes)
rm -f conftest.*
AC_DEFINE(HAVE_ASM_MMX, 1,
[Define to 1 if MMX in assembly is supported.])
AC_DEFINE(GIMP_ENABLE_MMX, 0, [Define to 1 to compile MMX code into paint-funcs. But read report for Bug 86290 first] )
have_asm_mmx=true
else
enable_sse=no
AC_MSG_RESULT(no)
echo "configure: failed program was:" >&AC_FD_CC
cat conftest.S >&AC_FD_CC
rm -rf conftest.* ;
AC_MSG_WARN([
****************************************************************
The installed assembler does not supports the SSE command set.
Update your binutils package, if you want to compile SSE code.
****************************************************************])
fi
],
[AC_MSG_RESULT(no)
AC_MSG_WARN(*** C compiler does not support __attribute((regparm(3))), MMX code will not be built)]);
else
enable_mmx=no
AC_MSG_RESULT(no)
AC_MSG_WARN([
****************************************************************
The installed assembler does not supports the MMX command set.
Update your binutils package, if you want to compile MMX code.
****************************************************************])
fi
rm conftest*
ac_ext="$save_ac_ext"
else
AC_MSG_RESULT(no) ;
enable_sse=no
fi
AM_CONDITIONAL(HAVE_ASM_MMX, test x$have_asm_mmx = xtrue)
AM_CONDITIONAL(HAVE_ASM_MMX, test x$enable_mmx = xyes)
###################################

203
libgimpbase/gimpcpuaccel.c Normal file
View File

@ -0,0 +1,203 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* CPU acceleration detection was taken from DirectFB but seems to be
* originating from mpeg2dec with the following copyright:
*
* Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
*/
#include "config.h"
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <glib.h>
#include "cpu-accel.h"
#ifdef ARCH_X86
static guint32
arch_accel (void)
{
guint32 eax, ebx, ecx, edx;
gint AMD;
guint32 caps = 0;
#define cpuid(op,eax,ebx,ecx,edx) \
asm ("pushl %%ebx\n\t" \
"cpuid\n\t" \
"movl %%ebx,%1\n\t" \
"popl %%ebx" \
: "=a" (eax), \
"=r" (ebx), \
"=c" (ecx), \
"=d" (edx) \
: "a" (op) \
: "cc")
asm ("pushfl\n\t"
"pushfl\n\t"
"popl %0\n\t"
"movl %0,%1\n\t"
"xorl $0x200000,%0\n\t"
"pushl %0\n\t"
"popfl\n\t"
"pushfl\n\t"
"popl %0\n\t"
"popfl"
: "=r" (eax),
"=r" (ebx)
:
: "cc");
if (eax == ebx) /* no cpuid */
return 0;
cpuid (0x00000000, eax, ebx, ecx, edx);
if (!eax) /* vendor string only */
return 0;
AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
cpuid (0x00000001, eax, ebx, ecx, edx);
if (! (edx & 0x00800000)) /* no MMX */
return 0;
#ifdef USE_MMX
caps = CPU_ACCEL_X86_MMX;
#ifdef USE_SSE
if (edx & 0x02000000) /* SSE - identical to AMD MMX extensions */
caps |= CPU_ACCEL_X86_SSE | CPU_ACCEL_X86_MMXEXT;
if (edx & 0x04000000) /* SSE2 */
caps |= CPU_ACCEL_X86_SSE2;
cpuid (0x80000000, eax, ebx, ecx, edx);
if (eax < 0x80000001) /* no extended capabilities */
return caps;
cpuid (0x80000001, eax, ebx, ecx, edx);
if (edx & 0x80000000)
caps |= CPU_ACCEL_X86_3DNOW;
if (AMD && (edx & 0x00400000)) /* AMD MMX extensions */
caps |= CPU_ACCEL_X86_MMXEXT;
#endif /* USE_SSE */
#endif /* USE_MMX */
return caps;
}
static jmp_buf sigill_return;
static void
sigill_handler (gint n)
{
g_printerr ("OS lacks support for SSE instructions.\n");
longjmp(sigill_return, 1);
}
#endif /* ARCH_X86 */
#if defined (ARCH_PPC) && defined (ENABLE_ALTIVEC)
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjump = 0;
static void
sigill_handler (gint sig)
{
if (!canjump)
{
signal (sig, SIG_DFL);
raise (sig);
}
canjump = 0;
siglongjmp (jmpbuf, 1);
}
static guint32 arch_accel (void)
{
signal (SIGILL, sigill_handler);
if (sigsetjmp (jmpbuf, 1))
{
signal (SIGILL, SIG_DFL);
return 0;
}
canjump = 1;
asm volatile ("mtspr 256, %0\n\t"
"vand %%v0, %%v0, %%v0"
:
: "r" (-1));
signal (SIGILL, SIG_DFL);
return CPU_ACCEL_PPC_ALTIVEC;
}
#endif /* ARCH_PPC */
guint32
cpu_accel (void)
{
#if defined (ARCH_X86) || (defined (ARCH_PPC) && defined (ENABLE_ALTIVEC))
static guint32 accel = ~0U;
if (accel != ~0U)
return accel;
accel = arch_accel ();
#ifdef USE_SSE
/* test OS support for SSE */
if (accel & CPU_ACCEL_X86_SSE)
{
if (setjmp (sigill_return))
{
accel &= ~(CPU_ACCEL_X86_SSE | CPU_ACCEL_X86_SSE2);
}
else
{
signal (SIGILL, sigill_handler);
__asm __volatile ("xorps %xmm0, %xmm0");
signal (SIGILL, SIG_DFL);
}
}
#endif /* USE_SSE */
return accel;
#else /* !ARCH_X86 && !ARCH_PPC/ENABLE_ALTIVEC */
#ifdef HAVE_MLIB
return CPU_ACCEL_MLIB;
#else
return 0;
#endif
#endif /* !ARCH_X86 && !ARCH_PPC/ENABLE_ALTIVEC */
}

View File

@ -0,0 +1,48 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* CPU acceleration detection was taken from DirectFB but seems to be
* originating from mpeg2dec with the following copyright:
*
* Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
*/
#ifndef __CPU_ACCEL_H__
#define __CPU_ACCEL_H__
/* generic accelerations */
#define CPU_ACCEL_MLIB 0x00000001
/* x86 accelerations */
#define CPU_ACCEL_X86_MMX 0x80000000
#define CPU_ACCEL_X86_3DNOW 0x40000000
#define CPU_ACCEL_X86_MMXEXT 0x20000000
#define CPU_ACCEL_X86_SSE 0x10000000
#define CPU_ACCEL_X86_SSE2 0x08000000
/* powerpc accelerations */
#define CPU_ACCEL_PPC_ALTIVEC 0x04000000
guint32 cpu_accel (void) G_GNUC_CONST;
#endif /* __CPU_ACCEL_H__ */