SDL_gfx: SDL_imageFilter.c Source File

- Main Page
- Data Structures
- Files

- File List
- Globals

# SDL_imageFilter.c

Go to the documentation of this file.

    00001 /*
    00002
    00003 SDL_imageFilter - bytes-image "filter" routines.
    00004 (Uses inline x86 MMX or ASM optimizations if available and enabled.)
    00005
    00006 LGPL (c) A. Schiffler
    00007
    00008 Note: Most of the MMX code is based on published routines
    00009 by Vladimir Kravtchenko at vk@cs.ubc.ca - credits go to
    00010 him for his work.
    00011
    00012 */
    00013
    00014 #include <stdio.h>
    00015 #include <stdlib.h>
    00016 #include <string.h>
    00017
    00018 #include "SDL_imageFilter.h"
    00019
    00023 #define SWAP_32(x) (((x) >> 24) | (((x) & 0x00ff0000) >> 8)  | (((x) & 0x0000ff00) << 8)  | ((x) << 24))
    00024
    00025 /* ------ Static variables ----- */
    00026
    00030 static int SDL_imageFilterUseMMX = 1;
    00031
    00032 /* Detect GCC */
    00033 #if defined(__GNUC__)
    00034 #define GCC__
    00035 #endif
    00036
    00042 unsigned int _cpuFlags()
    00043 {
    00044         int flags = 0;
    00045
    00046 #ifdef USE_MMX
    00047 #if !defined(GCC__)
    00048         __asm
    00049         {
    00050                 pusha
    00051                         mov eax, 1
    00052                         cpuid   /* get CPU ID flag */
    00053                         mov flags,edx   /* move result to mmx_bit */
    00054                         popa
    00055         }
    00056 #else
    00057         asm volatile ("pusha                 \n\t" "mov    %1, %%eax     \n\t"  /* request feature flag */
    00058                 "cpuid                \n\t"     /* get CPU ID flag */
    00059                 "mov    %%edx, %0     \n\t"     /* move result to mmx_bit */
    00060                 "popa                \n\t":"=m" (flags) /* %0 */
    00061                 :"i"(0x00000001)        /* %1 */
    00062                 );
    00063 #endif
    00064 #endif
    00065
    00066         return (flags);
    00067 }
    00068
    00074 int SDL_imageFilterMMXdetect(void)
    00075 {
    00076         unsigned int mmx_bit;
    00077
    00078         /* Check override flag */
    00079         if (SDL_imageFilterUseMMX == 0) {
    00080                 return (0);
    00081         }
    00082
    00083         mmx_bit = _cpuFlags();
    00084         mmx_bit &= 0x00800000;
    00085         mmx_bit = (mmx_bit && 0x00800000);
    00086
    00087         return (mmx_bit);
    00088 }
    00089
    00093 void SDL_imageFilterMMXoff()
    00094 {
    00095         SDL_imageFilterUseMMX = 0;
    00096 }
    00097
    00101 void SDL_imageFilterMMXon()
    00102 {
    00103         SDL_imageFilterUseMMX = 1;
    00104 }
    00105
    00106 /* ------------------------------------------------------------------------------------ */
    00107
    00118 int SDL_imageFilterAddMMX(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int SrcLength)
    00119 {
    00120 #ifdef USE_MMX
    00121 #if !defined(GCC__)
    00122         __asm
    00123         {
    00124                 pusha
    00125                         mov eax, Src1   /* load Src1 address into eax */
    00126                         mov ebx, Src2   /* load Src2 address into ebx */
    00127                         mov edi, Dest   /* load Dest address into edi */
    00128                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    00129                         shr ecx, 3      /* counter/8 (MMX loads 8 bytes at a time) */
    00130                         align 16        /* 16 byte alignment of the loop entry */
    00131 L1010:
    00132                 movq mm1, [eax] /* load 8 bytes from Src1 into mm1 */
    00133                 paddusb mm1, [ebx]      /* mm1=Src1+Src2 (add 8 bytes with saturation) */
    00134                 movq [edi], mm1 /* store result in Dest */
    00135                         add eax, 8      /* increase Src1, Src2 and Dest  */
    00136                         add ebx, 8      /* register pointers by 8 */
    00137                         add edi, 8
    00138                         dec ecx /* decrease loop counter */
    00139                         jnz L1010       /* check loop termination, proceed if required */
    00140                         emms /* exit MMX state */
    00141                         popa
    00142         }
    00143 #else
    00144         asm volatile
    00145                 ("pusha              \n\t" "mov          %2, %%eax \n\t"        /* load Src1 address into eax */
    00146                 "mov          %1, %%ebx \n\t"   /* load Src2 address into ebx */
    00147                 "mov          %0, %%edi \n\t"   /* load Dest address into edi */
    00148                 "mov          %3, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    00149                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    00150                 ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    00151                 "1: movq (%%eax), %%mm1 \n\t"           /* load 8 bytes from Src1 into mm1 */
    00152                 "paddusb (%%ebx), %%mm1 \n\t"   /* mm1=Src1+Src2 (add 8 bytes with saturation) */
    00153                 "movq    %%mm1, (%%edi) \n\t"   /* store result in Dest */
    00154                 "add          $8, %%eax \n\t"   /* increase Src1, Src2 and Dest  */
    00155                 "add          $8, %%ebx \n\t"   /* register pointers by 8 */
    00156                 "add          $8, %%edi \n\t" "dec              %%ecx \n\t"     /* decrease loop counter */
    00157                 "jnz             1b     \n\t"     /* check loop termination, proceed if required */
    00158                 "emms                   \n\t"   /* exit MMX state */
    00159                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    00160                 :"m"(Src2),             /* %1 */
    00161                 "m"(Src1),              /* %2 */
    00162                 "m"(SrcLength)          /* %3 */
    00163                 );
    00164 #endif
    00165         return (0);
    00166 #else
    00167         return (-1);
    00168 #endif
    00169 }
    00170
    00181 int SDL_imageFilterAdd(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length)
    00182 {
    00183         unsigned int i, istart;
    00184         unsigned char *cursrc1, *cursrc2, *curdst;
    00185         int result;
    00186
    00187         /* Validate input parameters */
    00188         if ((Src1 == NULL) || (Src2 == NULL) || (Dest == NULL))
    00189                 return(-1);
    00190         if (length == 0)
    00191                 return(0);
    00192
    00193         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    00194
    00195                 /* Use MMX assembly routine */
    00196                 SDL_imageFilterAddMMX(Src1, Src2, Dest, length);
    00197
    00198                 /* Check for unaligned bytes */
    00199                 if ((length & 7) > 0) {
    00200                         /* Setup to process unaligned bytes */
    00201                         istart = length & 0xfffffff8;
    00202                         cursrc1 = &Src1[istart];
    00203                         cursrc2 = &Src2[istart];
    00204                         curdst = &Dest[istart];
    00205                 } else {
    00206                         /* No unaligned bytes - we are done */
    00207                         return (0);
    00208                 }
    00209         } else {
    00210                 /* Setup to process whole image */
    00211                 istart = 0;
    00212                 cursrc1 = Src1;
    00213                 cursrc2 = Src2;
    00214                 curdst = Dest;
    00215         }
    00216
    00217         /* C routine to process image */
    00218         for (i = istart; i < length; i++) {
    00219                 result = (int) *cursrc1 + (int) *cursrc2;
    00220                 if (result > 255)
    00221                         result = 255;
    00222                 *curdst = (unsigned char) result;
    00223                 /* Advance pointers */
    00224                 cursrc1++;
    00225                 cursrc2++;
    00226                 curdst++;
    00227         }
    00228
    00229         return (0);
    00230 }
    00231
    00243 int SDL_imageFilterMeanMMX(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int SrcLength,
    00244                                                    unsigned char *Mask)
    00245 {
    00246 #ifdef USE_MMX
    00247 #if !defined(GCC__)
    00248         __asm
    00249         {
    00250                 pusha
    00251                         mov edx, Mask /* load Mask address into edx */
    00252                         movq mm0, [edx] /* load Mask into mm0 */
    00253                 mov eax, Src1 /* load Src1 address into eax */
    00254                         mov ebx, Src2 /* load Src2 address into ebx */
    00255                         mov edi, Dest /* load Dest address into edi */
    00256                         mov ecx, SrcLength /* load loop counter (SIZE) into ecx */
    00257                         shr ecx, 3      /* counter/8 (MMX loads 8 bytes at a time) */
    00258                         align 16        /* 16 byte alignment of the loop entry */
    00259 L21011:
    00260                 movq mm1,  [eax]        /* load 8 bytes from Src1 into mm1 */
    00261                 movq mm2,  [ebx]        /* load 8 bytes from Src2 into mm2 */
    00262                 /* --- Byte shift via Word shift --- */
    00263                 psrlw mm1, 1    /* shift 4 WORDS of mm1 1 bit to the right */
    00264                         psrlw mm2, 1    /* shift 4 WORDS of mm2 1 bit to the right */
    00265                         pand mm1, mm0   // apply Mask to 8 BYTES of mm1 */
    00266                         /* byte     0x0f, 0xdb, 0xc8 */
    00267                         pand mm2, mm0   // apply Mask to 8 BYTES of mm2 */
    00268                         /* byte     0x0f, 0xdb, 0xd0 */
    00269                         paddusb mm1,  mm2       /* mm1=mm1+mm2 (add 8 bytes with saturation) */
    00270                         movq [edi],  mm1        /* store result in Dest */
    00271                         add eax,  8     /* increase Src1, Src2 and Dest  */
    00272                         add ebx,  8     /* register pointers by 8 */
    00273                         add edi,  8
    00274                         dec ecx         /* decrease loop counter */
    00275                         jnz L21011      /* check loop termination, proceed if required */
    00276                         emms    /* exit MMX state */
    00277                         popa
    00278         }
    00279 #else
    00280         asm volatile
    00281                 ("pusha              \n\t" "movl         %4, %%edx \n\t"        /* load Mask address into edx */
    00282                 "movq    (%%edx), %%mm0 \n\t"   /* load Mask into mm0 */
    00283                 "mov          %2, %%eax \n\t"   /* load Src1 address into eax */
    00284                 "mov          %1, %%ebx \n\t"   /* load Src2 address into ebx */
    00285                 "mov          %0, %%edi \n\t"   /* load Dest address into edi */
    00286                 "mov          %3, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    00287                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    00288                 ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    00289                 "1:                      \n\t"
    00290                 "movq    (%%eax), %%mm1 \n\t"   /* load 8 bytes from Src1 into mm1 */
    00291                 "movq    (%%ebx), %%mm2 \n\t"   /* load 8 bytes from Src2 into mm2 */
    00292                 /* --- Byte shift via Word shift --- */
    00293                 "psrlw        $1, %%mm1 \n\t"   /* shift 4 WORDS of mm1 1 bit to the right */
    00294                 "psrlw        $1, %%mm2 \n\t"   /* shift 4 WORDS of mm2 1 bit to the right */
    00295                 /*      "pand      %%mm0, %%mm1 \n\t"    // apply Mask to 8 BYTES of mm1 */
    00296                 ".byte     0x0f, 0xdb, 0xc8 \n\t"
    00297                 /*      "pand      %%mm0, %%mm2 \n\t"    // apply Mask to 8 BYTES of mm2 */
    00298                 ".byte     0x0f, 0xdb, 0xd0 \n\t"
    00299                 "paddusb   %%mm2, %%mm1 \n\t"   /* mm1=mm1+mm2 (add 8 bytes with saturation) */
    00300                 "movq    %%mm1, (%%edi) \n\t"   /* store result in Dest */
    00301                 "add          $8, %%eax \n\t"   /* increase Src1, Src2 and Dest  */
    00302                 "add          $8, %%ebx \n\t"   /* register pointers by 8 */
    00303                 "add          $8, %%edi \n\t"
    00304                 "dec              %%ecx \n\t"   /* decrease loop counter */
    00305                 "jnz                 1b \n\t"     /* check loop termination, proceed if required */
    00306                 "emms                   \n\t"   /* exit MMX state */
    00307                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    00308                 :"m"(Src2),             /* %1 */
    00309                 "m"(Src1),              /* %2 */
    00310                 "m"(SrcLength),         /* %3 */
    00311                 "m"(Mask)                       /* %4 */
    00312                 );
    00313 #endif
    00314         return (0);
    00315 #else
    00316         return (-1);
    00317 #endif
    00318 }
    00319
    00330 int SDL_imageFilterMean(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length)
    00331 {
    00332         static unsigned char Mask[8] = { 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F };
    00333         unsigned int i, istart;
    00334         unsigned char *cursrc1, *cursrc2, *curdst;
    00335         int result;
    00336
    00337         /* Validate input parameters */
    00338         if ((Src1 == NULL) || (Src2 == NULL) || (Dest == NULL))
    00339                 return(-1);
    00340         if (length == 0)
    00341                 return(0);
    00342
    00343         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    00344                 /* MMX routine */
    00345                 SDL_imageFilterMeanMMX(Src1, Src2, Dest, length, Mask);
    00346
    00347                 /* Check for unaligned bytes */
    00348                 if ((length & 7) > 0) {
    00349                         /* Setup to process unaligned bytes */
    00350                         istart = length & 0xfffffff8;
    00351                         cursrc1 = &Src1[istart];
    00352                         cursrc2 = &Src2[istart];
    00353                         curdst = &Dest[istart];
    00354                 } else {
    00355                         /* No unaligned bytes - we are done */
    00356                         return (0);
    00357                 }
    00358         } else {
    00359                 /* Setup to process whole image */
    00360                 istart = 0;
    00361                 cursrc1 = Src1;
    00362                 cursrc2 = Src2;
    00363                 curdst = Dest;
    00364         }
    00365
    00366         /* C routine to process image */
    00367         for (i = istart; i < length; i++) {
    00368                 result = (int) *cursrc1 / 2 + (int) *cursrc2 / 2;
    00369                 *curdst = (unsigned char) result;
    00370                 /* Advance pointers */
    00371                 cursrc1++;
    00372                 cursrc2++;
    00373                 curdst++;
    00374         }
    00375
    00376         return (0);
    00377 }
    00378
    00389 int SDL_imageFilterSubMMX(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int SrcLength)
    00390 {
    00391 #ifdef USE_MMX
    00392 #if !defined(GCC__)
    00393         __asm
    00394         {
    00395                 pusha
    00396                         mov eax,  Src1  /* load Src1 address into eax */
    00397                         mov ebx,  Src2  /* load Src2 address into ebx */
    00398                         mov edi,  Dest  /* load Dest address into edi */
    00399                         mov ecx,  SrcLength     /* load loop counter (SIZE) into ecx */
    00400                         shr ecx,  3     /* counter/8 (MMX loads 8 bytes at a time) */
    00401                         align 16 /* 16 byte alignment of the loop entry */
    00402 L1012:
    00403                 movq mm1,  [eax]        /* load 8 bytes from Src1 into mm1 */
    00404                 psubusb mm1,  [ebx]     /* mm1=Src1-Src2 (sub 8 bytes with saturation) */
    00405                 movq [edi],  mm1        /* store result in Dest */
    00406                         add eax, 8      /* increase Src1, Src2 and Dest  */
    00407                         add ebx, 8      /* register pointers by 8 */
    00408                         add edi, 8
    00409                         dec ecx /* decrease loop counter */
    00410                         jnz L1012       /* check loop termination, proceed if required */
    00411                         emms /* exit MMX state */
    00412                         popa
    00413         }
    00414 #else
    00415         asm volatile
    00416                 ("pusha              \n\t" "mov %2, %%eax \n\t" /* load Src1 address into eax */
    00417                 "mov %1, %%ebx \n\t"    /* load Src2 address into ebx */
    00418                 "mov %0, %%edi \n\t"    /* load Dest address into edi */
    00419                 "mov %3, %%ecx \n\t"    /* load loop counter (SIZE) into ecx */
    00420                 "shr $3, %%ecx \n\t"    /* counter/8 (MMX loads 8 bytes at a time) */
    00421                 ".align 16       \n\t"  /* 16 byte alignment of the loop entry */
    00422                 "1: movq (%%eax), %%mm1 \n\t"     /* load 8 bytes from Src1 into mm1 */
    00423                 "psubusb (%%ebx), %%mm1 \n\t"   /* mm1=Src1-Src2 (sub 8 bytes with saturation) */
    00424                 "movq    %%mm1, (%%edi) \n\t"   /* store result in Dest */
    00425                 "add $8, %%eax \n\t"    /* increase Src1, Src2 and Dest  */
    00426                 "add $8, %%ebx \n\t"    /* register pointers by 8 */
    00427                 "add $8, %%edi \n\t" "dec %%ecx     \n\t"       /* decrease loop counter */
    00428                 "jnz 1b         \n\t"     /* check loop termination, proceed if required */
    00429                 "emms          \n\t"    /* exit MMX state */
    00430                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    00431                 :"m"(Src2),             /* %1 */
    00432                 "m"(Src1),              /* %2 */
    00433                 "m"(SrcLength)          /* %3 */
    00434                 );
    00435 #endif
    00436         return (0);
    00437 #else
    00438         return (-1);
    00439 #endif
    00440 }
    00441
    00452 int SDL_imageFilterSub(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length)
    00453 {
    00454         unsigned int i, istart;
    00455         unsigned char *cursrc1, *cursrc2, *curdst;
    00456         int result;
    00457
    00458         /* Validate input parameters */
    00459         if ((Src1 == NULL) || (Src2 == NULL) || (Dest == NULL))
    00460                 return(-1);
    00461         if (length == 0)
    00462                 return(0);
    00463
    00464         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    00465                 /* MMX routine */
    00466                 SDL_imageFilterSubMMX(Src1, Src2, Dest, length);
    00467
    00468                 /* Check for unaligned bytes */
    00469                 if ((length & 7) > 0) {
    00470                         /* Setup to process unaligned bytes */
    00471                         istart = length & 0xfffffff8;
    00472                         cursrc1 = &Src1[istart];
    00473                         cursrc2 = &Src2[istart];
    00474                         curdst = &Dest[istart];
    00475                 } else {
    00476                         /* No unaligned bytes - we are done */
    00477                         return (0);
    00478                 }
    00479         } else {
    00480                 /* Setup to process whole image */
    00481                 istart = 0;
    00482                 cursrc1 = Src1;
    00483                 cursrc2 = Src2;
    00484                 curdst = Dest;
    00485         }
    00486
    00487         /* C routine to process image */
    00488         for (i = istart; i < length; i++) {
    00489                 result = (int) *cursrc1 - (int) *cursrc2;
    00490                 if (result < 0)
    00491                         result = 0;
    00492                 *curdst = (unsigned char) result;
    00493                 /* Advance pointers */
    00494                 cursrc1++;
    00495                 cursrc2++;
    00496                 curdst++;
    00497         }
    00498
    00499         return (0);
    00500 }
    00501
    00512 int SDL_imageFilterAbsDiffMMX(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int SrcLength)
    00513 {
    00514 #ifdef USE_MMX
    00515 #if !defined(GCC__)
    00516         __asm
    00517         {
    00518                 pusha
    00519                         mov eax, Src1   /* load Src1 address into eax */
    00520                         mov ebx, Src2   /* load Src2 address into ebx */
    00521                         mov edi, Dest   /* load Dest address into edi */
    00522                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    00523                         shr ecx,  3     /* counter/8 (MMX loads 8 bytes at a time) */
    00524                         align 16        /* 16 byte alignment of the loop entry */
    00525 L1013:
    00526                 movq mm1,  [eax]        /* load 8 bytes from Src1 into mm1 */
    00527                 movq mm2,  [ebx]        /* load 8 bytes from Src2 into mm2 */
    00528                 psubusb mm1,  [ebx]     /* mm1=Src1-Src2 (sub 8 bytes with saturation) */
    00529                 psubusb mm2,  [eax]     /* mm2=Src2-Src1 (sub 8 bytes with saturation) */
    00530                 por mm1,  mm2   /* combine both mm2 and mm1 results */
    00531                         movq [edi],  mm1        /* store result in Dest */
    00532                         add eax, 8      /* increase Src1, Src2 and Dest  */
    00533                         add ebx, 8      /* register pointers by 8 */
    00534                         add edi, 8
    00535                         dec ecx         /* decrease loop counter */
    00536                         jnz L1013       /* check loop termination, proceed if required */
    00537                         emms         /* exit MMX state */
    00538                         popa
    00539         }
    00540 #else
    00541         asm volatile
    00542                 ("pusha              \n\t" "mov %2, %%eax \n\t" /* load Src1 address into eax */
    00543                 "mov %1, %%ebx \n\t"    /* load Src2 address into ebx */
    00544                 "mov %0, %%edi \n\t"    /* load Dest address into edi */
    00545                 "mov %3, %%ecx \n\t"    /* load loop counter (SIZE) into ecx */
    00546                 "shr $3, %%ecx \n\t"    /* counter/8 (MMX loads 8 bytes at a time) */
    00547                 ".align 16       \n\t"  /* 16 byte alignment of the loop entry */
    00548                 "1: movq (%%eax), %%mm1 \n\t"     /* load 8 bytes from Src1 into mm1 */
    00549                 "movq    (%%ebx), %%mm2 \n\t"   /* load 8 bytes from Src2 into mm2 */
    00550                 "psubusb (%%ebx), %%mm1 \n\t"   /* mm1=Src1-Src2 (sub 8 bytes with saturation) */
    00551                 "psubusb (%%eax), %%mm2 \n\t"   /* mm2=Src2-Src1 (sub 8 bytes with saturation) */
    00552                 "por       %%mm2, %%mm1 \n\t"   /* combine both mm2 and mm1 results */
    00553                 "movq    %%mm1, (%%edi) \n\t"   /* store result in Dest */
    00554                 "add $8, %%eax \n\t"    /* increase Src1, Src2 and Dest  */
    00555                 "add $8, %%ebx \n\t"    /* register pointers by 8 */
    00556                 "add $8, %%edi \n\t" "dec %%ecx     \n\t"       /* decrease loop counter */
    00557                 "jnz 1b        \n\t"      /* check loop termination, proceed if required */
    00558                 "emms          \n\t"    /* exit MMX state */
    00559                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    00560                 :"m"(Src2),             /* %1 */
    00561                 "m"(Src1),              /* %2 */
    00562                 "m"(SrcLength)          /* %3 */
    00563                 );
    00564 #endif
    00565         return (0);
    00566 #else
    00567         return (-1);
    00568 #endif
    00569 }
    00570
    00581 int SDL_imageFilterAbsDiff(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length)
    00582 {
    00583         unsigned int i, istart;
    00584         unsigned char *cursrc1, *cursrc2, *curdst;
    00585         int result;
    00586
    00587         /* Validate input parameters */
    00588         if ((Src1 == NULL) || (Src2 == NULL) || (Dest == NULL))
    00589                 return(-1);
    00590         if (length == 0)
    00591                 return(0);
    00592
    00593         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    00594                 /* MMX routine */
    00595                 SDL_imageFilterAbsDiffMMX(Src1, Src2, Dest, length);
    00596
    00597                 /* Check for unaligned bytes */
    00598                 if ((length & 7) > 0) {
    00599                         /* Setup to process unaligned bytes */
    00600                         istart = length & 0xfffffff8;
    00601                         cursrc1 = &Src1[istart];
    00602                         cursrc2 = &Src2[istart];
    00603                         curdst = &Dest[istart];
    00604                 } else {
    00605                         /* No unaligned bytes - we are done */
    00606                         return (0);
    00607                 }
    00608         } else {
    00609                 /* Setup to process whole image */
    00610                 istart = 0;
    00611                 cursrc1 = Src1;
    00612                 cursrc2 = Src2;
    00613                 curdst = Dest;
    00614         }
    00615
    00616         /* C routine to process image */
    00617         for (i = istart; i < length; i++) {
    00618                 result = abs((int) *cursrc1 - (int) *cursrc2);
    00619                 *curdst = (unsigned char) result;
    00620                 /* Advance pointers */
    00621                 cursrc1++;
    00622                 cursrc2++;
    00623                 curdst++;
    00624         }
    00625
    00626         return (0);
    00627 }
    00628
    00639 int SDL_imageFilterMultMMX(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int SrcLength)
    00640 {
    00641 #ifdef USE_MMX
    00642 #if !defined(GCC__)
    00643         __asm
    00644         {
    00645                 pusha
    00646                         mov eax, Src1   /* load Src1 address into eax */
    00647                         mov ebx, Src2   /* load Src2 address into ebx */
    00648                         mov edi, Dest   /* load Dest address into edi */
    00649                         mov ecx, SrcLength   /* load loop counter (SIZE) into ecx */
    00650                         shr ecx, 3   /* counter/8 (MMX loads 8 bytes at a time) */
    00651                         pxor mm0, mm0   /* zero mm0 register */
    00652                         align 16        /* 16 byte alignment of the loop entry */
    00653 L1014:
    00654                 movq mm1, [eax]   /* load 8 bytes from Src1 into mm1 */
    00655                 movq mm3, [ebx]   /* load 8 bytes from Src2 into mm3 */
    00656                 movq mm2, mm1   /* copy mm1 into mm2 */
    00657                         movq mm4, mm3   /* copy mm3 into mm4  */
    00658                         punpcklbw mm1, mm0   /* unpack low  bytes of Src1 into words */
    00659                         punpckhbw mm2, mm0   /* unpack high bytes of Src1 into words */
    00660                         punpcklbw mm3, mm0   /* unpack low  bytes of Src2 into words */
    00661                         punpckhbw mm4, mm0   /* unpack high bytes of Src2 into words */
    00662                         pmullw mm1, mm3   /* mul low  bytes of Src1 and Src2  */
    00663                         pmullw mm2, mm4   /* mul high bytes of Src1 and Src2 */
    00664                         /* Take abs value of the results (signed words) */
    00665                         movq mm5, mm1   /* copy mm1 into mm5 */
    00666                         movq mm6, mm2   /* copy mm2 into mm6 */
    00667                         psraw mm5, 15   /* fill mm5 words with word sign bit */
    00668                         psraw mm6, 15   /* fill mm6 words with word sign bit */
    00669                         pxor mm1, mm5   /* take 1's compliment of only neg. words */
    00670                         pxor mm2, mm6   /* take 1's compliment of only neg. words */
    00671                         psubsw mm1, mm5   /* add 1 to only neg. words, W-(-1) or W-0 */
    00672                         psubsw mm2, mm6   /* add 1 to only neg. words, W-(-1) or W-0 */
    00673                         packuswb mm1, mm2   /* pack words back into bytes with saturation */
    00674                         movq [edi], mm1   /* store result in Dest */
    00675                         add eax, 8   /* increase Src1, Src2 and Dest  */
    00676                         add ebx, 8   /* register pointers by 8 */
    00677                         add edi, 8
    00678                         dec ecx         /* decrease loop counter */
    00679                         jnz L1014       /* check loop termination, proceed if required */
    00680                         emms /* exit MMX state */
    00681                         popa
    00682         }
    00683 #else
    00684         asm volatile
    00685                 ("pusha              \n\t" "mov %2, %%eax \n\t" /* load Src1 address into eax */
    00686                 "mov %1, %%ebx \n\t"    /* load Src2 address into ebx */
    00687                 "mov %0, %%edi \n\t"    /* load Dest address into edi */
    00688                 "mov %3, %%ecx \n\t"    /* load loop counter (SIZE) into ecx */
    00689                 "shr $3, %%ecx \n\t"    /* counter/8 (MMX loads 8 bytes at a time) */
    00690                 "pxor      %%mm0, %%mm0 \n\t"   /* zero mm0 register */
    00691                 ".align 16       \n\t"  /* 16 byte alignment of the loop entry */
    00692                 "1: movq (%%eax), %%mm1 \n\t"     /* load 8 bytes from Src1 into mm1 */
    00693                 "movq    (%%ebx), %%mm3 \n\t"   /* load 8 bytes from Src2 into mm3 */
    00694                 "movq      %%mm1, %%mm2 \n\t"   /* copy mm1 into mm2 */
    00695                 "movq      %%mm3, %%mm4 \n\t"   /* copy mm3 into mm4  */
    00696                 "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack low  bytes of Src1 into words */
    00697                 "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack high bytes of Src1 into words */
    00698                 "punpcklbw %%mm0, %%mm3 \n\t"   /* unpack low  bytes of Src2 into words */
    00699                 "punpckhbw %%mm0, %%mm4 \n\t"   /* unpack high bytes of Src2 into words */
    00700                 "pmullw    %%mm3, %%mm1 \n\t"   /* mul low  bytes of Src1 and Src2  */
    00701                 "pmullw    %%mm4, %%mm2 \n\t"   /* mul high bytes of Src1 and Src2 */
    00702                 /* Take abs value of the results (signed words) */
    00703                 "movq      %%mm1, %%mm5 \n\t"   /* copy mm1 into mm5 */
    00704                 "movq      %%mm2, %%mm6 \n\t"   /* copy mm2 into mm6 */
    00705                 "psraw       $15, %%mm5 \n\t"   /* fill mm5 words with word sign bit */
    00706                 "psraw       $15, %%mm6 \n\t"   /* fill mm6 words with word sign bit */
    00707                 "pxor      %%mm5, %%mm1 \n\t"   /* take 1's compliment of only neg. words */
    00708                 "pxor      %%mm6, %%mm2 \n\t"   /* take 1's compliment of only neg. words */
    00709                 "psubsw    %%mm5, %%mm1 \n\t"   /* add 1 to only neg. words, W-(-1) or W-0 */
    00710                 "psubsw    %%mm6, %%mm2 \n\t"   /* add 1 to only neg. words, W-(-1) or W-0 */
    00711                 "packuswb  %%mm2, %%mm1 \n\t"   /* pack words back into bytes with saturation */
    00712                 "movq    %%mm1, (%%edi) \n\t"   /* store result in Dest */
    00713                 "add $8, %%eax \n\t"    /* increase Src1, Src2 and Dest  */
    00714                 "add $8, %%ebx \n\t"    /* register pointers by 8 */
    00715                 "add $8, %%edi \n\t" "dec %%ecx     \n\t"       /* decrease loop counter */
    00716                 "jnz 1b        \n\t"      /* check loop termination, proceed if required */
    00717                 "emms          \n\t"    /* exit MMX state */
    00718                 "popa \n\t":"=m" (Dest) /* %0 */
    00719                 :"m"(Src2),             /* %1 */
    00720                 "m"(Src1),              /* %2 */
    00721                 "m"(SrcLength)          /* %3 */
    00722                 );
    00723 #endif
    00724         return (0);
    00725 #else
    00726         return (-1);
    00727 #endif
    00728 }
    00729
    00740 int SDL_imageFilterMult(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length)
    00741 {
    00742         unsigned int i, istart;
    00743         unsigned char *cursrc1, *cursrc2, *curdst;
    00744         int result;
    00745
    00746         /* Validate input parameters */
    00747         if ((Src1 == NULL) || (Src2 == NULL) || (Dest == NULL))
    00748                 return(-1);
    00749         if (length == 0)
    00750                 return(0);
    00751
    00752         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    00753                 /* MMX routine */
    00754                 SDL_imageFilterMultMMX(Src1, Src2, Dest, length);
    00755
    00756                 /* Check for unaligned bytes */
    00757                 if ((length & 7) > 0) {
    00758                         /* Setup to process unaligned bytes */
    00759                         istart = length & 0xfffffff8;
    00760                         cursrc1 = &Src1[istart];
    00761                         cursrc2 = &Src2[istart];
    00762                         curdst = &Dest[istart];
    00763                 } else {
    00764                         /* No unaligned bytes - we are done */
    00765                         return (0);
    00766                 }
    00767         } else {
    00768                 /* Setup to process whole image */
    00769                 istart = 0;
    00770                 cursrc1 = Src1;
    00771                 cursrc2 = Src2;
    00772                 curdst = Dest;
    00773         }
    00774
    00775         /* C routine to process image */
    00776         for (i = istart; i < length; i++) {
    00777
    00778                 /* NOTE: this is probably wrong - dunno what the MMX code does */
    00779
    00780                 result = (int) *cursrc1 * (int) *cursrc2;
    00781                 if (result > 255)
    00782                         result = 255;
    00783                 *curdst = (unsigned char) result;
    00784                 /* Advance pointers */
    00785                 cursrc1++;
    00786                 cursrc2++;
    00787                 curdst++;
    00788         }
    00789
    00790         return (0);
    00791 }
    00792
    00803 int SDL_imageFilterMultNorASM(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int SrcLength)
    00804 {
    00805 #ifdef USE_MMX
    00806 #if !defined(GCC__)
    00807         __asm
    00808         {
    00809                 pusha
    00810                         mov edx, Src1   /* load Src1 address into edx */
    00811                         mov esi, Src2   /* load Src2 address into esi */
    00812                         mov edi, Dest   /* load Dest address into edi */
    00813                         mov ecx, SrcLength   /* load loop counter (SIZE) into ecx */
    00814                         align 16        /* 16 byte alignment of the loop entry */
    00815 L10141:
    00816                 mov al, [edx]   /* load a byte from Src1 */
    00817                 mul [esi]       /* mul with a byte from Src2 */
    00818                 mov [edi], al   /* move a byte result to Dest */
    00819                         inc edx         /* increment Src1, Src2, Dest */
    00820                         inc esi                 /* pointer registers by one */
    00821                         inc edi
    00822                         dec ecx /* decrease loop counter */
    00823                         jnz L10141      /* check loop termination, proceed if required */
    00824                         popa
    00825         }
    00826 #else
    00827         asm volatile
    00828                 ("pusha              \n\t" "mov %2, %%edx \n\t" /* load Src1 address into edx */
    00829                 "mov %1, %%esi \n\t"    /* load Src2 address into esi */
    00830                 "mov %0, %%edi \n\t"    /* load Dest address into edi */
    00831                 "mov %3, %%ecx \n\t"    /* load loop counter (SIZE) into ecx */
    00832                 ".align 16       \n\t"  /* 16 byte alignment of the loop entry */
    00833                 "1:mov  (%%edx), %%al \n\t"      /* load a byte from Src1 */
    00834                 "mulb (%%esi)       \n\t"       /* mul with a byte from Src2 */
    00835                 "mov %%al, (%%edi)  \n\t"       /* move a byte result to Dest */
    00836                 "inc %%edx \n\t"                /* increment Src1, Src2, Dest */
    00837                 "inc %%esi \n\t"                /* pointer registers by one */
    00838                 "inc %%edi \n\t" "dec %%ecx      \n\t"  /* decrease loop counter */
    00839                 "jnz 1b         \n\t"     /* check loop termination, proceed if required */
    00840                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    00841                 :"m"(Src2),             /* %1 */
    00842                 "m"(Src1),              /* %2 */
    00843                 "m"(SrcLength)          /* %3 */
    00844                 );
    00845 #endif
    00846         return (0);
    00847 #else
    00848         return (-1);
    00849 #endif
    00850 }
    00851
    00862 int SDL_imageFilterMultNor(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length)
    00863 {
    00864         unsigned int i, istart;
    00865         unsigned char *cursrc1, *cursrc2, *curdst;
    00866         int result;
    00867
    00868         /* Validate input parameters */
    00869         if ((Src1 == NULL) || (Src2 == NULL) || (Dest == NULL))
    00870                 return(-1);
    00871         if (length == 0)
    00872                 return(0);
    00873
    00874         if (SDL_imageFilterMMXdetect()) {
    00875                 if (length > 0) {
    00876                         /* ASM routine */
    00877                         SDL_imageFilterMultNorASM(Src1, Src2, Dest, length);
    00878
    00879                         /* Check for unaligned bytes */
    00880                         if ((length & 7) > 0) {
    00881                                 /* Setup to process unaligned bytes */
    00882                                 istart = length & 0xfffffff8;
    00883                                 cursrc1 = &Src1[istart];
    00884                                 cursrc2 = &Src2[istart];
    00885                                 curdst = &Dest[istart];
    00886                         } else {
    00887                                 /* No unaligned bytes - we are done */
    00888                                 return (0);
    00889                         }
    00890                 } else {
    00891                         /* No bytes - we are done */
    00892                         return (0);
    00893                 }
    00894         } else {
    00895                 /* Setup to process whole image */
    00896                 istart = 0;
    00897                 cursrc1 = Src1;
    00898                 cursrc2 = Src2;
    00899                 curdst = Dest;
    00900         }
    00901
    00902         /* C routine to process image */
    00903         for (i = istart; i < length; i++) {
    00904                 result = (int) *cursrc1 * (int) *cursrc2;
    00905                 *curdst = (unsigned char) result;
    00906                 /* Advance pointers */
    00907                 cursrc1++;
    00908                 cursrc2++;
    00909                 curdst++;
    00910         }
    00911
    00912         return (0);
    00913 }
    00914
    00925 int SDL_imageFilterMultDivby2MMX(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int SrcLength)
    00926 {
    00927 #ifdef USE_MMX
    00928 #if !defined(GCC__)
    00929         __asm
    00930         {
    00931                 pusha
    00932                         mov eax, Src1           /* load Src1 address into eax */
    00933                         mov ebx, Src2           /* load Src2 address into ebx */
    00934                         mov edi, Dest           /* load Dest address into edi */
    00935                         mov ecx,  SrcLength     /* load loop counter (SIZE) into ecx */
    00936                         shr ecx,  3     /* counter/8 (MMX loads 8 bytes at a time) */
    00937                         pxor mm0,  mm0  /* zero mm0 register */
    00938                         align 16                /* 16 byte alignment of the loop entry */
    00939 L1015:
    00940                 movq mm1,  [eax]        /* load 8 bytes from Src1 into mm1 */
    00941                 movq mm3,  [ebx]        /* load 8 bytes from Src2 into mm3 */
    00942                 movq mm2,  mm1  /* copy mm1 into mm2 */
    00943                         movq mm4,  mm3  /* copy mm3 into mm4  */
    00944                         punpcklbw mm1,  mm0     /* unpack low  bytes of Src1 into words */
    00945                         punpckhbw mm2,  mm0     /* unpack high bytes of Src1 into words */
    00946                         punpcklbw mm3,  mm0     /* unpack low  bytes of Src2 into words */
    00947                         punpckhbw mm4,  mm0     /* unpack high bytes of Src2 into words */
    00948                         psrlw mm1,  1   /* divide mm1 words by 2, Src1 low bytes */
    00949                         psrlw mm2,  1   /* divide mm2 words by 2, Src1 high bytes */
    00950                         pmullw mm1,  mm3        /* mul low  bytes of Src1 and Src2  */
    00951                         pmullw mm2,  mm4        /* mul high bytes of Src1 and Src2 */
    00952                         packuswb mm1,  mm2      /* pack words back into bytes with saturation */
    00953                         movq [edi],  mm1        /* store result in Dest */
    00954                         add eax,  8     /* increase Src1, Src2 and Dest  */
    00955                         add ebx,  8     /* register pointers by 8 */
    00956                         add edi,  8
    00957                         dec ecx         /* decrease loop counter */
    00958                         jnz L1015               /* check loop termination, proceed if required */
    00959                         emms                    /* exit MMX state */
    00960                         popa
    00961         }
    00962 #else
    00963         asm volatile
    00964                 ("pusha \n\t" "mov %2, %%eax \n\t"      /* load Src1 address into eax */
    00965                 "mov %1, %%ebx \n\t"    /* load Src2 address into ebx */
    00966                 "mov %0, %%edi \n\t"    /* load Dest address into edi */
    00967                 "mov %3, %%ecx \n\t"    /* load loop counter (SIZE) into ecx */
    00968                 "shr $3, %%ecx \n\t"    /* counter/8 (MMX loads 8 bytes at a time) */
    00969                 "pxor      %%mm0, %%mm0 \n\t"   /* zero mm0 register */
    00970                 ".align 16       \n\t"  /* 16 byte alignment of the loop entry */
    00971                 "1: movq (%%eax), %%mm1 \n\t"   /* load 8 bytes from Src1 into mm1 */
    00972                 "movq    (%%ebx), %%mm3 \n\t"   /* load 8 bytes from Src2 into mm3 */
    00973                 "movq      %%mm1, %%mm2 \n\t"   /* copy mm1 into mm2 */
    00974                 "movq      %%mm3, %%mm4 \n\t"   /* copy mm3 into mm4  */
    00975                 "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack low  bytes of Src1 into words */
    00976                 "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack high bytes of Src1 into words */
    00977                 "punpcklbw %%mm0, %%mm3 \n\t"   /* unpack low  bytes of Src2 into words */
    00978                 "punpckhbw %%mm0, %%mm4 \n\t"   /* unpack high bytes of Src2 into words */
    00979                 "psrlw        $1, %%mm1 \n\t"   /* divide mm1 words by 2, Src1 low bytes */
    00980                 "psrlw        $1, %%mm2 \n\t"   /* divide mm2 words by 2, Src1 high bytes */
    00981                 "pmullw    %%mm3, %%mm1 \n\t"   /* mul low  bytes of Src1 and Src2  */
    00982                 "pmullw    %%mm4, %%mm2 \n\t"   /* mul high bytes of Src1 and Src2 */
    00983                 "packuswb  %%mm2, %%mm1 \n\t"   /* pack words back into bytes with saturation */
    00984                 "movq    %%mm1, (%%edi) \n\t"   /* store result in Dest */
    00985                 "add $8, %%eax \n\t"    /* increase Src1, Src2 and Dest  */
    00986                 "add $8, %%ebx \n\t"    /* register pointers by 8 */
    00987                 "add $8, %%edi \n\t" "dec %%ecx     \n\t"       /* decrease loop counter */
    00988                 "jnz 1b        \n\t"    /* check loop termination, proceed if required */
    00989                 "emms          \n\t"    /* exit MMX state */
    00990                 "popa \n\t":"=m" (Dest) /* %0 */
    00991                 :"m"(Src2),             /* %1 */
    00992                 "m"(Src1),              /* %2 */
    00993                 "m"(SrcLength)          /* %3 */
    00994                 );
    00995 #endif
    00996         return (0);
    00997 #else
    00998         return (-1);
    00999 #endif
    01000 }
    01001
    01012 int SDL_imageFilterMultDivby2(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length)
    01013 {
    01014         unsigned int i, istart;
    01015         unsigned char *cursrc1, *cursrc2, *curdst;
    01016         int result;
    01017
    01018         /* Validate input parameters */
    01019         if ((Src1 == NULL) || (Src2 == NULL) || (Dest == NULL))
    01020                 return(-1);
    01021         if (length == 0)
    01022                 return(0);
    01023
    01024         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    01025                 /* MMX routine */
    01026                 SDL_imageFilterMultDivby2MMX(Src1, Src2, Dest, length);
    01027
    01028                 /* Check for unaligned bytes */
    01029                 if ((length & 7) > 0) {
    01030                         /* Setup to process unaligned bytes */
    01031                         istart = length & 0xfffffff8;
    01032                         cursrc1 = &Src1[istart];
    01033                         cursrc2 = &Src2[istart];
    01034                         curdst = &Dest[istart];
    01035                 } else {
    01036                         /* No unaligned bytes - we are done */
    01037                         return (0);
    01038                 }
    01039         } else {
    01040                 /* Setup to process whole image */
    01041                 istart = 0;
    01042                 cursrc1 = Src1;
    01043                 cursrc2 = Src2;
    01044                 curdst = Dest;
    01045         }
    01046
    01047         /* C routine to process image */
    01048         for (i = istart; i < length; i++) {
    01049                 result = ((int) *cursrc1 / 2) * (int) *cursrc2;
    01050                 if (result > 255)
    01051                         result = 255;
    01052                 *curdst = (unsigned char) result;
    01053                 /* Advance pointers */
    01054                 cursrc1++;
    01055                 cursrc2++;
    01056                 curdst++;
    01057         }
    01058
    01059         return (0);
    01060 }
    01061
    01072 int SDL_imageFilterMultDivby4MMX(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int SrcLength)
    01073 {
    01074 #ifdef USE_MMX
    01075 #if !defined(GCC__)
    01076         __asm
    01077         {
    01078                 pusha
    01079                         mov eax, Src1           /* load Src1 address into eax */
    01080                         mov ebx, Src2           /* load Src2 address into ebx */
    01081                         mov edi, Dest           /* load Dest address into edi */
    01082                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    01083                         shr ecx,  3     /* counter/8 (MMX loads 8 bytes at a time) */
    01084                         pxor mm0, mm0           /* zero mm0 register */
    01085                         align 16                /* 16 byte alignment of the loop entry */
    01086 L1016:
    01087                 movq mm1, [eax]         /* load 8 bytes from Src1 into mm1 */
    01088                 movq mm3, [ebx]         /* load 8 bytes from Src2 into mm3 */
    01089                 movq mm2, mm1           /* copy mm1 into mm2 */
    01090                         movq mm4, mm3           /* copy mm3 into mm4  */
    01091                         punpcklbw mm1, mm0      /* unpack low  bytes of Src1 into words */
    01092                         punpckhbw mm2, mm0      /* unpack high bytes of Src1 into words */
    01093                         punpcklbw mm3, mm0      /* unpack low  bytes of Src2 into words */
    01094                         punpckhbw mm4, mm0      /* unpack high bytes of Src2 into words */
    01095                         psrlw mm1, 1    /* divide mm1 words by 2, Src1 low bytes */
    01096                         psrlw mm2, 1    /* divide mm2 words by 2, Src1 high bytes */
    01097                         psrlw mm3, 1    /* divide mm3 words by 2, Src2 low bytes */
    01098                         psrlw mm4, 1    /* divide mm4 words by 2, Src2 high bytes */
    01099                         pmullw mm1, mm3         /* mul low  bytes of Src1 and Src2  */
    01100                         pmullw mm2, mm4         /* mul high bytes of Src1 and Src2 */
    01101                         packuswb mm1, mm2       /* pack words back into bytes with saturation */
    01102                         movq [edi], mm1         /* store result in Dest */
    01103                         add eax, 8      /* increase Src1, Src2 and Dest  */
    01104                         add ebx, 8      /* register pointers by 8 */
    01105                         add edi,  8
    01106                         dec ecx         /* decrease loop counter */
    01107                         jnz L1016               /* check loop termination, proceed if required */
    01108                         emms                    /* exit MMX state */
    01109                         popa
    01110         }
    01111 #else
    01112         asm volatile
    01113                 ("pusha              \n\t" "mov %2, %%eax \n\t" /* load Src1 address into eax */
    01114                 "mov %1, %%ebx \n\t"    /* load Src2 address into ebx */
    01115                 "mov %0, %%edi \n\t"    /* load Dest address into edi */
    01116                 "mov %3, %%ecx \n\t"    /* load loop counter (SIZE) into ecx */
    01117                 "shr $3, %%ecx \n\t"    /* counter/8 (MMX loads 8 bytes at a time) */
    01118                 "pxor      %%mm0, %%mm0 \n\t"   /* zero mm0 register */
    01119                 ".align 16       \n\t"  /* 16 byte alignment of the loop entry */
    01120                 "1: movq (%%eax), %%mm1 \n\t"   /* load 8 bytes from Src1 into mm1 */
    01121                 "movq    (%%ebx), %%mm3 \n\t"   /* load 8 bytes from Src2 into mm3 */
    01122                 "movq      %%mm1, %%mm2 \n\t"   /* copy mm1 into mm2 */
    01123                 "movq      %%mm3, %%mm4 \n\t"   /* copy mm3 into mm4  */
    01124                 "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack low  bytes of Src1 into words */
    01125                 "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack high bytes of Src1 into words */
    01126                 "punpcklbw %%mm0, %%mm3 \n\t"   /* unpack low  bytes of Src2 into words */
    01127                 "punpckhbw %%mm0, %%mm4 \n\t"   /* unpack high bytes of Src2 into words */
    01128                 "psrlw        $1, %%mm1 \n\t"   /* divide mm1 words by 2, Src1 low bytes */
    01129                 "psrlw        $1, %%mm2 \n\t"   /* divide mm2 words by 2, Src1 high bytes */
    01130                 "psrlw        $1, %%mm3 \n\t"   /* divide mm3 words by 2, Src2 low bytes */
    01131                 "psrlw        $1, %%mm4 \n\t"   /* divide mm4 words by 2, Src2 high bytes */
    01132                 "pmullw    %%mm3, %%mm1 \n\t"   /* mul low  bytes of Src1 and Src2  */
    01133                 "pmullw    %%mm4, %%mm2 \n\t"   /* mul high bytes of Src1 and Src2 */
    01134                 "packuswb  %%mm2, %%mm1 \n\t"   /* pack words back into bytes with saturation */
    01135                 "movq    %%mm1, (%%edi) \n\t"   /* store result in Dest */
    01136                 "add $8, %%eax \n\t"    /* increase Src1, Src2 and Dest  */
    01137                 "add $8, %%ebx \n\t"    /* register pointers by 8 */
    01138                 "add $8, %%edi \n\t" "dec %%ecx     \n\t"       /* decrease loop counter */
    01139                 "jnz 1b        \n\t"    /* check loop termination, proceed if required */
    01140                 "emms          \n\t"    /* exit MMX state */
    01141                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    01142                 :"m"(Src2),             /* %1 */
    01143                 "m"(Src1),              /* %2 */
    01144                 "m"(SrcLength)          /* %3 */
    01145                 );
    01146 #endif
    01147         return (0);
    01148 #else
    01149         return (-1);
    01150 #endif
    01151 }
    01152
    01163 int SDL_imageFilterMultDivby4(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length)
    01164 {
    01165         unsigned int i, istart;
    01166         unsigned char *cursrc1, *cursrc2, *curdst;
    01167         int result;
    01168
    01169         /* Validate input parameters */
    01170         if ((Src1 == NULL) || (Src2 == NULL) || (Dest == NULL))
    01171                 return(-1);
    01172         if (length == 0)
    01173                 return(0);
    01174
    01175         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    01176                 /* MMX routine */
    01177                 SDL_imageFilterMultDivby4MMX(Src1, Src2, Dest, length);
    01178
    01179                 /* Check for unaligned bytes */
    01180                 if ((length & 7) > 0) {
    01181                         /* Setup to process unaligned bytes */
    01182                         istart = length & 0xfffffff8;
    01183                         cursrc1 = &Src1[istart];
    01184                         cursrc2 = &Src2[istart];
    01185                         curdst = &Dest[istart];
    01186                 } else {
    01187                         /* No unaligned bytes - we are done */
    01188                         return (0);
    01189                 }
    01190         } else {
    01191                 /* Setup to process whole image */
    01192                 istart = 0;
    01193                 cursrc1 = Src1;
    01194                 cursrc2 = Src2;
    01195                 curdst = Dest;
    01196         }
    01197
    01198         /* C routine to process image */
    01199         for (i = istart; i < length; i++) {
    01200                 result = ((int) *cursrc1 / 2) * ((int) *cursrc2 / 2);
    01201                 if (result > 255)
    01202                         result = 255;
    01203                 *curdst = (unsigned char) result;
    01204                 /* Advance pointers */
    01205                 cursrc1++;
    01206                 cursrc2++;
    01207                 curdst++;
    01208         }
    01209
    01210         return (0);
    01211 }
    01212
    01223 int SDL_imageFilterBitAndMMX(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int SrcLength)
    01224 {
    01225 #ifdef USE_MMX
    01226 #if !defined(GCC__)
    01227         __asm
    01228         {
    01229                 pusha
    01230                         mov eax, Src1           /* load Src1 address into eax */
    01231                         mov ebx, Src2           /* load Src2 address into ebx */
    01232                         mov edi, Dest           /* load Dest address into edi */
    01233                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    01234                         shr ecx, 3      /* counter/8 (MMX loads 8 bytes at a time) */
    01235                         align 16                /* 16 byte alignment of the loop entry */
    01236 L1017:
    01237                 movq mm1, [eax]         /* load 8 bytes from Src1 into mm1 */
    01238                 pand mm1, [ebx]         /* mm1=Src1&Src2 */
    01239                 movq [edi], mm1         /* store result in Dest */
    01240                         add eax, 8      /* increase Src1, Src2 and Dest  */
    01241                         add ebx, 8      /* register pointers by 8 */
    01242                         add edi, 8
    01243                         dec ecx         /* decrease loop counter */
    01244                         jnz L1017               /* check loop termination, proceed if required */
    01245                         emms                    /* exit MMX state */
    01246                         popa
    01247         }
    01248 #else
    01249         asm volatile
    01250                 ("pusha              \n\t" "mov %2, %%eax \n\t" /* load Src1 address into eax */
    01251                 "mov %1, %%ebx \n\t"    /* load Src2 address into ebx */
    01252                 "mov %0, %%edi \n\t"    /* load Dest address into edi */
    01253                 "mov %3, %%ecx \n\t"    /* load loop counter (SIZE) into ecx */
    01254                 "shr $3, %%ecx \n\t"    /* counter/8 (MMX loads 8 bytes at a time) */
    01255                 ".align 16       \n\t"  /* 16 byte alignment of the loop entry */
    01256                 "1: movq (%%eax), %%mm1 \n\t"   /* load 8 bytes from Src1 into mm1 */
    01257                 "pand    (%%ebx), %%mm1 \n\t"   /* mm1=Src1&Src2 */
    01258                 "movq    %%mm1, (%%edi) \n\t"   /* store result in Dest */
    01259                 "add $8, %%eax \n\t"    /* increase Src1, Src2 and Dest  */
    01260                 "add $8, %%ebx \n\t"    /* register pointers by 8 */
    01261                 "add $8, %%edi \n\t" "dec %%ecx     \n\t"       /* decrease loop counter */
    01262                 "jnz 1b        \n\t"    /* check loop termination, proceed if required */
    01263                 "emms          \n\t"    /* exit MMX state */
    01264                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    01265                 :"m"(Src2),             /* %1 */
    01266                 "m"(Src1),              /* %2 */
    01267                 "m"(SrcLength)          /* %3 */
    01268                 );
    01269 #endif
    01270         return (0);
    01271 #else
    01272         return (-1);
    01273 #endif
    01274 }
    01275
    01286 int SDL_imageFilterBitAnd(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length)
    01287 {
    01288         unsigned int i, istart;
    01289         unsigned char *cursrc1, *cursrc2, *curdst;
    01290
    01291         /* Validate input parameters */
    01292         if ((Src1 == NULL) || (Src2 == NULL) || (Dest == NULL))
    01293                 return(-1);
    01294         if (length == 0)
    01295                 return(0);
    01296
    01297         if ((SDL_imageFilterMMXdetect()>0) && (length>7)) {
    01298                 /*  if (length > 7) { */
    01299                 /* Call MMX routine */
    01300
    01301                 SDL_imageFilterBitAndMMX(Src1, Src2, Dest, length);
    01302
    01303                 /* Check for unaligned bytes */
    01304                 if ((length & 7) > 0) {
    01305
    01306                         /* Setup to process unaligned bytes */
    01307                         istart = length & 0xfffffff8;
    01308                         cursrc1 = &Src1[istart];
    01309                         cursrc2 = &Src2[istart];
    01310                         curdst = &Dest[istart];
    01311                 } else {
    01312                         /* No unaligned bytes - we are done */
    01313                         return (0);
    01314                 }
    01315         } else {
    01316                 /* Setup to process whole image */
    01317                 istart = 0;
    01318                 cursrc1 = Src1;
    01319                 cursrc2 = Src2;
    01320                 curdst = Dest;
    01321         }
    01322
    01323         /* C routine to process image */
    01324         for (i = istart; i < length; i++) {
    01325                 *curdst = (*cursrc1) & (*cursrc2);
    01326                 /* Advance pointers */
    01327                 cursrc1++;
    01328                 cursrc2++;
    01329                 curdst++;
    01330         }
    01331
    01332         return (0);
    01333 }
    01334
    01345 int SDL_imageFilterBitOrMMX(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int SrcLength)
    01346 {
    01347 #ifdef USE_MMX
    01348 #if !defined(GCC__)
    01349         __asm
    01350         {
    01351                 pusha
    01352                         mov eax, Src1           /* load Src1 address into eax */
    01353                         mov ebx, Src2           /* load Src2 address into ebx */
    01354                         mov edi, Dest           /* load Dest address into edi */
    01355                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    01356                         shr ecx,  3     /* counter/8 (MMX loads 8 bytes at a time) */
    01357                         align 16                /* 16 byte alignment of the loop entry */
    01358 L91017:
    01359                 movq mm1, [eax]         /* load 8 bytes from Src1 into mm1 */
    01360                 por mm1, [ebx]          /* mm1=Src1|Src2 */
    01361                 movq [edi], mm1         /* store result in Dest */
    01362                         add eax, 8      /* increase Src1, Src2 and Dest  */
    01363                         add ebx, 8      /* register pointers by 8 */
    01364                         add edi,  8
    01365                         dec ecx         /* decrease loop counter */
    01366                         jnz L91017              /* check loop termination, proceed if required */
    01367                         emms                    /* exit MMX state */
    01368                         popa
    01369         }
    01370 #else
    01371         asm volatile
    01372                 ("pusha              \n\t" "mov %2, %%eax \n\t" /* load Src1 address into eax */
    01373                 "mov %1, %%ebx \n\t"    /* load Src2 address into ebx */
    01374                 "mov %0, %%edi \n\t"    /* load Dest address into edi */
    01375                 "mov %3, %%ecx \n\t"    /* load loop counter (SIZE) into ecx */
    01376                 "shr $3, %%ecx \n\t"    /* counter/8 (MMX loads 8 bytes at a time) */
    01377                 ".align 16       \n\t"  /* 16 byte alignment of the loop entry */
    01378                 "1: movq (%%eax), %%mm1 \n\t"   /* load 8 bytes from Src1 into mm1 */
    01379                 "por     (%%ebx), %%mm1 \n\t"   /* mm1=Src1|Src2 */
    01380                 "movq    %%mm1, (%%edi) \n\t"   /* store result in Dest */
    01381                 "add $8, %%eax \n\t"    /* increase Src1, Src2 and Dest  */
    01382                 "add $8, %%ebx \n\t"    /* register pointers by 8 */
    01383                 "add $8, %%edi \n\t" "dec %%ecx     \n\t"       /* decrease loop counter */
    01384                 "jnz 1b        \n\t"    /* check loop termination, proceed if required */
    01385                 "emms          \n\t"    /* exit MMX state */
    01386                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    01387                 :"m"(Src2),             /* %1 */
    01388                 "m"(Src1),              /* %2 */
    01389                 "m"(SrcLength)          /* %3 */
    01390                 );
    01391 #endif
    01392         return (0);
    01393 #else
    01394         return (-1);
    01395 #endif
    01396 }
    01397
    01408 int SDL_imageFilterBitOr(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length)
    01409 {
    01410         unsigned int i, istart;
    01411         unsigned char *cursrc1, *cursrc2, *curdst;
    01412
    01413         /* Validate input parameters */
    01414         if ((Src1 == NULL) || (Src2 == NULL) || (Dest == NULL))
    01415                 return(-1);
    01416         if (length == 0)
    01417                 return(0);
    01418
    01419         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    01420
    01421                 /* MMX routine */
    01422                 SDL_imageFilterBitOrMMX(Src1, Src2, Dest, length);
    01423
    01424                 /* Check for unaligned bytes */
    01425                 if ((length & 7) > 0) {
    01426                         /* Setup to process unaligned bytes */
    01427                         istart = length & 0xfffffff8;
    01428                         cursrc1 = &Src1[istart];
    01429                         cursrc2 = &Src2[istart];
    01430                         curdst = &Dest[istart];
    01431                 } else {
    01432                         /* No unaligned bytes - we are done */
    01433                         return (0);
    01434                 }
    01435         } else {
    01436                 /* Setup to process whole image */
    01437                 istart = 0;
    01438                 cursrc1 = Src1;
    01439                 cursrc2 = Src2;
    01440                 curdst = Dest;
    01441         }
    01442
    01443         /* C routine to process image */
    01444         for (i = istart; i < length; i++) {
    01445                 *curdst = *cursrc1 | *cursrc2;
    01446                 /* Advance pointers */
    01447                 cursrc1++;
    01448                 cursrc2++;
    01449                 curdst++;
    01450         }
    01451         return (0);
    01452 }
    01453
    01464 int SDL_imageFilterDivASM(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int SrcLength)
    01465 {
    01466 #ifdef USE_MMX
    01467 #if !defined(GCC__)
    01468         __asm
    01469         {
    01470                 pusha
    01471                         mov edx, Src1           /* load Src1 address into edx */
    01472                         mov esi, Src2           /* load Src2 address into esi */
    01473                         mov edi, Dest           /* load Dest address into edi */
    01474                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    01475                         align 16                /* 16 byte alignment of the loop entry */
    01476 L10191:
    01477                 mov bl, [esi]           /* load a byte from Src2 */
    01478                 cmp bl, 0       /* check if it zero */
    01479                         jnz L10192
    01480                         mov [edi], 255          /* division by zero = 255 !!! */
    01481                         jmp  L10193
    01482 L10192:
    01483                 xor ah, ah      /* prepare AX, zero AH register */
    01484                         mov al, [edx]           /* load a byte from Src1 into AL */
    01485                 div   bl                /* divide AL by BL */
    01486                         mov [edi], al           /* move a byte result to Dest */
    01487 L10193:
    01488                 inc edx         /* increment Src1, Src2, Dest */
    01489                         inc esi                 /* pointer registers by one */
    01490                         inc edi
    01491                         dec ecx         /* decrease loop counter */
    01492                         jnz L10191      /* check loop termination, proceed if required */
    01493                         popa
    01494         }
    01495 #else
    01496         asm volatile
    01497                 ("pusha \n\t" "mov %2, %%edx \n\t"      /* load Src1 address into edx */
    01498                 "mov %1, %%esi \n\t"    /* load Src2 address into esi */
    01499                 "mov %0, %%edi \n\t"    /* load Dest address into edi */
    01500                 "mov %3, %%ecx \n\t"    /* load loop counter (SIZE) into ecx */
    01501                 ".align 16     \n\t"    /* 16 byte alignment of the loop entry */
    01502                 "1: mov (%%esi), %%bl  \n\t"    /* load a byte from Src2 */
    01503                 "cmp       $0, %%bl  \n\t"      /* check if it zero */
    01504                 "jnz 2f              \n\t" "movb  $255, (%%edi) \n\t"   /* division by zero = 255 !!! */
    01505                 "jmp 3f              \n\t" "2:                  \n\t" "xor   %%ah, %%ah    \n\t"        /* prepare AX, zero AH register */
    01506                 "mov   (%%edx), %%al \n\t"      /* load a byte from Src1 into AL */
    01507                 "div   %%bl          \n\t"      /* divide AL by BL */
    01508                 "mov   %%al, (%%edi) \n\t"      /* move a byte result to Dest */
    01509                 "3: inc %%edx        \n\t"      /* increment Src1, Src2, Dest */
    01510                 "inc %%esi \n\t"                /* pointer registers by one */
    01511                 "inc %%edi \n\t" "dec %%ecx    \n\t"    /* decrease loop counter */
    01512                 "jnz 1b       \n\t"     /* check loop termination, proceed if required */
    01513                 "popa \n\t":"=m" (Dest) /* %0 */
    01514                 :"m"(Src2),             /* %1 */
    01515                 "m"(Src1),              /* %2 */
    01516                 "m"(SrcLength)          /* %3 */
    01517                 );
    01518 #endif
    01519         return (0);
    01520 #else
    01521         return (-1);
    01522 #endif
    01523 }
    01524
    01535 int SDL_imageFilterDiv(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length)
    01536 {
    01537         unsigned int i, istart;
    01538         unsigned char *cursrc1, *cursrc2, *curdst;
    01539         int result;
    01540
    01541         /* Validate input parameters */
    01542         if ((Src1 == NULL) || (Src2 == NULL) || (Dest == NULL))
    01543                 return(-1);
    01544         if (length == 0)
    01545                 return(0);
    01546
    01547         if (SDL_imageFilterMMXdetect()) {
    01548                 if (length > 0) {
    01549                         /* Call ASM routine */
    01550                         SDL_imageFilterDivASM(Src1, Src2, Dest, length);
    01551
    01552                         /* Never unaligned bytes - we are done */
    01553                         return (0);
    01554                 } else {
    01555                         return (-1);
    01556                 }
    01557         } else {
    01558                 /* Setup to process whole image */
    01559                 istart = 0;
    01560                 cursrc1 = Src1;
    01561                 cursrc2 = Src2;
    01562                 curdst = Dest;
    01563         }
    01564
    01565         /* C routine to process image */
    01566         for (i = istart; i < length; i++) {
    01567                 result = (int) *cursrc1 / (int) *cursrc2;
    01568                 *curdst = (unsigned char) result;
    01569                 /* Advance pointers */
    01570                 cursrc1++;
    01571                 cursrc2++;
    01572                 curdst++;
    01573         }
    01574
    01575         return (0);
    01576 }
    01577
    01578 /* ------------------------------------------------------------------------------------ */
    01579
    01589 int SDL_imageFilterBitNegationMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength)
    01590 {
    01591 #ifdef USE_MMX
    01592 #if !defined(GCC__)
    01593         __asm
    01594         {
    01595                 pusha
    01596                         pcmpeqb mm1, mm1        /* generate all 1's in mm1 */
    01597                         mov eax, Src1           /* load Src1 address into eax */
    01598                         mov edi, Dest           /* load Dest address into edi */
    01599                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    01600                         shr ecx,  3     /* counter/8 (MMX loads 8 bytes at a time) */
    01601                         align 16                /* 16 byte alignment of the loop entry */
    01602 L91117:
    01603                 movq mm0, [eax]         /* load 8 bytes from Src1 into mm1 */
    01604                 pxor mm0, mm1           /* negate mm0 by xoring with mm1 */
    01605                         movq [edi], mm0         /* store result in Dest */
    01606                         add eax, 8      /* increase Src1, Src2 and Dest  */
    01607                         add edi,  8
    01608                         dec ecx         /* decrease loop counter */
    01609                         jnz L91117              /* check loop termination, proceed if required */
    01610                         emms                    /* exit MMX state */
    01611                         popa
    01612         }
    01613 #else
    01614         asm volatile
    01615                 ("pusha              \n\t" "pcmpeqb   %%mm1, %%mm1 \n\t"        /* generate all 1's in mm1 */
    01616                 "mov %1, %%eax \n\t"    /* load Src1 address into eax */
    01617                 "mov %0, %%edi \n\t"    /* load Dest address into edi */
    01618                 "mov %2, %%ecx \n\t"    /* load loop counter (SIZE) into ecx */
    01619                 "shr $3, %%ecx \n\t"    /* counter/8 (MMX loads 8 bytes at a time) */
    01620                 ".align 16       \n\t"  /* 16 byte alignment of the loop entry */
    01621                 "1: movq (%%eax), %%mm0 \n\t"   /* load 8 bytes from Src1 into mm1 */
    01622                 "pxor      %%mm1, %%mm0 \n\t"   /* negate mm0 by xoring with mm1 */
    01623                 "movq    %%mm0, (%%edi) \n\t"   /* store result in Dest */
    01624                 "add $8, %%eax \n\t"    /* increase Src1, Src2 and Dest  */
    01625                 "add $8, %%edi \n\t" "dec %%ecx     \n\t"       /* decrease loop counter */
    01626                 "jnz 1b        \n\t"    /* check loop termination, proceed if required */
    01627                 "emms          \n\t"    /* exit MMX state */
    01628                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    01629                 :"m"(Src1),             /* %1 */
    01630                 "m"(SrcLength)          /* %2 */
    01631                 );
    01632 #endif
    01633         return (0);
    01634 #else
    01635         return (-1);
    01636 #endif
    01637 }
    01638
    01648 int SDL_imageFilterBitNegation(unsigned char *Src1, unsigned char *Dest, unsigned int length)
    01649 {
    01650         unsigned int i, istart;
    01651         unsigned char *cursrc1, *curdst;
    01652
    01653         /* Validate input parameters */
    01654         if ((Src1 == NULL) || (Dest == NULL))
    01655                 return(-1);
    01656         if (length == 0)
    01657                 return(0);
    01658
    01659         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    01660                 /* MMX routine */
    01661                 SDL_imageFilterBitNegationMMX(Src1, Dest, length);
    01662
    01663                 /* Check for unaligned bytes */
    01664                 if ((length & 7) > 0) {
    01665                         /* Setup to process unaligned bytes */
    01666                         istart = length & 0xfffffff8;
    01667                         cursrc1 = &Src1[istart];
    01668                         curdst = &Dest[istart];
    01669                 } else {
    01670                         /* No unaligned bytes - we are done */
    01671                         return (0);
    01672                 }
    01673         } else {
    01674                 /* Setup to process whole image */
    01675                 istart = 0;
    01676                 cursrc1 = Src1;
    01677                 curdst = Dest;
    01678         }
    01679
    01680         /* C routine to process image */
    01681         for (i = istart; i < length; i++) {
    01682                 *curdst = ~(*cursrc1);
    01683                 /* Advance pointers */
    01684                 cursrc1++;
    01685                 curdst++;
    01686         }
    01687
    01688         return (0);
    01689 }
    01690
    01701 int SDL_imageFilterAddByteMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength, unsigned char C)
    01702 {
    01703 #ifdef USE_MMX
    01704 #if !defined(GCC__)
    01705         __asm
    01706         {
    01707                 pusha
    01708                         /* ** Duplicate C in 8 bytes of MM1 ** */
    01709                         mov al, C       /* load C into AL */
    01710                         mov ah, al      /* copy AL into AH */
    01711                         mov bx, ax      /* copy AX into BX */
    01712                         shl eax, 16     /* shift 2 bytes of EAX left */
    01713                         mov ax, bx      /* copy BX into AX */
    01714                         movd mm1, eax           /* copy EAX into MM1 */
    01715                         movd mm2, eax           /* copy EAX into MM2 */
    01716                         punpckldq mm1, mm2      /* fill higher bytes of MM1 with C */
    01717                         mov eax, Src1           /* load Src1 address into eax */
    01718                         mov edi, Dest           /* load Dest address into edi */
    01719                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    01720                         shr ecx,  3     /* counter/8 (MMX loads 8 bytes at a time) */
    01721                         align 16                        /* 16 byte alignment of the loop entry */
    01722 L1021:
    01723                 movq mm0, [eax]         /* load 8 bytes from Src1 into MM0 */
    01724                 paddusb mm0,  mm1       /* MM0=SrcDest+C (add 8 bytes with saturation) */
    01725                         movq [edi], mm0         /* store result in Dest */
    01726                         add eax, 8      /* increase Dest register pointer by 8 */
    01727                         add edi, 8      /* increase Dest register pointer by 8 */
    01728                         dec              ecx            /* decrease loop counter */
    01729                         jnz             L1021           /* check loop termination, proceed if required */
    01730                         emms                            /* exit MMX state */
    01731                         popa
    01732         }
    01733 #else
    01734         asm volatile
    01735                 ("pusha              \n\t"
    01736                 /* ** Duplicate C in 8 bytes of MM1 ** */
    01737                 "mov           %3, %%al \n\t"   /* load C into AL */
    01738                 "mov         %%al, %%ah \n\t"   /* copy AL into AH */
    01739                 "mov         %%ax, %%bx \n\t"   /* copy AX into BX */
    01740                 "shl         $16, %%eax \n\t"   /* shift 2 bytes of EAX left */
    01741                 "mov         %%bx, %%ax \n\t"   /* copy BX into AX */
    01742                 "movd      %%eax, %%mm1 \n\t"   /* copy EAX into MM1 */
    01743                 "movd      %%eax, %%mm2 \n\t"   /* copy EAX into MM2 */
    01744                 "punpckldq %%mm2, %%mm1 \n\t"   /* fill higher bytes of MM1 with C */
    01745                 "mov          %1, %%eax \n\t"   /* load Src1 address into eax */
    01746                 "mov          %0, %%edi \n\t"   /* load Dest address into edi */
    01747                 "mov          %2, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    01748                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    01749                 ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    01750                 "1:                     \n\t"
    01751                 "movq    (%%eax), %%mm0 \n\t"   /* load 8 bytes from Src1 into MM0 */
    01752                 "paddusb   %%mm1, %%mm0 \n\t"   /* MM0=SrcDest+C (add 8 bytes with saturation) */
    01753                 "movq    %%mm0, (%%edi) \n\t"   /* store result in Dest */
    01754                 "add          $8, %%eax \n\t"   /* increase Dest register pointer by 8 */
    01755                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    01756                 "dec              %%ecx \n\t"   /* decrease loop counter */
    01757                 "jnz                 1b \n\t"   /* check loop termination, proceed if required */
    01758                 "emms                   \n\t"   /* exit MMX state */
    01759                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    01760                 :"m"(Src1),             /* %1 */
    01761                 "m"(SrcLength),         /* %2 */
    01762                 "m"(C)                  /* %3 */
    01763                 );
    01764 #endif
    01765         return (0);
    01766 #else
    01767         return (-1);
    01768 #endif
    01769 }
    01770
    01782 int SDL_imageFilterAddByte(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char C)
    01783 {
    01784         unsigned int i, istart;
    01785         int iC;
    01786         unsigned char *cursrc1, *curdest;
    01787         int result;
    01788
    01789         /* Validate input parameters */
    01790         if ((Src1 == NULL) || (Dest == NULL))
    01791                 return(-1);
    01792         if (length == 0)
    01793                 return(0);
    01794
    01795         /* Special case: C==0 */
    01796         if (C == 0) {
    01797                 memcpy(Src1, Dest, length);
    01798                 return (0);
    01799         }
    01800
    01801         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    01802
    01803                 /* MMX routine */
    01804                 SDL_imageFilterAddByteMMX(Src1, Dest, length, C);
    01805
    01806                 /* Check for unaligned bytes */
    01807                 if ((length & 7) > 0) {
    01808                         /* Setup to process unaligned bytes */
    01809                         istart = length & 0xfffffff8;
    01810                         cursrc1 = &Src1[istart];
    01811                         curdest = &Dest[istart];
    01812                 } else {
    01813                         /* No unaligned bytes - we are done */
    01814                         return (0);
    01815                 }
    01816         } else {
    01817                 /* Setup to process whole image */
    01818                 istart = 0;
    01819                 cursrc1 = Src1;
    01820                 curdest = Dest;
    01821         }
    01822
    01823         /* C routine to process image */
    01824         iC = (int) C;
    01825         for (i = istart; i < length; i++) {
    01826                 result = (int) *cursrc1 + iC;
    01827                 if (result > 255)
    01828                         result = 255;
    01829                 *curdest = (unsigned char) result;
    01830                 /* Advance pointers */
    01831                 cursrc1++;
    01832                 curdest++;
    01833         }
    01834         return (0);
    01835 }
    01836
    01848 int SDL_imageFilterAddUintMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength, unsigned int C, unsigned int D)
    01849 {
    01850 #ifdef USE_MMX
    01851 #if !defined(GCC__)
    01852         __asm
    01853         {
    01854                 pusha
    01855                         /* ** Duplicate (int)C in 8 bytes of MM1 ** */
    01856                         mov eax, C      /* load C into EAX */
    01857                         movd mm1, eax           /* copy EAX into MM1 */
    01858                         mov eax, D      /* load D into EAX */
    01859                         movd mm2, eax           /* copy EAX into MM2 */
    01860                         punpckldq mm1, mm2      /* fill higher bytes of MM1 with C */
    01861                         mov eax, Src1           /* load Src1 address into eax */
    01862                         mov edi, Dest           /* load Dest address into edi */
    01863                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    01864                         shr ecx,  3     /* counter/8 (MMX loads 8 bytes at a time) */
    01865                         align 16                        /* 16 byte alignment of the loop entry */
    01866 L11023:
    01867                 movq mm0, [eax]         /* load 8 bytes from SrcDest into MM0 */
    01868                 paddusb mm0,  mm1       /* MM0=SrcDest+C (add 8 bytes with saturation) */
    01869                         movq [edi],  mm0        /* store result in SrcDest */
    01870                         add eax, 8      /* increase Src1 register pointer by 8 */
    01871                         add edi, 8      /* increase Dest register pointer by 8 */
    01872                         dec              ecx            /* decrease loop counter */
    01873                         jnz             L11023          /* check loop termination, proceed if required */
    01874                         emms                            /* exit MMX state */
    01875                         popa
    01876         }
    01877 #else
    01878         asm volatile
    01879                 ("pusha              \n\t"
    01880                 /* ** Duplicate (int)C in 8 bytes of MM1 ** */
    01881                 "mov          %3, %%eax \n\t"   /* load C into EAX */
    01882                 "movd      %%eax, %%mm1 \n\t"   /* copy EAX into MM1 */
    01883                 "mov          %4, %%eax \n\t"   /* load D into EAX */
    01884                 "movd      %%eax, %%mm2 \n\t"   /* copy EAX into MM2 */
    01885                 "punpckldq %%mm2, %%mm1 \n\t"   /* fill higher bytes of MM1 with C */
    01886                 "mov          %1, %%eax \n\t"   /* load Src1 address into eax */
    01887                 "mov          %0, %%edi \n\t"   /* load Dest address into edi */
    01888                 "mov          %2, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    01889                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    01890                 ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    01891                 "1:                     \n\t"
    01892                 "movq    (%%eax), %%mm0 \n\t"   /* load 8 bytes from SrcDest into MM0 */
    01893                 "paddusb   %%mm1, %%mm0 \n\t"   /* MM0=SrcDest+C (add 8 bytes with saturation) */
    01894                 "movq    %%mm0, (%%edi) \n\t"   /* store result in SrcDest */
    01895                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    01896                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    01897                 "dec              %%ecx \n\t"   /* decrease loop counter */
    01898                 "jnz                 1b \n\t"   /* check loop termination, proceed if required */
    01899                 "emms                   \n\t"   /* exit MMX state */
    01900                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    01901                 :"m"(Src1),             /* %1 */
    01902                 "m"(SrcLength),         /* %2 */
    01903                 "m"(C),                 /* %3 */
    01904                 "m"(D)                  /* %4 */
    01905                 );
    01906 #endif
    01907         return (0);
    01908 #else
    01909         return (-1);
    01910 #endif
    01911 }
    01912
    01923 int SDL_imageFilterAddUint(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned int C)
    01924 {
    01925         unsigned int i, j, istart, D;
    01926         int iC[4];
    01927         unsigned char *cursrc1;
    01928         unsigned char *curdest;
    01929         int result;
    01930
    01931         /* Validate input parameters */
    01932         if ((Src1 == NULL) || (Dest == NULL))
    01933                 return(-1);
    01934         if (length == 0)
    01935                 return(0);
    01936
    01937         /* Special case: C==0 */
    01938         if (C == 0) {
    01939                 memcpy(Src1, Dest, length);
    01940                 return (0);
    01941         }
    01942
    01943         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    01944
    01945                 /* MMX routine */
    01946                 D=SWAP_32(C);
    01947                 SDL_imageFilterAddUintMMX(Src1, Dest, length, C, D);
    01948
    01949                 /* Check for unaligned bytes */
    01950                 if ((length & 7) > 0) {
    01951                         /* Setup to process unaligned bytes */
    01952                         istart = length & 0xfffffff8;
    01953                         cursrc1 = &Src1[istart];
    01954                         curdest = &Dest[istart];
    01955                 } else {
    01956                         /* No unaligned bytes - we are done */
    01957                         return (0);
    01958                 }
    01959         } else {
    01960                 /* Setup to process whole image */
    01961                 istart = 0;
    01962                 cursrc1 = Src1;
    01963                 curdest = Dest;
    01964         }
    01965
    01966         /* C routine to process bytes */
    01967         iC[3] = (int) ((C >> 24) & 0xff);
    01968         iC[2] = (int) ((C >> 16) & 0xff);
    01969         iC[1] = (int) ((C >>  8) & 0xff);
    01970         iC[0] = (int) ((C >>  0) & 0xff);
    01971         for (i = istart; i < length; i += 4) {
    01972                 for (j = 0; j < 4; j++) {
    01973                         if ((i+j)<length) {
    01974                                 result = (int) *cursrc1 + iC[j];
    01975                                 if (result > 255) result = 255;
    01976                                 *curdest = (unsigned char) result;
    01977                                 /* Advance pointers */
    01978                                 cursrc1++;
    01979                                 curdest++;
    01980                         }
    01981                 }
    01982         }
    01983         return (0);
    01984 }
    01985
    01997 int SDL_imageFilterAddByteToHalfMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength, unsigned char C,
    01998                                                                         unsigned char *Mask)
    01999 {
    02000 #ifdef USE_MMX
    02001 #if !defined(GCC__)
    02002         __asm
    02003         {
    02004                 pusha
    02005                         /* ** Duplicate C in 8 bytes of MM1 ** */
    02006                         mov al, C       /* load C into AL */
    02007                         mov ah, al      /* copy AL into AH */
    02008                         mov bx, ax      /* copy AX into BX */
    02009                         shl eax, 16     /* shift 2 bytes of EAX left */
    02010                         mov ax, bx      /* copy BX into AX */
    02011                         movd mm1, eax           /* copy EAX into MM1 */
    02012                         movd mm2, eax           /* copy EAX into MM2 */
    02013                         punpckldq mm1, mm2      /* fill higher bytes of MM1 with C */
    02014                         mov edx, Mask           /* load Mask address into edx */
    02015                         movq mm0, [edx]         /* load Mask into mm0 */
    02016                 mov eax, Src1           /* load Src1 address into eax */
    02017                         mov edi, Dest           /* load Dest address into edi */
    02018                         mov ecx,  SrcLength     /* load loop counter (SIZE) into ecx */
    02019                         shr ecx,  3     /* counter/8 (MMX loads 8 bytes at a time) */
    02020                         align 16                        /* 16 byte alignment of the loop entry */
    02021 L1022:
    02022                 movq mm2, [eax]         /* load 8 bytes from Src1 into MM2 */
    02023                 psrlw mm2, 1    /* shift 4 WORDS of MM2 1 bit to the right */
    02024                         pand mm2, mm0        // apply Mask to 8 BYTES of MM2 */
    02025                         /* byte     0x0f, 0xdb, 0xd0 */
    02026                         paddusb mm2,  mm1       /* MM2=SrcDest+C (add 8 bytes with saturation) */
    02027                         movq [edi], mm2         /* store result in Dest */
    02028                         add eax, 8      /* increase Src1 register pointer by 8 */
    02029                         add edi, 8      /* increase Dest register pointer by 8 */
    02030                         dec              ecx            /* decrease loop counter */
    02031                         jnz             L1022           /* check loop termination, proceed if required */
    02032                         emms                            /* exit MMX state */
    02033                         popa
    02034         }
    02035 #else
    02036         asm volatile
    02037                 ("pusha              \n\t"
    02038                 /* ** Duplicate C in 8 bytes of MM1 ** */
    02039                 "mov           %3, %%al \n\t"   /* load C into AL */
    02040                 "mov         %%al, %%ah \n\t"   /* copy AL into AH */
    02041                 "mov         %%ax, %%bx \n\t"   /* copy AX into BX */
    02042                 "shl         $16, %%eax \n\t"   /* shift 2 bytes of EAX left */
    02043                 "mov         %%bx, %%ax \n\t"   /* copy BX into AX */
    02044                 "movd      %%eax, %%mm1 \n\t"   /* copy EAX into MM1 */
    02045                 "movd      %%eax, %%mm2 \n\t"   /* copy EAX into MM2 */
    02046                 "punpckldq %%mm2, %%mm1 \n\t"   /* fill higher bytes of MM1 with C */
    02047                 "movl         %4, %%edx \n\t"   /* load Mask address into edx */
    02048                 "movq    (%%edx), %%mm0 \n\t"   /* load Mask into mm0 */
    02049                 "mov          %1, %%eax \n\t"   /* load Src1 address into eax */
    02050                 "mov          %0, %%edi \n\t"   /* load Dest address into edi */
    02051                 "mov          %2, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    02052                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    02053                 ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    02054                 "1:                     \n\t"
    02055                 "movq    (%%eax), %%mm2 \n\t"   /* load 8 bytes from Src1 into MM2 */
    02056                 "psrlw        $1, %%mm2 \n\t"   /* shift 4 WORDS of MM2 1 bit to the right */
    02057                 /*    "pand      %%mm0, %%mm2 \n\t"    // apply Mask to 8 BYTES of MM2 */
    02058                 ".byte     0x0f, 0xdb, 0xd0 \n\t"
    02059                 "paddusb   %%mm1, %%mm2 \n\t"   /* MM2=SrcDest+C (add 8 bytes with saturation) */
    02060                 "movq    %%mm2, (%%edi) \n\t"   /* store result in Dest */
    02061                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    02062                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    02063                 "dec              %%ecx \n\t"   /* decrease loop counter */
    02064                 "jnz                  1b \n\t"  /* check loop termination, proceed if required */
    02065                 "emms                   \n\t"   /* exit MMX state */
    02066                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    02067                 :"m"(Src1),             /* %1 */
    02068                 "m"(SrcLength),         /* %2 */
    02069                 "m"(C),                 /* %3 */
    02070                 "m"(Mask)                       /* %4 */
    02071                 );
    02072 #endif
    02073         return (0);
    02074 #else
    02075         return (-1);
    02076 #endif
    02077 }
    02078
    02089 int SDL_imageFilterAddByteToHalf(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char C)
    02090 {
    02091         static unsigned char Mask[8] = { 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F };
    02092         unsigned int i, istart;
    02093         int iC;
    02094         unsigned char *cursrc1;
    02095         unsigned char *curdest;
    02096         int result;
    02097
    02098         /* Validate input parameters */
    02099         if ((Src1 == NULL) || (Dest == NULL))
    02100                 return(-1);
    02101         if (length == 0)
    02102                 return(0);
    02103
    02104         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    02105
    02106                 /* MMX routine */
    02107                 SDL_imageFilterAddByteToHalfMMX(Src1, Dest, length, C, Mask);
    02108
    02109                 /* Check for unaligned bytes */
    02110                 if ((length & 7) > 0) {
    02111                         /* Setup to process unaligned bytes */
    02112                         istart = length & 0xfffffff8;
    02113                         cursrc1 = &Src1[istart];
    02114                         curdest = &Dest[istart];
    02115                 } else {
    02116                         /* No unaligned bytes - we are done */
    02117                         return (0);
    02118                 }
    02119         } else {
    02120                 /* Setup to process whole image */
    02121                 istart = 0;
    02122                 cursrc1 = Src1;
    02123                 curdest = Dest;
    02124         }
    02125
    02126         /* C routine to process image */
    02127         iC = (int) C;
    02128         for (i = istart; i < length; i++) {
    02129                 result = (int) (*cursrc1 / 2) + iC;
    02130                 if (result > 255)
    02131                         result = 255;
    02132                 *curdest = (unsigned char) result;
    02133                 /* Advance pointers */
    02134                 cursrc1++;
    02135                 curdest++;
    02136         }
    02137
    02138         return (0);
    02139 }
    02140
    02151 int SDL_imageFilterSubByteMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength, unsigned char C)
    02152 {
    02153 #ifdef USE_MMX
    02154 #if !defined(GCC__)
    02155         __asm
    02156         {
    02157                 pusha
    02158                         /* ** Duplicate C in 8 bytes of MM1 ** */
    02159                         mov al, C       /* load C into AL */
    02160                         mov ah, al      /* copy AL into AH */
    02161                         mov bx, ax      /* copy AX into BX */
    02162                         shl eax, 16     /* shift 2 bytes of EAX left */
    02163                         mov ax, bx      /* copy BX into AX */
    02164                         movd mm1, eax           /* copy EAX into MM1 */
    02165                         movd mm2, eax           /* copy EAX into MM2 */
    02166                         punpckldq mm1, mm2      /* fill higher bytes of MM1 with C */
    02167                         mov eax, Src1           /* load Src1 address into eax */
    02168                         mov edi, Dest           /* load Dest address into edi */
    02169                         mov ecx,  SrcLength     /* load loop counter (SIZE) into ecx */
    02170                         shr ecx,  3     /* counter/8 (MMX loads 8 bytes at a time) */
    02171                         align 16                        /* 16 byte alignment of the loop entry */
    02172 L1023:
    02173                 movq mm0, [eax]         /* load 8 bytes from SrcDest into MM0 */
    02174                 psubusb mm0,  mm1       /* MM0=SrcDest-C (sub 8 bytes with saturation) */
    02175                         movq [edi], mm0         /* store result in SrcDest */
    02176                         add eax, 8      /* increase Src1 register pointer by 8 */
    02177                         add edi, 8      /* increase Dest register pointer by 8 */
    02178                         dec              ecx            /* decrease loop counter */
    02179                         jnz             L1023           /* check loop termination, proceed if required */
    02180                         emms                            /* exit MMX state */
    02181                         popa
    02182         }
    02183 #else
    02184         asm volatile
    02185                 ("pusha              \n\t"
    02186                 /* ** Duplicate C in 8 bytes of MM1 ** */
    02187                 "mov           %3, %%al \n\t"   /* load C into AL */
    02188                 "mov         %%al, %%ah \n\t"   /* copy AL into AH */
    02189                 "mov         %%ax, %%bx \n\t"   /* copy AX into BX */
    02190                 "shl         $16, %%eax \n\t"   /* shift 2 bytes of EAX left */
    02191                 "mov         %%bx, %%ax \n\t"   /* copy BX into AX */
    02192                 "movd      %%eax, %%mm1 \n\t"   /* copy EAX into MM1 */
    02193                 "movd      %%eax, %%mm2 \n\t"   /* copy EAX into MM2 */
    02194                 "punpckldq %%mm2, %%mm1 \n\t"   /* fill higher bytes of MM1 with C */
    02195                 "mov          %1, %%eax \n\t"   /* load Src1 address into eax */
    02196                 "mov          %0, %%edi \n\t"   /* load Dest address into edi */
    02197                 "mov          %2, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    02198                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    02199                 ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    02200                 "1: movq (%%eax), %%mm0 \n\t"   /* load 8 bytes from SrcDest into MM0 */
    02201                 "psubusb   %%mm1, %%mm0 \n\t"   /* MM0=SrcDest-C (sub 8 bytes with saturation) */
    02202                 "movq    %%mm0, (%%edi) \n\t"   /* store result in SrcDest */
    02203                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    02204                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    02205                 "dec              %%ecx \n\t"   /* decrease loop counter */
    02206                 "jnz                 1b \n\t"   /* check loop termination, proceed if required */
    02207                 "emms                   \n\t"   /* exit MMX state */
    02208                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    02209                 :"m"(Src1),             /* %1 */
    02210                 "m"(SrcLength),         /* %2 */
    02211                 "m"(C)                  /* %3 */
    02212                 );
    02213 #endif
    02214         return (0);
    02215 #else
    02216         return (-1);
    02217 #endif
    02218 }
    02219
    02230 int SDL_imageFilterSubByte(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char C)
    02231 {
    02232         unsigned int i, istart;
    02233         int iC;
    02234         unsigned char *cursrc1;
    02235         unsigned char *curdest;
    02236         int result;
    02237
    02238         /* Validate input parameters */
    02239         if ((Src1 == NULL) || (Dest == NULL))
    02240                 return(-1);
    02241         if (length == 0)
    02242                 return(0);
    02243
    02244         /* Special case: C==0 */
    02245         if (C == 0) {
    02246                 memcpy(Src1, Dest, length);
    02247                 return (0);
    02248         }
    02249
    02250         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    02251
    02252                 /* MMX routine */
    02253                 SDL_imageFilterSubByteMMX(Src1, Dest, length, C);
    02254
    02255                 /* Check for unaligned bytes */
    02256                 if ((length & 7) > 0) {
    02257                         /* Setup to process unaligned bytes */
    02258                         istart = length & 0xfffffff8;
    02259                         cursrc1 = &Src1[istart];
    02260                         curdest = &Dest[istart];
    02261                 } else {
    02262                         /* No unaligned bytes - we are done */
    02263                         return (0);
    02264                 }
    02265         } else {
    02266                 /* Setup to process whole image */
    02267                 istart = 0;
    02268                 cursrc1 = Src1;
    02269                 curdest = Dest;
    02270         }
    02271
    02272         /* C routine to process image */
    02273         iC = (int) C;
    02274         for (i = istart; i < length; i++) {
    02275                 result = (int) *cursrc1 - iC;
    02276                 if (result < 0)
    02277                         result = 0;
    02278                 *curdest = (unsigned char) result;
    02279                 /* Advance pointers */
    02280                 cursrc1++;
    02281                 curdest++;
    02282         }
    02283         return (0);
    02284 }
    02285
    02297 int SDL_imageFilterSubUintMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength, unsigned int C, unsigned int D)
    02298 {
    02299 #ifdef USE_MMX
    02300 #if !defined(GCC__)
    02301         __asm
    02302         {
    02303                 pusha
    02304                         /* ** Duplicate (int)C in 8 bytes of MM1 ** */
    02305                         mov eax, C      /* load C into EAX */
    02306                         movd mm1, eax           /* copy EAX into MM1 */
    02307                         mov eax, D      /* load D into EAX */
    02308                         movd mm2, eax           /* copy EAX into MM2 */
    02309                         punpckldq mm1, mm2      /* fill higher bytes of MM1 with C */
    02310                         mov eax, Src1           /* load Src1 address into eax */
    02311                         mov edi, Dest           /* load Dest address into edi */
    02312                         mov ecx,  SrcLength     /* load loop counter (SIZE) into ecx */
    02313                         shr ecx,  3     /* counter/8 (MMX loads 8 bytes at a time) */
    02314                         align 16                        /* 16 byte alignment of the loop entry */
    02315 L11024:
    02316                 movq mm0, [eax]         /* load 8 bytes from SrcDest into MM0 */
    02317                 psubusb mm0, mm1        /* MM0=SrcDest-C (sub 8 bytes with saturation) */
    02318                         movq [edi], mm0         /* store result in SrcDest */
    02319                         add eax, 8      /* increase Src1 register pointer by 8 */
    02320                         add edi, 8      /* increase Dest register pointer by 8 */
    02321                         dec              ecx            /* decrease loop counter */
    02322                         jnz             L11024          /* check loop termination, proceed if required */
    02323                         emms                            /* exit MMX state */
    02324                         popa
    02325         }
    02326 #else
    02327         asm volatile
    02328                 ("pusha              \n\t"
    02329                 /* ** Duplicate (int)C in 8 bytes of MM1 ** */
    02330                 "mov          %3, %%eax \n\t"   /* load C into EAX */
    02331                 "movd      %%eax, %%mm1 \n\t"   /* copy EAX into MM1 */
    02332                 "mov          %4, %%eax \n\t"   /* load D into EAX */
    02333                 "movd      %%eax, %%mm2 \n\t"   /* copy EAX into MM2 */
    02334                 "punpckldq %%mm2, %%mm1 \n\t"   /* fill higher bytes of MM1 with C */
    02335                 "mov          %1, %%eax \n\t"   /* load Src1 address into eax */
    02336                 "mov          %0, %%edi \n\t"   /* load Dest address into edi */
    02337                 "mov          %2, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    02338                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    02339                 ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    02340                 "1: movq (%%eax), %%mm0 \n\t"   /* load 8 bytes from SrcDest into MM0 */
    02341                 "psubusb   %%mm1, %%mm0 \n\t"   /* MM0=SrcDest-C (sub 8 bytes with saturation) */
    02342                 "movq    %%mm0, (%%edi) \n\t"   /* store result in SrcDest */
    02343                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    02344                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    02345                 "dec              %%ecx \n\t"   /* decrease loop counter */
    02346                 "jnz                  1b \n\t"  /* check loop termination, proceed if required */
    02347                 "emms                   \n\t"   /* exit MMX state */
    02348                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    02349                 :"m"(Src1),             /* %1 */
    02350                 "m"(SrcLength),         /* %2 */
    02351                 "m"(C),                 /* %3 */
    02352                 "m"(D)                  /* %4 */
    02353                 );
    02354 #endif
    02355         return (0);
    02356 #else
    02357         return (-1);
    02358 #endif
    02359 }
    02360
    02371 int SDL_imageFilterSubUint(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned int C)
    02372 {
    02373         unsigned int i, j, istart, D;
    02374         int iC[4];
    02375         unsigned char *cursrc1;
    02376         unsigned char *curdest;
    02377         int result;
    02378
    02379         /* Validate input parameters */
    02380         if ((Src1 == NULL) || (Dest == NULL))
    02381                 return(-1);
    02382         if (length == 0)
    02383                 return(0);
    02384
    02385     /* Special case: C==0 */
    02386         if (C == 0) {
    02387                 memcpy(Src1, Dest, length);
    02388                 return (0);
    02389         }
    02390
    02391         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    02392
    02393                 /* MMX routine */
    02394                 D=SWAP_32(C);
    02395                 SDL_imageFilterSubUintMMX(Src1, Dest, length, C, D);
    02396
    02397                 /* Check for unaligned bytes */
    02398                 if ((length & 7) > 0) {
    02399                         /* Setup to process unaligned bytes */
    02400                         istart = length & 0xfffffff8;
    02401                         cursrc1 = &Src1[istart];
    02402                         curdest = &Dest[istart];
    02403                 } else {
    02404                         /* No unaligned bytes - we are done */
    02405                         return (0);
    02406                 }
    02407         } else {
    02408                 /* Setup to process whole image */
    02409                 istart = 0;
    02410                 cursrc1 = Src1;
    02411                 curdest = Dest;
    02412         }
    02413
    02414         /* C routine to process image */
    02415         iC[3] = (int) ((C >> 24) & 0xff);
    02416         iC[2] = (int) ((C >> 16) & 0xff);
    02417         iC[1] = (int) ((C >>  8) & 0xff);
    02418         iC[0] = (int) ((C >>  0) & 0xff);
    02419         for (i = istart; i < length; i += 4) {
    02420                 for (j = 0; j < 4; j++) {
    02421                         if ((i+j)<length) {
    02422                                 result = (int) *cursrc1 - iC[j];
    02423                                 if (result < 0) result = 0;
    02424                                 *curdest = (unsigned char) result;
    02425                                 /* Advance pointers */
    02426                                 cursrc1++;
    02427                                 curdest++;
    02428                         }
    02429                 }
    02430         }
    02431         return (0);
    02432 }
    02433
    02445 int SDL_imageFilterShiftRightMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength, unsigned char N,
    02446                                                                  unsigned char *Mask)
    02447 {
    02448 #ifdef USE_MMX
    02449 #if !defined(GCC__)
    02450         __asm
    02451         {
    02452                 pusha
    02453                         mov edx, Mask           /* load Mask address into edx */
    02454                         movq mm0, [edx]         /* load Mask into mm0 */
    02455                 xor ecx, ecx    /* zero ECX */
    02456                         mov cl,  N      /* load loop counter (N) into CL */
    02457                         movd mm3,  ecx  /* copy (N) into MM3  */
    02458                         pcmpeqb mm1, mm1        /* generate all 1's in mm1 */
    02459 L10240:                         /* ** Prepare proper bit-Mask in MM1 ** */
    02460                 psrlw mm1,  1   /* shift 4 WORDS of MM1 1 bit to the right */
    02461                         pand mm1, mm0   // apply Mask to 8 BYTES of MM1 */
    02462                         /*  byte     0x0f, 0xdb, 0xc8 */
    02463                         dec               cl            /* decrease loop counter */
    02464                         jnz            L10240           /* check loop termination, proceed if required */
    02465                         /* ** Shift all bytes of the image ** */
    02466                         mov eax, Src1           /* load Src1 address into eax */
    02467                         mov edi, Dest           /* load Dest address into edi */
    02468                         mov ecx,  SrcLength     /* load loop counter (SIZE) into ecx */
    02469                         shr ecx,  3     /* counter/8 (MMX loads 8 bytes at a time) */
    02470                         align 16                        /* 16 byte alignment of the loop entry */
    02471 L10241:
    02472                 movq mm0, [eax]         /* load 8 bytes from SrcDest into MM0 */
    02473                 psrlw mm0, mm3          /* shift 4 WORDS of MM0 (N) bits to the right */
    02474                         pand mm0, mm1    // apply proper bit-Mask to 8 BYTES of MM0 */
    02475                         /* byte     0x0f, 0xdb, 0xc1 */
    02476                         movq [edi], mm0         /* store result in SrcDest */
    02477                         add eax, 8      /* increase Src1 register pointer by 8 */
    02478                         add edi, 8      /* increase Dest register pointer by 8 */
    02479                         dec              ecx            /* decrease loop counter */
    02480                         jnz            L10241           /* check loop termination, proceed if required */
    02481                         emms                            /* exit MMX state */
    02482                         popa
    02483         }
    02484 #else
    02485         asm volatile
    02486                 ("pusha              \n\t" "movl         %4, %%edx \n\t"        /* load Mask address into edx */
    02487                 "movq    (%%edx), %%mm0 \n\t"   /* load Mask into mm0 */
    02488                 "xor       %%ecx, %%ecx \n\t"   /* zero ECX */
    02489                 "mov           %3, %%cl \n\t"   /* load loop counter (N) into CL */
    02490                 "movd      %%ecx, %%mm3 \n\t"   /* copy (N) into MM3  */
    02491                 "pcmpeqb   %%mm1, %%mm1 \n\t"   /* generate all 1's in mm1 */
    02492                 "1:                     \n\t"   /* ** Prepare proper bit-Mask in MM1 ** */
    02493                 "psrlw        $1, %%mm1 \n\t"   /* shift 4 WORDS of MM1 1 bit to the right */
    02494                 /*    "pand      %%mm0, %%mm1 \n\t"    // apply Mask to 8 BYTES of MM1 */
    02495                 ".byte     0x0f, 0xdb, 0xc8 \n\t"
    02496                 "dec               %%cl \n\t"   /* decrease loop counter */
    02497                 "jnz                 1b \n\t"   /* check loop termination, proceed if required */
    02498                 /* ** Shift all bytes of the image ** */
    02499                 "mov          %1, %%eax \n\t"   /* load Src1 address into eax */
    02500                 "mov          %0, %%edi \n\t"   /* load Dest address into edi */
    02501                 "mov          %2, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    02502                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    02503                 ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    02504                 "2:                     \n\t"
    02505                 "movq    (%%eax), %%mm0 \n\t"   /* load 8 bytes from SrcDest into MM0 */
    02506                 "psrlw     %%mm3, %%mm0 \n\t"   /* shift 4 WORDS of MM0 (N) bits to the right */
    02507                 /*    "pand      %%mm1, %%mm0 \n\t"    // apply proper bit-Mask to 8 BYTES of MM0 */
    02508                 ".byte     0x0f, 0xdb, 0xc1 \n\t"
    02509                 "movq    %%mm0, (%%edi) \n\t"   /* store result in SrcDest */
    02510                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    02511                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    02512                 "dec              %%ecx \n\t"   /* decrease loop counter */
    02513                 "jnz                 2b \n\t"   /* check loop termination, proceed if required */
    02514                 "emms                   \n\t"   /* exit MMX state */
    02515                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    02516                 :"m"(Src1),             /* %1 */
    02517                 "m"(SrcLength),         /* %2 */
    02518                 "m"(N),                 /* %3 */
    02519                 "m"(Mask)                       /* %4 */
    02520                 );
    02521 #endif
    02522         return (0);
    02523 #else
    02524         return (-1);
    02525 #endif
    02526 }
    02527
    02538 int SDL_imageFilterShiftRight(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char N)
    02539 {
    02540         static unsigned char Mask[8] = { 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F };
    02541         unsigned int i, istart;
    02542         unsigned char *cursrc1;
    02543         unsigned char *curdest;
    02544
    02545         /* Validate input parameters */
    02546         if ((Src1 == NULL) || (Dest == NULL))
    02547                 return(-1);
    02548         if (length == 0)
    02549                 return(0);
    02550
    02551         /* Check shift */
    02552         if (N > 8) {
    02553                 return (-1);
    02554         }
    02555
    02556         /* Special case: N==0 */
    02557         if (N == 0) {
    02558                 memcpy(Src1, Dest, length);
    02559                 return (0);
    02560         }
    02561
    02562         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    02563
    02564                 /* MMX routine */
    02565                 SDL_imageFilterShiftRightMMX(Src1, Dest, length, N, Mask);
    02566
    02567                 /* Check for unaligned bytes */
    02568                 if ((length & 7) > 0) {
    02569                         /* Setup to process unaligned bytes */
    02570                         istart = length & 0xfffffff8;
    02571                         cursrc1 = &Src1[istart];
    02572                         curdest = &Dest[istart];
    02573                 } else {
    02574                         /* No unaligned bytes - we are done */
    02575                         return (0);
    02576                 }
    02577         } else {
    02578                 /* Setup to process whole image */
    02579                 istart = 0;
    02580                 cursrc1 = Src1;
    02581                 curdest = Dest;
    02582         }
    02583
    02584         /* C routine to process image */
    02585         for (i = istart; i < length; i++) {
    02586                 *curdest = (unsigned char) *cursrc1 >> N;
    02587                 /* Advance pointers */
    02588                 cursrc1++;
    02589                 curdest++;
    02590         }
    02591
    02592         return (0);
    02593 }
    02594
    02605 int SDL_imageFilterShiftRightUintMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength, unsigned char N)
    02606 {
    02607 #ifdef USE_MMX
    02608 #if !defined(GCC__)
    02609         __asm
    02610         {
    02611                 pusha
    02612                         mov eax, Src1           /* load Src1 address into eax */
    02613                         mov edi, Dest           /* load Dest address into edi */
    02614                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    02615                         shr ecx, 3      /* counter/8 (MMX loads 8 bytes at a time) */
    02616                         align 16                        /* 16 byte alignment of the loop entry */
    02617 L13023:
    02618                 movq mm0, [eax]         /* load 8 bytes from SrcDest into MM0 */
    02619                 psrld mm0, N
    02620                         movq [edi], mm0         /* store result in SrcDest */
    02621                         add eax, 8      /* increase Src1 register pointer by 8 */
    02622                         add edi, 8      /* increase Dest register pointer by 8 */
    02623                         dec              ecx            /* decrease loop counter */
    02624                         jnz             L13023          /* check loop termination, proceed if required */
    02625                         emms                            /* exit MMX state */
    02626                         popa
    02627         }
    02628 #else
    02629         asm volatile
    02630                 ("pusha              \n\t"
    02631                 "mov          %1, %%eax \n\t"   /* load Src1 address into eax */
    02632                 "mov          %0, %%edi \n\t"   /* load Dest address into edi */
    02633                 "mov          %2, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    02634                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    02635                 ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    02636                 "1: movq (%%eax), %%mm0 \n\t"   /* load 8 bytes from SrcDest into MM0 */
    02637                 "psrld   %3, %%mm0 \n\t"
    02638                 "movq    %%mm0, (%%edi) \n\t"   /* store result in SrcDest */
    02639                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    02640                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    02641                 "dec              %%ecx \n\t"   /* decrease loop counter */
    02642                 "jnz                 1b \n\t"   /* check loop termination, proceed if required */
    02643                 "emms                   \n\t"   /* exit MMX state */
    02644                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    02645                 :"m"(Src1),             /* %1 */
    02646                 "m"(SrcLength),         /* %2 */
    02647                 "m"(N)                  /* %3 */
    02648                 );
    02649 #endif
    02650         return (0);
    02651 #else
    02652         return (-1);
    02653 #endif
    02654 }
    02655
    02666 int SDL_imageFilterShiftRightUint(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char N)
    02667 {
    02668         unsigned int i, istart;
    02669         unsigned char *cursrc1, *curdest;
    02670         unsigned int *icursrc1, *icurdest;
    02671         int result;
    02672
    02673         /* Validate input parameters */
    02674         if ((Src1 == NULL) || (Dest == NULL))
    02675                 return(-1);
    02676         if (length == 0)
    02677                 return(0);
    02678
    02679         if (N > 32) {
    02680                 return (-1);
    02681         }
    02682
    02683         /* Special case: N==0 */
    02684         if (N == 0) {
    02685                 memcpy(Src1, Dest, length);
    02686                 return (0);
    02687         }
    02688
    02689         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    02690
    02691                 SDL_imageFilterShiftRightUintMMX(Src1, Dest, length, N);
    02692
    02693                 /* Check for unaligned bytes */
    02694                 if ((length & 7) > 0) {
    02695                         /* Setup to process unaligned bytes */
    02696                         istart = length & 0xfffffff8;
    02697                         cursrc1 = &Src1[istart];
    02698                         curdest = &Dest[istart];
    02699                 } else {
    02700                         /* No unaligned bytes - we are done */
    02701                         return (0);
    02702                 }
    02703         } else {
    02704                 /* Setup to process whole image */
    02705                 istart = 0;
    02706                 cursrc1 = Src1;
    02707                 curdest = Dest;
    02708         }
    02709
    02710         /* C routine to process image */
    02711         icursrc1=(unsigned int *)cursrc1;
    02712         icurdest=(unsigned int *)curdest;
    02713         for (i = istart; i < length; i += 4) {
    02714                 if ((i+4)<length) {
    02715                         result = ((unsigned int)*icursrc1 >> N);
    02716                         *icurdest = (unsigned int)result;
    02717                 }
    02718                 /* Advance pointers */
    02719                 icursrc1++;
    02720                 icurdest++;
    02721         }
    02722
    02723         return (0);
    02724 }
    02725
    02736 int SDL_imageFilterMultByByteMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength, unsigned char C)
    02737 {
    02738 #ifdef USE_MMX
    02739 #if !defined(GCC__)
    02740         __asm
    02741         {
    02742                 pusha
    02743                         /* ** Duplicate C in 4 words of MM1 ** */
    02744                         mov al, C       /* load C into AL */
    02745                         xor ah, ah      /* zero AH */
    02746                         mov bx, ax      /* copy AX into BX */
    02747                         shl eax, 16     /* shift 2 bytes of EAX left */
    02748                         mov ax, bx      /* copy BX into AX */
    02749                         movd mm1, eax           /* copy EAX into MM1 */
    02750                         movd mm2, eax           /* copy EAX into MM2 */
    02751                         punpckldq mm1, mm2      /* fill higher words of MM1 with C */
    02752                         pxor mm0, mm0           /* zero MM0 register */
    02753                         mov eax, Src1           /* load Src1 address into eax */
    02754                         mov edi, Dest           /* load Dest address into edi */
    02755                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    02756                         shr ecx, 3      /* counter/8 (MMX loads 8 bytes at a time) */
    02757                         cmp al, 128     /* if (C <= 128) execute more efficient code */
    02758                         jg             L10251
    02759                         align 16                        /* 16 byte alignment of the loop entry */
    02760 L10250:
    02761                 movq mm3, [eax]         /* load 8 bytes from Src1 into MM3 */
    02762                 movq mm4, mm3           /* copy MM3 into MM4  */
    02763                         punpcklbw mm3, mm0      /* unpack low  bytes of SrcDest into words */
    02764                         punpckhbw mm4, mm0      /* unpack high bytes of SrcDest into words */
    02765                         pmullw mm3, mm1         /* mul low  bytes of SrcDest and MM1 */
    02766                         pmullw mm4, mm1         /* mul high bytes of SrcDest and MM1 */
    02767                         packuswb mm3, mm4       /* pack words back into bytes with saturation */
    02768                         movq [edi], mm3         /* store result in Dest */
    02769                         add eax, 8      /* increase Src1 register pointer by 8 */
    02770                         add edi, 8      /* increase Dest register pointer by 8 */
    02771                         dec              ecx            /* decrease loop counter */
    02772                         jnz            L10250           /* check loop termination, proceed if required */
    02773                         jmp            L10252
    02774                         align 16                        /* 16 byte alignment of the loop entry */
    02775 L10251:
    02776                 movq mm3, [eax]         /* load 8 bytes from Src1 into MM3 */
    02777                 movq mm4, mm3           /* copy MM3 into MM4  */
    02778                         punpcklbw mm3, mm0      /* unpack low  bytes of SrcDest into words */
    02779                         punpckhbw mm4, mm0      /* unpack high bytes of SrcDest into words */
    02780                         pmullw mm3, mm1         /* mul low  bytes of SrcDest and MM1 */
    02781                         pmullw mm4, mm1         /* mul high bytes of SrcDest and MM1 */
    02782                         /* ** Take abs value of the results (signed words) ** */
    02783                         movq mm5, mm3           /* copy mm3 into mm5 */
    02784                         movq mm6, mm4           /* copy mm4 into mm6 */
    02785                         psraw mm5, 15           /* fill mm5 words with word sign bit */
    02786                         psraw mm6, 15           /* fill mm6 words with word sign bit */
    02787                         pxor mm3, mm5           /* take 1's compliment of only neg words */
    02788                         pxor mm4, mm6           /* take 1's compliment of only neg words */
    02789                         psubsw mm3, mm5         /* add 1 to only neg words, W-(-1) or W-0 */
    02790                         psubsw mm4, mm6         /* add 1 to only neg words, W-(-1) or W-0 */
    02791                         packuswb mm3, mm4       /* pack words back into bytes with saturation */
    02792                         movq [edi], mm3         /* store result in Dest */
    02793                         add eax, 8      /* increase Src1 register pointer by 8 */
    02794                         add edi, 8      /* increase Dest register pointer by 8 */
    02795                         dec              ecx            /* decrease loop counter */
    02796                         jnz            L10251           /* check loop termination, proceed if required */
    02797 L10252:
    02798                 emms                            /* exit MMX state */
    02799                         popa
    02800         }
    02801 #else
    02802         asm volatile
    02803                 ("pusha              \n\t"
    02804                 /* ** Duplicate C in 4 words of MM1 ** */
    02805                 "mov           %3, %%al \n\t"   /* load C into AL */
    02806                 "xor         %%ah, %%ah \n\t"   /* zero AH */
    02807                 "mov         %%ax, %%bx \n\t"   /* copy AX into BX */
    02808                 "shl         $16, %%eax \n\t"   /* shift 2 bytes of EAX left */
    02809                 "mov         %%bx, %%ax \n\t"   /* copy BX into AX */
    02810                 "movd      %%eax, %%mm1 \n\t"   /* copy EAX into MM1 */
    02811                 "movd      %%eax, %%mm2 \n\t"   /* copy EAX into MM2 */
    02812                 "punpckldq %%mm2, %%mm1 \n\t"   /* fill higher words of MM1 with C */
    02813                 "pxor      %%mm0, %%mm0 \n\t"   /* zero MM0 register */
    02814                 "mov          %1, %%eax \n\t"   /* load Src1 address into eax */
    02815                 "mov          %0, %%edi \n\t"   /* load Dest address into edi */
    02816                 "mov          %2, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    02817                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    02818                 "cmp         $128, %%al \n\t"   /* if (C <= 128) execute more efficient code */
    02819                 "jg                  2f \n\t" ".align 16              \n\t"     /* 16 byte alignment of the loop entry */
    02820                 "1: movq (%%eax), %%mm3 \n\t"   /* load 8 bytes from Src1 into MM3 */
    02821                 "movq      %%mm3, %%mm4 \n\t"   /* copy MM3 into MM4  */
    02822                 "punpcklbw %%mm0, %%mm3 \n\t"   /* unpack low  bytes of SrcDest into words */
    02823                 "punpckhbw %%mm0, %%mm4 \n\t"   /* unpack high bytes of SrcDest into words */
    02824                 "pmullw    %%mm1, %%mm3 \n\t"   /* mul low  bytes of SrcDest and MM1 */
    02825                 "pmullw    %%mm1, %%mm4 \n\t"   /* mul high bytes of SrcDest and MM1 */
    02826                 "packuswb  %%mm4, %%mm3 \n\t"   /* pack words back into bytes with saturation */
    02827                 "movq    %%mm3, (%%edi) \n\t"   /* store result in Dest */
    02828                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    02829                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    02830                 "dec              %%ecx \n\t"   /* decrease loop counter */
    02831                 "jnz                 1b \n\t"   /* check loop termination, proceed if required */
    02832                 "jmp                 3f \n\t" ".align 16              \n\t"     /* 16 byte alignment of the loop entry */
    02833                 "2: movq (%%eax), %%mm3 \n\t"   /* load 8 bytes from Src1 into MM3 */
    02834                 "movq      %%mm3, %%mm4 \n\t"   /* copy MM3 into MM4  */
    02835                 "punpcklbw %%mm0, %%mm3 \n\t"   /* unpack low  bytes of SrcDest into words */
    02836                 "punpckhbw %%mm0, %%mm4 \n\t"   /* unpack high bytes of SrcDest into words */
    02837                 "pmullw    %%mm1, %%mm3 \n\t"   /* mul low  bytes of SrcDest and MM1 */
    02838                 "pmullw    %%mm1, %%mm4 \n\t"   /* mul high bytes of SrcDest and MM1 */
    02839                 /* ** Take abs value of the results (signed words) ** */
    02840                 "movq      %%mm3, %%mm5 \n\t"   /* copy mm3 into mm5 */
    02841                 "movq      %%mm4, %%mm6 \n\t"   /* copy mm4 into mm6 */
    02842                 "psraw       $15, %%mm5 \n\t"   /* fill mm5 words with word sign bit */
    02843                 "psraw       $15, %%mm6 \n\t"   /* fill mm6 words with word sign bit */
    02844                 "pxor      %%mm5, %%mm3 \n\t"   /* take 1's compliment of only neg. words */
    02845                 "pxor      %%mm6, %%mm4 \n\t"   /* take 1's compliment of only neg. words */
    02846                 "psubsw    %%mm5, %%mm3 \n\t"   /* add 1 to only neg. words, W-(-1) or W-0 */
    02847                 "psubsw    %%mm6, %%mm4 \n\t"   /* add 1 to only neg. words, W-(-1) or W-0 */
    02848                 "packuswb  %%mm4, %%mm3 \n\t"   /* pack words back into bytes with saturation */
    02849                 "movq    %%mm3, (%%edi) \n\t"   /* store result in Dest */
    02850                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    02851                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    02852                 "dec              %%ecx \n\t"   /* decrease loop counter */
    02853                 "jnz                 2b \n\t"   /* check loop termination, proceed if required */
    02854                 "3: emms               \n\t"    /* exit MMX state */
    02855                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    02856                 :"m"(Src1),             /* %1 */
    02857                 "m"(SrcLength),         /* %2 */
    02858                 "m"(C)                  /* %3 */
    02859                 );
    02860 #endif
    02861         return (0);
    02862 #else
    02863         return (-1);
    02864 #endif
    02865 }
    02866
    02877 int SDL_imageFilterMultByByte(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char C)
    02878 {
    02879         unsigned int i, istart;
    02880         int iC;
    02881         unsigned char *cursrc1;
    02882         unsigned char *curdest;
    02883         int result;
    02884
    02885         /* Validate input parameters */
    02886         if ((Src1 == NULL) || (Dest == NULL))
    02887                 return(-1);
    02888         if (length == 0)
    02889                 return(0);
    02890
    02891         /* Special case: C==1 */
    02892         if (C == 1) {
    02893                 memcpy(Src1, Dest, length);
    02894                 return (0);
    02895         }
    02896
    02897         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    02898
    02899                 SDL_imageFilterMultByByteMMX(Src1, Dest, length, C);
    02900
    02901                 /* Check for unaligned bytes */
    02902                 if ((length & 7) > 0) {
    02903                         /* Setup to process unaligned bytes */
    02904                         istart = length & 0xfffffff8;
    02905                         cursrc1 = &Src1[istart];
    02906                         curdest = &Dest[istart];
    02907                 } else {
    02908                         /* No unaligned bytes - we are done */
    02909                         return (0);
    02910                 }
    02911         } else {
    02912                 /* Setup to process whole image */
    02913                 istart = 0;
    02914                 cursrc1 = Src1;
    02915                 curdest = Dest;
    02916         }
    02917
    02918         /* C routine to process image */
    02919         iC = (int) C;
    02920         for (i = istart; i < length; i++) {
    02921                 result = (int) *cursrc1 * iC;
    02922                 if (result > 255)
    02923                         result = 255;
    02924                 *curdest = (unsigned char) result;
    02925                 /* Advance pointers */
    02926                 cursrc1++;
    02927                 curdest++;
    02928         }
    02929
    02930         return (0);
    02931 }
    02932
    02944 int SDL_imageFilterShiftRightAndMultByByteMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength, unsigned char N,
    02945                                                                                           unsigned char C)
    02946 {
    02947 #ifdef USE_MMX
    02948 #if !defined(GCC__)
    02949         __asm
    02950         {
    02951                 pusha
    02952                         /* ** Duplicate C in 4 words of MM1 ** */
    02953                         mov al, C       /* load C into AL */
    02954                         xor ah, ah      /* zero AH */
    02955                         mov bx, ax      /* copy AX into BX */
    02956                         shl eax, 16     /* shift 2 bytes of EAX left */
    02957                         mov ax, bx      /* copy BX into AX */
    02958                         movd mm1, eax           /* copy EAX into MM1 */
    02959                         movd mm2, eax           /* copy EAX into MM2 */
    02960                         punpckldq mm1, mm2      /* fill higher words of MM1 with C */
    02961                         xor ecx, ecx    /* zero ECX */
    02962                         mov cl, N       /* load N into CL */
    02963                         movd mm7, ecx           /* copy N into MM7 */
    02964                         pxor mm0, mm0           /* zero MM0 register */
    02965                         mov eax, Src1           /* load Src1 address into eax */
    02966                         mov edi, Dest           /* load Dest address into edi */
    02967                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    02968                         shr ecx, 3      /* counter/8 (MMX loads 8 bytes at a time) */
    02969                         align 16                        /* 16 byte alignment of the loop entry */
    02970 L1026:
    02971                 movq mm3, [eax]         /* load 8 bytes from Src1 into MM3 */
    02972                 movq mm4, mm3           /* copy MM3 into MM4  */
    02973                         punpcklbw mm3, mm0      /* unpack low  bytes of SrcDest into words */
    02974                         punpckhbw mm4, mm0      /* unpack high bytes of SrcDest into words */
    02975                         psrlw mm3, mm7          /* shift 4 WORDS of MM3 (N) bits to the right */
    02976                         psrlw mm4, mm7          /* shift 4 WORDS of MM4 (N) bits to the right */
    02977                         pmullw mm3, mm1         /* mul low  bytes of SrcDest by MM1 */
    02978                         pmullw mm4, mm1         /* mul high bytes of SrcDest by MM1 */
    02979                         packuswb mm3, mm4       /* pack words back into bytes with saturation */
    02980                         movq [edi], mm3         /* store result in Dest */
    02981                         add eax, 8      /* increase Src1 register pointer by 8 */
    02982                         add edi, 8      /* increase Dest register pointer by 8 */
    02983                         dec              ecx            /* decrease loop counter */
    02984                         jnz             L1026           /* check loop termination, proceed if required */
    02985                         emms                            /* exit MMX state */
    02986                         popa
    02987         }
    02988 #else
    02989         asm volatile
    02990                 ("pusha              \n\t"
    02991                 /* ** Duplicate C in 4 words of MM1 ** */
    02992                 "mov           %4, %%al \n\t"   /* load C into AL */
    02993                 "xor         %%ah, %%ah \n\t"   /* zero AH */
    02994                 "mov         %%ax, %%bx \n\t"   /* copy AX into BX */
    02995                 "shl         $16, %%eax \n\t"   /* shift 2 bytes of EAX left */
    02996                 "mov         %%bx, %%ax \n\t"   /* copy BX into AX */
    02997                 "movd      %%eax, %%mm1 \n\t"   /* copy EAX into MM1 */
    02998                 "movd      %%eax, %%mm2 \n\t"   /* copy EAX into MM2 */
    02999                 "punpckldq %%mm2, %%mm1 \n\t"   /* fill higher words of MM1 with C */
    03000                 "xor       %%ecx, %%ecx \n\t"   /* zero ECX */
    03001                 "mov           %3, %%cl \n\t"   /* load N into CL */
    03002                 "movd      %%ecx, %%mm7 \n\t"   /* copy N into MM7 */
    03003                 "pxor      %%mm0, %%mm0 \n\t"   /* zero MM0 register */
    03004                 "mov          %1, %%eax \n\t"   /* load Src1 address into eax */
    03005                 "mov          %0, %%edi \n\t"   /* load Dest address into edi */
    03006                 "mov          %2, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    03007                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    03008                 ".align 16             \n\t"    /* 16 byte alignment of the loop entry */
    03009                 "1: movq (%%eax), %%mm3 \n\t"   /* load 8 bytes from Src1 into MM3 */
    03010                 "movq      %%mm3, %%mm4 \n\t"   /* copy MM3 into MM4  */
    03011                 "punpcklbw %%mm0, %%mm3 \n\t"   /* unpack low  bytes of SrcDest into words */
    03012                 "punpckhbw %%mm0, %%mm4 \n\t"   /* unpack high bytes of SrcDest into words */
    03013                 "psrlw     %%mm7, %%mm3 \n\t"   /* shift 4 WORDS of MM3 (N) bits to the right */
    03014                 "psrlw     %%mm7, %%mm4 \n\t"   /* shift 4 WORDS of MM4 (N) bits to the right */
    03015                 "pmullw    %%mm1, %%mm3 \n\t"   /* mul low  bytes of SrcDest by MM1 */
    03016                 "pmullw    %%mm1, %%mm4 \n\t"   /* mul high bytes of SrcDest by MM1 */
    03017                 "packuswb  %%mm4, %%mm3 \n\t"   /* pack words back into bytes with saturation */
    03018                 "movq    %%mm3, (%%edi) \n\t"   /* store result in Dest */
    03019                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    03020                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    03021                 "dec              %%ecx \n\t"   /* decrease loop counter */
    03022                 "jnz                 1b \n\t"   /* check loop termination, proceed if required */
    03023                 "emms                   \n\t"   /* exit MMX state */
    03024                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    03025                 :"m"(Src1),             /* %1 */
    03026                 "m"(SrcLength),         /* %2 */
    03027                 "m"(N),                 /* %3 */
    03028                 "m"(C)                  /* %4 */
    03029                 );
    03030 #endif
    03031         return (0);
    03032 #else
    03033         return (-1);
    03034 #endif
    03035 }
    03036
    03048 int SDL_imageFilterShiftRightAndMultByByte(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char N,
    03049                                                                                    unsigned char C)
    03050 {
    03051         unsigned int i, istart;
    03052         int iC;
    03053         unsigned char *cursrc1;
    03054         unsigned char *curdest;
    03055         int result;
    03056
    03057         /* Validate input parameters */
    03058         if ((Src1 == NULL) || (Dest == NULL))
    03059                 return(-1);
    03060         if (length == 0)
    03061                 return(0);
    03062
    03063         /* Check shift */
    03064         if (N > 8) {
    03065                 return (-1);
    03066         }
    03067
    03068         /* Special case: N==0 && C==1 */
    03069         if ((N == 0) && (C == 1)) {
    03070                 memcpy(Src1, Dest, length);
    03071                 return (0);
    03072         }
    03073
    03074         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    03075
    03076                 SDL_imageFilterShiftRightAndMultByByteMMX(Src1, Dest, length, N, C);
    03077
    03078                 /* Check for unaligned bytes */
    03079                 if ((length & 7) > 0) {
    03080                         /* Setup to process unaligned bytes */
    03081                         istart = length & 0xfffffff8;
    03082                         cursrc1 = &Src1[istart];
    03083                         curdest = &Dest[istart];
    03084                 } else {
    03085                         /* No unaligned bytes - we are done */
    03086                         return (0);
    03087                 }
    03088         } else {
    03089                 /* Setup to process whole image */
    03090                 istart = 0;
    03091                 cursrc1 = Src1;
    03092                 curdest = Dest;
    03093         }
    03094
    03095         /* C routine to process image */
    03096         iC = (int) C;
    03097         for (i = istart; i < length; i++) {
    03098                 result = (int) (*cursrc1 >> N) * iC;
    03099                 if (result > 255)
    03100                         result = 255;
    03101                 *curdest = (unsigned char) result;
    03102                 /* Advance pointers */
    03103                 cursrc1++;
    03104                 curdest++;
    03105         }
    03106
    03107         return (0);
    03108 }
    03109
    03121 int SDL_imageFilterShiftLeftByteMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength, unsigned char N,
    03122                                                                         unsigned char *Mask)
    03123 {
    03124 #ifdef USE_MMX
    03125 #if !defined(GCC__)
    03126         __asm
    03127         {
    03128                 pusha
    03129                         mov edx, Mask           /* load Mask address into edx */
    03130                         movq mm0, [edx]         /* load Mask into mm0 */
    03131                 xor ecx, ecx    /* zero ECX */
    03132                         mov cl, N       /* load loop counter (N) into CL */
    03133                         movd mm3, ecx           /* copy (N) into MM3  */
    03134                         pcmpeqb mm1, mm1        /* generate all 1's in mm1 */
    03135 L10270:                         /* ** Prepare proper bit-Mask in MM1 ** */
    03136                 psllw mm1, 1    /* shift 4 WORDS of MM1 1 bit to the left */
    03137                         pand mm1, mm0        // apply Mask to 8 BYTES of MM1 */
    03138                         /*  byte     0x0f, 0xdb, 0xc8 */
    03139                         dec cl                          /* decrease loop counter */
    03140                         jnz            L10270           /* check loop termination, proceed if required */
    03141                         /* ** Shift all bytes of the image ** */
    03142                         mov eax, Src1           /* load Src1 address into eax */
    03143                         mov edi, Dest           /* load SrcDest address into edi */
    03144                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    03145                         shr ecx, 3      /* counter/8 (MMX loads 8 bytes at a time) */
    03146                         align 16                        /* 16 byte alignment of the loop entry */
    03147 L10271:
    03148                 movq mm0, [eax]         /* load 8 bytes from Src1 into MM0 */
    03149                 psllw mm0, mm3          /* shift 4 WORDS of MM0 (N) bits to the left */
    03150                         pand mm0, mm1    // apply proper bit-Mask to 8 BYTES of MM0 */
    03151                         /* byte     0x0f, 0xdb, 0xc1 */
    03152                         movq [edi], mm0         /* store result in Dest */
    03153                         add eax, 8      /* increase Src1 register pointer by 8 */
    03154                         add edi, 8      /* increase Dest register pointer by 8 */
    03155                         dec              ecx            /* decrease loop counter */
    03156                         jnz            L10271           /* check loop termination, proceed if required */
    03157                         emms                            /* exit MMX state */
    03158                         popa
    03159         }
    03160 #else
    03161         asm volatile
    03162                 ("pusha              \n\t" "movl         %4, %%edx \n\t"        /* load Mask address into edx */
    03163                 "movq    (%%edx), %%mm0 \n\t"   /* load Mask into mm0 */
    03164                 "xor       %%ecx, %%ecx \n\t"   /* zero ECX */
    03165                 "mov           %3, %%cl \n\t"   /* load loop counter (N) into CL */
    03166                 "movd      %%ecx, %%mm3 \n\t"   /* copy (N) into MM3  */
    03167                 "pcmpeqb   %%mm1, %%mm1 \n\t"   /* generate all 1's in mm1 */
    03168                 "1:                     \n\t"   /* ** Prepare proper bit-Mask in MM1 ** */
    03169                 "psllw        $1, %%mm1 \n\t"   /* shift 4 WORDS of MM1 1 bit to the left */
    03170                 /*    "pand      %%mm0, %%mm1 \n\t"    // apply Mask to 8 BYTES of MM1 */
    03171                 ".byte     0x0f, 0xdb, 0xc8 \n\t" "dec %%cl               \n\t" /* decrease loop counter */
    03172                 "jnz                 1b \n\t"   /* check loop termination, proceed if required */
    03173                 /* ** Shift all bytes of the image ** */
    03174                 "mov          %1, %%eax \n\t"   /* load Src1 address into eax */
    03175                 "mov          %0, %%edi \n\t"   /* load SrcDest address into edi */
    03176                 "mov          %2, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    03177                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    03178                 ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    03179                 "2: movq (%%eax), %%mm0 \n\t"   /* load 8 bytes from Src1 into MM0 */
    03180                 "psllw     %%mm3, %%mm0 \n\t"   /* shift 4 WORDS of MM0 (N) bits to the left */
    03181                 /*    "pand      %%mm1, %%mm0 \n\t"    // apply proper bit-Mask to 8 BYTES of MM0 */
    03182                 ".byte     0x0f, 0xdb, 0xc1 \n\t" "movq    %%mm0, (%%edi) \n\t" /* store result in Dest */
    03183                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    03184                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    03185                 "dec              %%ecx \n\t"   /* decrease loop counter */
    03186                 "jnz                 2b \n\t"   /* check loop termination, proceed if required */
    03187                 "emms                   \n\t"   /* exit MMX state */
    03188                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    03189                 :"m"(Src1),             /* %1 */
    03190                 "m"(SrcLength),         /* %2 */
    03191                 "m"(N),                 /* %3 */
    03192                 "m"(Mask)                       /* %4 */
    03193                 );
    03194 #endif
    03195         return (0);
    03196 #else
    03197         return (-1);
    03198 #endif
    03199 }
    03200
    03211 int SDL_imageFilterShiftLeftByte(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char N)
    03212 {
    03213         static unsigned char Mask[8] = { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE };
    03214         unsigned int i, istart;
    03215         unsigned char *cursrc1, *curdest;
    03216         int result;
    03217
    03218         /* Validate input parameters */
    03219         if ((Src1 == NULL) || (Dest == NULL))
    03220                 return(-1);
    03221         if (length == 0)
    03222                 return(0);
    03223
    03224         if (N > 8) {
    03225                 return (-1);
    03226         }
    03227
    03228         /* Special case: N==0 */
    03229         if (N == 0) {
    03230                 memcpy(Src1, Dest, length);
    03231                 return (0);
    03232         }
    03233
    03234         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    03235
    03236                 SDL_imageFilterShiftLeftByteMMX(Src1, Dest, length, N, Mask);
    03237
    03238                 /* Check for unaligned bytes */
    03239                 if ((length & 7) > 0) {
    03240                         /* Setup to process unaligned bytes */
    03241                         istart = length & 0xfffffff8;
    03242                         cursrc1 = &Src1[istart];
    03243                         curdest = &Dest[istart];
    03244                 } else {
    03245                         /* No unaligned bytes - we are done */
    03246                         return (0);
    03247                 }
    03248         } else {
    03249                 /* Setup to process whole image */
    03250                 istart = 0;
    03251                 cursrc1 = Src1;
    03252                 curdest = Dest;
    03253         }
    03254
    03255         /* C routine to process image */
    03256         for (i = istart; i < length; i++) {
    03257                 result = ((int) *cursrc1 << N) & 0xff;
    03258                 *curdest = (unsigned char) result;
    03259                 /* Advance pointers */
    03260                 cursrc1++;
    03261                 curdest++;
    03262         }
    03263
    03264         return (0);
    03265 }
    03266
    03277 int SDL_imageFilterShiftLeftUintMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength, unsigned char N)
    03278 {
    03279 #ifdef USE_MMX
    03280 #if !defined(GCC__)
    03281         __asm
    03282         {
    03283                 pusha
    03284                         mov eax, Src1           /* load Src1 address into eax */
    03285                         mov edi, Dest           /* load Dest address into edi */
    03286                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    03287                         shr ecx, 3      /* counter/8 (MMX loads 8 bytes at a time) */
    03288                         align 16                        /* 16 byte alignment of the loop entry */
    03289 L12023:
    03290                 movq mm0, [eax]         /* load 8 bytes from SrcDest into MM0 */
    03291                 pslld mm0, N    /* MM0=SrcDest+C (add 8 bytes with saturation) */
    03292                         movq [edi], mm0         /* store result in SrcDest */
    03293                         add eax, 8      /* increase Src1 register pointer by 8 */
    03294                         add edi, 8      /* increase Dest register pointer by 8 */
    03295                         dec              ecx            /* decrease loop counter */
    03296                         jnz             L12023          /* check loop termination, proceed if required */
    03297                         emms                            /* exit MMX state */
    03298                         popa
    03299         }
    03300 #else
    03301         asm volatile
    03302                 ("pusha              \n\t"
    03303                 "mov          %1, %%eax \n\t"   /* load Src1 address into eax */
    03304                 "mov          %0, %%edi \n\t"   /* load Dest address into edi */
    03305                 "mov          %2, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    03306                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    03307                 ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    03308                 "1: movq (%%eax), %%mm0 \n\t"   /* load 8 bytes from SrcDest into MM0 */
    03309                 "pslld   %3, %%mm0 \n\t"        /* MM0=SrcDest+C (add 8 bytes with saturation) */
    03310                 "movq    %%mm0, (%%edi) \n\t"   /* store result in SrcDest */
    03311                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    03312                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    03313                 "dec              %%ecx \n\t"   /* decrease loop counter */
    03314                 "jnz                 1b \n\t"   /* check loop termination, proceed if required */
    03315                 "emms                   \n\t"   /* exit MMX state */
    03316                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    03317                 :"m"(Src1),             /* %1 */
    03318                 "m"(SrcLength),         /* %2 */
    03319                 "m"(N)                  /* %3 */
    03320                 );
    03321 #endif
    03322         return (0);
    03323 #else
    03324         return (-1);
    03325 #endif
    03326 }
    03327
    03338 int SDL_imageFilterShiftLeftUint(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char N)
    03339 {
    03340         unsigned int i, istart;
    03341         unsigned char *cursrc1, *curdest;
    03342         unsigned int *icursrc1, *icurdest;
    03343         int result;
    03344
    03345         /* Validate input parameters */
    03346         if ((Src1 == NULL) || (Dest == NULL))
    03347                 return(-1);
    03348         if (length == 0)
    03349                 return(0);
    03350
    03351         if (N > 32) {
    03352                 return (-1);
    03353         }
    03354
    03355         /* Special case: N==0 */
    03356         if (N == 0) {
    03357                 memcpy(Src1, Dest, length);
    03358                 return (0);
    03359         }
    03360
    03361         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    03362
    03363                 SDL_imageFilterShiftLeftUintMMX(Src1, Dest, length, N);
    03364
    03365                 /* Check for unaligned bytes */
    03366                 if ((length & 7) > 0) {
    03367                         /* Setup to process unaligned bytes */
    03368                         istart = length & 0xfffffff8;
    03369                         cursrc1 = &Src1[istart];
    03370                         curdest = &Dest[istart];
    03371                 } else {
    03372                         /* No unaligned bytes - we are done */
    03373                         return (0);
    03374                 }
    03375         } else {
    03376                 /* Setup to process whole image */
    03377                 istart = 0;
    03378                 cursrc1 = Src1;
    03379                 curdest = Dest;
    03380         }
    03381
    03382         /* C routine to process image */
    03383         icursrc1=(unsigned int *)cursrc1;
    03384         icurdest=(unsigned int *)curdest;
    03385         for (i = istart; i < length; i += 4) {
    03386                 if ((i+4)<length) {
    03387                         result = ((unsigned int)*icursrc1 << N);
    03388                         *icurdest = (unsigned int)result;
    03389                 }
    03390                 /* Advance pointers */
    03391                 icursrc1++;
    03392                 icurdest++;
    03393         }
    03394
    03395         return (0);
    03396 }
    03397
    03408 int SDL_imageFilterShiftLeftMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength, unsigned char N)
    03409 {
    03410 #ifdef USE_MMX
    03411 #if !defined(GCC__)
    03412         __asm
    03413         {
    03414                 pusha
    03415                         xor eax, eax    /* zero EAX */
    03416                         mov al, N       /* load N into AL */
    03417                         movd mm7, eax           /* copy N into MM7 */
    03418                         pxor mm0, mm0           /* zero MM0 register */
    03419                         mov eax, Src1           /* load Src1 address into eax */
    03420                         mov edi, Dest           /* load Dest address into edi */
    03421                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    03422                         shr ecx, 3      /* counter/8 (MMX loads 8 bytes at a time) */
    03423                         cmp al, 7       /* if (N <= 7) execute more efficient code */
    03424                         jg             L10281
    03425                         align 16                        /* 16 byte alignment of the loop entry */
    03426 L10280:
    03427                 movq mm3, [eax]         /* load 8 bytes from Src1 into MM3 */
    03428                 movq mm4, mm3           /* copy MM3 into MM4  */
    03429                         punpcklbw mm3, mm0      /* unpack low  bytes of SrcDest into words */
    03430                         punpckhbw mm4, mm0      /* unpack high bytes of SrcDest into words */
    03431                         psllw mm3, mm7          /* shift 4 WORDS of MM3 (N) bits to the right */
    03432                         psllw mm4, mm7          /* shift 4 WORDS of MM4 (N) bits to the right */
    03433                         packuswb mm3, mm4       /* pack words back into bytes with saturation */
    03434                         movq [edi], mm3         /* store result in Dest */
    03435                         add eax, 8      /* increase Src1 register pointer by 8 */
    03436                         add edi, 8      /* increase Dest register pointer by 8 */
    03437                         dec              ecx            /* decrease loop counter */
    03438                         jnz            L10280           /* check loop termination, proceed if required */
    03439                         jmp            L10282
    03440                         align 16                        /* 16 byte alignment of the loop entry */
    03441 L10281:
    03442                 movq mm3, [eax]         /* load 8 bytes from Src1 into MM3 */
    03443                 movq mm4, mm3           /* copy MM3 into MM4  */
    03444                         punpcklbw mm3, mm0      /* unpack low  bytes of SrcDest into words */
    03445                         punpckhbw mm4, mm0      /* unpack high bytes of SrcDest into words */
    03446                         psllw mm3, mm7          /* shift 4 WORDS of MM3 (N) bits to the right */
    03447                         psllw mm4, mm7          /* shift 4 WORDS of MM4 (N) bits to the right */
    03448                         /* ** Take abs value of the signed words ** */
    03449                         movq mm5, mm3           /* copy mm3 into mm5 */
    03450                         movq mm6, mm4           /* copy mm4 into mm6 */
    03451                         psraw mm5, 15           /* fill mm5 words with word sign bit */
    03452                         psraw mm6, 15           /* fill mm6 words with word sign bit */
    03453                         pxor mm3, mm5           /* take 1's compliment of only neg words */
    03454                         pxor mm4, mm6           /* take 1's compliment of only neg words */
    03455                         psubsw mm3, mm5         /* add 1 to only neg words, W-(-1) or W-0 */
    03456                         psubsw mm4, mm6         /* add 1 to only neg words, W-(-1) or W-0 */
    03457                         packuswb mm3, mm4       /* pack words back into bytes with saturation */
    03458                         movq [edi], mm3         /* store result in Dest */
    03459                         add eax, 8      /* increase Src1 register pointer by 8 */
    03460                         add edi, 8      /* increase Dest register pointer by 8 */
    03461                         dec              ecx            /* decrease loop counter */
    03462                         jnz            L10281           /* check loop termination, proceed if required */
    03463 L10282:
    03464                 emms                            /* exit MMX state */
    03465                         popa
    03466         }
    03467 #else
    03468         asm volatile
    03469                 ("pusha              \n\t" "xor       %%eax, %%eax \n\t"        /* zero EAX */
    03470                 "mov           %3, %%al \n\t"   /* load N into AL */
    03471                 "movd      %%eax, %%mm7 \n\t"   /* copy N into MM7 */
    03472                 "pxor      %%mm0, %%mm0 \n\t"   /* zero MM0 register */
    03473                 "mov         %1, %%eax  \n\t"   /* load Src1 address into eax */
    03474                 "mov         %0, %%edi  \n\t"   /* load Dest address into edi */
    03475                 "mov         %2, %%ecx  \n\t"   /* load loop counter (SIZE) into ecx */
    03476                 "shr         $3, %%ecx  \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    03477                 "cmp           $7, %%al \n\t"   /* if (N <= 7) execute more efficient code */
    03478                 "jg                  2f \n\t" ".align 16              \n\t"     /* 16 byte alignment of the loop entry */
    03479                 "1: movq (%%eax), %%mm3 \n\t"   /* load 8 bytes from Src1 into MM3 */
    03480                 "movq      %%mm3, %%mm4 \n\t"   /* copy MM3 into MM4  */
    03481                 "punpcklbw %%mm0, %%mm3 \n\t"   /* unpack low  bytes of SrcDest into words */
    03482                 "punpckhbw %%mm0, %%mm4 \n\t"   /* unpack high bytes of SrcDest into words */
    03483                 "psllw     %%mm7, %%mm3 \n\t"   /* shift 4 WORDS of MM3 (N) bits to the right */
    03484                 "psllw     %%mm7, %%mm4 \n\t"   /* shift 4 WORDS of MM4 (N) bits to the right */
    03485                 "packuswb  %%mm4, %%mm3 \n\t"   /* pack words back into bytes with saturation */
    03486                 "movq    %%mm3, (%%edi) \n\t"   /* store result in Dest */
    03487                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    03488                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    03489                 "dec              %%ecx \n\t"   /* decrease loop counter */
    03490                 "jnz                 1b \n\t"   /* check loop termination, proceed if required */
    03491                 "jmp                 3f \n\t" ".align 16              \n\t"     /* 16 byte alignment of the loop entry */
    03492                 "2: movq (%%eax), %%mm3 \n\t"   /* load 8 bytes from Src1 into MM3 */
    03493                 "movq      %%mm3, %%mm4 \n\t"   /* copy MM3 into MM4  */
    03494                 "punpcklbw %%mm0, %%mm3 \n\t"   /* unpack low  bytes of SrcDest into words */
    03495                 "punpckhbw %%mm0, %%mm4 \n\t"   /* unpack high bytes of SrcDest into words */
    03496                 "psllw     %%mm7, %%mm3 \n\t"   /* shift 4 WORDS of MM3 (N) bits to the right */
    03497                 "psllw     %%mm7, %%mm4 \n\t"   /* shift 4 WORDS of MM4 (N) bits to the right */
    03498                 /* ** Take abs value of the signed words ** */
    03499                 "movq      %%mm3, %%mm5 \n\t"   /* copy mm3 into mm5 */
    03500                 "movq      %%mm4, %%mm6 \n\t"   /* copy mm4 into mm6 */
    03501                 "psraw       $15, %%mm5 \n\t"   /* fill mm5 words with word sign bit */
    03502                 "psraw       $15, %%mm6 \n\t"   /* fill mm6 words with word sign bit */
    03503                 "pxor      %%mm5, %%mm3 \n\t"   /* take 1's compliment of only neg. words */
    03504                 "pxor      %%mm6, %%mm4 \n\t"   /* take 1's compliment of only neg. words */
    03505                 "psubsw    %%mm5, %%mm3 \n\t"   /* add 1 to only neg. words, W-(-1) or W-0 */
    03506                 "psubsw    %%mm6, %%mm4 \n\t"   /* add 1 to only neg. words, W-(-1) or W-0 */
    03507                 "packuswb  %%mm4, %%mm3 \n\t"   /* pack words back into bytes with saturation */
    03508                 "movq    %%mm3, (%%edi) \n\t"   /* store result in Dest */
    03509                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    03510                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    03511                 "dec              %%ecx \n\t"   /* decrease loop counter */
    03512                 "jnz                 2b \n\t"   /* check loop termination, proceed if required */
    03513                 "3: emms                \n\t"   /* exit MMX state */
    03514                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    03515                 :"m"(Src1),             /* %1 */
    03516                 "m"(SrcLength),         /* %2 */
    03517                 "m"(N)                  /* %3 */
    03518                 );
    03519 #endif
    03520         return (0);
    03521 #else
    03522         return (-1);
    03523 #endif
    03524 }
    03525
    03536 int SDL_imageFilterShiftLeft(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char N)
    03537 {
    03538         unsigned int i, istart;
    03539         unsigned char *cursrc1, *curdest;
    03540         int result;
    03541
    03542         /* Validate input parameters */
    03543         if ((Src1 == NULL) || (Dest == NULL))
    03544                 return(-1);
    03545         if (length == 0)
    03546                 return(0);
    03547
    03548         if (N > 8) {
    03549                 return (-1);
    03550         }
    03551
    03552         /* Special case: N==0 */
    03553         if (N == 0) {
    03554                 memcpy(Src1, Dest, length);
    03555                 return (0);
    03556         }
    03557
    03558         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    03559
    03560                 SDL_imageFilterShiftLeftMMX(Src1, Dest, length, N);
    03561
    03562                 /* Check for unaligned bytes */
    03563                 if ((length & 7) > 0) {
    03564                         /* Setup to process unaligned bytes */
    03565                         istart = length & 0xfffffff8;
    03566                         cursrc1 = &Src1[istart];
    03567                         curdest = &Dest[istart];
    03568                 } else {
    03569                         /* No unaligned bytes - we are done */
    03570                         return (0);
    03571                 }
    03572         } else {
    03573                 /* Setup to process whole image */
    03574                 istart = 0;
    03575                 cursrc1 = Src1;
    03576                 curdest = Dest;
    03577         }
    03578
    03579         /* C routine to process image */
    03580         for (i = istart; i < length; i++) {
    03581                 result = (int) *cursrc1 << N;
    03582                 if (result > 255)
    03583                         result = 255;
    03584                 *curdest = (unsigned char) result;
    03585                 /* Advance pointers */
    03586                 cursrc1++;
    03587                 curdest++;
    03588         }
    03589
    03590         return (0);
    03591 }
    03592
    03603 int SDL_imageFilterBinarizeUsingThresholdMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength, unsigned char T)
    03604 {
    03605 #ifdef USE_MMX
    03606 #if !defined(GCC__)
    03607         __asm
    03608         {
    03609                 pusha
    03610                         /* ** Duplicate T in 8 bytes of MM3 ** */
    03611                         pcmpeqb mm1, mm1        /* generate all 1's in mm1 */
    03612                         pcmpeqb mm2, mm2        /* generate all 1's in mm2 */
    03613                         mov al, T       /* load T into AL */
    03614                         mov ah, al      /* copy AL into AH */
    03615                         mov bx, ax      /* copy AX into BX */
    03616                         shl eax, 16     /* shift 2 bytes of EAX left */
    03617                         mov ax, bx      /* copy BX into AX */
    03618                         movd mm3, eax           /* copy EAX into MM3 */
    03619                         movd mm4, eax           /* copy EAX into MM4 */
    03620                         punpckldq mm3, mm4      /* fill higher bytes of MM3 with T */
    03621                         psubusb mm2, mm3        /* store 0xFF - T in MM2 */
    03622                         mov eax, Src1           /* load Src1 address into eax */
    03623                         mov edi, Dest           /* load Dest address into edi */
    03624                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    03625                         shr ecx, 3      /* counter/8 (MMX loads 8 bytes at a time) */
    03626                         align 16                        /* 16 byte alignment of the loop entry */
    03627 L1029:
    03628                 movq mm0, [eax]         /* load 8 bytes from SrcDest into MM0 */
    03629                 paddusb mm0, mm2        /* MM0=SrcDest+(0xFF-T) (add 8 bytes with saturation) */
    03630                         pcmpeqb mm0, mm1        /* binarize 255:0, comparing to 255 */
    03631                         movq [edi], mm0         /* store result in SrcDest */
    03632                         add eax, 8      /* increase Src1 register pointer by 8 */
    03633                         add edi, 8      /* increase Dest register pointer by 8 */
    03634                         dec              ecx            /* decrease loop counter */
    03635                         jnz             L1029           /* check loop termination, proceed if required */
    03636                         emms                            /* exit MMX state */
    03637                         popa
    03638         }
    03639 #else
    03640         asm volatile
    03641                 ("pusha              \n\t"
    03642                 /* ** Duplicate T in 8 bytes of MM3 ** */
    03643                 "pcmpeqb   %%mm1, %%mm1 \n\t"   /* generate all 1's in mm1 */
    03644                 "pcmpeqb   %%mm2, %%mm2 \n\t"   /* generate all 1's in mm2 */
    03645                 "mov           %3, %%al \n\t"   /* load T into AL */
    03646                 "mov         %%al, %%ah \n\t"   /* copy AL into AH */
    03647                 "mov         %%ax, %%bx \n\t"   /* copy AX into BX */
    03648                 "shl         $16, %%eax \n\t"   /* shift 2 bytes of EAX left */
    03649                 "mov         %%bx, %%ax \n\t"   /* copy BX into AX */
    03650                 "movd      %%eax, %%mm3 \n\t"   /* copy EAX into MM3 */
    03651                 "movd      %%eax, %%mm4 \n\t"   /* copy EAX into MM4 */
    03652                 "punpckldq %%mm4, %%mm3 \n\t"   /* fill higher bytes of MM3 with T */
    03653                 "psubusb   %%mm3, %%mm2 \n\t"   /* store 0xFF - T in MM2 */
    03654                 "mov          %1, %%eax \n\t"   /* load Src1 address into eax */
    03655                 "mov          %0, %%edi \n\t"   /* load Dest address into edi */
    03656                 "mov          %2, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    03657                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    03658                 ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    03659                 "1:                     \n\t"
    03660                 "movq    (%%eax), %%mm0 \n\t"   /* load 8 bytes from SrcDest into MM0 */
    03661                 "paddusb   %%mm2, %%mm0 \n\t"   /* MM0=SrcDest+(0xFF-T) (add 8 bytes with saturation) */
    03662                 "pcmpeqb   %%mm1, %%mm0 \n\t"   /* binarize 255:0, comparing to 255 */
    03663                 "movq    %%mm0, (%%edi) \n\t"   /* store result in SrcDest */
    03664                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    03665                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    03666                 "dec              %%ecx \n\t"   /* decrease loop counter */
    03667                 "jnz                 1b \n\t"   /* check loop termination, proceed if required */
    03668                 "emms                   \n\t"   /* exit MMX state */
    03669                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    03670                 :"m"(Src1),             /* %1 */
    03671                 "m"(SrcLength),         /* %2 */
    03672                 "m"(T)                  /* %3 */
    03673                 );
    03674 #endif
    03675         return (0);
    03676 #else
    03677         return (-1);
    03678 #endif
    03679 }
    03680
    03691 int SDL_imageFilterBinarizeUsingThreshold(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char T)
    03692 {
    03693         unsigned int i, istart;
    03694         unsigned char *cursrc1;
    03695         unsigned char *curdest;
    03696
    03697         /* Validate input parameters */
    03698         if ((Src1 == NULL) || (Dest == NULL))
    03699                 return(-1);
    03700         if (length == 0)
    03701                 return(0);
    03702
    03703         /* Special case: T==0 */
    03704         if (T == 0) {
    03705                 memset(Dest, 255, length);
    03706                 return (0);
    03707         }
    03708
    03709         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    03710
    03711                 SDL_imageFilterBinarizeUsingThresholdMMX(Src1, Dest, length, T);
    03712
    03713                 /* Check for unaligned bytes */
    03714                 if ((length & 7) > 0) {
    03715                         /* Setup to process unaligned bytes */
    03716                         istart = length & 0xfffffff8;
    03717                         cursrc1 = &Src1[istart];
    03718                         curdest = &Dest[istart];
    03719                 } else {
    03720                         /* No unaligned bytes - we are done */
    03721                         return (0);
    03722                 }
    03723         } else {
    03724                 /* Setup to process whole image */
    03725                 istart = 0;
    03726                 cursrc1 = Src1;
    03727                 curdest = Dest;
    03728         }
    03729
    03730         /* C routine to process image */
    03731         for (i = istart; i < length; i++) {
    03732                 *curdest = ((unsigned char) *cursrc1 >= T) ? 255 : 0;
    03733                 /* Advance pointers */
    03734                 cursrc1++;
    03735                 curdest++;
    03736         }
    03737
    03738         return (0);
    03739 }
    03740
    03752 int SDL_imageFilterClipToRangeMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength, unsigned char Tmin,
    03753                                                                   unsigned char Tmax)
    03754 {
    03755 #ifdef USE_MMX
    03756 #if !defined(GCC__)
    03757         __asm
    03758         {
    03759                 pusha
    03760                         pcmpeqb mm1, mm1        /* generate all 1's in mm1 */
    03761                         /* ** Duplicate Tmax in 8 bytes of MM3 ** */
    03762                         mov al, Tmax    /* load Tmax into AL */
    03763                         mov ah, al      /* copy AL into AH */
    03764                         mov bx, ax      /* copy AX into BX */
    03765                         shl eax, 16     /* shift 2 bytes of EAX left */
    03766                         mov ax, bx      /* copy BX into AX */
    03767                         movd mm3, eax           /* copy EAX into MM3 */
    03768                         movd mm4, eax           /* copy EAX into MM4 */
    03769                         punpckldq mm3, mm4      /* fill higher bytes of MM3 with Tmax */
    03770                         psubusb mm1, mm3        /* store 0xFF - Tmax in MM1 */
    03771                         /* ** Duplicate Tmin in 8 bytes of MM5 ** */
    03772                         mov al, Tmin    /* load Tmin into AL */
    03773                         mov ah, al      /* copy AL into AH */
    03774                         mov bx, ax      /* copy AX into BX */
    03775                         shl eax, 16     /* shift 2 bytes of EAX left */
    03776                         mov ax, bx      /* copy BX into AX */
    03777                         movd mm5, eax           /* copy EAX into MM5 */
    03778                         movd mm4, eax           /* copy EAX into MM4 */
    03779                         punpckldq mm5, mm4      /* fill higher bytes of MM5 with Tmin */
    03780                         movq mm7, mm5           /* copy MM5 into MM7 */
    03781                         paddusb mm7, mm1        /* store 0xFF - Tmax + Tmin in MM7 */
    03782                         mov eax, Src1           /* load Src1 address into eax */
    03783                         mov edi, Dest           /* load Dest address into edi */
    03784                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    03785                         shr ecx, 3      /* counter/8 (MMX loads 8 bytes at a time) */
    03786                         align 16                        /* 16 byte alignment of the loop entry */
    03787 L1030:
    03788                 movq mm0, [eax]         /* load 8 bytes from Src1 into MM0 */
    03789                 paddusb mm0, mm1        /* MM0=SrcDest+(0xFF-Tmax) */
    03790                         psubusb mm0, mm7        /* MM0=MM0-(0xFF-Tmax+Tmin) */
    03791                         paddusb mm0, mm5        /* MM0=MM0+Tmin */
    03792                         movq [edi], mm0         /* store result in Dest */
    03793                         add eax, 8      /* increase Src1 register pointer by 8 */
    03794                         add edi, 8      /* increase Dest register pointer by 8 */
    03795                         dec              ecx            /* decrease loop counter */
    03796                         jnz             L1030           /* check loop termination, proceed if required */
    03797                         emms                            /* exit MMX state */
    03798                         popa
    03799         }
    03800 #else
    03801         asm volatile
    03802                 ("pusha              \n\t" "pcmpeqb   %%mm1, %%mm1 \n\t"        /* generate all 1's in mm1 */
    03803                 /* ** Duplicate Tmax in 8 bytes of MM3 ** */
    03804                 "mov           %4, %%al \n\t"   /* load Tmax into AL */
    03805                 "mov         %%al, %%ah \n\t"   /* copy AL into AH */
    03806                 "mov         %%ax, %%bx \n\t"   /* copy AX into BX */
    03807                 "shl         $16, %%eax \n\t"   /* shift 2 bytes of EAX left */
    03808                 "mov         %%bx, %%ax \n\t"   /* copy BX into AX */
    03809                 "movd      %%eax, %%mm3 \n\t"   /* copy EAX into MM3 */
    03810                 "movd      %%eax, %%mm4 \n\t"   /* copy EAX into MM4 */
    03811                 "punpckldq %%mm4, %%mm3 \n\t"   /* fill higher bytes of MM3 with Tmax */
    03812                 "psubusb   %%mm3, %%mm1 \n\t"   /* store 0xFF - Tmax in MM1 */
    03813                 /* ** Duplicate Tmin in 8 bytes of MM5 ** */
    03814                 "mov           %3, %%al \n\t"   /* load Tmin into AL */
    03815                 "mov         %%al, %%ah \n\t"   /* copy AL into AH */
    03816                 "mov         %%ax, %%bx \n\t"   /* copy AX into BX */
    03817                 "shl         $16, %%eax \n\t"   /* shift 2 bytes of EAX left */
    03818                 "mov         %%bx, %%ax \n\t"   /* copy BX into AX */
    03819                 "movd      %%eax, %%mm5 \n\t"   /* copy EAX into MM5 */
    03820                 "movd      %%eax, %%mm4 \n\t"   /* copy EAX into MM4 */
    03821                 "punpckldq %%mm4, %%mm5 \n\t"   /* fill higher bytes of MM5 with Tmin */
    03822                 "movq      %%mm5, %%mm7 \n\t"   /* copy MM5 into MM7 */
    03823                 "paddusb   %%mm1, %%mm7 \n\t"   /* store 0xFF - Tmax + Tmin in MM7 */
    03824                 "mov          %1, %%eax \n\t"   /* load Src1 address into eax */
    03825                 "mov          %0, %%edi \n\t"   /* load Dest address into edi */
    03826                 "mov          %2, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    03827                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    03828                 ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    03829                 "1:                     \n\t"
    03830                 "movq    (%%eax), %%mm0 \n\t"   /* load 8 bytes from Src1 into MM0 */
    03831                 "paddusb   %%mm1, %%mm0 \n\t"   /* MM0=SrcDest+(0xFF-Tmax) */
    03832                 "psubusb   %%mm7, %%mm0 \n\t"   /* MM0=MM0-(0xFF-Tmax+Tmin) */
    03833                 "paddusb   %%mm5, %%mm0 \n\t"   /* MM0=MM0+Tmin */
    03834                 "movq    %%mm0, (%%edi) \n\t"   /* store result in Dest */
    03835                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    03836                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    03837                 "dec              %%ecx \n\t"   /* decrease loop counter */
    03838                 "jnz                 1b \n\t"   /* check loop termination, proceed if required */
    03839                 "emms                   \n\t"   /* exit MMX state */
    03840                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    03841                 :"m"(Src1),             /* %1 */
    03842                 "m"(SrcLength),         /* %2 */
    03843                 "m"(Tmin),              /* %3 */
    03844                 "m"(Tmax)                       /* %4 */
    03845                 );
    03846 #endif
    03847         return (0);
    03848 #else
    03849         return (-1);
    03850 #endif
    03851 }
    03852
    03864 int SDL_imageFilterClipToRange(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char Tmin,
    03865                                                            unsigned char Tmax)
    03866 {
    03867         unsigned int i, istart;
    03868         unsigned char *cursrc1;
    03869         unsigned char *curdest;
    03870
    03871         /* Validate input parameters */
    03872         if ((Src1 == NULL) || (Dest == NULL))
    03873                 return(-1);
    03874         if (length == 0)
    03875                 return(0);
    03876
    03877         /* Special case: Tmin==0 && Tmax = 255 */
    03878         if ((Tmin == 0) && (Tmax == 25)) {
    03879                 memcpy(Src1, Dest, length);
    03880                 return (0);
    03881         }
    03882
    03883         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    03884
    03885                 SDL_imageFilterClipToRangeMMX(Src1, Dest, length, Tmin, Tmax);
    03886
    03887                 /* Check for unaligned bytes */
    03888                 if ((length & 7) > 0) {
    03889                         /* Setup to process unaligned bytes */
    03890                         istart = length & 0xfffffff8;
    03891                         cursrc1 = &Src1[istart];
    03892                         curdest = &Dest[istart];
    03893                 } else {
    03894                         /* No unaligned bytes - we are done */
    03895                         return (0);
    03896                 }
    03897         } else {
    03898                 /* Setup to process whole image */
    03899                 istart = 0;
    03900                 cursrc1 = Src1;
    03901                 curdest = Dest;
    03902         }
    03903
    03904         /* C routine to process image */
    03905         for (i = istart; i < length; i++) {
    03906                 if (*cursrc1 < Tmin) {
    03907                         *curdest = Tmin;
    03908                 } else if (*cursrc1 > Tmax) {
    03909                         *curdest = Tmax;
    03910                 } else {
    03911                         *curdest = *cursrc1;
    03912                 }
    03913                 /* Advance pointers */
    03914                 cursrc1++;
    03915                 curdest++;
    03916         }
    03917
    03918         return (0);
    03919 }
    03920
    03934 int SDL_imageFilterNormalizeLinearMMX(unsigned char *Src1, unsigned char *Dest, unsigned int SrcLength, int Cmin, int Cmax,
    03935                                                                           int Nmin, int Nmax)
    03936 {
    03937 #ifdef USE_MMX
    03938 #if !defined(GCC__)
    03939         __asm
    03940         {
    03941                 pusha
    03942                         mov ax, WORD PTR Nmax           /* load Nmax in AX */
    03943                         mov bx, WORD PTR Cmax           /* load Cmax in BX */
    03944                         sub ax, WORD PTR Nmin           /* AX = Nmax - Nmin */
    03945                         sub bx, WORD PTR Cmin           /* BX = Cmax - Cmin */
    03946                         jz             L10311           /* check division by zero */
    03947                         xor dx, dx      /* prepare for division, zero DX */
    03948                         div               bx            /* AX = AX/BX */
    03949                         jmp            L10312
    03950 L10311:
    03951                 mov ax, 255     /* if div by zero, assume result max byte value */
    03952 L10312:                         /* ** Duplicate AX in 4 words of MM0 ** */
    03953                 mov bx, ax      /* copy AX into BX */
    03954                         shl eax, 16     /* shift 2 bytes of EAX left */
    03955                         mov ax, bx      /* copy BX into AX */
    03956                         movd mm0, eax           /* copy EAX into MM0 */
    03957                         movd mm1, eax           /* copy EAX into MM1 */
    03958                         punpckldq mm0, mm1      /* fill higher words of MM0 with AX */
    03959                         /* ** Duplicate Cmin in 4 words of MM1 ** */
    03960                         mov ax, WORD PTR Cmin           /* load Cmin into AX */
    03961                         mov bx, ax      /* copy AX into BX */
    03962                         shl eax, 16     /* shift 2 bytes of EAX left */
    03963                         mov ax, bx      /* copy BX into AX */
    03964                         movd mm1, eax           /* copy EAX into MM1 */
    03965                         movd mm2, eax           /* copy EAX into MM2 */
    03966                         punpckldq mm1, mm2      /* fill higher words of MM1 with Cmin */
    03967                         /* ** Duplicate Nmin in 4 words of MM2 ** */
    03968                         mov ax, WORD PTR Nmin           /* load Nmin into AX */
    03969                         mov bx, ax      /* copy AX into BX */
    03970                         shl eax, 16     /* shift 2 bytes of EAX left */
    03971                         mov ax, bx      /* copy BX into AX */
    03972                         movd mm2, eax           /* copy EAX into MM2 */
    03973                         movd mm3, eax           /* copy EAX into MM3 */
    03974                         punpckldq mm2, mm3      /* fill higher words of MM2 with Nmin */
    03975                         pxor mm7, mm7           /* zero MM7 register */
    03976                         mov eax, Src1           /* load Src1 address into eax */
    03977                         mov edi, Dest           /* load Dest address into edi */
    03978                         mov ecx, SrcLength      /* load loop counter (SIZE) into ecx */
    03979                         shr ecx, 3      /* counter/8 (MMX loads 8 bytes at a time) */
    03980                         align 16                        /* 16 byte alignment of the loop entry */
    03981 L1031:
    03982                 movq mm3, [eax]         /* load 8 bytes from Src1 into MM3 */
    03983                 movq mm4, mm3           /* copy MM3 into MM4  */
    03984                         punpcklbw mm3, mm7      /* unpack low  bytes of SrcDest into words */
    03985                         punpckhbw mm4, mm7      /* unpack high bytes of SrcDest into words */
    03986                         psubusb mm3, mm1        /* S-Cmin, low  bytes */
    03987                         psubusb mm4, mm1        /* S-Cmin, high bytes */
    03988                         pmullw mm3, mm0         /* MM0*(S-Cmin), low  bytes */
    03989                         pmullw mm4, mm0         /* MM0*(S-Cmin), high bytes */
    03990                         paddusb mm3, mm2        /* MM0*(S-Cmin)+Nmin, low  bytes */
    03991                         paddusb mm4, mm2        /* MM0*(S-Cmin)+Nmin, high bytes */
    03992                         /* ** Take abs value of the signed words ** */
    03993                         movq mm5, mm3           /* copy mm3 into mm5 */
    03994                         movq mm6, mm4           /* copy mm4 into mm6 */
    03995                         psraw mm5, 15           /* fill mm5 words with word sign bit */
    03996                         psraw mm6, 15           /* fill mm6 words with word sign bit */
    03997                         pxor mm3, mm5           /* take 1's compliment of only neg words */
    03998                         pxor mm4, mm6           /* take 1's compliment of only neg words */
    03999                         psubsw mm3, mm5         /* add 1 to only neg words, W-(-1) or W-0 */
    04000                         psubsw mm4, mm6         /* add 1 to only neg words, W-(-1) or W-0 */
    04001                         packuswb mm3, mm4       /* pack words back into bytes with saturation */
    04002                         movq [edi], mm3         /* store result in Dest */
    04003                         add eax, 8      /* increase Src1 register pointer by 8 */
    04004                         add edi, 8      /* increase Dest register pointer by 8 */
    04005                         dec              ecx            /* decrease loop counter */
    04006                         jnz             L1031           /* check loop termination, proceed if required */
    04007                         emms                            /* exit MMX state */
    04008                         popa
    04009         }
    04010 #else
    04011         asm volatile
    04012                 ("pusha              \n\t" "mov           %6, %%ax \n\t"        /* load Nmax in AX */
    04013                 "mov           %4, %%bx \n\t"   /* load Cmax in BX */
    04014                 "sub           %5, %%ax \n\t"   /* AX = Nmax - Nmin */
    04015                 "sub           %3, %%bx \n\t"   /* BX = Cmax - Cmin */
    04016                 "jz                  1f \n\t"   /* check division by zero */
    04017                 "xor         %%dx, %%dx \n\t"   /* prepare for division, zero DX */
    04018                 "div               %%bx \n\t"   /* AX = AX/BX */
    04019                 "jmp                 2f \n\t" "1:                     \n\t" "mov         $255, %%ax \n\t"       /* if div by zero, assume result max. byte value */
    04020                 "2:                    \n\t"    /* ** Duplicate AX in 4 words of MM0 ** */
    04021                 "mov         %%ax, %%bx \n\t"   /* copy AX into BX */
    04022                 "shl         $16, %%eax \n\t"   /* shift 2 bytes of EAX left */
    04023                 "mov         %%bx, %%ax \n\t"   /* copy BX into AX */
    04024                 "movd      %%eax, %%mm0 \n\t"   /* copy EAX into MM0 */
    04025                 "movd      %%eax, %%mm1 \n\t"   /* copy EAX into MM1 */
    04026                 "punpckldq %%mm1, %%mm0 \n\t"   /* fill higher words of MM0 with AX */
    04027                 /* ** Duplicate Cmin in 4 words of MM1 ** */
    04028                 "mov           %3, %%ax \n\t"   /* load Cmin into AX */
    04029                 "mov         %%ax, %%bx \n\t"   /* copy AX into BX */
    04030                 "shl         $16, %%eax \n\t"   /* shift 2 bytes of EAX left */
    04031                 "mov         %%bx, %%ax \n\t"   /* copy BX into AX */
    04032                 "movd      %%eax, %%mm1 \n\t"   /* copy EAX into MM1 */
    04033                 "movd      %%eax, %%mm2 \n\t"   /* copy EAX into MM2 */
    04034                 "punpckldq %%mm2, %%mm1 \n\t"   /* fill higher words of MM1 with Cmin */
    04035                 /* ** Duplicate Nmin in 4 words of MM2 ** */
    04036                 "mov           %5, %%ax \n\t"   /* load Nmin into AX */
    04037                 "mov         %%ax, %%bx \n\t"   /* copy AX into BX */
    04038                 "shl         $16, %%eax \n\t"   /* shift 2 bytes of EAX left */
    04039                 "mov         %%bx, %%ax \n\t"   /* copy BX into AX */
    04040                 "movd      %%eax, %%mm2 \n\t"   /* copy EAX into MM2 */
    04041                 "movd      %%eax, %%mm3 \n\t"   /* copy EAX into MM3 */
    04042                 "punpckldq %%mm3, %%mm2 \n\t"   /* fill higher words of MM2 with Nmin */
    04043                 "pxor      %%mm7, %%mm7 \n\t"   /* zero MM7 register */
    04044                 "mov          %1, %%eax \n\t"   /* load Src1 address into eax */
    04045                 "mov          %0, %%edi \n\t"   /* load Dest address into edi */
    04046                 "mov          %2, %%ecx \n\t"   /* load loop counter (SIZE) into ecx */
    04047                 "shr          $3, %%ecx \n\t"   /* counter/8 (MMX loads 8 bytes at a time) */
    04048                 ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    04049                 "1:                     \n\t"
    04050                 "movq    (%%eax), %%mm3 \n\t"   /* load 8 bytes from Src1 into MM3 */
    04051                 "movq      %%mm3, %%mm4 \n\t"   /* copy MM3 into MM4  */
    04052                 "punpcklbw %%mm7, %%mm3 \n\t"   /* unpack low  bytes of SrcDest into words */
    04053                 "punpckhbw %%mm7, %%mm4 \n\t"   /* unpack high bytes of SrcDest into words */
    04054                 "psubusb   %%mm1, %%mm3 \n\t"   /* S-Cmin, low  bytes */
    04055                 "psubusb   %%mm1, %%mm4 \n\t"   /* S-Cmin, high bytes */
    04056                 "pmullw    %%mm0, %%mm3 \n\t"   /* MM0*(S-Cmin), low  bytes */
    04057                 "pmullw    %%mm0, %%mm4 \n\t"   /* MM0*(S-Cmin), high bytes */
    04058                 "paddusb   %%mm2, %%mm3 \n\t"   /* MM0*(S-Cmin)+Nmin, low  bytes */
    04059                 "paddusb   %%mm2, %%mm4 \n\t"   /* MM0*(S-Cmin)+Nmin, high bytes */
    04060                 /* ** Take abs value of the signed words ** */
    04061                 "movq      %%mm3, %%mm5 \n\t"   /* copy mm3 into mm5 */
    04062                 "movq      %%mm4, %%mm6 \n\t"   /* copy mm4 into mm6 */
    04063                 "psraw       $15, %%mm5 \n\t"   /* fill mm5 words with word sign bit */
    04064                 "psraw       $15, %%mm6 \n\t"   /* fill mm6 words with word sign bit */
    04065                 "pxor      %%mm5, %%mm3 \n\t"   /* take 1's compliment of only neg. words */
    04066                 "pxor      %%mm6, %%mm4 \n\t"   /* take 1's compliment of only neg. words */
    04067                 "psubsw    %%mm5, %%mm3 \n\t"   /* add 1 to only neg. words, W-(-1) or W-0 */
    04068                 "psubsw    %%mm6, %%mm4 \n\t"   /* add 1 to only neg. words, W-(-1) or W-0 */
    04069                 "packuswb  %%mm4, %%mm3 \n\t"   /* pack words back into bytes with saturation */
    04070                 "movq    %%mm3, (%%edi) \n\t"   /* store result in Dest */
    04071                 "add          $8, %%eax \n\t"   /* increase Src1 register pointer by 8 */
    04072                 "add          $8, %%edi \n\t"   /* increase Dest register pointer by 8 */
    04073                 "dec              %%ecx \n\t"   /* decrease loop counter */
    04074                 "jnz                 1b \n\t"   /* check loop termination, proceed if required */
    04075                 "emms                   \n\t"   /* exit MMX state */
    04076                 "popa                   \n\t":"=m" (Dest)       /* %0 */
    04077                 :"m"(Src1),             /* %1 */
    04078                 "m"(SrcLength),         /* %2 */
    04079                 "m"(Cmin),              /* %3 */
    04080                 "m"(Cmax),              /* %4 */
    04081                 "m"(Nmin),              /* %5 */
    04082                 "m"(Nmax)                       /* %6 */
    04083                 );
    04084 #endif
    04085         return (0);
    04086 #else
    04087         return (-1);
    04088 #endif
    04089 }
    04090
    04104 int SDL_imageFilterNormalizeLinear(unsigned char *Src, unsigned char *Dest, unsigned int length, int Cmin, int Cmax, int Nmin,
    04105                                                                    int Nmax)
    04106 {
    04107         unsigned int i, istart;
    04108         unsigned char *cursrc;
    04109         unsigned char *curdest;
    04110         int dN, dC, factor;
    04111         int result;
    04112
    04113         /* Validate input parameters */
    04114         if ((Src == NULL) || (Dest == NULL))
    04115                 return(-1);
    04116         if (length == 0)
    04117                 return(0);
    04118
    04119         if ((SDL_imageFilterMMXdetect()) && (length > 7)) {
    04120
    04121                 SDL_imageFilterNormalizeLinearMMX(Src, Dest, length, Cmin, Cmax, Nmin, Nmax);
    04122
    04123                 /* Check for unaligned bytes */
    04124                 if ((length & 7) > 0) {
    04125                         /* Setup to process unaligned bytes */
    04126                         istart = length & 0xfffffff8;
    04127                         cursrc = &Src[istart];
    04128                         curdest = &Dest[istart];
    04129                 } else {
    04130                         /* No unaligned bytes - we are done */
    04131                         return (0);
    04132                 }
    04133         } else {
    04134                 /* Setup to process whole image */
    04135                 istart = 0;
    04136                 cursrc = Src;
    04137                 curdest = Dest;
    04138         }
    04139
    04140         /* C routine to process image */
    04141         dC = Cmax - Cmin;
    04142         if (dC == 0)
    04143                 return (0);
    04144         dN = Nmax - Nmin;
    04145         factor = dN / dC;
    04146         for (i = istart; i < length; i++) {
    04147                 result = factor * ((int) (*cursrc) - Cmin) + Nmin;
    04148                 if (result > 255)
    04149                         result = 255;
    04150                 *curdest = (unsigned char) result;
    04151                 /* Advance pointers */
    04152                 cursrc++;
    04153                 curdest++;
    04154         }
    04155
    04156         return (0);
    04157 }
    04158
    04159 /* ------------------------------------------------------------------------------------ */
    04160
    04175 int SDL_imageFilterConvolveKernel3x3Divide(unsigned char *Src, unsigned char *Dest, int rows, int columns,
    04176                                                                                    signed short *Kernel, unsigned char Divisor)
    04177 {
    04178         /* Validate input parameters */
    04179         if ((Src == NULL) || (Dest == NULL) || (Kernel == NULL))
    04180                 return(-1);
    04181
    04182         if ((columns < 3) || (rows < 3) || (Divisor == 0))
    04183                 return (-1);
    04184
    04185         if ((SDL_imageFilterMMXdetect())) {
    04186 #ifdef USE_MMX
    04187 #if !defined(GCC__)
    04188                 __asm
    04189                 {
    04190                         pusha
    04191                                 pxor mm0, mm0           /* zero MM0 */
    04192                                 xor ebx, ebx    /* zero EBX */
    04193                                 mov bl, Divisor         /* load Divisor into BL */
    04194                                 mov edx, Kernel         /* load Kernel address into EDX */
    04195                                 movq mm5, [edx]         /* MM5 = {0,K2,K1,K0} */
    04196                         add edx, 8      /* second row              |K0 K1 K2 0| */
    04197                                 movq mm6, [edx]         /* MM6 = {0,K5,K4,K3}  K = |K3 K4 K5 0| */
    04198                         add edx, 8      /* third row               |K6 K7 K8 0| */
    04199                                 movq mm7, [edx]         /* MM7 = {0,K8,K7,K6} */
    04200                         /* ---, */
    04201                         mov eax, columns        /* load columns into EAX */
    04202                                 mov esi, Src    /* ESI = Src row 0 address */
    04203                                 mov edi, Dest           /* load Dest address to EDI */
    04204                                 add edi, eax    /* EDI = EDI + columns */
    04205                                 inc              edi            /* 1 byte offset from the left edge */
    04206                                 mov edx, rows           /* initialize ROWS counter */
    04207                                 sub edx, 2      /* do not use first and last row */
    04208                                 /* ---, */
    04209 L10320:
    04210                         mov ecx, eax    /* initialize COLUMS counter */
    04211                                 sub ecx, 2      /* do not use first and last column */
    04212                                 align 16                        /* 16 byte alignment of the loop entry */
    04213 L10322:
    04214                         /* ---, */
    04215                         movq mm1, [esi]         /* load 8 bytes of the image first row */
    04216                         add esi, eax    /* move one row below */
    04217                                 movq mm2, [esi]         /* load 8 bytes of the image second row */
    04218                         add esi, eax    /* move one row below */
    04219                                 movq mm3, [esi]         /* load 8 bytes of the image third row */
    04220                         punpcklbw mm1, mm0      /* unpack first 4 bytes into words */
    04221                                 punpcklbw mm2, mm0      /* unpack first 4 bytes into words */
    04222                                 punpcklbw mm3, mm0      /* unpack first 4 bytes into words */
    04223                                 pmullw mm1, mm5         /* multiply words first row  image*Kernel */
    04224                                 pmullw mm2, mm6         /* multiply words second row image*Kernel */
    04225                                 pmullw mm3, mm7         /* multiply words third row  image*Kernel */
    04226                                 paddsw mm1, mm2         /* add 4 words of the first and second rows */
    04227                                 paddsw mm1, mm3         /* add 4 words of the third row and result */
    04228                                 movq mm2, mm1           /* copy MM1 into MM2 */
    04229                                 psrlq mm1, 32           /* shift 2 left words to the right */
    04230                                 paddsw mm1, mm2         /* add 2 left and 2 right result words */
    04231                                 movq mm3, mm1           /* copy MM1 into MM3 */
    04232                                 psrlq mm1, 16           /* shift 1 left word to the right */
    04233                                 paddsw mm1, mm3         /* add 1 left and 1 right result words */
    04234                                 /* --, */
    04235                                 movd mm2, eax           /* save EAX in MM2 */
    04236                                 movd mm3, edx           /* save EDX in MM3 */
    04237                                 movd eax, mm1           /* copy MM1 into EAX */
    04238                                 psraw mm1, 15           /* spread sign bit of the result */
    04239                                 movd edx, mm1           /* fill EDX with a sign bit */
    04240                                 idiv bx         /* IDIV - VERY EXPENSIVE */
    04241                                 movd mm1, eax           /* move result of division into MM1 */
    04242                                 packuswb mm1, mm0       /* pack division result with saturation */
    04243                                 movd eax, mm1           /* copy saturated result into EAX */
    04244                                 mov [edi], al           /* copy a byte result into Dest */
    04245                                 movd edx, mm3           /* restore saved EDX */
    04246                                 movd eax, mm2           /* restore saved EAX */
    04247                                 /* --, */
    04248                                 sub esi, eax    /* move two rows up */
    04249                                 sub esi, eax    /* */
    04250                                 inc              esi            /* move Src  pointer to the next pixel */
    04251                                 inc              edi            /* move Dest pointer to the next pixel */
    04252                                 /* ---, */
    04253                                 dec              ecx            /* decrease loop counter COLUMNS */
    04254                                 jnz            L10322           /* check loop termination, proceed if required */
    04255                                 add esi, 2      /* move to the next row in Src */
    04256                                 add edi, 2      /* move to the next row in Dest */
    04257                                 dec              edx            /* decrease loop counter ROWS */
    04258                                 jnz            L10320           /* check loop termination, proceed if required */
    04259                                 /* ---, */
    04260                                 emms                            /* exit MMX state */
    04261                                 popa
    04262                 }
    04263 #else
    04264                 asm volatile
    04265                         ("pusha              \n\t" "pxor      %%mm0, %%mm0 \n\t"        /* zero MM0 */
    04266                         "xor       %%ebx, %%ebx \n\t"   /* zero EBX */
    04267                         "mov           %5, %%bl \n\t"   /* load Divisor into BL */
    04268                         "mov          %4, %%edx \n\t"   /* load Kernel address into EDX */
    04269                         "movq    (%%edx), %%mm5 \n\t"   /* MM5 = {0,K2,K1,K0} */
    04270                         "add          $8, %%edx \n\t"   /* second row              |K0 K1 K2 0| */
    04271                         "movq    (%%edx), %%mm6 \n\t"   /* MM6 = {0,K5,K4,K3}  K = |K3 K4 K5 0| */
    04272                         "add          $8, %%edx \n\t"   /* third row               |K6 K7 K8 0| */
    04273                         "movq    (%%edx), %%mm7 \n\t"   /* MM7 = {0,K8,K7,K6} */
    04274                         /* --- */
    04275                         "mov          %3, %%eax \n\t"   /* load columns into EAX */
    04276                         "mov          %1, %%esi \n\t"   /* ESI = Src row 0 address */
    04277                         "mov          %0, %%edi \n\t"   /* load Dest address to EDI */
    04278                         "add       %%eax, %%edi \n\t"   /* EDI = EDI + columns */
    04279                         "inc              %%edi \n\t"   /* 1 byte offset from the left edge */
    04280                         "mov          %2, %%edx \n\t"   /* initialize ROWS counter */
    04281                         "sub          $2, %%edx \n\t"   /* do not use first and last row */
    04282                         /* --- */
    04283                         ".L10320:               \n\t" "mov       %%eax, %%ecx \n\t"     /* initialize COLUMS counter */
    04284                         "sub          $2, %%ecx \n\t"   /* do not use first and last column */
    04285                         ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    04286                         ".L10322:               \n\t"
    04287                         /* --- */
    04288                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the image first row */
    04289                         "add       %%eax, %%esi \n\t"   /* move one row below */
    04290                         "movq    (%%esi), %%mm2 \n\t"   /* load 8 bytes of the image second row */
    04291                         "add       %%eax, %%esi \n\t"   /* move one row below */
    04292                         "movq    (%%esi), %%mm3 \n\t"   /* load 8 bytes of the image third row */
    04293                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first 4 bytes into words */
    04294                         "punpcklbw %%mm0, %%mm2 \n\t"   /* unpack first 4 bytes into words */
    04295                         "punpcklbw %%mm0, %%mm3 \n\t"   /* unpack first 4 bytes into words */
    04296                         "pmullw    %%mm5, %%mm1 \n\t"   /* multiply words first row  image*Kernel */
    04297                         "pmullw    %%mm6, %%mm2 \n\t"   /* multiply words second row image*Kernel */
    04298                         "pmullw    %%mm7, %%mm3 \n\t"   /* multiply words third row  image*Kernel */
    04299                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the first and second rows */
    04300                         "paddsw    %%mm3, %%mm1 \n\t"   /* add 4 words of the third row and result */
    04301                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    04302                         "psrlq       $32, %%mm1 \n\t"   /* shift 2 left words to the right */
    04303                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 2 left and 2 right result words */
    04304                         "movq      %%mm1, %%mm3 \n\t"   /* copy MM1 into MM3 */
    04305                         "psrlq       $16, %%mm1 \n\t"   /* shift 1 left word to the right */
    04306                         "paddsw    %%mm3, %%mm1 \n\t"   /* add 1 left and 1 right result words */
    04307                         /* -- */
    04308                         "movd      %%eax, %%mm2 \n\t"   /* save EAX in MM2 */
    04309                         "movd      %%edx, %%mm3 \n\t"   /* save EDX in MM3 */
    04310                         "movd      %%mm1, %%eax \n\t"   /* copy MM1 into EAX */
    04311                         "psraw       $15, %%mm1 \n\t"   /* spread sign bit of the result */
    04312                         "movd      %%mm1, %%edx \n\t"   /* fill EDX with a sign bit */
    04313                         "idivw             %%bx \n\t"   /* IDIV - VERY EXPENSIVE */
    04314                         "movd      %%eax, %%mm1 \n\t"   /* move result of division into MM1 */
    04315                         "packuswb  %%mm0, %%mm1 \n\t"   /* pack division result with saturation */
    04316                         "movd      %%mm1, %%eax \n\t"   /* copy saturated result into EAX */
    04317                         "mov      %%al, (%%edi) \n\t"   /* copy a byte result into Dest */
    04318                         "movd      %%mm3, %%edx \n\t"   /* restore saved EDX */
    04319                         "movd      %%mm2, %%eax \n\t"   /* restore saved EAX */
    04320                         /* -- */
    04321                         "sub       %%eax, %%esi \n\t"   /* move two rows up */
    04322                         "sub       %%eax, %%esi \n\t"   /* */
    04323                         "inc              %%esi \n\t"   /* move Src  pointer to the next pixel */
    04324                         "inc              %%edi \n\t"   /* move Dest pointer to the next pixel */
    04325                         /* --- */
    04326                         "dec              %%ecx \n\t"   /* decrease loop counter COLUMNS */
    04327                         "jnz            .L10322 \n\t"   /* check loop termination, proceed if required */
    04328                         "add          $2, %%esi \n\t"   /* move to the next row in Src */
    04329                         "add          $2, %%edi \n\t"   /* move to the next row in Dest */
    04330                         "dec              %%edx \n\t"   /* decrease loop counter ROWS */
    04331                         "jnz            .L10320 \n\t"   /* check loop termination, proceed if required */
    04332                         /* --- */
    04333                         "emms                   \n\t"   /* exit MMX state */
    04334                         "popa                   \n\t":"=m" (Dest)       /* %0 */
    04335                         :"m"(Src),              /* %1 */
    04336                         "m"(rows),              /* %2 */
    04337                         "m"(columns),           /* %3 */
    04338                         "m"(Kernel),            /* %4 */
    04339                         "m"(Divisor)            /* %5 */
    04340                         );
    04341 #endif
    04342 #endif
    04343                 return (0);
    04344         } else {
    04345                 /* No non-MMX implementation yet */
    04346                 return (-1);
    04347         }
    04348 }
    04349
    04364 int SDL_imageFilterConvolveKernel5x5Divide(unsigned char *Src, unsigned char *Dest, int rows, int columns,
    04365                                                                                    signed short *Kernel, unsigned char Divisor)
    04366 {
    04367         /* Validate input parameters */
    04368         if ((Src == NULL) || (Dest == NULL) || (Kernel == NULL))
    04369                 return(-1);
    04370
    04371         if ((columns < 5) || (rows < 5) || (Divisor == 0))
    04372                 return (-1);
    04373
    04374         if ((SDL_imageFilterMMXdetect())) {
    04375 #ifdef USE_MMX
    04376 #if !defined(GCC__)
    04377                 __asm
    04378                 {
    04379                         pusha
    04380                                 pxor mm0, mm0           /* zero MM0 */
    04381                                 xor ebx, ebx    /* zero EBX */
    04382                                 mov bl, Divisor         /* load Divisor into BL */
    04383                                 movd mm5, ebx           /* copy Divisor into MM5 */
    04384                                 mov edx, Kernel         /* load Kernel address into EDX */
    04385                                 mov esi, Src    /* load Src  address to ESI */
    04386                                 mov edi, Dest           /* load Dest address to EDI */
    04387                                 add edi, 2      /* 2 column offset from the left edge */
    04388                                 mov eax, columns        /* load columns into EAX */
    04389                                 shl eax, 1      /* EAX = columns * 2 */
    04390                                 add edi, eax    /* 2 row offset from the top edge */
    04391                                 shr eax, 1      /* EAX = columns */
    04392                                 mov ebx, rows           /* initialize ROWS counter */
    04393                                 sub ebx, 4      /* do not use first 2 and last 2 rows */
    04394                                 /* ---, */
    04395 L10330:
    04396                         mov ecx, eax    /* initialize COLUMNS counter */
    04397                                 sub ecx, 4      /* do not use first 2 and last 2 columns */
    04398                                 align 16                        /* 16 byte alignment of the loop entry */
    04399 L10332:
    04400                         pxor mm7, mm7           /* zero MM7 (accumulator) */
    04401                                 movd mm6, esi           /* save ESI in MM6 */
    04402                                 /* --- 1 */
    04403                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    04404                         movq mm2, mm1           /* copy MM1 into MM2 */
    04405                                 add esi, eax    /* move Src pointer 1 row below */
    04406                                 movq mm3, [edx]         /* load 4 words of Kernel */
    04407                         add edx, 8      /* move pointer to other 4 words */
    04408                                 movq mm4, [edx]         /* load 4 words of Kernel */
    04409                         add edx, 8      /* move pointer to other 4 words */
    04410                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    04411                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    04412                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    04413                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    04414                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    04415                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    04416                                 /* --- 2 */
    04417                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    04418                         movq mm2, mm1           /* copy MM1 into MM2 */
    04419                                 add esi, eax    /* move Src pointer 1 row below */
    04420                                 movq mm3, [edx]         /* load 4 words of Kernel */
    04421                         add edx, 8      /* move pointer to other 4 words */
    04422                                 movq mm4, [edx]         /* load 4 words of Kernel */
    04423                         add edx, 8      /* move pointer to other 4 words */
    04424                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    04425                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    04426                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    04427                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    04428                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    04429                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    04430                                 /* --- 3 */
    04431                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    04432                         movq mm2, mm1           /* copy MM1 into MM2 */
    04433                                 add esi, eax    /* move Src pointer 1 row below */
    04434                                 movq mm3, [edx]         /* load 4 words of Kernel */
    04435                         add edx, 8      /* move pointer to other 4 words */
    04436                                 movq mm4, [edx]         /* load 4 words of Kernel */
    04437                         add edx, 8      /* move pointer to other 4 words */
    04438                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    04439                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    04440                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    04441                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    04442                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    04443                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    04444                                 /* --- 4 */
    04445                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    04446                         movq mm2, mm1           /* copy MM1 into MM2 */
    04447                                 add esi, eax    /* move Src pointer 1 row below */
    04448                                 movq mm3, [edx]         /* load 4 words of Kernel */
    04449                         add edx, 8      /* move pointer to other 4 words */
    04450                                 movq mm4, [edx]         /* load 4 words of Kernel */
    04451                         add edx, 8      /* move pointer to other 4 words */
    04452                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    04453                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    04454                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    04455                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    04456                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    04457                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    04458                                 /* --- 5 */
    04459                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    04460                         movq mm2, mm1           /* copy MM1 into MM2 */
    04461                                 movq mm3, [edx]         /* load 4 words of Kernel */
    04462                         add edx, 8      /* move pointer to other 4 words */
    04463                                 movq mm4, [edx]         /* load 4 words of Kernel */
    04464                         punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    04465                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    04466                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    04467                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    04468                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    04469                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    04470                                 /* ---, */
    04471                                 movq mm3, mm7           /* copy MM7 into MM3 */
    04472                                 psrlq mm7, 32           /* shift 2 left words to the right */
    04473                                 paddsw mm7, mm3         /* add 2 left and 2 right result words */
    04474                                 movq mm2, mm7           /* copy MM7 into MM2 */
    04475                                 psrlq mm7, 16           /* shift 1 left word to the right */
    04476                                 paddsw mm7, mm2         /* add 1 left and 1 right result words */
    04477                                 /* ---, */
    04478                                 movd mm1, eax           /* save EDX in MM1 */
    04479                                 movd mm2, ebx           /* save EDX in MM2 */
    04480                                 movd mm3, edx           /* save EDX in MM3 */
    04481                                 movd eax, mm7           /* load summation result into EAX */
    04482                                 psraw mm7, 15           /* spread sign bit of the result */
    04483                                 movd ebx, mm5           /* load Divisor into EBX */
    04484                                 movd edx, mm7           /* fill EDX with a sign bit */
    04485                                 idiv bx         /* IDIV - VERY EXPENSIVE */
    04486                                 movd mm7, eax           /* move result of division into MM7 */
    04487                                 packuswb mm7, mm0       /* pack division result with saturation */
    04488                                 movd eax, mm7           /* copy saturated result into EAX */
    04489                                 mov [edi], al           /* copy a byte result into Dest */
    04490                                 movd edx, mm3           /* restore saved EDX */
    04491                                 movd ebx, mm2           /* restore saved EBX */
    04492                                 movd eax, mm1           /* restore saved EAX */
    04493                                 /* --, */
    04494                                 movd esi, mm6           /* move Src pointer to the top pixel */
    04495                                 sub edx, 72     /* EDX = Kernel address */
    04496                                 inc              esi            /* move Src  pointer to the next pixel */
    04497                                 inc              edi            /* move Dest pointer to the next pixel */
    04498                                 /* ---, */
    04499                                 dec              ecx            /* decrease loop counter COLUMNS */
    04500                                 jnz            L10332           /* check loop termination, proceed if required */
    04501                                 add esi, 4      /* move to the next row in Src */
    04502                                 add edi, 4      /* move to the next row in Dest */
    04503                                 dec              ebx            /* decrease loop counter ROWS */
    04504                                 jnz            L10330           /* check loop termination, proceed if required */
    04505                                 /* ---, */
    04506                                 emms                            /* exit MMX state */
    04507                                 popa
    04508                 }
    04509 #else
    04510                 asm volatile
    04511                         ("pusha              \n\t" "pxor      %%mm0, %%mm0 \n\t"        /* zero MM0 */
    04512                         "xor       %%ebx, %%ebx \n\t"   /* zero EBX */
    04513                         "mov           %5, %%bl \n\t"   /* load Divisor into BL */
    04514                         "movd      %%ebx, %%mm5 \n\t"   /* copy Divisor into MM5 */
    04515                         "mov          %4, %%edx \n\t"   /* load Kernel address into EDX */
    04516                         "mov          %1, %%esi \n\t"   /* load Src  address to ESI */
    04517                         "mov          %0, %%edi \n\t"   /* load Dest address to EDI */
    04518                         "add          $2, %%edi \n\t"   /* 2 column offset from the left edge */
    04519                         "mov          %3, %%eax \n\t"   /* load columns into EAX */
    04520                         "shl          $1, %%eax \n\t"   /* EAX = columns * 2 */
    04521                         "add       %%eax, %%edi \n\t"   /* 2 row offset from the top edge */
    04522                         "shr          $1, %%eax \n\t"   /* EAX = columns */
    04523                         "mov          %2, %%ebx \n\t"   /* initialize ROWS counter */
    04524                         "sub          $4, %%ebx \n\t"   /* do not use first 2 and last 2 rows */
    04525                         /* --- */
    04526                         ".L10330:               \n\t" "mov       %%eax, %%ecx \n\t"     /* initialize COLUMNS counter */
    04527                         "sub          $4, %%ecx \n\t"   /* do not use first 2 and last 2 columns */
    04528                         ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    04529                         ".L10332:               \n\t" "pxor      %%mm7, %%mm7 \n\t"     /* zero MM7 (accumulator) */
    04530                         "movd      %%esi, %%mm6 \n\t"   /* save ESI in MM6 */
    04531                         /* --- 1 */
    04532                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    04533                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    04534                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    04535                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    04536                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04537                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    04538                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04539                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    04540                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    04541                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    04542                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    04543                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    04544                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    04545                         /* --- 2 */
    04546                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    04547                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    04548                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    04549                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    04550                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04551                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    04552                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04553                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    04554                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    04555                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    04556                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    04557                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    04558                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    04559                         /* --- 3 */
    04560                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    04561                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    04562                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    04563                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    04564                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04565                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    04566                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04567                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    04568                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    04569                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    04570                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    04571                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    04572                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    04573                         /* --- 4 */
    04574                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    04575                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    04576                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    04577                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    04578                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04579                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    04580                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04581                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    04582                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    04583                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    04584                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    04585                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    04586                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    04587                         /* --- 5 */
    04588                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    04589                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    04590                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    04591                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04592                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    04593                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    04594                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    04595                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    04596                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    04597                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    04598                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    04599                         /* --- */
    04600                         "movq      %%mm7, %%mm3 \n\t"   /* copy MM7 into MM3 */
    04601                         "psrlq       $32, %%mm7 \n\t"   /* shift 2 left words to the right */
    04602                         "paddsw    %%mm3, %%mm7 \n\t"   /* add 2 left and 2 right result words */
    04603                         "movq      %%mm7, %%mm2 \n\t"   /* copy MM7 into MM2 */
    04604                         "psrlq       $16, %%mm7 \n\t"   /* shift 1 left word to the right */
    04605                         "paddsw    %%mm2, %%mm7 \n\t"   /* add 1 left and 1 right result words */
    04606                         /* --- */
    04607                         "movd      %%eax, %%mm1 \n\t"   /* save EDX in MM1 */
    04608                         "movd      %%ebx, %%mm2 \n\t"   /* save EDX in MM2 */
    04609                         "movd      %%edx, %%mm3 \n\t"   /* save EDX in MM3 */
    04610                         "movd      %%mm7, %%eax \n\t"   /* load summation result into EAX */
    04611                         "psraw       $15, %%mm7 \n\t"   /* spread sign bit of the result */
    04612                         "movd      %%mm5, %%ebx \n\t"   /* load Divisor into EBX */
    04613                         "movd      %%mm7, %%edx \n\t"   /* fill EDX with a sign bit */
    04614                         "idivw             %%bx \n\t"   /* IDIV - VERY EXPENSIVE */
    04615                         "movd      %%eax, %%mm7 \n\t"   /* move result of division into MM7 */
    04616                         "packuswb  %%mm0, %%mm7 \n\t"   /* pack division result with saturation */
    04617                         "movd      %%mm7, %%eax \n\t"   /* copy saturated result into EAX */
    04618                         "mov      %%al, (%%edi) \n\t"   /* copy a byte result into Dest */
    04619                         "movd      %%mm3, %%edx \n\t"   /* restore saved EDX */
    04620                         "movd      %%mm2, %%ebx \n\t"   /* restore saved EBX */
    04621                         "movd      %%mm1, %%eax \n\t"   /* restore saved EAX */
    04622                         /* -- */
    04623                         "movd      %%mm6, %%esi \n\t"   /* move Src pointer to the top pixel */
    04624                         "sub         $72, %%edx \n\t"   /* EDX = Kernel address */
    04625                         "inc              %%esi \n\t"   /* move Src  pointer to the next pixel */
    04626                         "inc              %%edi \n\t"   /* move Dest pointer to the next pixel */
    04627                         /* --- */
    04628                         "dec              %%ecx \n\t"   /* decrease loop counter COLUMNS */
    04629                         "jnz            .L10332 \n\t"   /* check loop termination, proceed if required */
    04630                         "add          $4, %%esi \n\t"   /* move to the next row in Src */
    04631                         "add          $4, %%edi \n\t"   /* move to the next row in Dest */
    04632                         "dec              %%ebx \n\t"   /* decrease loop counter ROWS */
    04633                         "jnz            .L10330 \n\t"   /* check loop termination, proceed if required */
    04634                         /* --- */
    04635                         "emms                   \n\t"   /* exit MMX state */
    04636                         "popa                   \n\t":"=m" (Dest)       /* %0 */
    04637                         :"m"(Src),              /* %1 */
    04638                         "m"(rows),              /* %2 */
    04639                         "m"(columns),           /* %3 */
    04640                         "m"(Kernel),            /* %4 */
    04641                         "m"(Divisor)            /* %5 */
    04642                         );
    04643 #endif
    04644 #endif
    04645                 return (0);
    04646         } else {
    04647                 /* No non-MMX implementation yet */
    04648                 return (-1);
    04649         }
    04650 }
    04651
    04666 int SDL_imageFilterConvolveKernel7x7Divide(unsigned char *Src, unsigned char *Dest, int rows, int columns,
    04667                                                                                    signed short *Kernel, unsigned char Divisor)
    04668 {
    04669         /* Validate input parameters */
    04670         if ((Src == NULL) || (Dest == NULL) || (Kernel == NULL))
    04671                 return(-1);
    04672
    04673         if ((columns < 7) || (rows < 7) || (Divisor == 0))
    04674                 return (-1);
    04675
    04676         if ((SDL_imageFilterMMXdetect())) {
    04677 #ifdef USE_MMX
    04678 #if !defined(GCC__)
    04679                 __asm
    04680                 {
    04681                         pusha
    04682                                 pxor mm0, mm0           /* zero MM0 */
    04683                                 xor ebx, ebx    /* zero EBX */
    04684                                 mov bl, Divisor         /* load Divisor into BL */
    04685                                 movd mm5, ebx           /* copy Divisor into MM5 */
    04686                                 mov edx, Kernel         /* load Kernel address into EDX */
    04687                                 mov esi, Src    /* load Src  address to ESI */
    04688                                 mov edi, Dest           /* load Dest address to EDI */
    04689                                 add edi, 3      /* 3 column offset from the left edge */
    04690                                 mov eax, columns        /* load columns into EAX */
    04691                                 add edi, eax    /* 3 row offset from the top edge */
    04692                                 add edi, eax
    04693                                 add edi, eax
    04694                                 mov ebx, rows           /* initialize ROWS counter */
    04695                                 sub ebx, 6      /* do not use first 3 and last 3 rows */
    04696                                 /* ---, */
    04697 L10340:
    04698                         mov ecx, eax    /* initialize COLUMNS counter */
    04699                                 sub ecx, 6      /* do not use first 3 and last 3 columns */
    04700                                 align 16                        /* 16 byte alignment of the loop entry */
    04701 L10342:
    04702                         pxor mm7, mm7           /* zero MM7 (accumulator) */
    04703                                 movd mm6, esi           /* save ESI in MM6 */
    04704                                 /* --- 1 */
    04705                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    04706                         movq mm2, mm1           /* copy MM1 into MM2 */
    04707                                 add esi, eax    /* move Src pointer 1 row below */
    04708                                 movq mm3, [edx]         /* load 4 words of Kernel */
    04709                         add edx, 8      /* move pointer to other 4 words */
    04710                                 movq mm4, [edx]         /* load 4 words of Kernel */
    04711                         add edx, 8      /* move pointer to other 4 words */
    04712                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    04713                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    04714                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    04715                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    04716                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    04717                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    04718                                 /* --- 2 */
    04719                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    04720                         movq mm2, mm1           /* copy MM1 into MM2 */
    04721                                 add esi, eax    /* move Src pointer 1 row below */
    04722                                 movq mm3, [edx]         /* load 4 words of Kernel */
    04723                         add edx, 8      /* move pointer to other 4 words */
    04724                                 movq mm4, [edx]         /* load 4 words of Kernel */
    04725                         add edx, 8      /* move pointer to other 4 words */
    04726                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    04727                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    04728                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    04729                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    04730                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    04731                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    04732                                 /* --- 3 */
    04733                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    04734                         movq mm2, mm1           /* copy MM1 into MM2 */
    04735                                 add esi, eax    /* move Src pointer 1 row below */
    04736                                 movq mm3, [edx]         /* load 4 words of Kernel */
    04737                         add edx, 8      /* move pointer to other 4 words */
    04738                                 movq mm4, [edx]         /* load 4 words of Kernel */
    04739                         add edx, 8      /* move pointer to other 4 words */
    04740                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    04741                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    04742                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    04743                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    04744                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    04745                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    04746                                 /* --- 4 */
    04747                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    04748                         movq mm2, mm1           /* copy MM1 into MM2 */
    04749                                 add esi, eax    /* move Src pointer 1 row below */
    04750                                 movq mm3, [edx]         /* load 4 words of Kernel */
    04751                         add edx, 8      /* move pointer to other 4 words */
    04752                                 movq mm4, [edx]         /* load 4 words of Kernel */
    04753                         add edx, 8      /* move pointer to other 4 words */
    04754                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    04755                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    04756                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    04757                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    04758                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    04759                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    04760                                 /* --- 5 */
    04761                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    04762                         movq mm2, mm1           /* copy MM1 into MM2 */
    04763                                 add esi, eax    /* move Src pointer 1 row below */
    04764                                 movq mm3, [edx]         /* load 4 words of Kernel */
    04765                         add edx, 8      /* move pointer to other 4 words */
    04766                                 movq mm4, [edx]         /* load 4 words of Kernel */
    04767                         add edx, 8      /* move pointer to other 4 words */
    04768                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    04769                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    04770                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    04771                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    04772                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    04773                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    04774                                 /* --- 6 */
    04775                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    04776                         movq mm2, mm1           /* copy MM1 into MM2 */
    04777                                 add esi, eax    /* move Src pointer 1 row below */
    04778                                 movq mm3, [edx]         /* load 4 words of Kernel */
    04779                         add edx, 8      /* move pointer to other 4 words */
    04780                                 movq mm4, [edx]         /* load 4 words of Kernel */
    04781                         add edx, 8      /* move pointer to other 4 words */
    04782                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    04783                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    04784                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    04785                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    04786                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    04787                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    04788                                 /* --- 7 */
    04789                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    04790                         movq mm2, mm1           /* copy MM1 into MM2 */
    04791                                 movq mm3, [edx]         /* load 4 words of Kernel */
    04792                         add edx, 8      /* move pointer to other 4 words */
    04793                                 movq mm4, [edx]         /* load 4 words of Kernel */
    04794                         punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    04795                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    04796                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    04797                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    04798                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    04799                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    04800                                 /* ---, */
    04801                                 movq mm3, mm7           /* copy MM7 into MM3 */
    04802                                 psrlq mm7, 32           /* shift 2 left words to the right */
    04803                                 paddsw mm7, mm3         /* add 2 left and 2 right result words */
    04804                                 movq mm2, mm7           /* copy MM7 into MM2 */
    04805                                 psrlq mm7, 16           /* shift 1 left word to the right */
    04806                                 paddsw mm7, mm2         /* add 1 left and 1 right result words */
    04807                                 /* ---, */
    04808                                 movd mm1, eax           /* save EDX in MM1 */
    04809                                 movd mm2, ebx           /* save EDX in MM2 */
    04810                                 movd mm3, edx           /* save EDX in MM3 */
    04811                                 movd eax, mm7           /* load summation result into EAX */
    04812                                 psraw mm7, 15           /* spread sign bit of the result */
    04813                                 movd ebx, mm5           /* load Divisor into EBX */
    04814                                 movd edx, mm7           /* fill EDX with a sign bit */
    04815                                 idiv bx         /* IDIV - VERY EXPENSIVE */
    04816                                 movd mm7, eax           /* move result of division into MM7 */
    04817                                 packuswb mm7, mm0       /* pack division result with saturation */
    04818                                 movd eax, mm7           /* copy saturated result into EAX */
    04819                                 mov [edi], al           /* copy a byte result into Dest */
    04820                                 movd edx, mm3           /* restore saved EDX */
    04821                                 movd ebx, mm2           /* restore saved EBX */
    04822                                 movd eax, mm1           /* restore saved EAX */
    04823                                 /* --, */
    04824                                 movd esi, mm6           /* move Src pointer to the top pixel */
    04825                                 sub edx, 104    /* EDX = Kernel address */
    04826                                 inc              esi            /* move Src  pointer to the next pixel */
    04827                                 inc              edi            /* move Dest pointer to the next pixel */
    04828                                 /* ---, */
    04829                                 dec              ecx            /* decrease loop counter COLUMNS */
    04830                                 jnz            L10342           /* check loop termination, proceed if required */
    04831                                 add esi, 6      /* move to the next row in Src */
    04832                                 add edi, 6      /* move to the next row in Dest */
    04833                                 dec              ebx            /* decrease loop counter ROWS */
    04834                                 jnz            L10340           /* check loop termination, proceed if required */
    04835                                 /* ---, */
    04836                                 emms                            /* exit MMX state */
    04837                                 popa
    04838                 }
    04839 #else
    04840                 asm volatile
    04841                         ("pusha              \n\t" "pxor      %%mm0, %%mm0 \n\t"        /* zero MM0 */
    04842                         "xor       %%ebx, %%ebx \n\t"   /* zero EBX */
    04843                         "mov           %5, %%bl \n\t"   /* load Divisor into BL */
    04844                         "movd      %%ebx, %%mm5 \n\t"   /* copy Divisor into MM5 */
    04845                         "mov          %4, %%edx \n\t"   /* load Kernel address into EDX */
    04846                         "mov          %1, %%esi \n\t"   /* load Src  address to ESI */
    04847                         "mov          %0, %%edi \n\t"   /* load Dest address to EDI */
    04848                         "add          $3, %%edi \n\t"   /* 3 column offset from the left edge */
    04849                         "mov          %3, %%eax \n\t"   /* load columns into EAX */
    04850                         "add       %%eax, %%edi \n\t"   /* 3 row offset from the top edge */
    04851                         "add       %%eax, %%edi \n\t" "add       %%eax, %%edi \n\t" "mov          %2, %%ebx \n\t"       /* initialize ROWS counter */
    04852                         "sub          $6, %%ebx \n\t"   /* do not use first 3 and last 3 rows */
    04853                         /* --- */
    04854                         ".L10340:               \n\t" "mov       %%eax, %%ecx \n\t"     /* initialize COLUMNS counter */
    04855                         "sub          $6, %%ecx \n\t"   /* do not use first 3 and last 3 columns */
    04856                         ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    04857                         ".L10342:               \n\t" "pxor      %%mm7, %%mm7 \n\t"     /* zero MM7 (accumulator) */
    04858                         "movd      %%esi, %%mm6 \n\t"   /* save ESI in MM6 */
    04859                         /* --- 1 */
    04860                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    04861                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    04862                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    04863                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    04864                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04865                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    04866                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04867                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    04868                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    04869                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    04870                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    04871                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    04872                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    04873                         /* --- 2 */
    04874                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    04875                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    04876                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    04877                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    04878                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04879                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    04880                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04881                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    04882                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    04883                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    04884                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    04885                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    04886                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    04887                         /* --- 3 */
    04888                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    04889                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    04890                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    04891                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    04892                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04893                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    04894                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04895                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    04896                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    04897                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    04898                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    04899                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    04900                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    04901                         /* --- 4 */
    04902                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    04903                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    04904                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    04905                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    04906                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04907                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    04908                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04909                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    04910                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    04911                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    04912                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    04913                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    04914                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    04915                         /* --- 5 */
    04916                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    04917                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    04918                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    04919                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    04920                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04921                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    04922                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04923                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    04924                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    04925                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    04926                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    04927                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    04928                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    04929                         /* --- 6 */
    04930                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    04931                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    04932                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    04933                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    04934                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04935                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    04936                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04937                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    04938                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    04939                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    04940                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    04941                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    04942                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    04943                         /* --- 7 */
    04944                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    04945                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    04946                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    04947                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    04948                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    04949                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    04950                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    04951                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    04952                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    04953                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    04954                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    04955                         /* --- */
    04956                         "movq      %%mm7, %%mm3 \n\t"   /* copy MM7 into MM3 */
    04957                         "psrlq       $32, %%mm7 \n\t"   /* shift 2 left words to the right */
    04958                         "paddsw    %%mm3, %%mm7 \n\t"   /* add 2 left and 2 right result words */
    04959                         "movq      %%mm7, %%mm2 \n\t"   /* copy MM7 into MM2 */
    04960                         "psrlq       $16, %%mm7 \n\t"   /* shift 1 left word to the right */
    04961                         "paddsw    %%mm2, %%mm7 \n\t"   /* add 1 left and 1 right result words */
    04962                         /* --- */
    04963                         "movd      %%eax, %%mm1 \n\t"   /* save EDX in MM1 */
    04964                         "movd      %%ebx, %%mm2 \n\t"   /* save EDX in MM2 */
    04965                         "movd      %%edx, %%mm3 \n\t"   /* save EDX in MM3 */
    04966                         "movd      %%mm7, %%eax \n\t"   /* load summation result into EAX */
    04967                         "psraw       $15, %%mm7 \n\t"   /* spread sign bit of the result */
    04968                         "movd      %%mm5, %%ebx \n\t"   /* load Divisor into EBX */
    04969                         "movd      %%mm7, %%edx \n\t"   /* fill EDX with a sign bit */
    04970                         "idivw             %%bx \n\t"   /* IDIV - VERY EXPENSIVE */
    04971                         "movd      %%eax, %%mm7 \n\t"   /* move result of division into MM7 */
    04972                         "packuswb  %%mm0, %%mm7 \n\t"   /* pack division result with saturation */
    04973                         "movd      %%mm7, %%eax \n\t"   /* copy saturated result into EAX */
    04974                         "mov      %%al, (%%edi) \n\t"   /* copy a byte result into Dest */
    04975                         "movd      %%mm3, %%edx \n\t"   /* restore saved EDX */
    04976                         "movd      %%mm2, %%ebx \n\t"   /* restore saved EBX */
    04977                         "movd      %%mm1, %%eax \n\t"   /* restore saved EAX */
    04978                         /* -- */
    04979                         "movd      %%mm6, %%esi \n\t"   /* move Src pointer to the top pixel */
    04980                         "sub        $104, %%edx \n\t"   /* EDX = Kernel address */
    04981                         "inc              %%esi \n\t"   /* move Src  pointer to the next pixel */
    04982                         "inc              %%edi \n\t"   /* move Dest pointer to the next pixel */
    04983                         /* --- */
    04984                         "dec              %%ecx \n\t"   /* decrease loop counter COLUMNS */
    04985                         "jnz            .L10342 \n\t"   /* check loop termination, proceed if required */
    04986                         "add          $6, %%esi \n\t"   /* move to the next row in Src */
    04987                         "add          $6, %%edi \n\t"   /* move to the next row in Dest */
    04988                         "dec              %%ebx \n\t"   /* decrease loop counter ROWS */
    04989                         "jnz            .L10340 \n\t"   /* check loop termination, proceed if required */
    04990                         /* --- */
    04991                         "emms                   \n\t"   /* exit MMX state */
    04992                         "popa                   \n\t":"=m" (Dest)       /* %0 */
    04993                         :"m"(Src),              /* %1 */
    04994                         "m"(rows),              /* %2 */
    04995                         "m"(columns),           /* %3 */
    04996                         "m"(Kernel),            /* %4 */
    04997                         "m"(Divisor)            /* %5 */
    04998                         );
    04999 #endif
    05000 #endif
    05001                 return (0);
    05002         } else {
    05003                 /* No non-MMX implementation yet */
    05004                 return (-1);
    05005         }
    05006 }
    05007
    05022 int SDL_imageFilterConvolveKernel9x9Divide(unsigned char *Src, unsigned char *Dest, int rows, int columns,
    05023                                                                                    signed short *Kernel, unsigned char Divisor)
    05024 {
    05025         /* Validate input parameters */
    05026         if ((Src == NULL) || (Dest == NULL) || (Kernel == NULL))
    05027                 return(-1);
    05028
    05029         if ((columns < 9) || (rows < 9) || (Divisor == 0))
    05030                 return (-1);
    05031
    05032         if ((SDL_imageFilterMMXdetect())) {
    05033 #ifdef USE_MMX
    05034 #if !defined(GCC__)
    05035                 __asm
    05036                 {
    05037                         pusha
    05038                                 pxor mm0, mm0           /* zero MM0 */
    05039                                 xor ebx, ebx    /* zero EBX */
    05040                                 mov bl, Divisor         /* load Divisor into BL */
    05041                                 movd mm5, ebx           /* copy Divisor into MM5 */
    05042                                 mov edx, Kernel         /* load Kernel address into EDX */
    05043                                 mov esi, Src    /* load Src  address to ESI */
    05044                                 mov edi, Dest           /* load Dest address to EDI */
    05045                                 add edi, 4      /* 4 column offset from the left edge */
    05046                                 mov eax, columns        /* load columns into EAX */
    05047                                 add edi, eax    /* 4 row offset from the top edge */
    05048                                 add edi, eax
    05049                                 add edi, eax
    05050                                 add edi, eax
    05051                                 mov ebx, rows           /* initialize ROWS counter */
    05052                                 sub ebx, 8      /* do not use first 4 and last 4 rows */
    05053                                 /* ---, */
    05054 L10350:
    05055                         mov ecx, eax    /* initialize COLUMNS counter */
    05056                                 sub ecx, 8      /* do not use first 4 and last 4 columns */
    05057                                 align 16                        /* 16 byte alignment of the loop entry */
    05058 L10352:
    05059                         pxor mm7, mm7           /* zero MM7 (accumulator) */
    05060                                 movd mm6, esi           /* save ESI in MM6 */
    05061                                 /* --- 1 */
    05062                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05063                         movq mm2, mm1           /* copy MM1 into MM2 */
    05064                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    05065                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05066                         add edx, 8      /* move pointer to other 4 words */
    05067                                 movq mm4, [edx]         /* load 4 words of Kernel */
    05068                         add edx, 8      /* move pointer to other 4 words */
    05069                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05070                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    05071                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05072                                 pmullw mm2, mm4         /* mult. 4 high words of Src and Kernel */
    05073                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    05074                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05075                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05076                         dec              esi
    05077                                 add esi, eax    /* move Src pointer 1 row below */
    05078                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05079                         add edx, 8      /* move pointer to other 4 words */
    05080                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05081                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05082                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05083                                 /* --- 2 */
    05084                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05085                         movq mm2, mm1           /* copy MM1 into MM2 */
    05086                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    05087                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05088                         add edx, 8      /* move pointer to other 4 words */
    05089                                 movq mm4, [edx]         /* load 4 words of Kernel */
    05090                         add edx, 8      /* move pointer to other 4 words */
    05091                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05092                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    05093                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05094                                 pmullw mm2, mm4         /* mult. 4 high words of Src and Kernel */
    05095                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    05096                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05097                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05098                         dec              esi
    05099                                 add esi, eax    /* move Src pointer 1 row below */
    05100                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05101                         add edx, 8      /* move pointer to other 4 words */
    05102                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05103                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05104                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05105                                 /* --- 3 */
    05106                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05107                         movq mm2, mm1           /* copy MM1 into MM2 */
    05108                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    05109                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05110                         add edx, 8      /* move pointer to other 4 words */
    05111                                 movq mm4, [edx]         /* load 4 words of Kernel */
    05112                         add edx, 8      /* move pointer to other 4 words */
    05113                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05114                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    05115                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05116                                 pmullw mm2, mm4         /* mult. 4 high words of Src and Kernel */
    05117                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    05118                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05119                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05120                         dec              esi
    05121                                 add esi, eax    /* move Src pointer 1 row below */
    05122                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05123                         add edx, 8      /* move pointer to other 4 words */
    05124                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05125                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05126                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05127                                 /* --- 4 */
    05128                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05129                         movq mm2, mm1           /* copy MM1 into MM2 */
    05130                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    05131                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05132                         add edx, 8      /* move pointer to other 4 words */
    05133                                 movq mm4, [edx]         /* load 4 words of Kernel */
    05134                         add edx, 8      /* move pointer to other 4 words */
    05135                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05136                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    05137                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05138                                 pmullw mm2, mm4         /* mult. 4 high words of Src and Kernel */
    05139                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    05140                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05141                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05142                         dec              esi
    05143                                 add esi, eax    /* move Src pointer 1 row below */
    05144                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05145                         add edx, 8      /* move pointer to other 4 words */
    05146                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05147                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05148                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05149                                 /* --- 5 */
    05150                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05151                         movq mm2, mm1           /* copy MM1 into MM2 */
    05152                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    05153                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05154                         add edx, 8      /* move pointer to other 4 words */
    05155                                 movq mm4, [edx]         /* load 4 words of Kernel */
    05156                         add edx, 8      /* move pointer to other 4 words */
    05157                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05158                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    05159                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05160                                 pmullw mm2, mm4         /* mult. 4 high words of Src and Kernel */
    05161                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    05162                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05163                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05164                         dec              esi
    05165                                 add esi, eax    /* move Src pointer 1 row below */
    05166                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05167                         add edx, 8      /* move pointer to other 4 words */
    05168                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05169                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05170                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05171                                 /* --- 6 */
    05172                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05173                         movq mm2, mm1           /* copy MM1 into MM2 */
    05174                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    05175                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05176                         add edx, 8      /* move pointer to other 4 words */
    05177                                 movq mm4, [edx]         /* load 4 words of Kernel */
    05178                         add edx, 8      /* move pointer to other 4 words */
    05179                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05180                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    05181                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05182                                 pmullw mm2, mm4         /* mult. 4 high words of Src and Kernel */
    05183                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    05184                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05185                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05186                         dec              esi
    05187                                 add esi, eax    /* move Src pointer 1 row below */
    05188                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05189                         add edx, 8      /* move pointer to other 4 words */
    05190                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05191                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05192                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05193                                 /* --- 7 */
    05194                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05195                         movq mm2, mm1           /* copy MM1 into MM2 */
    05196                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    05197                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05198                         add edx, 8      /* move pointer to other 4 words */
    05199                                 movq mm4, [edx]         /* load 4 words of Kernel */
    05200                         add edx, 8      /* move pointer to other 4 words */
    05201                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05202                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    05203                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05204                                 pmullw mm2, mm4         /* mult. 4 high words of Src and Kernel */
    05205                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    05206                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05207                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05208                         dec              esi
    05209                                 add esi, eax    /* move Src pointer 1 row below */
    05210                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05211                         add edx, 8      /* move pointer to other 4 words */
    05212                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05213                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05214                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05215                                 /* --- 8 */
    05216                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05217                         movq mm2, mm1           /* copy MM1 into MM2 */
    05218                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    05219                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05220                         add edx, 8      /* move pointer to other 4 words */
    05221                                 movq mm4, [edx]         /* load 4 words of Kernel */
    05222                         add edx, 8      /* move pointer to other 4 words */
    05223                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05224                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    05225                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05226                                 pmullw mm2, mm4         /* mult. 4 high words of Src and Kernel */
    05227                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    05228                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05229                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05230                         dec              esi
    05231                                 add esi, eax    /* move Src pointer 1 row below */
    05232                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05233                         add edx, 8      /* move pointer to other 4 words */
    05234                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05235                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05236                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05237                                 /* --- 9 */
    05238                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05239                         movq mm2, mm1           /* copy MM1 into MM2 */
    05240                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    05241                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05242                         add edx, 8      /* move pointer to other 4 words */
    05243                                 movq mm4, [edx]         /* load 4 words of Kernel */
    05244                         add edx, 8      /* move pointer to other 4 words */
    05245                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05246                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    05247                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05248                                 pmullw mm2, mm4         /* mult. 4 high words of Src and Kernel */
    05249                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    05250                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05251                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05252                         movq mm3, [edx]         /* load 4 words of Kernel */
    05253                         punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05254                                 pmullw mm1, mm3         /* mult. 4 low  words of Src and Kernel */
    05255                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05256                                 /* ---, */
    05257                                 movq mm3, mm7           /* copy MM7 into MM3 */
    05258                                 psrlq mm7, 32           /* shift 2 left words to the right */
    05259                                 paddsw mm7, mm3         /* add 2 left and 2 right result words */
    05260                                 movq mm2, mm7           /* copy MM7 into MM2 */
    05261                                 psrlq mm7, 16           /* shift 1 left word to the right */
    05262                                 paddsw mm7, mm2         /* add 1 left and 1 right result words */
    05263                                 /* ---, */
    05264                                 movd mm1, eax           /* save EDX in MM1 */
    05265                                 movd mm2, ebx           /* save EDX in MM2 */
    05266                                 movd mm3, edx           /* save EDX in MM3 */
    05267                                 movd eax, mm7           /* load summation result into EAX */
    05268                                 psraw mm7, 15           /* spread sign bit of the result */
    05269                                 movd ebx, mm5           /* load Divisor into EBX */
    05270                                 movd edx, mm7           /* fill EDX with a sign bit */
    05271                                 idiv bx         /* IDIV - VERY EXPENSIVE */
    05272                                 movd mm7, eax           /* move result of division into MM7 */
    05273                                 packuswb mm7, mm0       /* pack division result with saturation */
    05274                                 movd eax, mm7           /* copy saturated result into EAX */
    05275                                 mov [edi], al           /* copy a byte result into Dest */
    05276                                 movd edx, mm3           /* restore saved EDX */
    05277                                 movd ebx, mm2           /* restore saved EBX */
    05278                                 movd eax, mm1           /* restore saved EAX */
    05279                                 /* --, */
    05280                                 movd esi, mm6           /* move Src pointer to the top pixel */
    05281                                 sub edx, 208    /* EDX = Kernel address */
    05282                                 inc              esi            /* move Src  pointer to the next pixel */
    05283                                 inc              edi            /* move Dest pointer to the next pixel */
    05284                                 /* ---, */
    05285                                 dec              ecx            /* decrease loop counter COLUMNS */
    05286                                 jnz            L10352           /* check loop termination, proceed if required */
    05287                                 add esi, 8      /* move to the next row in Src */
    05288                                 add edi, 8      /* move to the next row in Dest */
    05289                                 dec              ebx            /* decrease loop counter ROWS */
    05290                                 jnz            L10350           /* check loop termination, proceed if required */
    05291                                 /* ---, */
    05292                                 emms                            /* exit MMX state */
    05293                                 popa
    05294                 }
    05295 #else
    05296                 asm volatile
    05297                         ("pusha              \n\t" "pxor      %%mm0, %%mm0 \n\t"        /* zero MM0 */
    05298                         "xor       %%ebx, %%ebx \n\t"   /* zero EBX */
    05299                         "mov           %5, %%bl \n\t"   /* load Divisor into BL */
    05300                         "movd      %%ebx, %%mm5 \n\t"   /* copy Divisor into MM5 */
    05301                         "mov          %4, %%edx \n\t"   /* load Kernel address into EDX */
    05302                         "mov          %1, %%esi \n\t"   /* load Src  address to ESI */
    05303                         "mov          %0, %%edi \n\t"   /* load Dest address to EDI */
    05304                         "add          $4, %%edi \n\t"   /* 4 column offset from the left edge */
    05305                         "mov          %3, %%eax \n\t"   /* load columns into EAX */
    05306                         "add       %%eax, %%edi \n\t"   /* 4 row offset from the top edge */
    05307                         "add       %%eax, %%edi \n\t" "add       %%eax, %%edi \n\t" "add       %%eax, %%edi \n\t" "mov          %2, %%ebx \n\t" /* initialize ROWS counter */
    05308                         "sub          $8, %%ebx \n\t"   /* do not use first 4 and last 4 rows */
    05309                         /* --- */
    05310                         ".L10350:               \n\t" "mov       %%eax, %%ecx \n\t"     /* initialize COLUMNS counter */
    05311                         "sub          $8, %%ecx \n\t"   /* do not use first 4 and last 4 columns */
    05312                         ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    05313                         ".L10352:               \n\t" "pxor      %%mm7, %%mm7 \n\t"     /* zero MM7 (accumulator) */
    05314                         "movd      %%esi, %%mm6 \n\t"   /* save ESI in MM6 */
    05315                         /* --- 1 */
    05316                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05317                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    05318                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    05319                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05320                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05321                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    05322                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05323                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05324                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    05325                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05326                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    05327                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    05328                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05329                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05330                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    05331                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05332                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05333                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05334                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05335                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05336                         /* --- 2 */
    05337                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05338                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    05339                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    05340                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05341                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05342                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    05343                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05344                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05345                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    05346                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05347                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    05348                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    05349                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05350                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05351                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    05352                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05353                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05354                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05355                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05356                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05357                         /* --- 3 */
    05358                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05359                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    05360                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    05361                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05362                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05363                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    05364                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05365                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05366                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    05367                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05368                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    05369                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    05370                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05371                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05372                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    05373                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05374                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05375                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05376                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05377                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05378                         /* --- 4 */
    05379                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05380                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    05381                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    05382                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05383                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05384                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    05385                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05386                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05387                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    05388                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05389                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    05390                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    05391                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05392                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05393                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    05394                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05395                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05396                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05397                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05398                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05399                         /* --- 5 */
    05400                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05401                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    05402                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    05403                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05404                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05405                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    05406                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05407                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05408                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    05409                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05410                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    05411                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    05412                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05413                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05414                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    05415                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05416                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05417                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05418                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05419                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05420                         /* --- 6 */
    05421                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05422                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    05423                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    05424                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05425                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05426                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    05427                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05428                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05429                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    05430                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05431                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    05432                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    05433                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05434                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05435                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    05436                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05437                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05438                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05439                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05440                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05441                         /* --- 7 */
    05442                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05443                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    05444                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    05445                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05446                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05447                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    05448                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05449                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05450                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    05451                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05452                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    05453                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    05454                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05455                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05456                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    05457                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05458                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05459                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05460                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05461                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05462                         /* --- 8 */
    05463                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05464                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    05465                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    05466                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05467                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05468                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    05469                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05470                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05471                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    05472                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05473                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    05474                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    05475                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05476                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05477                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    05478                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05479                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05480                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05481                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05482                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05483                         /* --- 9 */
    05484                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05485                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    05486                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    05487                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05488                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05489                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    05490                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05491                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05492                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    05493                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05494                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    05495                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    05496                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05497                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05498                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05499                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05500                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05501                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05502                         /* --- */
    05503                         "movq      %%mm7, %%mm3 \n\t"   /* copy MM7 into MM3 */
    05504                         "psrlq       $32, %%mm7 \n\t"   /* shift 2 left words to the right */
    05505                         "paddsw    %%mm3, %%mm7 \n\t"   /* add 2 left and 2 right result words */
    05506                         "movq      %%mm7, %%mm2 \n\t"   /* copy MM7 into MM2 */
    05507                         "psrlq       $16, %%mm7 \n\t"   /* shift 1 left word to the right */
    05508                         "paddsw    %%mm2, %%mm7 \n\t"   /* add 1 left and 1 right result words */
    05509                         /* --- */
    05510                         "movd      %%eax, %%mm1 \n\t"   /* save EDX in MM1 */
    05511                         "movd      %%ebx, %%mm2 \n\t"   /* save EDX in MM2 */
    05512                         "movd      %%edx, %%mm3 \n\t"   /* save EDX in MM3 */
    05513                         "movd      %%mm7, %%eax \n\t"   /* load summation result into EAX */
    05514                         "psraw       $15, %%mm7 \n\t"   /* spread sign bit of the result */
    05515                         "movd      %%mm5, %%ebx \n\t"   /* load Divisor into EBX */
    05516                         "movd      %%mm7, %%edx \n\t"   /* fill EDX with a sign bit */
    05517                         "idivw             %%bx \n\t"   /* IDIV - VERY EXPENSIVE */
    05518                         "movd      %%eax, %%mm7 \n\t"   /* move result of division into MM7 */
    05519                         "packuswb  %%mm0, %%mm7 \n\t"   /* pack division result with saturation */
    05520                         "movd      %%mm7, %%eax \n\t"   /* copy saturated result into EAX */
    05521                         "mov      %%al, (%%edi) \n\t"   /* copy a byte result into Dest */
    05522                         "movd      %%mm3, %%edx \n\t"   /* restore saved EDX */
    05523                         "movd      %%mm2, %%ebx \n\t"   /* restore saved EBX */
    05524                         "movd      %%mm1, %%eax \n\t"   /* restore saved EAX */
    05525                         /* -- */
    05526                         "movd      %%mm6, %%esi \n\t"   /* move Src pointer to the top pixel */
    05527                         "sub        $208, %%edx \n\t"   /* EDX = Kernel address */
    05528                         "inc              %%esi \n\t"   /* move Src  pointer to the next pixel */
    05529                         "inc              %%edi \n\t"   /* move Dest pointer to the next pixel */
    05530                         /* --- */
    05531                         "dec              %%ecx \n\t"   /* decrease loop counter COLUMNS */
    05532                         "jnz            .L10352 \n\t"   /* check loop termination, proceed if required */
    05533                         "add          $8, %%esi \n\t"   /* move to the next row in Src */
    05534                         "add          $8, %%edi \n\t"   /* move to the next row in Dest */
    05535                         "dec              %%ebx \n\t"   /* decrease loop counter ROWS */
    05536                         "jnz            .L10350 \n\t"   /* check loop termination, proceed if required */
    05537                         /* --- */
    05538                         "emms                   \n\t"   /* exit MMX state */
    05539                         "popa                   \n\t":"=m" (Dest)       /* %0 */
    05540                         :"m"(Src),              /* %1 */
    05541                         "m"(rows),              /* %2 */
    05542                         "m"(columns),           /* %3 */
    05543                         "m"(Kernel),            /* %4 */
    05544                         "m"(Divisor)            /* %5 */
    05545                         );
    05546 #endif
    05547 #endif
    05548                 return (0);
    05549         } else {
    05550                 /* No non-MMX implementation yet */
    05551                 return (-1);
    05552         }
    05553 }
    05554
    05569 int SDL_imageFilterConvolveKernel3x3ShiftRight(unsigned char *Src, unsigned char *Dest, int rows, int columns,
    05570                                                                                            signed short *Kernel, unsigned char NRightShift)
    05571 {
    05572         /* Validate input parameters */
    05573         if ((Src == NULL) || (Dest == NULL) || (Kernel == NULL))
    05574                 return(-1);
    05575
    05576         if ((columns < 3) || (rows < 3) || (NRightShift > 7))
    05577                 return (-1);
    05578
    05579         if ((SDL_imageFilterMMXdetect())) {
    05580 #ifdef USE_MMX
    05581 #if !defined(GCC__)
    05582                 __asm
    05583                 {
    05584                         pusha
    05585                                 pxor mm0, mm0           /* zero MM0 */
    05586                                 xor ebx, ebx    /* zero EBX */
    05587                                 mov bl, NRightShift     /* load NRightShift into BL */
    05588                                 movd mm4, ebx           /* copy NRightShift into MM4 */
    05589                                 mov edx, Kernel         /* load Kernel address into EDX */
    05590                                 movq mm5, [edx]         /* MM5 = {0,K2,K1,K0} */
    05591                         add edx, 8      /* second row              |K0 K1 K2 0| */
    05592                                 movq mm6, [edx]         /* MM6 = {0,K5,K4,K3}  K = |K3 K4 K5 0| */
    05593                         add edx, 8      /* third row               |K6 K7 K8 0| */
    05594                                 movq mm7, [edx]         /* MM7 = {0,K8,K7,K6} */
    05595                         /* ---, */
    05596                         mov eax, columns        /* load columns into EAX */
    05597                                 mov esi, Src    /* ESI = Src row 0 address */
    05598                                 mov edi, Dest           /* load Dest address to EDI */
    05599                                 add edi, eax    /* EDI = EDI + columns */
    05600                                 inc              edi            /* 1 byte offset from the left edge */
    05601                                 mov edx, rows           /* initialize ROWS counter */
    05602                                 sub edx, 2      /* do not use first and last row */
    05603                                 /* ---, */
    05604 L10360:
    05605                         mov ecx, eax    /* initialize COLUMS counter */
    05606                                 sub ecx, 2      /* do not use first and last column */
    05607                                 align 16                        /* 16 byte alignment of the loop entry */
    05608 L10362:
    05609                         /* ---, */
    05610                         movq mm1, [esi]         /* load 8 bytes of the image first row */
    05611                         add esi, eax    /* move one row below */
    05612                                 movq mm2, [esi]         /* load 8 bytes of the image second row */
    05613                         add esi, eax    /* move one row below */
    05614                                 movq mm3, [esi]         /* load 8 bytes of the image third row */
    05615                         punpcklbw mm1, mm0      /* unpack first 4 bytes into words */
    05616                                 punpcklbw mm2, mm0      /* unpack first 4 bytes into words */
    05617                                 punpcklbw mm3, mm0      /* unpack first 4 bytes into words */
    05618                                 psrlw mm1, mm4          /* shift right each pixel NshiftRight times */
    05619                                 psrlw mm2, mm4          /* shift right each pixel NshiftRight times */
    05620                                 psrlw mm3, mm4          /* shift right each pixel NshiftRight times */
    05621                                 pmullw mm1, mm5         /* multiply words first row  image*Kernel */
    05622                                 pmullw mm2, mm6         /* multiply words second row image*Kernel */
    05623                                 pmullw mm3, mm7         /* multiply words third row  image*Kernel */
    05624                                 paddsw mm1, mm2         /* add 4 words of the first and second rows */
    05625                                 paddsw mm1, mm3         /* add 4 words of the third row and result */
    05626                                 movq mm2, mm1           /* copy MM1 into MM2 */
    05627                                 psrlq mm1, 32           /* shift 2 left words to the right */
    05628                                 paddsw mm1, mm2         /* add 2 left and 2 right result words */
    05629                                 movq mm3, mm1           /* copy MM1 into MM3 */
    05630                                 psrlq mm1, 16           /* shift 1 left word to the right */
    05631                                 paddsw mm1, mm3         /* add 1 left and 1 right result words */
    05632                                 packuswb mm1, mm0       /* pack shift result with saturation */
    05633                                 movd ebx, mm1           /* copy saturated result into EBX */
    05634                                 mov [edi], bl           /* copy a byte result into Dest */
    05635                                 /* --, */
    05636                                 sub esi, eax    /* move two rows up */
    05637                                 sub esi, eax
    05638                                 inc              esi            /* move Src  pointer to the next pixel */
    05639                                 inc              edi            /* move Dest pointer to the next pixel */
    05640                                 /* ---, */
    05641                                 dec              ecx            /* decrease loop counter COLUMNS */
    05642                                 jnz            L10362           /* check loop termination, proceed if required */
    05643                                 add esi, 2      /* move to the next row in Src */
    05644                                 add edi, 2      /* move to the next row in Dest */
    05645                                 dec              edx            /* decrease loop counter ROWS */
    05646                                 jnz            L10360           /* check loop termination, proceed if required */
    05647                                 /* ---, */
    05648                                 emms                            /* exit MMX state */
    05649                                 popa
    05650                 }
    05651 #else
    05652                 asm volatile
    05653                         ("pusha              \n\t" "pxor      %%mm0, %%mm0 \n\t"        /* zero MM0 */
    05654                         "xor       %%ebx, %%ebx \n\t"   /* zero EBX */
    05655                         "mov           %5, %%bl \n\t"   /* load NRightShift into BL */
    05656                         "movd      %%ebx, %%mm4 \n\t"   /* copy NRightShift into MM4 */
    05657                         "mov          %4, %%edx \n\t"   /* load Kernel address into EDX */
    05658                         "movq    (%%edx), %%mm5 \n\t"   /* MM5 = {0,K2,K1,K0} */
    05659                         "add          $8, %%edx \n\t"   /* second row              |K0 K1 K2 0| */
    05660                         "movq    (%%edx), %%mm6 \n\t"   /* MM6 = {0,K5,K4,K3}  K = |K3 K4 K5 0| */
    05661                         "add          $8, %%edx \n\t"   /* third row               |K6 K7 K8 0| */
    05662                         "movq    (%%edx), %%mm7 \n\t"   /* MM7 = {0,K8,K7,K6} */
    05663                         /* --- */
    05664                         "mov          %3, %%eax \n\t"   /* load columns into EAX */
    05665                         "mov          %1, %%esi \n\t"   /* ESI = Src row 0 address */
    05666                         "mov          %0, %%edi \n\t"   /* load Dest address to EDI */
    05667                         "add       %%eax, %%edi \n\t"   /* EDI = EDI + columns */
    05668                         "inc              %%edi \n\t"   /* 1 byte offset from the left edge */
    05669                         "mov          %2, %%edx \n\t"   /* initialize ROWS counter */
    05670                         "sub          $2, %%edx \n\t"   /* do not use first and last row */
    05671                         /* --- */
    05672                         ".L10360:               \n\t" "mov       %%eax, %%ecx \n\t"     /* initialize COLUMS counter */
    05673                         "sub          $2, %%ecx \n\t"   /* do not use first and last column */
    05674                         ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    05675                         ".L10362:               \n\t"
    05676                         /* --- */
    05677                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the image first row */
    05678                         "add       %%eax, %%esi \n\t"   /* move one row below */
    05679                         "movq    (%%esi), %%mm2 \n\t"   /* load 8 bytes of the image second row */
    05680                         "add       %%eax, %%esi \n\t"   /* move one row below */
    05681                         "movq    (%%esi), %%mm3 \n\t"   /* load 8 bytes of the image third row */
    05682                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first 4 bytes into words */
    05683                         "punpcklbw %%mm0, %%mm2 \n\t"   /* unpack first 4 bytes into words */
    05684                         "punpcklbw %%mm0, %%mm3 \n\t"   /* unpack first 4 bytes into words */
    05685                         "psrlw     %%mm4, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    05686                         "psrlw     %%mm4, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    05687                         "psrlw     %%mm4, %%mm3 \n\t"   /* shift right each pixel NshiftRight times */
    05688                         "pmullw    %%mm5, %%mm1 \n\t"   /* multiply words first row  image*Kernel */
    05689                         "pmullw    %%mm6, %%mm2 \n\t"   /* multiply words second row image*Kernel */
    05690                         "pmullw    %%mm7, %%mm3 \n\t"   /* multiply words third row  image*Kernel */
    05691                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the first and second rows */
    05692                         "paddsw    %%mm3, %%mm1 \n\t"   /* add 4 words of the third row and result */
    05693                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    05694                         "psrlq       $32, %%mm1 \n\t"   /* shift 2 left words to the right */
    05695                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 2 left and 2 right result words */
    05696                         "movq      %%mm1, %%mm3 \n\t"   /* copy MM1 into MM3 */
    05697                         "psrlq       $16, %%mm1 \n\t"   /* shift 1 left word to the right */
    05698                         "paddsw    %%mm3, %%mm1 \n\t"   /* add 1 left and 1 right result words */
    05699                         "packuswb  %%mm0, %%mm1 \n\t"   /* pack shift result with saturation */
    05700                         "movd      %%mm1, %%ebx \n\t"   /* copy saturated result into EBX */
    05701                         "mov      %%bl, (%%edi) \n\t"   /* copy a byte result into Dest */
    05702                         /* -- */
    05703                         "sub       %%eax, %%esi \n\t"   /* move two rows up */
    05704                         "sub       %%eax, %%esi \n\t" "inc              %%esi \n\t"     /* move Src  pointer to the next pixel */
    05705                         "inc              %%edi \n\t"   /* move Dest pointer to the next pixel */
    05706                         /* --- */
    05707                         "dec              %%ecx \n\t"   /* decrease loop counter COLUMNS */
    05708                         "jnz            .L10362 \n\t"   /* check loop termination, proceed if required */
    05709                         "add          $2, %%esi \n\t"   /* move to the next row in Src */
    05710                         "add          $2, %%edi \n\t"   /* move to the next row in Dest */
    05711                         "dec              %%edx \n\t"   /* decrease loop counter ROWS */
    05712                         "jnz            .L10360 \n\t"   /* check loop termination, proceed if required */
    05713                         /* --- */
    05714                         "emms                   \n\t"   /* exit MMX state */
    05715                         "popa                   \n\t":"=m" (Dest)       /* %0 */
    05716                         :"m"(Src),              /* %1 */
    05717                         "m"(rows),              /* %2 */
    05718                         "m"(columns),           /* %3 */
    05719                         "m"(Kernel),            /* %4 */
    05720                         "m"(NRightShift)        /* %5 */
    05721                         );
    05722 #endif
    05723 #endif
    05724                 return (0);
    05725         } else {
    05726                 /* No non-MMX implementation yet */
    05727                 return (-1);
    05728         }
    05729 }
    05730
    05745 int SDL_imageFilterConvolveKernel5x5ShiftRight(unsigned char *Src, unsigned char *Dest, int rows, int columns,
    05746                                                                                            signed short *Kernel, unsigned char NRightShift)
    05747 {
    05748         /* Validate input parameters */
    05749         if ((Src == NULL) || (Dest == NULL) || (Kernel == NULL))
    05750                 return(-1);
    05751
    05752         if ((columns < 5) || (rows < 5) || (NRightShift > 7))
    05753                 return (-1);
    05754
    05755         if ((SDL_imageFilterMMXdetect())) {
    05756 #ifdef USE_MMX
    05757 #if !defined(GCC__)
    05758                 __asm
    05759                 {
    05760                         pusha
    05761                                 pxor mm0, mm0           /* zero MM0 */
    05762                                 xor ebx, ebx    /* zero EBX */
    05763                                 mov bl, NRightShift     /* load NRightShift into BL */
    05764                                 movd mm5, ebx           /* copy NRightShift into MM5 */
    05765                                 mov edx, Kernel         /* load Kernel address into EDX */
    05766                                 mov esi, Src    /* load Src  address to ESI */
    05767                                 mov edi, Dest           /* load Dest address to EDI */
    05768                                 add edi, 2      /* 2 column offset from the left edge */
    05769                                 mov eax, columns        /* load columns into EAX */
    05770                                 shl eax, 1      /* EAX = columns * 2 */
    05771                                 add edi, eax    /* 2 row offset from the top edge */
    05772                                 shr eax, 1      /* EAX = columns */
    05773                                 mov ebx, rows           /* initialize ROWS counter */
    05774                                 sub ebx, 4      /* do not use first 2 and last 2 rows */
    05775                                 /* ---, */
    05776 L10370:
    05777                         mov ecx, eax    /* initialize COLUMNS counter */
    05778                                 sub ecx, 4      /* do not use first 2 and last 2 columns */
    05779                                 align 16                        /* 16 byte alignment of the loop entry */
    05780 L10372:
    05781                         pxor mm7, mm7           /* zero MM7 (accumulator) */
    05782                                 movd mm6, esi           /* save ESI in MM6 */
    05783                                 /* --- 1 */
    05784                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05785                         movq mm2, mm1           /* copy MM1 into MM2 */
    05786                                 add esi, eax    /* move Src pointer 1 row below */
    05787                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05788                         add edx, 8      /* move pointer to other 4 words */
    05789                                 movq mm4, [edx]         /* load 4 words of Kernel */
    05790                         add edx, 8      /* move pointer to other 4 words */
    05791                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05792                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    05793                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    05794                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    05795                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    05796                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    05797                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    05798                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05799                                 /* --- 2 */
    05800                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05801                         movq mm2, mm1           /* copy MM1 into MM2 */
    05802                                 add esi, eax    /* move Src pointer 1 row below */
    05803                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05804                         add edx, 8      /* move pointer to other 4 words */
    05805                                 movq mm4, [edx]         /* load 4 words of Kernel */
    05806                         add edx, 8      /* move pointer to other 4 words */
    05807                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05808                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    05809                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    05810                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    05811                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    05812                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    05813                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    05814                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05815                                 /* --- 3 */
    05816                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05817                         movq mm2, mm1           /* copy MM1 into MM2 */
    05818                                 add esi, eax    /* move Src pointer 1 row below */
    05819                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05820                         add edx, 8      /* move pointer to other 4 words */
    05821                                 movq mm4, [edx]         /* load 4 words of Kernel */
    05822                         add edx, 8      /* move pointer to other 4 words */
    05823                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05824                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    05825                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    05826                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    05827                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    05828                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    05829                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    05830                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05831                                 /* --- 4 */
    05832                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05833                         movq mm2, mm1           /* copy MM1 into MM2 */
    05834                                 add esi, eax    /* move Src pointer 1 row below */
    05835                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05836                         add edx, 8      /* move pointer to other 4 words */
    05837                                 movq mm4, [edx]         /* load 4 words of Kernel */
    05838                         add edx, 8      /* move pointer to other 4 words */
    05839                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05840                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    05841                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    05842                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    05843                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    05844                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    05845                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    05846                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05847                                 /* --- 5 */
    05848                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    05849                         movq mm2, mm1           /* copy MM1 into MM2 */
    05850                                 movq mm3, [edx]         /* load 4 words of Kernel */
    05851                         add edx, 8      /* move pointer to other 4 words */
    05852                                 movq mm4, [edx]         /* load 4 words of Kernel */
    05853                         punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    05854                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    05855                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    05856                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    05857                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    05858                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    05859                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    05860                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    05861                                 /* ---, */
    05862                                 movq mm3, mm7           /* copy MM7 into MM3 */
    05863                                 psrlq mm7, 32           /* shift 2 left words to the right */
    05864                                 paddsw mm7, mm3         /* add 2 left and 2 right result words */
    05865                                 movq mm2, mm7           /* copy MM7 into MM2 */
    05866                                 psrlq mm7, 16           /* shift 1 left word to the right */
    05867                                 paddsw mm7, mm2         /* add 1 left and 1 right result words */
    05868                                 movd mm1, eax           /* save EAX in MM1 */
    05869                                 packuswb mm7, mm0       /* pack division result with saturation */
    05870                                 movd eax, mm7           /* copy saturated result into EAX */
    05871                                 mov [edi], al           /* copy a byte result into Dest */
    05872                                 movd eax, mm1           /* restore saved EAX */
    05873                                 /* --, */
    05874                                 movd esi, mm6           /* move Src pointer to the top pixel */
    05875                                 sub edx, 72     /* EDX = Kernel address */
    05876                                 inc              esi            /* move Src  pointer to the next pixel */
    05877                                 inc              edi            /* move Dest pointer to the next pixel */
    05878                                 /* ---, */
    05879                                 dec              ecx            /* decrease loop counter COLUMNS */
    05880                                 jnz            L10372           /* check loop termination, proceed if required */
    05881                                 add esi, 4      /* move to the next row in Src */
    05882                                 add edi, 4      /* move to the next row in Dest */
    05883                                 dec              ebx            /* decrease loop counter ROWS */
    05884                                 jnz            L10370           /* check loop termination, proceed if required */
    05885                                 /* ---, */
    05886                                 emms                            /* exit MMX state */
    05887                                 popa
    05888                 }
    05889 #else
    05890                 asm volatile
    05891                         ("pusha              \n\t" "pxor      %%mm0, %%mm0 \n\t"        /* zero MM0 */
    05892                         "xor       %%ebx, %%ebx \n\t"   /* zero EBX */
    05893                         "mov           %5, %%bl \n\t"   /* load NRightShift into BL */
    05894                         "movd      %%ebx, %%mm5 \n\t"   /* copy NRightShift into MM5 */
    05895                         "mov          %4, %%edx \n\t"   /* load Kernel address into EDX */
    05896                         "mov          %1, %%esi \n\t"   /* load Src  address to ESI */
    05897                         "mov          %0, %%edi \n\t"   /* load Dest address to EDI */
    05898                         "add          $2, %%edi \n\t"   /* 2 column offset from the left edge */
    05899                         "mov          %3, %%eax \n\t"   /* load columns into EAX */
    05900                         "shl          $1, %%eax \n\t"   /* EAX = columns * 2 */
    05901                         "add       %%eax, %%edi \n\t"   /* 2 row offset from the top edge */
    05902                         "shr          $1, %%eax \n\t"   /* EAX = columns */
    05903                         "mov          %2, %%ebx \n\t"   /* initialize ROWS counter */
    05904                         "sub          $4, %%ebx \n\t"   /* do not use first 2 and last 2 rows */
    05905                         /* --- */
    05906                         ".L10370:               \n\t" "mov       %%eax, %%ecx \n\t"     /* initialize COLUMNS counter */
    05907                         "sub          $4, %%ecx \n\t"   /* do not use first 2 and last 2 columns */
    05908                         ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    05909                         ".L10372:               \n\t" "pxor      %%mm7, %%mm7 \n\t"     /* zero MM7 (accumulator) */
    05910                         "movd      %%esi, %%mm6 \n\t"   /* save ESI in MM6 */
    05911                         /* --- 1 */
    05912                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05913                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    05914                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    05915                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05916                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05917                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    05918                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05919                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05920                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    05921                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    05922                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    05923                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05924                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    05925                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    05926                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05927                         /* --- 2 */
    05928                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05929                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    05930                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    05931                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05932                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05933                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    05934                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05935                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05936                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    05937                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    05938                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    05939                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05940                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    05941                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    05942                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05943                         /* --- 3 */
    05944                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05945                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    05946                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    05947                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05948                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05949                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    05950                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05951                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05952                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    05953                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    05954                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    05955                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05956                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    05957                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    05958                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05959                         /* --- 4 */
    05960                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05961                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    05962                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    05963                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05964                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05965                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    05966                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05967                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05968                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    05969                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    05970                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    05971                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05972                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    05973                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    05974                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05975                         /* --- 5 */
    05976                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    05977                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    05978                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    05979                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    05980                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    05981                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    05982                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    05983                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    05984                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    05985                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    05986                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    05987                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    05988                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    05989                         /* --- */
    05990                         "movq      %%mm7, %%mm3 \n\t"   /* copy MM7 into MM3 */
    05991                         "psrlq       $32, %%mm7 \n\t"   /* shift 2 left words to the right */
    05992                         "paddsw    %%mm3, %%mm7 \n\t"   /* add 2 left and 2 right result words */
    05993                         "movq      %%mm7, %%mm2 \n\t"   /* copy MM7 into MM2 */
    05994                         "psrlq       $16, %%mm7 \n\t"   /* shift 1 left word to the right */
    05995                         "paddsw    %%mm2, %%mm7 \n\t"   /* add 1 left and 1 right result words */
    05996                         "movd      %%eax, %%mm1 \n\t"   /* save EAX in MM1 */
    05997                         "packuswb  %%mm0, %%mm7 \n\t"   /* pack division result with saturation */
    05998                         "movd      %%mm7, %%eax \n\t"   /* copy saturated result into EAX */
    05999                         "mov      %%al, (%%edi) \n\t"   /* copy a byte result into Dest */
    06000                         "movd      %%mm1, %%eax \n\t"   /* restore saved EAX */
    06001                         /* -- */
    06002                         "movd      %%mm6, %%esi \n\t"   /* move Src pointer to the top pixel */
    06003                         "sub         $72, %%edx \n\t"   /* EDX = Kernel address */
    06004                         "inc              %%esi \n\t"   /* move Src  pointer to the next pixel */
    06005                         "inc              %%edi \n\t"   /* move Dest pointer to the next pixel */
    06006                         /* --- */
    06007                         "dec              %%ecx \n\t"   /* decrease loop counter COLUMNS */
    06008                         "jnz            .L10372 \n\t"   /* check loop termination, proceed if required */
    06009                         "add          $4, %%esi \n\t"   /* move to the next row in Src */
    06010                         "add          $4, %%edi \n\t"   /* move to the next row in Dest */
    06011                         "dec              %%ebx \n\t"   /* decrease loop counter ROWS */
    06012                         "jnz            .L10370 \n\t"   /* check loop termination, proceed if required */
    06013                         /* --- */
    06014                         "emms                   \n\t"   /* exit MMX state */
    06015                         "popa                   \n\t":"=m" (Dest)       /* %0 */
    06016                         :"m"(Src),              /* %1 */
    06017                         "m"(rows),              /* %2 */
    06018                         "m"(columns),           /* %3 */
    06019                         "m"(Kernel),            /* %4 */
    06020                         "m"(NRightShift)        /* %5 */
    06021                         );
    06022 #endif
    06023 #endif
    06024                 return (0);
    06025         } else {
    06026                 /* No non-MMX implementation yet */
    06027                 return (-1);
    06028         }
    06029 }
    06030
    06045 int SDL_imageFilterConvolveKernel7x7ShiftRight(unsigned char *Src, unsigned char *Dest, int rows, int columns,
    06046                                                                                            signed short *Kernel, unsigned char NRightShift)
    06047 {
    06048         /* Validate input parameters */
    06049         if ((Src == NULL) || (Dest == NULL) || (Kernel == NULL))
    06050                 return(-1);
    06051
    06052         if ((columns < 7) || (rows < 7) || (NRightShift > 7))
    06053                 return (-1);
    06054
    06055         if ((SDL_imageFilterMMXdetect())) {
    06056 #ifdef USE_MMX
    06057 #if !defined(GCC__)
    06058                 __asm
    06059                 {
    06060                         pusha
    06061                                 pxor mm0, mm0           /* zero MM0 */
    06062                                 xor ebx, ebx    /* zero EBX */
    06063                                 mov bl, NRightShift     /* load NRightShift into BL */
    06064                                 movd mm5, ebx           /* copy NRightShift into MM5 */
    06065                                 mov edx, Kernel         /* load Kernel address into EDX */
    06066                                 mov esi, Src    /* load Src  address to ESI */
    06067                                 mov edi, Dest           /* load Dest address to EDI */
    06068                                 add edi, 3      /* 3 column offset from the left edge */
    06069                                 mov eax, columns        /* load columns into EAX */
    06070                                 add edi, eax    /* 3 row offset from the top edge */
    06071                                 add edi, eax
    06072                                 add edi, eax
    06073                                 mov ebx, rows           /* initialize ROWS counter */
    06074                                 sub ebx, 6      /* do not use first 3 and last 3 rows */
    06075                                 /* ---, */
    06076 L10380:
    06077                         mov ecx, eax    /* initialize COLUMNS counter */
    06078                                 sub ecx, 6      /* do not use first 3 and last 3 columns */
    06079                                 align 16                        /* 16 byte alignment of the loop entry */
    06080 L10382:
    06081                         pxor mm7, mm7           /* zero MM7 (accumulator) */
    06082                                 movd mm6, esi           /* save ESI in MM6 */
    06083                                 /* --- 1 */
    06084                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06085                         movq mm2, mm1           /* copy MM1 into MM2 */
    06086                                 add esi, eax    /* move Src pointer 1 row below */
    06087                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06088                         add edx, 8      /* move pointer to other 4 words */
    06089                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06090                         add edx, 8      /* move pointer to other 4 words */
    06091                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06092                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06093                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06094                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06095                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06096                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06097                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06098                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06099                                 /* --- 2 */
    06100                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06101                         movq mm2, mm1           /* copy MM1 into MM2 */
    06102                                 add esi, eax    /* move Src pointer 1 row below */
    06103                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06104                         add edx, 8      /* move pointer to other 4 words */
    06105                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06106                         add edx, 8      /* move pointer to other 4 words */
    06107                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06108                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06109                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06110                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06111                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06112                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06113                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06114                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06115                                 /* --- 3 */
    06116                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06117                         movq mm2, mm1           /* copy MM1 into MM2 */
    06118                                 add esi, eax    /* move Src pointer 1 row below */
    06119                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06120                         add edx, 8      /* move pointer to other 4 words */
    06121                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06122                         add edx, 8      /* move pointer to other 4 words */
    06123                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06124                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06125                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06126                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06127                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06128                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06129                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06130                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06131                                 /* --- 4 */
    06132                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06133                         movq mm2, mm1           /* copy MM1 into MM2 */
    06134                                 add esi, eax    /* move Src pointer 1 row below */
    06135                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06136                         add edx, 8      /* move pointer to other 4 words */
    06137                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06138                         add edx, 8      /* move pointer to other 4 words */
    06139                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06140                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06141                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06142                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06143                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06144                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06145                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06146                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06147                                 /* --- 5 */
    06148                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06149                         movq mm2, mm1           /* copy MM1 into MM2 */
    06150                                 add esi, eax    /* move Src pointer 1 row below */
    06151                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06152                         add edx, 8      /* move pointer to other 4 words */
    06153                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06154                         add edx, 8      /* move pointer to other 4 words */
    06155                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06156                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06157                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06158                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06159                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06160                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06161                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06162                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06163                                 /* --- 6 */
    06164                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06165                         movq mm2, mm1           /* copy MM1 into MM2 */
    06166                                 add esi, eax    /* move Src pointer 1 row below */
    06167                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06168                         add edx, 8      /* move pointer to other 4 words */
    06169                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06170                         add edx, 8      /* move pointer to other 4 words */
    06171                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06172                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06173                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06174                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06175                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06176                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06177                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06178                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06179                                 /* --- 7 */
    06180                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06181                         movq mm2, mm1           /* copy MM1 into MM2 */
    06182                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06183                         add edx, 8      /* move pointer to other 4 words */
    06184                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06185                         punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06186                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06187                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06188                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06189                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06190                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06191                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06192                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06193                                 /* ---, */
    06194                                 movq mm3, mm7           /* copy MM7 into MM3 */
    06195                                 psrlq mm7, 32           /* shift 2 left words to the right */
    06196                                 paddsw mm7, mm3         /* add 2 left and 2 right result words */
    06197                                 movq mm2, mm7           /* copy MM7 into MM2 */
    06198                                 psrlq mm7, 16           /* shift 1 left word to the right */
    06199                                 paddsw mm7, mm2         /* add 1 left and 1 right result words */
    06200                                 movd mm1, eax           /* save EAX in MM1 */
    06201                                 packuswb mm7, mm0       /* pack division result with saturation */
    06202                                 movd eax, mm7           /* copy saturated result into EAX */
    06203                                 mov [edi], al           /* copy a byte result into Dest */
    06204                                 movd eax, mm1           /* restore saved EAX */
    06205                                 /* --, */
    06206                                 movd esi, mm6           /* move Src pointer to the top pixel */
    06207                                 sub edx, 104    /* EDX = Kernel address */
    06208                                 inc              esi            /* move Src  pointer to the next pixel */
    06209                                 inc              edi            /* move Dest pointer to the next pixel */
    06210                                 /* ---, */
    06211                                 dec              ecx            /* decrease loop counter COLUMNS */
    06212                                 jnz            L10382           /* check loop termination, proceed if required */
    06213                                 add esi, 6      /* move to the next row in Src */
    06214                                 add edi, 6      /* move to the next row in Dest */
    06215                                 dec              ebx            /* decrease loop counter ROWS */
    06216                                 jnz            L10380           /* check loop termination, proceed if required */
    06217                                 /* ---, */
    06218                                 emms                            /* exit MMX state */
    06219                                 popa
    06220                 }
    06221 #else
    06222                 asm volatile
    06223                         ("pusha              \n\t" "pxor      %%mm0, %%mm0 \n\t"        /* zero MM0 */
    06224                         "xor       %%ebx, %%ebx \n\t"   /* zero EBX */
    06225                         "mov           %5, %%bl \n\t"   /* load NRightShift into BL */
    06226                         "movd      %%ebx, %%mm5 \n\t"   /* copy NRightShift into MM5 */
    06227                         "mov          %4, %%edx \n\t"   /* load Kernel address into EDX */
    06228                         "mov          %1, %%esi \n\t"   /* load Src  address to ESI */
    06229                         "mov          %0, %%edi \n\t"   /* load Dest address to EDI */
    06230                         "add          $3, %%edi \n\t"   /* 3 column offset from the left edge */
    06231                         "mov          %3, %%eax \n\t"   /* load columns into EAX */
    06232                         "add       %%eax, %%edi \n\t"   /* 3 row offset from the top edge */
    06233                         "add       %%eax, %%edi \n\t" "add       %%eax, %%edi \n\t" "mov          %2, %%ebx \n\t"       /* initialize ROWS counter */
    06234                         "sub          $6, %%ebx \n\t"   /* do not use first 3 and last 3 rows */
    06235                         /* --- */
    06236                         ".L10380:               \n\t" "mov       %%eax, %%ecx \n\t"     /* initialize COLUMNS counter */
    06237                         "sub          $6, %%ecx \n\t"   /* do not use first 3 and last 3 columns */
    06238                         ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    06239                         ".L10382:               \n\t" "pxor      %%mm7, %%mm7 \n\t"     /* zero MM7 (accumulator) */
    06240                         "movd      %%esi, %%mm6 \n\t"   /* save ESI in MM6 */
    06241                         /* --- 1 */
    06242                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06243                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06244                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    06245                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06246                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06247                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06248                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06249                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06250                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06251                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06252                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06253                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06254                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06255                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06256                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06257                         /* --- 2 */
    06258                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06259                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06260                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    06261                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06262                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06263                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06264                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06265                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06266                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06267                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06268                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06269                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06270                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06271                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06272                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06273                         /* --- 3 */
    06274                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06275                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06276                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    06277                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06278                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06279                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06280                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06281                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06282                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06283                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06284                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06285                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06286                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06287                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06288                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06289                         /* --- 4 */
    06290                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06291                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06292                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    06293                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06294                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06295                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06296                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06297                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06298                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06299                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06300                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06301                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06302                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06303                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06304                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06305                         /* --- 5 */
    06306                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06307                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06308                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    06309                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06310                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06311                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06312                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06313                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06314                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06315                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06316                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06317                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06318                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06319                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06320                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06321                         /* --- 6 */
    06322                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06323                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06324                         "add       %%eax, %%esi \n\t"   /* move Src pointer 1 row below */
    06325                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06326                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06327                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06328                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06329                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06330                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06331                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06332                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06333                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06334                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06335                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06336                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06337                         /* --- 7 */
    06338                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06339                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06340                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06341                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06342                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06343                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06344                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06345                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06346                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06347                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06348                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06349                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06350                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06351                         /* --- */
    06352                         "movq      %%mm7, %%mm3 \n\t"   /* copy MM7 into MM3 */
    06353                         "psrlq       $32, %%mm7 \n\t"   /* shift 2 left words to the right */
    06354                         "paddsw    %%mm3, %%mm7 \n\t"   /* add 2 left and 2 right result words */
    06355                         "movq      %%mm7, %%mm2 \n\t"   /* copy MM7 into MM2 */
    06356                         "psrlq       $16, %%mm7 \n\t"   /* shift 1 left word to the right */
    06357                         "paddsw    %%mm2, %%mm7 \n\t"   /* add 1 left and 1 right result words */
    06358                         "movd      %%eax, %%mm1 \n\t"   /* save EAX in MM1 */
    06359                         "packuswb  %%mm0, %%mm7 \n\t"   /* pack division result with saturation */
    06360                         "movd      %%mm7, %%eax \n\t"   /* copy saturated result into EAX */
    06361                         "mov      %%al, (%%edi) \n\t"   /* copy a byte result into Dest */
    06362                         "movd      %%mm1, %%eax \n\t"   /* restore saved EAX */
    06363                         /* -- */
    06364                         "movd      %%mm6, %%esi \n\t"   /* move Src pointer to the top pixel */
    06365                         "sub        $104, %%edx \n\t"   /* EDX = Kernel address */
    06366                         "inc              %%esi \n\t"   /* move Src  pointer to the next pixel */
    06367                         "inc              %%edi \n\t"   /* move Dest pointer to the next pixel */
    06368                         /* --- */
    06369                         "dec              %%ecx \n\t"   /* decrease loop counter COLUMNS */
    06370                         "jnz            .L10382 \n\t"   /* check loop termination, proceed if required */
    06371                         "add          $6, %%esi \n\t"   /* move to the next row in Src */
    06372                         "add          $6, %%edi \n\t"   /* move to the next row in Dest */
    06373                         "dec              %%ebx \n\t"   /* decrease loop counter ROWS */
    06374                         "jnz            .L10380 \n\t"   /* check loop termination, proceed if required */
    06375                         /* --- */
    06376                         "emms                   \n\t"   /* exit MMX state */
    06377                         "popa                   \n\t":"=m" (Dest)       /* %0 */
    06378                         :"m"(Src),              /* %1 */
    06379                         "m"(rows),              /* %2 */
    06380                         "m"(columns),           /* %3 */
    06381                         "m"(Kernel),            /* %4 */
    06382                         "m"(NRightShift)        /* %5 */
    06383                         );
    06384 #endif
    06385 #endif
    06386                 return (0);
    06387         } else {
    06388                 /* No non-MMX implementation yet */
    06389                 return (-1);
    06390         }
    06391 }
    06392
    06407 int SDL_imageFilterConvolveKernel9x9ShiftRight(unsigned char *Src, unsigned char *Dest, int rows, int columns,
    06408                                                                                            signed short *Kernel, unsigned char NRightShift)
    06409 {
    06410         /* Validate input parameters */
    06411         if ((Src == NULL) || (Dest == NULL) || (Kernel == NULL))
    06412                 return(-1);
    06413
    06414         if ((columns < 9) || (rows < 9) || (NRightShift > 7))
    06415                 return (-1);
    06416
    06417         if ((SDL_imageFilterMMXdetect())) {
    06418 #ifdef USE_MMX
    06419 #if !defined(GCC__)
    06420                 __asm
    06421                 {
    06422                         pusha
    06423                                 pxor mm0, mm0           /* zero MM0 */
    06424                                 xor ebx, ebx    /* zero EBX */
    06425                                 mov bl, NRightShift     /* load NRightShift into BL */
    06426                                 movd mm5, ebx           /* copy NRightShift into MM5 */
    06427                                 mov edx, Kernel         /* load Kernel address into EDX */
    06428                                 mov esi, Src    /* load Src  address to ESI */
    06429                                 mov edi, Dest           /* load Dest address to EDI */
    06430                                 add edi, 4      /* 4 column offset from the left edge */
    06431                                 mov eax, columns        /* load columns into EAX */
    06432                                 add edi, eax    /* 4 row offset from the top edge */
    06433                                 add edi, eax
    06434                                 add edi, eax
    06435                                 add edi, eax
    06436                                 mov ebx, rows           /* initialize ROWS counter */
    06437                                 sub ebx, 8      /* do not use first 4 and last 4 rows */
    06438                                 /* ---, */
    06439 L10390:
    06440                         mov ecx, eax    /* initialize COLUMNS counter */
    06441                                 sub ecx, 8      /* do not use first 4 and last 4 columns */
    06442                                 align 16                        /* 16 byte alignment of the loop entry */
    06443 L10392:
    06444                         pxor mm7, mm7           /* zero MM7 (accumulator) */
    06445                                 movd mm6, esi           /* save ESI in MM6 */
    06446                                 /* --- 1 */
    06447                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06448                         movq mm2, mm1           /* copy MM1 into MM2 */
    06449                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    06450                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06451                         add edx, 8      /* move pointer to other 4 words */
    06452                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06453                         add edx, 8      /* move pointer to other 4 words */
    06454                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06455                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06456                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06457                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06458                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06459                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06460                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06461                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06462                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06463                         dec              esi
    06464                                 add esi, eax    /* move Src pointer 1 row below */
    06465                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06466                         add edx, 8      /* move pointer to other 4 words */
    06467                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06468                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06469                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06470                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06471                                 /* --- 2 */
    06472                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06473                         movq mm2, mm1           /* copy MM1 into MM2 */
    06474                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    06475                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06476                         add edx, 8      /* move pointer to other 4 words */
    06477                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06478                         add edx, 8      /* move pointer to other 4 words */
    06479                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06480                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06481                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06482                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06483                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06484                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06485                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06486                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06487                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06488                         dec              esi
    06489                                 add esi, eax    /* move Src pointer 1 row below */
    06490                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06491                         add edx, 8      /* move pointer to other 4 words */
    06492                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06493                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06494                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06495                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06496                                 /* --- 3 */
    06497                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06498                         movq mm2, mm1           /* copy MM1 into MM2 */
    06499                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    06500                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06501                         add edx, 8      /* move pointer to other 4 words */
    06502                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06503                         add edx, 8      /* move pointer to other 4 words */
    06504                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06505                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06506                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06507                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06508                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06509                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06510                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06511                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06512                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06513                         dec              esi
    06514                                 add esi, eax    /* move Src pointer 1 row below */
    06515                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06516                         add edx, 8      /* move pointer to other 4 words */
    06517                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06518                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06519                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06520                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06521                                 /* --- 4 */
    06522                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06523                         movq mm2, mm1           /* copy MM1 into MM2 */
    06524                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    06525                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06526                         add edx, 8      /* move pointer to other 4 words */
    06527                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06528                         add edx, 8      /* move pointer to other 4 words */
    06529                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06530                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06531                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06532                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06533                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06534                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06535                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06536                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06537                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06538                         dec              esi
    06539                                 add esi, eax    /* move Src pointer 1 row below */
    06540                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06541                         add edx, 8      /* move pointer to other 4 words */
    06542                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06543                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06544                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06545                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06546                                 /* --- 5 */
    06547                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06548                         movq mm2, mm1           /* copy MM1 into MM2 */
    06549                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    06550                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06551                         add edx, 8      /* move pointer to other 4 words */
    06552                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06553                         add edx, 8      /* move pointer to other 4 words */
    06554                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06555                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06556                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06557                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06558                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06559                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06560                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06561                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06562                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06563                         dec              esi
    06564                                 add esi, eax    /* move Src pointer 1 row below */
    06565                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06566                         add edx, 8      /* move pointer to other 4 words */
    06567                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06568                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06569                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06570                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06571                                 /* --- 6 */
    06572                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06573                         movq mm2, mm1           /* copy MM1 into MM2 */
    06574                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    06575                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06576                         add edx, 8      /* move pointer to other 4 words */
    06577                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06578                         add edx, 8      /* move pointer to other 4 words */
    06579                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06580                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06581                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06582                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06583                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06584                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06585                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06586                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06587                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06588                         dec              esi
    06589                                 add esi, eax    /* move Src pointer 1 row below */
    06590                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06591                         add edx, 8      /* move pointer to other 4 words */
    06592                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06593                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06594                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06595                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06596                                 /* --- 7 */
    06597                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06598                         movq mm2, mm1           /* copy MM1 into MM2 */
    06599                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    06600                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06601                         add edx, 8      /* move pointer to other 4 words */
    06602                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06603                         add edx, 8      /* move pointer to other 4 words */
    06604                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06605                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06606                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06607                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06608                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06609                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06610                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06611                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06612                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06613                         dec              esi
    06614                                 add esi, eax    /* move Src pointer 1 row below */
    06615                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06616                         add edx, 8      /* move pointer to other 4 words */
    06617                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06618                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06619                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06620                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06621                                 /* --- 8 */
    06622                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06623                         movq mm2, mm1           /* copy MM1 into MM2 */
    06624                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    06625                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06626                         add edx, 8      /* move pointer to other 4 words */
    06627                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06628                         add edx, 8      /* move pointer to other 4 words */
    06629                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06630                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06631                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06632                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06633                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06634                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06635                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06636                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06637                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06638                         dec              esi
    06639                                 add esi, eax    /* move Src pointer 1 row below */
    06640                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06641                         add edx, 8      /* move pointer to other 4 words */
    06642                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06643                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06644                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06645                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06646                                 /* --- 9 */
    06647                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06648                         movq mm2, mm1           /* copy MM1 into MM2 */
    06649                                 inc              esi            /* move pointer to the next 8 bytes of Src */
    06650                                 movq mm3, [edx]         /* load 4 words of Kernel */
    06651                         add edx, 8      /* move pointer to other 4 words */
    06652                                 movq mm4, [edx]         /* load 4 words of Kernel */
    06653                         add edx, 8      /* move pointer to other 4 words */
    06654                                 punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06655                                 punpckhbw mm2, mm0      /* unpack second 4 bytes into words */
    06656                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06657                                 psrlw mm2, mm5          /* shift right each pixel NshiftRight times */
    06658                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06659                                 pmullw mm2, mm4         /* mult 4 high words of Src and Kernel */
    06660                                 paddsw mm1, mm2         /* add 4 words of the high and low bytes */
    06661                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06662                                 movq mm1, [esi]         /* load 8 bytes of the Src */
    06663                         movq mm3, [edx]         /* load 4 words of Kernel */
    06664                         punpcklbw mm1, mm0      /* unpack first  4 bytes into words */
    06665                                 psrlw mm1, mm5          /* shift right each pixel NshiftRight times */
    06666                                 pmullw mm1, mm3         /* mult 4 low  words of Src and Kernel */
    06667                                 paddsw mm7, mm1         /* add MM1 to accumulator MM7 */
    06668                                 /* ---, */
    06669                                 movq mm3, mm7           /* copy MM7 into MM3 */
    06670                                 psrlq mm7, 32           /* shift 2 left words to the right */
    06671                                 paddsw mm7, mm3         /* add 2 left and 2 right result words */
    06672                                 movq mm2, mm7           /* copy MM7 into MM2 */
    06673                                 psrlq mm7, 16           /* shift 1 left word to the right */
    06674                                 paddsw mm7, mm2         /* add 1 left and 1 right result words */
    06675                                 movd mm1, eax           /* save EAX in MM1 */
    06676                                 packuswb mm7, mm0       /* pack division result with saturation */
    06677                                 movd eax, mm7           /* copy saturated result into EAX */
    06678                                 mov [edi], al           /* copy a byte result into Dest */
    06679                                 movd eax, mm1           /* restore saved EAX */
    06680                                 /* --, */
    06681                                 movd esi, mm6           /* move Src pointer to the top pixel */
    06682                                 sub edx, 208    /* EDX = Kernel address */
    06683                                 inc              esi            /* move Src  pointer to the next pixel */
    06684                                 inc              edi            /* move Dest pointer to the next pixel */
    06685                                 /* ---, */
    06686                                 dec              ecx            /* decrease loop counter COLUMNS */
    06687                                 jnz            L10392           /* check loop termination, proceed if required */
    06688                                 add esi, 8      /* move to the next row in Src */
    06689                                 add edi, 8      /* move to the next row in Dest */
    06690                                 dec              ebx            /* decrease loop counter ROWS */
    06691                                 jnz            L10390           /* check loop termination, proceed if required */
    06692                                 /* ---, */
    06693                                 emms                            /* exit MMX state */
    06694                                 popa
    06695                 }
    06696 #else
    06697                 asm volatile
    06698                         ("pusha              \n\t" "pxor      %%mm0, %%mm0 \n\t"        /* zero MM0 */
    06699                         "xor       %%ebx, %%ebx \n\t"   /* zero EBX */
    06700                         "mov           %5, %%bl \n\t"   /* load NRightShift into BL */
    06701                         "movd      %%ebx, %%mm5 \n\t"   /* copy NRightShift into MM5 */
    06702                         "mov          %4, %%edx \n\t"   /* load Kernel address into EDX */
    06703                         "mov          %1, %%esi \n\t"   /* load Src  address to ESI */
    06704                         "mov          %0, %%edi \n\t"   /* load Dest address to EDI */
    06705                         "add          $4, %%edi \n\t"   /* 4 column offset from the left edge */
    06706                         "mov          %3, %%eax \n\t"   /* load columns into EAX */
    06707                         "add       %%eax, %%edi \n\t"   /* 4 row offset from the top edge */
    06708                         "add       %%eax, %%edi \n\t" "add       %%eax, %%edi \n\t" "add       %%eax, %%edi \n\t" "mov          %2, %%ebx \n\t" /* initialize ROWS counter */
    06709                         "sub          $8, %%ebx \n\t"   /* do not use first 4 and last 4 rows */
    06710                         /* --- */
    06711                         ".L10390:               \n\t" "mov       %%eax, %%ecx \n\t"     /* initialize COLUMNS counter */
    06712                         "sub          $8, %%ecx \n\t"   /* do not use first 4 and last 4 columns */
    06713                         ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    06714                         ".L10392:               \n\t" "pxor      %%mm7, %%mm7 \n\t"     /* zero MM7 (accumulator) */
    06715                         "movd      %%esi, %%mm6 \n\t"   /* save ESI in MM6 */
    06716                         /* --- 1 */
    06717                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06718                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06719                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    06720                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06721                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06722                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06723                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06724                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06725                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06726                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06727                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06728                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06729                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06730                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06731                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06732                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06733                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    06734                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06735                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06736                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06737                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06738                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06739                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06740                         /* --- 2 */
    06741                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06742                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06743                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    06744                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06745                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06746                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06747                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06748                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06749                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06750                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06751                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06752                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06753                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06754                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06755                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06756                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06757                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    06758                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06759                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06760                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06761                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06762                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06763                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06764                         /* --- 3 */
    06765                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06766                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06767                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    06768                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06769                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06770                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06771                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06772                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06773                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06774                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06775                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06776                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06777                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06778                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06779                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06780                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06781                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    06782                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06783                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06784                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06785                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06786                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06787                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06788                         /* --- 4 */
    06789                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06790                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06791                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    06792                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06793                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06794                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06795                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06796                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06797                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06798                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06799                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06800                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06801                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06802                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06803                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06804                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06805                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    06806                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06807                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06808                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06809                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06810                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06811                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06812                         /* --- 5 */
    06813                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06814                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06815                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    06816                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06817                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06818                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06819                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06820                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06821                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06822                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06823                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06824                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06825                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06826                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06827                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06828                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06829                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    06830                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06831                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06832                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06833                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06834                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06835                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06836                         /* --- 6 */
    06837                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06838                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06839                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    06840                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06841                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06842                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06843                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06844                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06845                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06846                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06847                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06848                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06849                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06850                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06851                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06852                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06853                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    06854                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06855                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06856                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06857                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06858                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06859                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06860                         /* --- 7 */
    06861                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06862                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06863                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    06864                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06865                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06866                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06867                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06868                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06869                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06870                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06871                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06872                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06873                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06874                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06875                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06876                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06877                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    06878                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06879                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06880                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06881                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06882                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06883                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06884                         /* --- 8 */
    06885                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06886                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06887                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    06888                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06889                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06890                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06891                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06892                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06893                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06894                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06895                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06896                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06897                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06898                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06899                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06900                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06901                         "dec              %%esi \n\t" "add       %%eax, %%esi \n\t"     /* move Src pointer 1 row below */
    06902                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06903                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06904                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06905                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06906                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06907                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06908                         /* --- 9 */
    06909                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06910                         "movq      %%mm1, %%mm2 \n\t"   /* copy MM1 into MM2 */
    06911                         "inc              %%esi \n\t"   /* move pointer to the next 8 bytes of Src */
    06912                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06913                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06914                         "movq    (%%edx), %%mm4 \n\t"   /* load 4 words of Kernel */
    06915                         "add          $8, %%edx \n\t"   /* move pointer to other 4 words */
    06916                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06917                         "punpckhbw %%mm0, %%mm2 \n\t"   /* unpack second 4 bytes into words */
    06918                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06919                         "psrlw     %%mm5, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    06920                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06921                         "pmullw    %%mm4, %%mm2 \n\t"   /* mult. 4 high words of Src and Kernel */
    06922                         "paddsw    %%mm2, %%mm1 \n\t"   /* add 4 words of the high and low bytes */
    06923                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06924                         "movq    (%%esi), %%mm1 \n\t"   /* load 8 bytes of the Src */
    06925                         "movq    (%%edx), %%mm3 \n\t"   /* load 4 words of Kernel */
    06926                         "punpcklbw %%mm0, %%mm1 \n\t"   /* unpack first  4 bytes into words */
    06927                         "psrlw     %%mm5, %%mm1 \n\t"   /* shift right each pixel NshiftRight times */
    06928                         "pmullw    %%mm3, %%mm1 \n\t"   /* mult. 4 low  words of Src and Kernel */
    06929                         "paddsw    %%mm1, %%mm7 \n\t"   /* add MM1 to accumulator MM7 */
    06930                         /* --- */
    06931                         "movq      %%mm7, %%mm3 \n\t"   /* copy MM7 into MM3 */
    06932                         "psrlq       $32, %%mm7 \n\t"   /* shift 2 left words to the right */
    06933                         "paddsw    %%mm3, %%mm7 \n\t"   /* add 2 left and 2 right result words */
    06934                         "movq      %%mm7, %%mm2 \n\t"   /* copy MM7 into MM2 */
    06935                         "psrlq       $16, %%mm7 \n\t"   /* shift 1 left word to the right */
    06936                         "paddsw    %%mm2, %%mm7 \n\t"   /* add 1 left and 1 right result words */
    06937                         "movd      %%eax, %%mm1 \n\t"   /* save EAX in MM1 */
    06938                         "packuswb  %%mm0, %%mm7 \n\t"   /* pack division result with saturation */
    06939                         "movd      %%mm7, %%eax \n\t"   /* copy saturated result into EAX */
    06940                         "mov      %%al, (%%edi) \n\t"   /* copy a byte result into Dest */
    06941                         "movd      %%mm1, %%eax \n\t"   /* restore saved EAX */
    06942                         /* -- */
    06943                         "movd      %%mm6, %%esi \n\t"   /* move Src pointer to the top pixel */
    06944                         "sub        $208, %%edx \n\t"   /* EDX = Kernel address */
    06945                         "inc              %%esi \n\t"   /* move Src  pointer to the next pixel */
    06946                         "inc              %%edi \n\t"   /* move Dest pointer to the next pixel */
    06947                         /* --- */
    06948                         "dec              %%ecx \n\t"   /* decrease loop counter COLUMNS */
    06949                         "jnz            .L10392 \n\t"   /* check loop termination, proceed if required */
    06950                         "add          $8, %%esi \n\t"   /* move to the next row in Src */
    06951                         "add          $8, %%edi \n\t"   /* move to the next row in Dest */
    06952                         "dec              %%ebx \n\t"   /* decrease loop counter ROWS */
    06953                         "jnz            .L10390 \n\t"   /* check loop termination, proceed if required */
    06954                         /* --- */
    06955                         "emms                   \n\t"   /* exit MMX state */
    06956                         "popa                   \n\t":"=m" (Dest)       /* %0 */
    06957                         :"m"(Src),              /* %1 */
    06958                         "m"(rows),              /* %2 */
    06959                         "m"(columns),           /* %3 */
    06960                         "m"(Kernel),            /* %4 */
    06961                         "m"(NRightShift)        /* %5 */
    06962                         );
    06963 #endif
    06964 #endif
    06965                 return (0);
    06966         } else {
    06967                 /* No non-MMX implementation yet */
    06968                 return (-1);
    06969         }
    06970 }
    06971
    06972 /* ------------------------------------------------------------------------------------ */
    06973
    06986 int SDL_imageFilterSobelX(unsigned char *Src, unsigned char *Dest, int rows, int columns)
    06987 {
    06988         /* Validate input parameters */
    06989         if ((Src == NULL) || (Dest == NULL))
    06990                 return(-1);
    06991
    06992         if ((columns < 8) || (rows < 3))
    06993                 return (-1);
    06994
    06995         if ((SDL_imageFilterMMXdetect())) {
    06996 #ifdef USE_MMX
    06997 #if !defined(GCC__)
    06998                 __asm
    06999                 {
    07000                         pusha
    07001                                 pxor mm0, mm0           /* zero MM0 */
    07002                                 mov eax, columns        /* load columns into EAX */
    07003                                 /* ---, */
    07004                                 mov esi, Src    /* ESI = Src row 0 address */
    07005                                 mov edi, Dest           /* load Dest address to EDI */
    07006                                 add edi, eax    /* EDI = EDI + columns */
    07007                                 inc              edi            /* 1 byte offset from the left edge */
    07008                                 mov edx, rows           /* initialize ROWS counter */
    07009                                 sub edx, 2      /* do not use first and last rows */
    07010                                 /* ---, */
    07011 L10400:
    07012                         mov ecx, eax    /* initialize COLUMS counter */
    07013                                 shr ecx, 3      /* EBX/8 (MMX loads 8 bytes at a time) */
    07014                                 mov ebx, esi    /* save ESI in EBX */
    07015                                 movd mm1, edi           /* save EDI in MM1 */
    07016                                 align 16                        /* 16 byte alignment of the loop entry */
    07017 L10402:
    07018                         /* ---, */
    07019                         movq mm4, [esi]         /* load 8 bytes from Src */
    07020                         movq mm5, mm4           /* save MM4 in MM5 */
    07021                                 add esi, 2      /* move ESI pointer 2 bytes right */
    07022                                 punpcklbw mm4, mm0      /* unpack 4 low  bytes into words */
    07023                                 punpckhbw mm5, mm0      /* unpack 4 high bytes into words */
    07024                                 movq mm6, [esi]         /* load 8 bytes from Src */
    07025                         movq mm7, mm6           /* save MM6 in MM7 */
    07026                                 sub esi, 2      /* move ESI pointer back 2 bytes left */
    07027                                 punpcklbw mm6, mm0      /* unpack 4 low  bytes into words */
    07028                                 punpckhbw mm7, mm0      /* unpack 4 high bytes into words */
    07029                                 add esi, eax    /* move to the next row of Src */
    07030                                 movq mm2, [esi]         /* load 8 bytes from Src */
    07031                         movq mm3, mm2           /* save MM2 in MM3 */
    07032                                 add esi, 2      /* move ESI pointer 2 bytes right */
    07033                                 punpcklbw mm2, mm0      /* unpack 4 low  bytes into words */
    07034                                 punpckhbw mm3, mm0      /* unpack 4 high bytes into words */
    07035                                 paddw mm4, mm2          /* add 4 low  bytes to accumolator MM4 */
    07036                                 paddw mm5, mm3          /* add 4 high bytes to accumolator MM5 */
    07037                                 paddw mm4, mm2          /* add 4 low  bytes to accumolator MM4 */
    07038                                 paddw mm5, mm3          /* add 4 high bytes to accumolator MM5 */
    07039                                 movq mm2, [esi]         /* load 8 bytes from Src */
    07040                         movq mm3, mm2           /* save MM2 in MM3 */
    07041                                 sub esi, 2      /* move ESI pointer back 2 bytes left */
    07042                                 punpcklbw mm2, mm0      /* unpack 4 low  bytes into words */
    07043                                 punpckhbw mm3, mm0      /* unpack 4 high bytes into words */
    07044                                 paddw mm6, mm2          /* add 4 low  bytes to accumolator MM6 */
    07045                                 paddw mm7, mm3          /* add 4 high bytes to accumolator MM7 */
    07046                                 paddw mm6, mm2          /* add 4 low  bytes to accumolator MM6 */
    07047                                 paddw mm7, mm3          /* add 4 high bytes to accumolator MM7 */
    07048                                 add esi, eax    /* move to the next row of Src */
    07049                                 movq mm2, [esi]         /* load 8 bytes from Src */
    07050                         movq mm3, mm2           /* save MM2 in MM3 */
    07051                                 add esi, 2      /* move ESI pointer 2 bytes right */
    07052                                 punpcklbw mm2, mm0      /* unpack 4 low  bytes into words */
    07053                                 punpckhbw mm3, mm0      /* unpack 4 high bytes into words */
    07054                                 paddw mm4, mm2          /* add 4 low  bytes to accumolator MM4 */
    07055                                 paddw mm5, mm3          /* add 4 high bytes to accumolator MM5 */
    07056                                 movq mm2, [esi]         /* load 8 bytes from Src */
    07057                         movq mm3, mm2           /* save MM2 in MM3 */
    07058                                 sub esi, 2      /* move ESI pointer back 2 bytes left */
    07059                                 punpcklbw mm2, mm0      /* unpack 4 low  bytes into words */
    07060                                 punpckhbw mm3, mm0      /* unpack 4 high bytes into words */
    07061                                 paddw mm6, mm2          /* add 4 low  bytes to accumolator MM6 */
    07062                                 paddw mm7, mm3          /* add 4 high bytes to accumolator MM7 */
    07063                                 /* ---, */
    07064                                 movq mm2, mm4           /* copy MM4 into MM2 */
    07065                                 psrlq mm4, 32           /* shift 2 left words to the right */
    07066                                 psubw mm4, mm2          /* MM4 = MM4 - MM2 */
    07067                                 movq mm3, mm6           /* copy MM6 into MM3 */
    07068                                 psrlq mm6, 32           /* shift 2 left words to the right */
    07069                                 psubw mm6, mm3          /* MM6 = MM6 - MM3 */
    07070                                 punpckldq mm4, mm6      /* combine 2 words of MM6 and 2 words of MM4 */
    07071                                 movq mm2, mm5           /* copy MM6 into MM2 */
    07072                                 psrlq mm5, 32           /* shift 2 left words to the right */
    07073                                 psubw mm5, mm2          /* MM5 = MM5 - MM2 */
    07074                                 movq mm3, mm7           /* copy MM7 into MM3 */
    07075                                 psrlq mm7, 32           /* shift 2 left words to the right */
    07076                                 psubw mm7, mm3          /* MM7 = MM7 - MM3 */
    07077                                 punpckldq mm5, mm7      /* combine 2 words of MM7 and 2 words of MM5 */
    07078                                 /* Take abs values of MM4 and MM5 */
    07079                                 movq mm6, mm4           /* copy MM4 into MM6 */
    07080                                 movq mm7, mm5           /* copy MM5 into MM7 */
    07081                                 psraw mm6, 15           /* fill MM6 words with word sign bit */
    07082                                 psraw mm7, 15           /* fill MM7 words with word sign bit */
    07083                                 pxor mm4, mm6           /* take 1's compliment of only neg words */
    07084                                 pxor mm5, mm7           /* take 1's compliment of only neg words */
    07085                                 psubsw mm4, mm6         /* add 1 to only neg words, W-(-1) or W-0 */
    07086                                 psubsw mm5, mm7         /* add 1 to only neg words, W-(-1) or W-0 */
    07087                                 packuswb mm4, mm5       /* combine and pack/saturate MM5 and MM4 */
    07088                                 movq [edi], mm4         /* store result in Dest */
    07089                                 /* ---, */
    07090                                 sub esi, eax    /* move to the current top row in Src */
    07091                                 sub esi, eax
    07092                                 add esi, 8      /* move Src  pointer to the next 8 pixels */
    07093                                 add edi, 8      /* move Dest pointer to the next 8 pixels */
    07094                                 /* ---, */
    07095                                 dec              ecx            /* decrease loop counter COLUMNS */
    07096                                 jnz            L10402           /* check loop termination, proceed if required */
    07097                                 mov esi, ebx    /* restore most left current row Src  address */
    07098                                 movd edi, mm1           /* restore most left current row Dest address */
    07099                                 add esi, eax    /* move to the next row in Src */
    07100                                 add edi, eax    /* move to the next row in Dest */
    07101                                 dec              edx            /* decrease loop counter ROWS */
    07102                                 jnz            L10400           /* check loop termination, proceed if required */
    07103                                 /* ---, */
    07104                                 emms                            /* exit MMX state */
    07105                                 popa
    07106                 }
    07107 #else
    07108                 asm volatile
    07109                         ("pusha              \n\t" "pxor      %%mm0, %%mm0 \n\t"        /* zero MM0 */
    07110                         "mov          %3, %%eax \n\t"   /* load columns into EAX */
    07111                         /* --- */
    07112                         "mov          %1, %%esi \n\t"   /* ESI = Src row 0 address */
    07113                         "mov          %0, %%edi \n\t"   /* load Dest address to EDI */
    07114                         "add       %%eax, %%edi \n\t"   /* EDI = EDI + columns */
    07115                         "inc              %%edi \n\t"   /* 1 byte offset from the left edge */
    07116                         "mov          %2, %%edx \n\t"   /* initialize ROWS counter */
    07117                         "sub          $2, %%edx \n\t"   /* do not use first and last rows */
    07118                         /* --- */
    07119                         ".L10400:                \n\t" "mov       %%eax, %%ecx \n\t"    /* initialize COLUMS counter */
    07120                         "shr          $3, %%ecx \n\t"   /* EBX/8 (MMX loads 8 bytes at a time) */
    07121                         "mov       %%esi, %%ebx \n\t"   /* save ESI in EBX */
    07122                         "movd      %%edi, %%mm1 \n\t"   /* save EDI in MM1 */
    07123                         ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    07124                         ".L10402:               \n\t"
    07125                         /* --- */
    07126                         "movq    (%%esi), %%mm4 \n\t"   /* load 8 bytes from Src */
    07127                         "movq      %%mm4, %%mm5 \n\t"   /* save MM4 in MM5 */
    07128                         "add          $2, %%esi \n\t"   /* move ESI pointer 2 bytes right */
    07129                         "punpcklbw %%mm0, %%mm4 \n\t"   /* unpack 4 low  bytes into words */
    07130                         "punpckhbw %%mm0, %%mm5 \n\t"   /* unpack 4 high bytes into words */
    07131                         "movq    (%%esi), %%mm6 \n\t"   /* load 8 bytes from Src */
    07132                         "movq      %%mm6, %%mm7 \n\t"   /* save MM6 in MM7 */
    07133                         "sub          $2, %%esi \n\t"   /* move ESI pointer back 2 bytes left */
    07134                         "punpcklbw %%mm0, %%mm6 \n\t"   /* unpack 4 low  bytes into words */
    07135                         "punpckhbw %%mm0, %%mm7 \n\t"   /* unpack 4 high bytes into words */
    07136                         "add       %%eax, %%esi \n\t"   /* move to the next row of Src */
    07137                         "movq    (%%esi), %%mm2 \n\t"   /* load 8 bytes from Src */
    07138                         "movq      %%mm2, %%mm3 \n\t"   /* save MM2 in MM3 */
    07139                         "add          $2, %%esi \n\t"   /* move ESI pointer 2 bytes right */
    07140                         "punpcklbw %%mm0, %%mm2 \n\t"   /* unpack 4 low  bytes into words */
    07141                         "punpckhbw %%mm0, %%mm3 \n\t"   /* unpack 4 high bytes into words */
    07142                         "paddw     %%mm2, %%mm4 \n\t"   /* add 4 low  bytes to accumolator MM4 */
    07143                         "paddw     %%mm3, %%mm5 \n\t"   /* add 4 high bytes to accumolator MM5 */
    07144                         "paddw     %%mm2, %%mm4 \n\t"   /* add 4 low  bytes to accumolator MM4 */
    07145                         "paddw     %%mm3, %%mm5 \n\t"   /* add 4 high bytes to accumolator MM5 */
    07146                         "movq    (%%esi), %%mm2 \n\t"   /* load 8 bytes from Src */
    07147                         "movq      %%mm2, %%mm3 \n\t"   /* save MM2 in MM3 */
    07148                         "sub          $2, %%esi \n\t"   /* move ESI pointer back 2 bytes left */
    07149                         "punpcklbw %%mm0, %%mm2 \n\t"   /* unpack 4 low  bytes into words */
    07150                         "punpckhbw %%mm0, %%mm3 \n\t"   /* unpack 4 high bytes into words */
    07151                         "paddw     %%mm2, %%mm6 \n\t"   /* add 4 low  bytes to accumolator MM6 */
    07152                         "paddw     %%mm3, %%mm7 \n\t"   /* add 4 high bytes to accumolator MM7 */
    07153                         "paddw     %%mm2, %%mm6 \n\t"   /* add 4 low  bytes to accumolator MM6 */
    07154                         "paddw     %%mm3, %%mm7 \n\t"   /* add 4 high bytes to accumolator MM7 */
    07155                         "add       %%eax, %%esi \n\t"   /* move to the next row of Src */
    07156                         "movq    (%%esi), %%mm2 \n\t"   /* load 8 bytes from Src */
    07157                         "movq      %%mm2, %%mm3 \n\t"   /* save MM2 in MM3 */
    07158                         "add          $2, %%esi \n\t"   /* move ESI pointer 2 bytes right */
    07159                         "punpcklbw %%mm0, %%mm2 \n\t"   /* unpack 4 low  bytes into words */
    07160                         "punpckhbw %%mm0, %%mm3 \n\t"   /* unpack 4 high bytes into words */
    07161                         "paddw     %%mm2, %%mm4 \n\t"   /* add 4 low  bytes to accumolator MM4 */
    07162                         "paddw     %%mm3, %%mm5 \n\t"   /* add 4 high bytes to accumolator MM5 */
    07163                         "movq    (%%esi), %%mm2 \n\t"   /* load 8 bytes from Src */
    07164                         "movq      %%mm2, %%mm3 \n\t"   /* save MM2 in MM3 */
    07165                         "sub          $2, %%esi \n\t"   /* move ESI pointer back 2 bytes left */
    07166                         "punpcklbw %%mm0, %%mm2 \n\t"   /* unpack 4 low  bytes into words */
    07167                         "punpckhbw %%mm0, %%mm3 \n\t"   /* unpack 4 high bytes into words */
    07168                         "paddw     %%mm2, %%mm6 \n\t"   /* add 4 low  bytes to accumolator MM6 */
    07169                         "paddw     %%mm3, %%mm7 \n\t"   /* add 4 high bytes to accumolator MM7 */
    07170                         /* --- */
    07171                         "movq      %%mm4, %%mm2 \n\t"   /* copy MM4 into MM2 */
    07172                         "psrlq       $32, %%mm4 \n\t"   /* shift 2 left words to the right */
    07173                         "psubw     %%mm2, %%mm4 \n\t"   /* MM4 = MM4 - MM2 */
    07174                         "movq      %%mm6, %%mm3 \n\t"   /* copy MM6 into MM3 */
    07175                         "psrlq       $32, %%mm6 \n\t"   /* shift 2 left words to the right */
    07176                         "psubw     %%mm3, %%mm6 \n\t"   /* MM6 = MM6 - MM3 */
    07177                         "punpckldq %%mm6, %%mm4 \n\t"   /* combine 2 words of MM6 and 2 words of MM4 */
    07178                         "movq      %%mm5, %%mm2 \n\t"   /* copy MM6 into MM2 */
    07179                         "psrlq       $32, %%mm5 \n\t"   /* shift 2 left words to the right */
    07180                         "psubw     %%mm2, %%mm5 \n\t"   /* MM5 = MM5 - MM2 */
    07181                         "movq      %%mm7, %%mm3 \n\t"   /* copy MM7 into MM3 */
    07182                         "psrlq       $32, %%mm7 \n\t"   /* shift 2 left words to the right */
    07183                         "psubw     %%mm3, %%mm7 \n\t"   /* MM7 = MM7 - MM3 */
    07184                         "punpckldq %%mm7, %%mm5 \n\t"   /* combine 2 words of MM7 and 2 words of MM5 */
    07185                         /* Take abs values of MM4 and MM5 */
    07186                         "movq      %%mm4, %%mm6 \n\t"   /* copy MM4 into MM6 */
    07187                         "movq      %%mm5, %%mm7 \n\t"   /* copy MM5 into MM7 */
    07188                         "psraw       $15, %%mm6 \n\t"   /* fill MM6 words with word sign bit */
    07189                         "psraw       $15, %%mm7 \n\t"   /* fill MM7 words with word sign bit */
    07190                         "pxor      %%mm6, %%mm4 \n\t"   /* take 1's compliment of only neg. words */
    07191                         "pxor      %%mm7, %%mm5 \n\t"   /* take 1's compliment of only neg. words */
    07192                         "psubsw    %%mm6, %%mm4 \n\t"   /* add 1 to only neg. words, W-(-1) or W-0 */
    07193                         "psubsw    %%mm7, %%mm5 \n\t"   /* add 1 to only neg. words, W-(-1) or W-0 */
    07194                         "packuswb  %%mm5, %%mm4 \n\t"   /* combine and pack/saturate MM5 and MM4 */
    07195                         "movq    %%mm4, (%%edi) \n\t"   /* store result in Dest */
    07196                         /* --- */
    07197                         "sub       %%eax, %%esi \n\t"   /* move to the current top row in Src */
    07198                         "sub       %%eax, %%esi \n\t" "add $8,          %%esi \n\t"     /* move Src  pointer to the next 8 pixels */
    07199                         "add $8,          %%edi \n\t"   /* move Dest pointer to the next 8 pixels */
    07200                         /* --- */
    07201                         "dec              %%ecx \n\t"   /* decrease loop counter COLUMNS */
    07202                         "jnz            .L10402 \n\t"   /* check loop termination, proceed if required */
    07203                         "mov       %%ebx, %%esi \n\t"   /* restore most left current row Src  address */
    07204                         "movd      %%mm1, %%edi \n\t"   /* restore most left current row Dest address */
    07205                         "add       %%eax, %%esi \n\t"   /* move to the next row in Src */
    07206                         "add       %%eax, %%edi \n\t"   /* move to the next row in Dest */
    07207                         "dec              %%edx \n\t"   /* decrease loop counter ROWS */
    07208                         "jnz            .L10400 \n\t"   /* check loop termination, proceed if required */
    07209                         /* --- */
    07210                         "emms                   \n\t"   /* exit MMX state */
    07211                         "popa                   \n\t":"=m" (Dest)       /* %0 */
    07212                         :"m"(Src),              /* %1 */
    07213                         "m"(rows),              /* %2 */
    07214                         "m"(columns)            /* %3 */
    07215                         );
    07216 #endif
    07217 #endif
    07218                 return (0);
    07219         } else {
    07220                 /* No non-MMX implementation yet */
    07221                 return (-1);
    07222         }
    07223 }
    07224
    07238 int SDL_imageFilterSobelXShiftRight(unsigned char *Src, unsigned char *Dest, int rows, int columns,
    07239                                                                         unsigned char NRightShift)
    07240 {
    07241         /* Validate input parameters */
    07242         if ((Src == NULL) || (Dest == NULL))
    07243                 return(-1);
    07244         if ((columns < 8) || (rows < 3) || (NRightShift > 7))
    07245                 return (-1);
    07246
    07247         if ((SDL_imageFilterMMXdetect())) {
    07248 #ifdef USE_MMX
    07249 #if !defined(GCC__)
    07250                 __asm
    07251                 {
    07252                         pusha
    07253                                 pxor mm0, mm0           /* zero MM0 */
    07254                                 mov eax, columns        /* load columns into EAX */
    07255                                 xor ebx, ebx    /* zero EBX */
    07256                                 mov bl, NRightShift     /* load NRightShift into BL */
    07257                                 movd mm1, ebx           /* copy NRightShift into MM1 */
    07258                                 /* ---, */
    07259                                 mov esi, Src    /* ESI = Src row 0 address */
    07260                                 mov edi, Dest           /* load Dest address to EDI */
    07261                                 add edi, eax    /* EDI = EDI + columns */
    07262                                 inc              edi            /* 1 byte offset from the left edge */
    07263                                 /* initialize ROWS counter */
    07264                                 sub rows, 2     /* do not use first and last rows */
    07265                                 /* ---, */
    07266 L10410:
    07267                         mov ecx, eax    /* initialize COLUMS counter */
    07268                                 shr ecx, 3      /* EBX/8 (MMX loads 8 bytes at a time) */
    07269                                 mov ebx, esi    /* save ESI in EBX */
    07270                                 mov edx, edi    /* save EDI in EDX */
    07271                                 align 16                        /* 16 byte alignment of the loop entry */
    07272 L10412:
    07273                         /* ---, */
    07274                         movq mm4, [esi]         /* load 8 bytes from Src */
    07275                         movq mm5, mm4           /* save MM4 in MM5 */
    07276                                 add esi, 2      /* move ESI pointer 2 bytes right */
    07277                                 punpcklbw mm4, mm0      /* unpack 4 low  bytes into words */
    07278                                 punpckhbw mm5, mm0      /* unpack 4 high bytes into words */
    07279                                 psrlw mm4, mm1          /* shift right each pixel NshiftRight times */
    07280                                 psrlw mm5, mm1          /* shift right each pixel NshiftRight times */
    07281                                 movq mm6, [esi]         /* load 8 bytes from Src */
    07282                         movq mm7, mm6           /* save MM6 in MM7 */
    07283                                 sub esi, 2      /* move ESI pointer back 2 bytes left */
    07284                                 punpcklbw mm6, mm0      /* unpack 4 low  bytes into words */
    07285                                 punpckhbw mm7, mm0      /* unpack 4 high bytes into words */
    07286                                 psrlw mm6, mm1          /* shift right each pixel NshiftRight times */
    07287                                 psrlw mm7, mm1          /* shift right each pixel NshiftRight times */
    07288                                 add esi, eax    /* move to the next row of Src */
    07289                                 movq mm2, [esi]         /* load 8 bytes from Src */
    07290                         movq mm3, mm2           /* save MM2 in MM3 */
    07291                                 add esi, 2      /* move ESI pointer 2 bytes right */
    07292                                 punpcklbw mm2, mm0      /* unpack 4 low  bytes into words */
    07293                                 punpckhbw mm3, mm0      /* unpack 4 high bytes into words */
    07294                                 psrlw mm2, mm1          /* shift right each pixel NshiftRight times */
    07295                                 psrlw mm3, mm1          /* shift right each pixel NshiftRight times */
    07296                                 paddw mm4, mm2          /* add 4 low  bytes to accumolator MM4 */
    07297                                 paddw mm5, mm3          /* add 4 high bytes to accumolator MM5 */
    07298                                 paddw mm4, mm2          /* add 4 low  bytes to accumolator MM4 */
    07299                                 paddw mm5, mm3          /* add 4 high bytes to accumolator MM5 */
    07300                                 movq mm2, [esi]         /* load 8 bytes from Src */
    07301                         movq mm3, mm2           /* save MM2 in MM3 */
    07302                                 sub esi, 2      /* move ESI pointer back 2 bytes left */
    07303                                 punpcklbw mm2, mm0      /* unpack 4 low  bytes into words */
    07304                                 punpckhbw mm3, mm0      /* unpack 4 high bytes into words */
    07305                                 psrlw mm2, mm1          /* shift right each pixel NshiftRight times */
    07306                                 psrlw mm3, mm1          /* shift right each pixel NshiftRight times */
    07307                                 paddw mm6, mm2          /* add 4 low  bytes to accumolator MM6 */
    07308                                 paddw mm7, mm3          /* add 4 high bytes to accumolator MM7 */
    07309                                 paddw mm6, mm2          /* add 4 low  bytes to accumolator MM6 */
    07310                                 paddw mm7, mm3          /* add 4 high bytes to accumolator MM7 */
    07311                                 add esi, eax    /* move to the next row of Src */
    07312                                 movq mm2, [esi]         /* load 8 bytes from Src */
    07313                         movq mm3, mm2           /* save MM2 in MM3 */
    07314                                 add esi, 2      /* move ESI pointer 2 bytes right */
    07315                                 punpcklbw mm2, mm0      /* unpack 4 low  bytes into words */
    07316                                 punpckhbw mm3, mm0      /* unpack 4 high bytes into words */
    07317                                 psrlw mm2, mm1          /* shift right each pixel NshiftRight times */
    07318                                 psrlw mm3, mm1          /* shift right each pixel NshiftRight times */
    07319                                 paddw mm4, mm2          /* add 4 low  bytes to accumolator MM4 */
    07320                                 paddw mm5, mm3          /* add 4 high bytes to accumolator MM5 */
    07321                                 movq mm2, [esi]         /* load 8 bytes from Src */
    07322                         movq mm3, mm2           /* save MM2 in MM3 */
    07323                                 sub esi, 2      /* move ESI pointer back 2 bytes left */
    07324                                 punpcklbw mm2, mm0      /* unpack 4 low  bytes into words */
    07325                                 punpckhbw mm3, mm0      /* unpack 4 high bytes into words */
    07326                                 psrlw mm2, mm1          /* shift right each pixel NshiftRight times */
    07327                                 psrlw mm3, mm1          /* shift right each pixel NshiftRight times */
    07328                                 paddw mm6, mm2          /* add 4 low  bytes to accumolator MM6 */
    07329                                 paddw mm7, mm3          /* add 4 high bytes to accumolator MM7 */
    07330                                 /* ---, */
    07331                                 movq mm2, mm4           /* copy MM4 into MM2 */
    07332                                 psrlq mm4, 32           /* shift 2 left words to the right */
    07333                                 psubw mm4, mm2          /* MM4 = MM4 - MM2 */
    07334                                 movq mm3, mm6           /* copy MM6 into MM3 */
    07335                                 psrlq mm6, 32           /* shift 2 left words to the right */
    07336                                 psubw mm6, mm3          /* MM6 = MM6 - MM3 */
    07337                                 punpckldq mm4, mm6      /* combine 2 words of MM6 and 2 words of MM4 */
    07338                                 movq mm2, mm5           /* copy MM6 into MM2 */
    07339                                 psrlq mm5, 32           /* shift 2 left words to the right */
    07340                                 psubw mm5, mm2          /* MM5 = MM5 - MM2 */
    07341                                 movq mm3, mm7           /* copy MM7 into MM3 */
    07342                                 psrlq mm7, 32           /* shift 2 left words to the right */
    07343                                 psubw mm7, mm3          /* MM7 = MM7 - MM3 */
    07344                                 punpckldq mm5, mm7      /* combine 2 words of MM7 and 2 words of MM5 */
    07345                                 /* Take abs values of MM4 and MM5 */
    07346                                 movq mm6, mm4           /* copy MM4 into MM6 */
    07347                                 movq mm7, mm5           /* copy MM5 into MM7 */
    07348                                 psraw mm6, 15           /* fill MM6 words with word sign bit */
    07349                                 psraw mm7, 15           /* fill MM7 words with word sign bit */
    07350                                 pxor mm4, mm6           /* take 1's compliment of only neg words */
    07351                                 pxor mm5, mm7           /* take 1's compliment of only neg words */
    07352                                 psubsw mm4, mm6         /* add 1 to only neg words, W-(-1) or W-0 */
    07353                                 psubsw mm5, mm7         /* add 1 to only neg words, W-(-1) or W-0 */
    07354                                 packuswb mm4, mm5       /* combine and pack/saturate MM5 and MM4 */
    07355                                 movq [edi], mm4         /* store result in Dest */
    07356                                 /* ---, */
    07357                                 sub esi, eax    /* move to the current top row in Src */
    07358                                 sub esi, eax
    07359                                 add esi, 8      /* move Src  pointer to the next 8 pixels */
    07360                                 add edi, 8      /* move Dest pointer to the next 8 pixels */
    07361                                 /* ---, */
    07362                                 dec              ecx            /* decrease loop counter COLUMNS */
    07363                                 jnz            L10412           /* check loop termination, proceed if required */
    07364                                 mov esi, ebx    /* restore most left current row Src  address */
    07365                                 mov edi, edx    /* restore most left current row Dest address */
    07366                                 add esi, eax    /* move to the next row in Src */
    07367                                 add edi, eax    /* move to the next row in Dest */
    07368                                 dec rows        /* decrease loop counter ROWS */
    07369                                 jnz            L10410           /* check loop termination, proceed if required */
    07370                                 /* ---, */
    07371                                 emms                            /* exit MMX state */
    07372                                 popa
    07373                 }
    07374 #else
    07375                 asm volatile
    07376                         ("pusha              \n\t" "pxor      %%mm0, %%mm0 \n\t"        /* zero MM0 */
    07377                         "mov          %3, %%eax \n\t"   /* load columns into EAX */
    07378                         "xor       %%ebx, %%ebx \n\t"   /* zero EBX */
    07379                         "mov           %4, %%bl \n\t"   /* load NRightShift into BL */
    07380                         "movd      %%ebx, %%mm1 \n\t"   /* copy NRightShift into MM1 */
    07381                         /* --- */
    07382                         "mov          %1, %%esi \n\t"   /* ESI = Src row 0 address */
    07383                         "mov          %0, %%edi \n\t"   /* load Dest address to EDI */
    07384                         "add       %%eax, %%edi \n\t"   /* EDI = EDI + columns */
    07385                         "inc              %%edi \n\t"   /* 1 byte offset from the left edge */
    07386                         /* initialize ROWS counter */
    07387                         "subl            $2, %2 \n\t"   /* do not use first and last rows */
    07388                         /* --- */
    07389                         ".L10410:                \n\t" "mov       %%eax, %%ecx \n\t"    /* initialize COLUMS counter */
    07390                         "shr          $3, %%ecx \n\t"   /* EBX/8 (MMX loads 8 bytes at a time) */
    07391                         "mov       %%esi, %%ebx \n\t"   /* save ESI in EBX */
    07392                         "mov       %%edi, %%edx \n\t"   /* save EDI in EDX */
    07393                         ".align 16              \n\t"   /* 16 byte alignment of the loop entry */
    07394                         ".L10412:               \n\t"
    07395                         /* --- */
    07396                         "movq    (%%esi), %%mm4 \n\t"   /* load 8 bytes from Src */
    07397                         "movq      %%mm4, %%mm5 \n\t"   /* save MM4 in MM5 */
    07398                         "add          $2, %%esi \n\t"   /* move ESI pointer 2 bytes right */
    07399                         "punpcklbw %%mm0, %%mm4 \n\t"   /* unpack 4 low  bytes into words */
    07400                         "punpckhbw %%mm0, %%mm5 \n\t"   /* unpack 4 high bytes into words */
    07401                         "psrlw     %%mm1, %%mm4 \n\t"   /* shift right each pixel NshiftRight times */
    07402                         "psrlw     %%mm1, %%mm5 \n\t"   /* shift right each pixel NshiftRight times */
    07403                         "movq    (%%esi), %%mm6 \n\t"   /* load 8 bytes from Src */
    07404                         "movq      %%mm6, %%mm7 \n\t"   /* save MM6 in MM7 */
    07405                         "sub          $2, %%esi \n\t"   /* move ESI pointer back 2 bytes left */
    07406                         "punpcklbw %%mm0, %%mm6 \n\t"   /* unpack 4 low  bytes into words */
    07407                         "punpckhbw %%mm0, %%mm7 \n\t"   /* unpack 4 high bytes into words */
    07408                         "psrlw     %%mm1, %%mm6 \n\t"   /* shift right each pixel NshiftRight times */
    07409                         "psrlw     %%mm1, %%mm7 \n\t"   /* shift right each pixel NshiftRight times */
    07410                         "add       %%eax, %%esi \n\t"   /* move to the next row of Src */
    07411                         "movq    (%%esi), %%mm2 \n\t"   /* load 8 bytes from Src */
    07412                         "movq      %%mm2, %%mm3 \n\t"   /* save MM2 in MM3 */
    07413                         "add          $2, %%esi \n\t"   /* move ESI pointer 2 bytes right */
    07414                         "punpcklbw %%mm0, %%mm2 \n\t"   /* unpack 4 low  bytes into words */
    07415                         "punpckhbw %%mm0, %%mm3 \n\t"   /* unpack 4 high bytes into words */
    07416                         "psrlw     %%mm1, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    07417                         "psrlw     %%mm1, %%mm3 \n\t"   /* shift right each pixel NshiftRight times */
    07418                         "paddw     %%mm2, %%mm4 \n\t"   /* add 4 low  bytes to accumolator MM4 */
    07419                         "paddw     %%mm3, %%mm5 \n\t"   /* add 4 high bytes to accumolator MM5 */
    07420                         "paddw     %%mm2, %%mm4 \n\t"   /* add 4 low  bytes to accumolator MM4 */
    07421                         "paddw     %%mm3, %%mm5 \n\t"   /* add 4 high bytes to accumolator MM5 */
    07422                         "movq    (%%esi), %%mm2 \n\t"   /* load 8 bytes from Src */
    07423                         "movq      %%mm2, %%mm3 \n\t"   /* save MM2 in MM3 */
    07424                         "sub          $2, %%esi \n\t"   /* move ESI pointer back 2 bytes left */
    07425                         "punpcklbw %%mm0, %%mm2 \n\t"   /* unpack 4 low  bytes into words */
    07426                         "punpckhbw %%mm0, %%mm3 \n\t"   /* unpack 4 high bytes into words */
    07427                         "psrlw     %%mm1, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    07428                         "psrlw     %%mm1, %%mm3 \n\t"   /* shift right each pixel NshiftRight times */
    07429                         "paddw     %%mm2, %%mm6 \n\t"   /* add 4 low  bytes to accumolator MM6 */
    07430                         "paddw     %%mm3, %%mm7 \n\t"   /* add 4 high bytes to accumolator MM7 */
    07431                         "paddw     %%mm2, %%mm6 \n\t"   /* add 4 low  bytes to accumolator MM6 */
    07432                         "paddw     %%mm3, %%mm7 \n\t"   /* add 4 high bytes to accumolator MM7 */
    07433                         "add       %%eax, %%esi \n\t"   /* move to the next row of Src */
    07434                         "movq    (%%esi), %%mm2 \n\t"   /* load 8 bytes from Src */
    07435                         "movq      %%mm2, %%mm3 \n\t"   /* save MM2 in MM3 */
    07436                         "add          $2, %%esi \n\t"   /* move ESI pointer 2 bytes right */
    07437                         "punpcklbw %%mm0, %%mm2 \n\t"   /* unpack 4 low  bytes into words */
    07438                         "punpckhbw %%mm0, %%mm3 \n\t"   /* unpack 4 high bytes into words */
    07439                         "psrlw     %%mm1, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    07440                         "psrlw     %%mm1, %%mm3 \n\t"   /* shift right each pixel NshiftRight times */
    07441                         "paddw     %%mm2, %%mm4 \n\t"   /* add 4 low  bytes to accumolator MM4 */
    07442                         "paddw     %%mm3, %%mm5 \n\t"   /* add 4 high bytes to accumolator MM5 */
    07443                         "movq    (%%esi), %%mm2 \n\t"   /* load 8 bytes from Src */
    07444                         "movq      %%mm2, %%mm3 \n\t"   /* save MM2 in MM3 */
    07445                         "sub          $2, %%esi \n\t"   /* move ESI pointer back 2 bytes left */
    07446                         "punpcklbw %%mm0, %%mm2 \n\t"   /* unpack 4 low  bytes into words */
    07447                         "punpckhbw %%mm0, %%mm3 \n\t"   /* unpack 4 high bytes into words */
    07448                         "psrlw     %%mm1, %%mm2 \n\t"   /* shift right each pixel NshiftRight times */
    07449                         "psrlw     %%mm1, %%mm3 \n\t"   /* shift right each pixel NshiftRight times */
    07450                         "paddw     %%mm2, %%mm6 \n\t"   /* add 4 low  bytes to accumolator MM6 */
    07451                         "paddw     %%mm3, %%mm7 \n\t"   /* add 4 high bytes to accumolator MM7 */
    07452                         /* --- */
    07453                         "movq      %%mm4, %%mm2 \n\t"   /* copy MM4 into MM2 */
    07454                         "psrlq       $32, %%mm4 \n\t"   /* shift 2 left words to the right */
    07455                         "psubw     %%mm2, %%mm4 \n\t"   /* MM4 = MM4 - MM2 */
    07456                         "movq      %%mm6, %%mm3 \n\t"   /* copy MM6 into MM3 */
    07457                         "psrlq       $32, %%mm6 \n\t"   /* shift 2 left words to the right */
    07458                         "psubw     %%mm3, %%mm6 \n\t"   /* MM6 = MM6 - MM3 */
    07459                         "punpckldq %%mm6, %%mm4 \n\t"   /* combine 2 words of MM6 and 2 words of MM4 */
    07460                         "movq      %%mm5, %%mm2 \n\t"   /* copy MM6 into MM2 */
    07461                         "psrlq       $32, %%mm5 \n\t"   /* shift 2 left words to the right */
    07462                         "psubw     %%mm2, %%mm5 \n\t"   /* MM5 = MM5 - MM2 */
    07463                         "movq      %%mm7, %%mm3 \n\t"   /* copy MM7 into MM3 */
    07464                         "psrlq       $32, %%mm7 \n\t"   /* shift 2 left words to the right */
    07465                         "psubw     %%mm3, %%mm7 \n\t"   /* MM7 = MM7 - MM3 */
    07466                         "punpckldq %%mm7, %%mm5 \n\t"   /* combine 2 words of MM7 and 2 words of MM5 */
    07467                         /* Take abs values of MM4 and MM5 */
    07468                         "movq      %%mm4, %%mm6 \n\t"   /* copy MM4 into MM6 */
    07469                         "movq      %%mm5, %%mm7 \n\t"   /* copy MM5 into MM7 */
    07470                         "psraw       $15, %%mm6 \n\t"   /* fill MM6 words with word sign bit */
    07471                         "psraw       $15, %%mm7 \n\t"   /* fill MM7 words with word sign bit */
    07472                         "pxor      %%mm6, %%mm4 \n\t"   /* take 1's compliment of only neg. words */
    07473                         "pxor      %%mm7, %%mm5 \n\t"   /* take 1's compliment of only neg. words */
    07474                         "psubsw    %%mm6, %%mm4 \n\t"   /* add 1 to only neg. words, W-(-1) or W-0 */
    07475                         "psubsw    %%mm7, %%mm5 \n\t"   /* add 1 to only neg. words, W-(-1) or W-0 */
    07476                         "packuswb  %%mm5, %%mm4 \n\t"   /* combine and pack/saturate MM5 and MM4 */
    07477                         "movq    %%mm4, (%%edi) \n\t"   /* store result in Dest */
    07478                         /* --- */
    07479                         "sub       %%eax, %%esi \n\t"   /* move to the current top row in Src */
    07480                         "sub       %%eax, %%esi \n\t" "add $8,          %%esi \n\t"     /* move Src  pointer to the next 8 pixels */
    07481                         "add $8,          %%edi \n\t"   /* move Dest pointer to the next 8 pixels */
    07482                         /* --- */
    07483                         "dec              %%ecx \n\t"   /* decrease loop counter COLUMNS */
    07484                         "jnz            .L10412 \n\t"   /* check loop termination, proceed if required */
    07485                         "mov       %%ebx, %%esi \n\t"   /* restore most left current row Src  address */
    07486                         "mov       %%edx, %%edi \n\t"   /* restore most left current row Dest address */
    07487                         "add       %%eax, %%esi \n\t"   /* move to the next row in Src */
    07488                         "add       %%eax, %%edi \n\t"   /* move to the next row in Dest */
    07489                         "decl                %2 \n\t"   /* decrease loop counter ROWS */
    07490                         "jnz            .L10410 \n\t"   /* check loop termination, proceed if required */
    07491                         /* --- */
    07492                         "emms                   \n\t"   /* exit MMX state */
    07493                         "popa                   \n\t":"=m" (Dest)       /* %0 */
    07494                         :"m"(Src),              /* %1 */
    07495                         "m"(rows),              /* %2 */
    07496                         "m"(columns),           /* %3 */
    07497                         "m"(NRightShift)        /* %4 */
    07498                         );
    07499 #endif
    07500 #endif
    07501                 return (0);
    07502         } else {
    07503                 /* No non-MMX implementation yet */
    07504                 return (-1);
    07505         }
    07506 }
    07507
    07511 void SDL_imageFilterAlignStack(void)
    07512 {
    07513 #ifdef USE_MMX
    07514 #if !defined(GCC__)
    07515         __asm
    07516         {                               /* --- stack alignment --- */
    07517                 mov ebx, esp    /* load ESP into EBX */
    07518                         sub ebx, 4      /* reserve space on stack for old value of ESP */
    07519                         and ebx, -32    /* align EBX along a 32 byte boundary */
    07520                         mov [ebx], esp          /* save old value of ESP in stack, behind the bndry */
    07521                         mov esp, ebx    /* align ESP along a 32 byte boundary */
    07522         }
    07523 #else
    07524         asm volatile
    07525                 (                               /* --- stack alignment --- */
    07526                 "mov       %%esp, %%ebx \n\t"   /* load ESP into EBX */
    07527                 "sub          $4, %%ebx \n\t"   /* reserve space on stack for old value of ESP */
    07528                 "and        $-32, %%ebx \n\t"   /* align EBX along a 32 byte boundary */
    07529                 "mov     %%esp, (%%ebx) \n\t"   /* save old value of ESP in stack, behind the bndry */
    07530                 "mov       %%ebx, %%esp \n\t"   /* align ESP along a 32 byte boundary */
    07531                 ::);
    07532 #endif
    07533 #endif
    07534 }
    07535
    07539 void SDL_imageFilterRestoreStack(void)
    07540 {
    07541 #ifdef USE_MMX
    07542 #if !defined(GCC__)
    07543         __asm
    07544         {                               /* --- restoring old stack --- */
    07545                 mov ebx, [esp]          /* load old value of ESP */
    07546                 mov esp, ebx    /* restore old value of ESP */
    07547         }
    07548 #else
    07549         asm volatile
    07550                 (                               /* --- restoring old stack --- */
    07551                 "mov     (%%esp), %%ebx \n\t"   /* load old value of ESP */
    07552                 "mov       %%ebx, %%esp \n\t"   /* restore old value of ESP */
    07553                 ::);
    07554 #endif
    07555 #endif
    07556 }