Change to the linux kernel coding style
[wmaker-crm.git] / wrlib / x86_specific.c
dissimilarity index 94%
index a67f571..9cbbf47 100644 (file)
-/* x86_convert.c - convert RImage to XImage with x86 optimizations
- *
- * Raster graphics library
- *
- * Copyright (c) 2000-2003 Alfredo K. Kojima
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public
- *  License along with this library; if not, write to the Free
- *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <config.h>
-
-#ifdef ASM_X86
-
-
-#ifdef ASM_X86_MMX
-
-int
-x86_check_mmx()
-{
-    static int result = -1;
-
-    if (result >= 0)
-        return result;
-
-    result = 0;
-
-    asm volatile
-        ("pushal                \n\t" // please dont forget this in any asm
-         "pushfl                \n\t" // check whether cpuid supported
-         "pop %%eax             \n\t"
-         "movl %%eax, %%ebx     \n\t"
-         "xorl $(1<<21), %%eax  \n\t"
-         "pushl %%eax           \n\t"
-         "popfl                 \n\t"
-         "pushfl                \n\t"
-         "popl %%eax            \n\t"
-         "xorl %%ebx, %%eax     \n\t"
-         "andl $(1<<21), %%eax  \n\t"
-         "jz .NotPentium        \n\t"
-         "xorl %%eax, %%eax     \n\t" // no eax effect because of the movl below
-                                      // except reseting flags. is it needed?
-         "movl $1, %%eax        \n\t"
-         "cpuid                 \n\t"
-         "test $(1<<23), %%edx  \n\t"
-         "jz .NotMMX            \n\t"
-
-         "popal                 \n\t" // popal needed because the address of
-         "movl $1, %0           \n\t" // variable %0 may be kept in a register
-         "jmp .noPop            \n"
-
-".NotMMX:                       \n"
-".NotPentium:                   \n\t"
-         "popal                 \n"
-".noPop:                        \n\t"
-
-         : "=m" (result));
-
-    return result;
-}
-
-
-/*
- * TODO:
- *              32/8    24/8    32/16   24/16   32/24   24/24
- * PPlain       YES     YES
- * MMX                          DONE
- *
- *
- * - try to align stack (local variable space) into quadword boundary
- */
-void
-x86_mmx_TrueColor_32_to_16(unsigned char *image,
-                           unsigned short *ximage,
-                           short *err,
-                           short *nerr,
-                           unsigned short *rtable,
-                           unsigned short *gtable,
-                           unsigned short *btable,
-                           int dr,
-                           int dg,
-                           int db,
-                           unsigned int roffs,
-                           unsigned int goffs,
-                           unsigned int boffs,
-                           int width,
-                           int height,
-                           int line_offset)
-{
-    union {
-        long long rrggbbaa;
-        struct {
-            short int rr, gg, bb, aa;
-        } words;
-    } rrggbbaa;
-
-    union {
-        long long pixel;
-        struct {
-            short int rr, gg, bb, aa;
-        } words;
-    } pixel;
-
-    short *tmp_err;
-    short *tmp_nerr;
-    int x;
-
-    asm volatile
-        (
-         "pushl %%ebx                   \n\t"
-
-         // pack dr, dg and db into mm6
-         "movl  %7, %%eax               \n\t"
-         "movl  %8, %%ebx               \n\t"
-         "movl  %9, %%ecx               \n\t"
-         "movw  %%ax, %16               \n\t"
-         "movw  %%bx, %17               \n\t"
-         "movw  %%cx, %18               \n\t"
-         "movw  $0,  %19                \n\t"
-
-         "movq  %16, %%mm6              \n\t" // dr dg db 0
-
-         // pack 4|4|4|4 into mm7, for shifting (/16)
-         "movl $0x00040004, %16         \n\t"
-         "movl $0x00040004, %18         \n\t"
-         "movq %16, %%mm7               \n\t"
-
-         // store constant values for using with mmx when dithering
-         "movl $0x00070007, %16         \n\t"
-         "movl $0x00070007, %18         \n\t"
-         "movq %16, %%mm5               \n\t"
-
-         "movl $0x00050005, %16         \n\t"
-         "movl $0x00050005, %18         \n\t"
-         "movq %16, %%mm4               \n\t"
-
-         "movl $0x00030003, %16         \n\t"
-         "movl $0x00030003, %18         \n\t"
-         "movq %16, %%mm3               \n\t"
-
-         // process 1 pixel / cycle, each component treated as 16bit
-         "movl %0, %%esi                \n"   // esi = image->data
-
-".LoopYa:                               \n\t"
-         "movl %13, %%eax               \n\t"
-         "movl %%eax, %26               \n\t" // x = width
-
-         "movl %14, %%eax               \n\t"
-         "decl %%eax                    \n\t" // y--
-         "movl %%eax, %14               \n\t"
-         "js .Enda                      \n\t" // if y < 0, goto end
-         "andl $1, %%eax                \n\t"
-         "jz .LoopY_1a                  \n"   // if (y&1) goto LoopY_1
-
-".LoopY_0a:                             \n\t"
-
-         "movl %2, %%ebx                \n\t" // ebx = err
-         "movl %%ebx, %25               \n\t" // [-36] = err
-         "movl %3, %%eax                \n\t" //
-         "movl %%eax, %24               \n\t" // [-32] = nerr
-
-         "jmp .LoopXa                   \n"
-
-".LoopY_1a:                             \n\t"
-
-         "movl %3, %%ebx                \n\t" // ebx = nerr
-         "movl %%ebx, %25               \n\t" // [-36] = nerr
-         "movl %2, %%eax                \n\t" //
-         "movl %%eax, %24               \n\t" // [-32] = eerr
-
-         ".align 16                     \n"
-".LoopXa:                               \n\t"
-
-         // calculate errors and pixel components
-
-         // depend on ebx, esi, mm6
-         "movq (%%ebx), %%mm1           \n\t" // mm1 = error[0..3]
-         "punpcklbw (%%esi), %%mm0      \n\t" // mm0 = image->data[0..3]
-         "psrlw $8, %%mm0               \n\t" // fixup mm0
-         "paddusb %%mm1, %%mm0          \n\t" // mm0 = mm0 + mm1 (sat. to 255)
-         "movq %%mm0, %20               \n\t" // save the pixel
-
-         "movzwl %20, %%ecx             \n\t" // ecx = pixel.red
-         "movl %4, %%edi                \n\t" // edi = rtable
-         //agi
-         "leal (%%edi, %%ecx, 2), %%eax \n\t" // eax = &rtable[pixel.red]
-         // agi
-         "movw (%%eax), %%dx            \n\t" // dx = rtable[pixel.red]
-         "movw %%dx, %16                \n\t" // save rr
-
-         "movzwl %21, %%ecx             \n\t" // ecx = pixel.green
-         "movl %5, %%edi                \n\t" // edi = gtable
-         //agi
-         "leal (%%edi, %%ecx, 2), %%eax \n\t" // eax = &gtable[pixel.green]
-         //agi
-         "movw (%%eax), %%dx            \n\t" // dx = gtable[pixel.green]
-         "movw %%dx, %17                \n\t" // save gg
-
-         "movzwl %22, %%ecx             \n\t" // ecx = pixel.blue
-         "movl %6, %%edi                \n\t" // ebx = btable
-         //agi
-         "leal (%%edi, %%ecx, 2), %%eax \n\t" // eax = &btable[pixel.blue]
-         //agi
-         "movw (%%eax), %%dx            \n\t" // dx = btable[pixel.blue]
-         "movw %%dx, %18                \n\t" // save bb
-
-         "movw $0, %19                  \n\t" // save dummy aa
-
-         "movq %16, %%mm1               \n\t" // load mm1 with rrggbbaa
-         "pmullw %%mm6, %%mm1           \n\t" // mm1 = rr*dr|...
-         "psubsw %%mm1, %%mm0           \n\t" // error = pixel - mm1
-
-
-         // distribute the error
-
-         // depend on mm0, mm7, mm3, mm4, mm5
-
-         "movl %25, %%ebx               \n\t"
-
-         "movq %%mm0, %%mm1             \n\t"
-         "pmullw %%mm5, %%mm1           \n\t" // mm1 = mm1*7
-         "psrlw %%mm7, %%mm1            \n\t" // mm1 = mm1/16
-         "paddw 8(%%ebx), %%mm1         \n\t"
-         "movq %%mm1, 8(%%ebx)          \n\t" // err[x+1,y] = rer*7/16
-
-
-         "movl %24, %%ebx               \n\t"
-
-         "movq %%mm0, %%mm1             \n\t"
-         "pmullw %%mm4, %%mm1           \n\t" // mm1 = mm1*5
-         "psrlw %%mm7, %%mm1            \n\t" // mm1 = mm1/16
-         "paddw -8(%%ebx), %%mm1        \n\t"
-         "movq %%mm1, -8(%%ebx)         \n\t" // err[x-1,y+1] += rer*3/16
-
-         "movq %%mm0, %%mm1             \n\t"
-         "pmullw %%mm3, %%mm1           \n\t" // mm1 = mm1*3
-         "psrlw %%mm7, %%mm1            \n\t" // mm1 = mm1/16
-         "paddw 8(%%ebx), %%mm1         \n\t"
-         "movq %%mm1, (%%ebx)           \n\t" // err[x,y+1] += rer*5/16
-
-         "psrlw %%mm7, %%mm0            \n\t" // mm0 = mm0/16
-         "movq %%mm0, 8(%%ebx)          \n\t" // err[x+1,y+1] = rer/16
-
-
-         // calculate final pixel value and store
-         "movl %10, %%ecx               \n\t"
-         "movw %16, %%ax                \n\t"
-         "shlw %%cl, %%ax               \n\t" //NP* ax = r<<roffs
-
-         "movl %11, %%ecx               \n\t"
-         "movw %17, %%bx                \n\t"
-         "shlw %%cl, %%bx               \n\t" //NP*
-         "orw %%bx, %%ax                \n\t"
-
-         "movl %12, %%ecx               \n\t"
-         "movw %18, %%bx                \n\t"
-         "shlw %%cl, %%bx               \n\t" //NP*
-         "orw %%bx, %%ax                \n\t"
-
-         "movl %1, %%edx                \n\t"
-         "movw %%ax, (%%edx)            \n\t"
-         "addl $2, %%edx                \n\t" // increment ximage
-         "movl %%edx, %1                \n\t"
-
-         // prepare for next iteration on X
-
-         "addl $8, %24                  \n\t" // nerr += 8
-
-         "movl %25, %%ebx               \n\t"
-         "addl $8, %%ebx                \n\t"
-         "movl %%ebx, %25               \n\t" // ebx = err += 8
-
-
-         // Note: in the last pixel, this would cause an invalid memory access
-         // because, punpcklbw is used (which reads 8 bytes) and the last
-         // pixel is only 4 bytes. This is no problem because the image data
-         // was allocated with extra 4 bytes when created.
-         "addl $4, %%esi                \n\t" // image->data += 4
-
-
-         "decl %26                      \n\t" // x--
-         "jnz .LoopXa                   \n\t" // if x>0, goto .LoopX
-
-
-         // depend on edx
-         "addl %15, %%edx               \n\t" // add extra offset to ximage
-         "movl %%edx, %1                \n\t"
-
-
-         "jmp .LoopYa                   \n"
-
-".Enda:                                 \n\t" // THE END
-         "emms                          \n\t"
-         "popl %%ebx                    \n\t"
-         :
-         :
-         "m" (image),                      // %0
-         "m" (ximage),                     // %1
-         "m" (err),                        // %2
-         "m" (nerr),                       // %3
-         "m" (rtable),                     // %4
-         "m" (gtable),                     // %5
-         "m" (btable),                     // %6
-         "m" (dr),                         // %7
-         "m" (dg),                         // %8
-         "m" (db),                         // %9
-         "m" (roffs),                      // %10
-         "m" (goffs),                      // %11
-         "m" (boffs),                      // %12
-         "m" (width),                      // %13
-         "m" (height),                     // %14
-         "m" (line_offset),                // %15
-         "m" (rrggbbaa.words.rr),          // %16 (access to rr)
-         "m" (rrggbbaa.words.gg),          // %17 (access to gg)
-         "m" (rrggbbaa.words.bb),          // %18 (access to bb)
-         "m" (rrggbbaa.words.aa),          // %19 (access to aa)
-         "m" (pixel.words.rr),             // %20 (access to pixel.r)
-         "m" (pixel.words.gg),             // %21 (access to pixel.g)
-         "m" (pixel.words.bb),             // %22 (access to pixel.b)
-         "m" (pixel.words.aa),             // %23 (access to pixel.a)
-         "m" (tmp_err),                    // %24
-         "m" (tmp_nerr),                   // %25
-         "m" (x)                           // %26
-         : "eax", "ecx", "edx", "esi", "edi"
-        );
-}
-
-
-void
-x86_mmx_TrueColor_24_to_16(unsigned char *image,
-                           unsigned short *ximage,
-                           short *err,
-                           short *nerr,
-                           short *rtable,
-                           short *gtable,
-                           short *btable,
-                           int dr,
-                           int dg,
-                           int db,
-                           unsigned int roffs,
-                           unsigned int goffs,
-                           unsigned int boffs,
-                           int width,
-                           int height,
-                           int line_offset)
-{
-    union {
-        long long rrggbbaa;
-        struct {
-            short int rr, gg, bb, aa;
-        } words;
-    } rrggbbaa;
-    
-    union {
-        long long pixel;
-        struct {
-            short int rr, gg, bb, aa;
-        } words;
-    } pixel;
-
-    short *tmp_err;
-    short *tmp_nerr;
-
-    int x;
-    int w1;
-    int w2;
-
-    asm volatile
-        (
-         "pushl %%ebx                   \n\t"
-
-         "movl %13, %%eax               \n\t" // eax = width
-         "movl %%eax, %%ebx             \n\t"
-         "shrl $2, %%eax                \n\t"
-         "movl %%eax, %27               \n\t" // w1 = width / 4
-         "andl $3, %%ebx                \n\t"
-         "movl %%ebx, %28               \n"   // w2 = width %% 4
-
-
-".LoopYc:                               \n\t"
-         "movl %13, %%eax               \n\t"
-         "movl %%eax, %26               \n\t" // x = width
-
-         "decl %14                      \n\t" // height--
-         "js .Endc                      \n\t" // if height < 0 then end
-
-         "movl %14, %%eax               \n\t"
-         "decl %%eax                    \n\t" // y--
-         "movl %%eax, %14               \n\t"
-         "js .Endc                      \n\t" // if y < 0, goto end
-         "andl $1, %%eax                \n\t"
-         "jz .LoopY_1c                  \n"   // if (y&1) goto LoopY_1
-
-".LoopY_0c:                             \n\t"
-
-         "movl %2, %%ebx                \n\t" // ebx = err
-         "movl %%ebx, %25               \n\t" // [-36] = err
-         "movl %3, %%eax                \n\t" //
-         "movl %%eax, %24               \n\t" // [-32] = nerr
-
-         "jmp .LoopX_1c                 \n"
-
-".LoopY_1c:                             \n\t"
-
-         "movl %3, %%ebx                \n\t" // ebx = nerr
-         "movl %%ebx, %25               \n\t" // [-36] = nerr
-         "movl %2, %%eax                \n\t" //
-         "movl %%eax, %24               \n\t" // [-32] = eerr
-
-         ".align 16                     \n\t"
-
-         "movl %%eax, %26               \n"   // x = w1
-".LoopX_1c:                             \n\t"
-         "decl %26                      \n\t" // x--
-         "js .Xend1_c                   \n\t" // if x < 0 then end
-
-         // do conversion of 4 pixels
-         "movq %2, %%mm0                \n\t" // mm0 = err
-
-
-
-
-         "jmp .LoopX_1c                 \n"
-".Xend1_c:                              \n\t"
-
-         "movl %28, %%eax               \n\t"
-         "movl %%eax, %26               \n"   // x = w2
-".LoopX_2c:                             \n\t"
-         "decl %26                      \n\t" // x--
-         "js .Xend2_c                   \n\t" //
-         // do conversion
-         "jmp .LoopX_2c                 \n"
-".Xend2_c:                              \n\t"
-
-         "movl %27, %%eax               \n\t"
-         "jmp .LoopYc                   \n"
-
-".Endc:                                 \n\t" // THE END
-         "emms                          \n\t"
-         "popl %%ebx                    \n\t"
-         :
-         :
-         "m" (image),                      // %0
-         "m" (ximage),                     // %1
-         "m" (err),                        // %2
-         "m" (nerr),                       // %3
-         "m" (rtable),                     // %4
-         "m" (gtable),                     // %5
-         "m" (btable),                     // %6
-         "m" (dr),                         // %7
-         "m" (dg),                         // %8
-         "m" (db),                         // %9
-         "m" (roffs),                      // %10
-         "m" (goffs),                      // %11
-         "m" (boffs),                      // %12
-         "m" (width),                      // %13
-         "m" (height),                     // %14
-         "m" (line_offset),                // %15
-         "m" (rrggbbaa.words.rr),          // %16 (access to rr)
-         "m" (rrggbbaa.words.gg),          // %17 (access to gg)
-         "m" (rrggbbaa.words.bb),          // %18 (access to bb)
-         "m" (rrggbbaa.words.aa),          // %19 (access to aa)
-         "m" (pixel.words.rr),             // %20 (access to pixel.r)
-         "m" (pixel.words.gg),             // %21 (access to pixel.g)
-         "m" (pixel.words.bb),             // %22 (access to pixel.b)
-         "m" (pixel.words.aa),             // %23 (access to pixel.a)
-         "m" (tmp_err),                    // %24
-         "m" (tmp_nerr),                   // %25
-         "m" (x),                          // %26
-         "m" (w1),                         // %27
-         "m" (w2)                          // %28
-         : "eax", "ecx", "edx", "esi", "edi"
-        );
-}
-
-
-
-#endif /* ASM_X86_MMX */
-
-
-
-void
-x86_PseudoColor_32_to_8(unsigned char *image,
-                        unsigned char *ximage,
-                        char *err,
-                        char *nerr,
-                        short *ctable,
-                        int dr,
-                        int dg,
-                        int db,
-                        unsigned long *pixels,
-                        int cpc,
-                        int width,
-                        int height,
-                        int bytesPerPixel,
-                        int line_offset)
-{
-    int x;
-    int cpcpc;
-
-    int rr;
-    int gg;
-    int bb;
-
-    char *tmp_err;
-    char *tmp_nerr;
-
-    char ndr; // aparently not used
-    char ndg; // aparently not used
-    char ndb; // aparently not used
-
-    asm volatile
-        (
-         "pushal                        \n\t"
-
-         "movl %9, %%eax                \n\t"
-         "mulb %9                       \n\t"
-         "movl %%eax, %15               \n\t" // cpcpc = cpc*cpc
-
-         // eax will always be <= 0xffff
-
-         // process 1 pixel / cycle, each component treated as 16bit
-         "movl %0, %%esi                \n"   // esi = image->data
-
-".LoopYb:                               \n\t"
-         "movl %10, %%ecx               \n\t"
-         "movl %%ecx, %14               \n\t" // x = width
-
-         "movl %11, %%ecx               \n\t"
-         "decl %%ecx                    \n\t" // y--
-         "movl %%ecx, %11               \n\t"
-         "js .Endb                      \n\t" // if y < 0, goto end
-         "andl $1, %%ecx                \n\t"
-         "jz .LoopY_1b                  \n"   // if (y&1) goto LoopY_1
-
-".LoopY_0b:                             \n\t"
-
-         "movl %2, %%ebx                \n\t" // ebx = err
-//useless "movl %%ebx, %20              \n\t" // [-36] = err
-         "movl %3, %%ecx                \n\t" //
-         "movl %%ecx, %19               \n\t" // [-32] = nerr
-
-         "movl $0, (%%ecx)              \n\t" // init error of nerr[0] to 0
-
-         "jmp .LoopXb                   \n"
-
-".LoopY_1b:                             \n\t"
-
-         "movl %3, %%ebx                \n\t" // ebx = nerr
-//useless "movl %%ebx, %20              \n\t" // [-36] = nerr
-         "movl %2, %%ecx                \n\t" //
-         "movl %%ecx, %19               \n\t" // [-32] = err
-
-         "movl $0, (%%ecx)              \n\t" // init error of nerr[0] to 0
-
-
-         ".align 16                     \n"
-".LoopXb:                               \n\t"
-
-
-         "movl %4, %%edi                \n\t" // edi = ctable
-         "xorl %%edx, %%edx             \n\t" // zero the upper word on edx
-
-         // RED
-
-         // depends on ebx==err, esi==image->data, edi
-         "movzbw (%%esi), %%dx          \n\t" // dx = image->data[0]
-         "movsbw (%%ebx), %%ax          \n\t" // ax = error[0]
-         "addw %%ax, %%dx               \n\t" // pixel.red = data[0] + error[0]
-
-         "testb %%dh, %%dh              \n\t" // test if pixel.red < 0 or > 255
-         "jz .OKRb                      \n\t" // 0 <= pixel.red <= 255
-         "js .NEGRb                     \n\t" // pixel.red < 0
-         "movw $0xff, %%dx              \n\t" // pixel.red > 255
-         "jmp .OKRb                     \n"
-".NEGRb:                                \n\t"
-         "xorw %%dx, %%dx               \n"
-".OKRb:                                 \n\t"
-         //partial reg
-         "leal (%%edi, %%edx, 2), %%ecx \n\t" // ecx = &ctable[pixel.red]
-         //agi
-         "movl (%%ecx), %%eax           \n\t" // ax = ctable[pixel.red]
-         "movw %%ax, %16                \n\t" // save rr
-
-         "mulb %5                       \n\t" // ax = rr*dr
-         "subw %%ax, %%dx               \n\t" // rer = dx = dx - rr*dr
-
-         "movswl %%dx, %%eax            \n\t" // save rer
-
-         // distribute error
-         "leal (, %%eax, 8), %%ecx      \n\t"
-         "subw %%dx, %%cx               \n\t" // cx = rer * 7
-         "sarw $4, %%cx                 \n\t" // cx = rer * 7 / 16
-         "addb %%cl, 4(%%ebx)           \n\t" // err[x+1] += rer * 7 / 16
-
-         "movl %19, %%ecx               \n\t" // ecx = nerr
-
-         "leaw (%%eax, %%eax, 4), %%dx  \n\t" // dx = rer * 5
-         "sarw $4, %%dx                 \n\t" // dx = rer * 5 / 16
-         "addb %%dl, (%%ecx)            \n\t" // nerr[x] += rer * 5 / 16
-
-         "leaw (%%eax, %%eax, 2), %%dx  \n\t" // dx = rer * 3
-         "sarw $4, %%dx                 \n\t" // dx = rer * 3 / 16
-         "addb %%dl, -4(%%ecx)          \n\t" // nerr[x-1] += rer * 3 / 16
-
-         "sarw $4, %%ax                 \n\t" // ax = rer / 16
-         "movb %%al, 4(%%ecx)           \n\t" // nerr[x+1] = rer / 16
-
-
-         // GREEN
-
-         // depends on ebx, esi, edi
-         "movzbw 1(%%esi), %%dx         \n\t" // dx = image->data[1]
-         "movsbw 1(%%ebx), %%ax         \n\t" // ax = error[1]
-         "addw %%ax, %%dx               \n\t" // pixel.grn = data[1] + error[1]
-
-         "testb %%dh, %%dh              \n\t" // test if pixel.grn < 0 or > 255
-         "jz .OKGb                      \n\t" // 0 <= pixel.grn <= 255
-         "js .NEGGb                     \n\t" // pixel.grn < 0
-         "movw $0xff, %%dx              \n\t" // pixel.grn > 255
-         "jmp .OKGb                     \n"
-".NEGGb:                                \n\t"
-         "xorw %%dx, %%dx               \n"
-".OKGb:                                 \n\t"
-         // partial reg
-         "leal (%%edi, %%edx, 2), %%ecx \n\t" // ecx = &ctable[pixel.grn]
-         //agi
-         "movw (%%ecx), %%ax            \n\t" // ax = ctable[pixel.grn]
-         "movw %%ax, %17                \n\t" // save gg
-
-         "mulb %6                       \n\t" // ax = gg*dg
-         "subw %%ax, %%dx               \n\t" // ger = dx = dx - gg*dg
-
-         "movswl %%dx, %%eax            \n\t" // save ger
-
-         // distribute error
-
-         "leal (, %%eax, 8), %%ecx      \n\t"
-         "subw %%dx, %%cx               \n\t" // cx = ger * 7
-         "sarw $4, %%cx                 \n\t" // cx = ger * 7 / 16
-         "addb %%cl, 5(%%ebx)           \n\t" // err[x+1] += ger * 7 / 16
-
-         "movl %19, %%ecx               \n\t" // ecx = nerr
-
-         "leaw (%%eax, %%eax, 4), %%dx  \n\t" // dx = ger * 5
-         "sarw $4, %%dx                 \n\t" // dx = ger * 5 / 16
-         "addb %%dl, 1(%%ecx)           \n\t" // nerr[x] += ger * 5 / 16
-
-         "leaw (%%eax, %%eax, 2), %%dx  \n\t" // dx = ger * 3
-         "sarw $4, %%dx                 \n\t" // dx = ger * 3 / 16
-         "addb %%dl, -3(%%ecx)          \n\t" // nerr[x-1] += ger * 3 / 16
-
-         "sarw $4, %%ax                 \n\t" // ax = ger / 16
-         "movb %%al, 5(%%ecx)           \n\t" // nerr[x+1] = ger / 16
-
-
-         // BLUE
-
-         // depends on ebx, esi
-         "movzbw 2(%%esi), %%dx         \n\t" // dx = image->data[2]
-         "movsbw 2(%%ebx), %%ax         \n\t" // ax = error[2]
-         "addw %%ax, %%dx               \n\t" // pixel.grn = data[2] + error[2]
-
-         "testb %%dh, %%dh              \n\t" // test if pixel.blu < 0 or > 255
-         "jz .OKBb                      \n\t" // 0 <= pixel.blu <= 255
-         "js .NEGBb                     \n\t" // pixel.blu < 0
-         "movw $0xff, %%dx              \n\t" // pixel.blu > 255
-         "jmp .OKBb                     \n"
-".NEGBb:                                \n\t"
-         "xorw %%dx, %%dx               \n"
-".OKBb:                                 \n\t"
-         //partial reg
-         "leal (%%edi, %%edx, 2), %%ecx \n\t" // ecx = &ctable[pixel.blu]
-         //agi
-         "movw (%%ecx), %%ax            \n\t" // ax = ctable[pixel.blu]
-         "movw %%ax, %18                \n\t" // save bb
-
-         "mulb %7                       \n\t" // ax = bb*db
-         "subw %%ax, %%dx               \n\t" // ber = dx = dx - bb*db
-         "movswl %%dx, %%eax            \n\t" // save ber
-
-         // distribute error
-         "leal (, %%eax, 8), %%ecx      \n\t"
-         "subw %%dx, %%cx               \n\t" // cx = ber * 7
-         "sarw $4, %%cx                 \n\t" // cx = ber * 7 / 16
-         "addb %%cl, 6(%%ebx)           \n\t" // err[x+1] += ber * 7 / 16
-
-         "movl %19, %%ecx               \n\t" // ecx = nerr
-
-         "leaw (%%eax, %%eax, 4), %%dx  \n\t" // dx = ber * 5
-         "sarw $4, %%dx                 \n\t" // dx = ber * 5 / 16
-         "addb %%dl, 2(%%ecx)           \n\t" // nerr[x] += ber * 5 / 16
-
-         "leaw (%%eax, %%eax, 2), %%dx  \n\t" // dx = ber * 3
-         "sarw $4, %%dx                 \n\t" // dx = ber * 3 / 16
-         "addb %%dl, -4(%%ecx)          \n\t" // nerr[x-1] += ber * 3 / 16
-
-         "sarw $4, %%ax                 \n\t" // ax = ber / 16
-         "movb %%al, 6(%%ecx)           \n\t" // nerr[x+1] = ber / 16
-
-         "andl $0xffff, %%eax           \n\t"
-         // depends on eax & 0xffff0000 == 0
-         // calculate the index of the value of the pixel
-         "movw %16, %%ax                \n\t" // ax = rr
-         "mulb %15                      \n\t" // ax = cpcpc*rr
-         "movw %%ax, %%cx               \n\t"
-         "movw %17, %%ax                \n\t" // ax = gg
-         "mulb %9                       \n\t" // ax = cpc*gg
-         "addw %%cx, %%ax               \n\t" // ax = cpc*gg + cpcpc*rr
-         "addw %18, %%ax                \n\t" // ax = cpcpc*rr + cpc*gg + bb
-
-         "movl %8, %%ecx                \n\t"
-         //agi
-         "leal (%%ecx, %%eax, 4), %%edx \n\t"
-         //agi
-         "movb (%%edx), %%cl            \n\t" // cl = pixels[ax]
-
-         // store the pixel
-         "movl %1, %%eax                \n\t"
-         "movb %%cl, (%%eax)            \n\t" // *ximage = cl
-         "incl %1                       \n\t" // ximage++
-
-         // prepare for next iteration on X
-
-         "addl $4, %19                  \n\t" // nerr += 4
-         "addl $4, %%ebx                \n\t" // err += 4
-
-         "addl %12, %%esi               \n\t" // image->data += bpp
-
-         "decl %14                      \n\t" // x--
-         "jnz .LoopXb                   \n\t" // if x>0, goto .LoopX
-
-
-         "movl %13, %%eax               \n\t"
-         "addl %%eax, %1                \n\t" // add extra offset to ximage
-
-         "jmp .LoopYb                   \n"
-
-".Endb:                                 \n\t"
-         "emms                          \n\t"
-         "popal                         \n\t"
-         :
-         :
-         "m" (image),         // %0
-         "m" (ximage),        // %1
-         "m" (err),           // %2
-         "m" (nerr),          // %3
-         "m" (ctable),        // %4
-         "m" (dr),            // %5
-         "m" (dg),            // %6
-         "m" (db),            // %7
-         "m" (pixels),        // %8
-         "m" (cpc),           // %9
-         "m" (width),         // %10
-         "m" (height),        // %11
-         "m" (bytesPerPixel), // %12
-         "m" (line_offset),   // %13
-         "m" (x),             // %14
-         "m" (cpcpc),         // %15
-         "m" (rr),            // %16
-         "m" (gg),            // %17
-         "m" (bb),            // %18
-         "m" (tmp_err),       // %19
-         "m" (tmp_nerr),      // %20
-         "m" (ndr),           // %21
-         "m" (ndg),           // %22
-         "m" (ndb)            // %23
-        );
-}
-
-#endif /* ASM_X86 */
-
+/* x86_convert.c - convert RImage to XImage with x86 optimizations
+ *
+ * Raster graphics library
+ *
+ * Copyright (c) 2000-2003 Alfredo K. Kojima
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#ifdef ASM_X86
+
+#ifdef ASM_X86_MMX
+
+int x86_check_mmx()
+{
+       static int result = -1;
+
+       if (result >= 0)
+               return result;
+
+       result = 0;
+
+       asm volatile
+        ("pushal                \n\t"  // please dont forget this in any asm
+         "pushfl                \n\t"  // check whether cpuid supported
+         "pop %%eax             \n\t" "movl %%eax, %%ebx     \n\t" "xorl $(1<<21), %%eax  \n\t" "pushl %%eax           \n\t" "popfl                 \n\t" "pushfl                \n\t" "popl %%eax            \n\t" "xorl %%ebx, %%eax     \n\t" "andl $(1<<21), %%eax  \n\t" "jz .NotPentium        \n\t" "xorl %%eax, %%eax     \n\t"        // no eax effect because of the movl below
+         // except reseting flags. is it needed?
+         "movl $1, %%eax        \n\t" "cpuid                 \n\t" "test $(1<<23), %%edx  \n\t" "jz .NotMMX            \n\t" "popal                 \n\t"      // popal needed because the address of
+         "movl $1, %0           \n\t"  // variable %0 may be kept in a register
+         "jmp .noPop            \n"
+         ".NotMMX:                       \n"
+         ".NotPentium:                   \n\t"
+         "popal                 \n" ".noPop:                        \n\t":"=m" (result));
+
+       return result;
+}
+
+/*
+ * TODO:
+ *              32/8    24/8    32/16   24/16   32/24   24/24
+ * PPlain       YES     YES
+ * MMX                          DONE
+ *
+ *
+ * - try to align stack (local variable space) into quadword boundary
+ */
+void
+x86_mmx_TrueColor_32_to_16(unsigned char *image,
+                          unsigned short *ximage,
+                          short *err,
+                          short *nerr,
+                          unsigned short *rtable,
+                          unsigned short *gtable,
+                          unsigned short *btable,
+                          int dr,
+                          int dg,
+                          int db,
+                          unsigned int roffs,
+                          unsigned int goffs, unsigned int boffs, int width, int height, int line_offset)
+{
+       union {
+               long long rrggbbaa;
+               struct {
+                       short int rr, gg, bb, aa;
+               } words;
+       } rrggbbaa;
+
+       union {
+               long long pixel;
+               struct {
+                       short int rr, gg, bb, aa;
+               } words;
+       } pixel;
+
+       short *tmp_err;
+       short *tmp_nerr;
+       int x;
+
+       asm volatile
+        ("pushl %%ebx                   \n\t"
+         // pack dr, dg and db into mm6
+         "movl  %7, %%eax               \n\t" "movl  %8, %%ebx               \n\t" "movl  %9, %%ecx               \n\t" "movw  %%ax, %16               \n\t" "movw  %%bx, %17               \n\t" "movw  %%cx, %18               \n\t" "movw  $0,  %19                \n\t" "movq  %16, %%mm6              \n\t"       // dr dg db 0
+         // pack 4|4|4|4 into mm7, for shifting (/16)
+         "movl $0x00040004, %16         \n\t"
+         "movl $0x00040004, %18         \n\t" "movq %16, %%mm7               \n\t"
+         // store constant values for using with mmx when dithering
+         "movl $0x00070007, %16         \n\t"
+         "movl $0x00070007, %18         \n\t"
+         "movq %16, %%mm5               \n\t"
+         "movl $0x00050005, %16         \n\t"
+         "movl $0x00050005, %18         \n\t"
+         "movq %16, %%mm4               \n\t"
+         "movl $0x00030003, %16         \n\t"
+         "movl $0x00030003, %18         \n\t" "movq %16, %%mm3               \n\t"
+         // process 1 pixel / cycle, each component treated as 16bit
+         "movl %0, %%esi                \n"    // esi = image->data
+          ".LoopYa:                               \n\t" "movl %13, %%eax               \n\t" "movl %%eax, %26               \n\t"      // x = width
+          "movl %14, %%eax               \n\t" "decl %%eax                    \n\t"    // y--
+         "movl %%eax, %14               \n\t" "js .Enda                      \n\t"     // if y < 0, goto end
+         "andl $1, %%eax                \n\t" "jz .LoopY_1a                  \n"       // if (y&1) goto LoopY_1
+          ".LoopY_0a:                             \n\t" "movl %2, %%ebx                \n\t"   // ebx = err
+         "movl %%ebx, %25               \n\t"  // [-36] = err
+         "movl %3, %%eax                \n\t"  //
+         "movl %%eax, %24               \n\t"  // [-32] = nerr
+          "jmp .LoopXa                   \n" ".LoopY_1a:                             \n\t" "movl %3, %%ebx                \n\t"        // ebx = nerr
+         "movl %%ebx, %25               \n\t"  // [-36] = nerr
+         "movl %2, %%eax                \n\t"  //
+         "movl %%eax, %24               \n\t"  // [-32] = eerr
+          ".align 16                     \n" ".LoopXa:                               \n\t"
+         // calculate errors and pixel components
+         // depend on ebx, esi, mm6
+         "movq (%%ebx), %%mm1           \n\t"  // mm1 = error[0..3]
+         "punpcklbw (%%esi), %%mm0      \n\t"  // mm0 = image->data[0..3]
+         "psrlw $8, %%mm0               \n\t"  // fixup mm0
+         "paddusb %%mm1, %%mm0          \n\t"  // mm0 = mm0 + mm1 (sat. to 255)
+         "movq %%mm0, %20               \n\t"  // save the pixel
+          "movzwl %20, %%ecx             \n\t" // ecx = pixel.red
+         "movl %4, %%edi                \n\t"  // edi = rtable
+         //agi
+         "leal (%%edi, %%ecx, 2), %%eax \n\t"  // eax = &rtable[pixel.red]
+         // agi
+         "movw (%%eax), %%dx            \n\t"  // dx = rtable[pixel.red]
+         "movw %%dx, %16                \n\t"  // save rr
+          "movzwl %21, %%ecx             \n\t" // ecx = pixel.green
+         "movl %5, %%edi                \n\t"  // edi = gtable
+         //agi
+         "leal (%%edi, %%ecx, 2), %%eax \n\t"  // eax = &gtable[pixel.green]
+         //agi
+         "movw (%%eax), %%dx            \n\t"  // dx = gtable[pixel.green]
+         "movw %%dx, %17                \n\t"  // save gg
+          "movzwl %22, %%ecx             \n\t" // ecx = pixel.blue
+         "movl %6, %%edi                \n\t"  // ebx = btable
+         //agi
+         "leal (%%edi, %%ecx, 2), %%eax \n\t"  // eax = &btable[pixel.blue]
+         //agi
+         "movw (%%eax), %%dx            \n\t"  // dx = btable[pixel.blue]
+         "movw %%dx, %18                \n\t"  // save bb
+          "movw $0, %19                  \n\t" // save dummy aa
+          "movq %16, %%mm1               \n\t" // load mm1 with rrggbbaa
+         "pmullw %%mm6, %%mm1           \n\t"  // mm1 = rr*dr|...
+         "psubsw %%mm1, %%mm0           \n\t"  // error = pixel - mm1
+         // distribute the error
+         // depend on mm0, mm7, mm3, mm4, mm5
+          "movl %25, %%ebx               \n\t" "movq %%mm0, %%mm1             \n\t" "pmullw %%mm5, %%mm1           \n\t"       // mm1 = mm1*7
+         "psrlw %%mm7, %%mm1            \n\t"  // mm1 = mm1/16
+         "paddw 8(%%ebx), %%mm1         \n\t" "movq %%mm1, 8(%%ebx)          \n\t"     // err[x+1,y] = rer*7/16
+          "movl %24, %%ebx               \n\t" "movq %%mm0, %%mm1             \n\t" "pmullw %%mm4, %%mm1           \n\t"       // mm1 = mm1*5
+         "psrlw %%mm7, %%mm1            \n\t"  // mm1 = mm1/16
+         "paddw -8(%%ebx), %%mm1        \n\t" "movq %%mm1, -8(%%ebx)         \n\t"     // err[x-1,y+1] += rer*3/16
+          "movq %%mm0, %%mm1             \n\t" "pmullw %%mm3, %%mm1           \n\t"    // mm1 = mm1*3
+         "psrlw %%mm7, %%mm1            \n\t"  // mm1 = mm1/16
+         "paddw 8(%%ebx), %%mm1         \n\t" "movq %%mm1, (%%ebx)           \n\t"     // err[x,y+1] += rer*5/16
+          "psrlw %%mm7, %%mm0            \n\t" // mm0 = mm0/16
+         "movq %%mm0, 8(%%ebx)          \n\t"  // err[x+1,y+1] = rer/16
+         // calculate final pixel value and store
+         "movl %10, %%ecx               \n\t" "movw %16, %%ax                \n\t" "shlw %%cl, %%ax               \n\t"        //NP* ax = r<<roffs
+          "movl %11, %%ecx               \n\t" "movw %17, %%bx                \n\t" "shlw %%cl, %%bx               \n\t"       //NP*
+         "orw %%bx, %%ax                \n\t" "movl %12, %%ecx               \n\t" "movw %18, %%bx                \n\t" "shlw %%cl, %%bx               \n\t"   //NP*
+         "orw %%bx, %%ax                \n\t" "movl %1, %%edx                \n\t" "movw %%ax, (%%edx)            \n\t" "addl $2, %%edx                \n\t"   // increment ximage
+         "movl %%edx, %1                \n\t"
+         // prepare for next iteration on X
+          "addl $8, %24                  \n\t" // nerr += 8
+          "movl %25, %%ebx               \n\t" "addl $8, %%ebx                \n\t" "movl %%ebx, %25               \n\t"       // ebx = err += 8
+         // Note: in the last pixel, this would cause an invalid memory access
+         // because, punpcklbw is used (which reads 8 bytes) and the last
+         // pixel is only 4 bytes. This is no problem because the image data
+         // was allocated with extra 4 bytes when created.
+         "addl $4, %%esi                \n\t"  // image->data += 4
+          "decl %26                      \n\t" // x--
+         "jnz .LoopXa                   \n\t"  // if x>0, goto .LoopX
+         // depend on edx
+         "addl %15, %%edx               \n\t"  // add extra offset to ximage
+         "movl %%edx, %1                \n\t" "jmp .LoopYa                   \n" ".Enda:                                 \n\t" // THE END
+         "emms                          \n\t" "popl %%ebx                    \n\t":: "m" (image),      // %0
+         "m"(ximage),          // %1
+         "m"(err),             // %2
+         "m"(nerr),            // %3
+         "m"(rtable),          // %4
+         "m"(gtable),          // %5
+         "m"(btable),          // %6
+         "m"(dr),              // %7
+         "m"(dg),              // %8
+         "m"(db),              // %9
+         "m"(roffs),           // %10
+         "m"(goffs),           // %11
+         "m"(boffs),           // %12
+         "m"(width),           // %13
+         "m"(height),          // %14
+         "m"(line_offset),     // %15
+         "m"(rrggbbaa.words.rr),       // %16 (access to rr)
+         "m"(rrggbbaa.words.gg),       // %17 (access to gg)
+         "m"(rrggbbaa.words.bb),       // %18 (access to bb)
+         "m"(rrggbbaa.words.aa),       // %19 (access to aa)
+         "m"(pixel.words.rr),  // %20 (access to pixel.r)
+         "m"(pixel.words.gg),  // %21 (access to pixel.g)
+         "m"(pixel.words.bb),  // %22 (access to pixel.b)
+         "m"(pixel.words.aa),  // %23 (access to pixel.a)
+         "m"(tmp_err),         // %24
+         "m"(tmp_nerr),        // %25
+         "m"(x)                // %26
+         :"eax", "ecx", "edx", "esi", "edi");
+}
+
+void
+x86_mmx_TrueColor_24_to_16(unsigned char *image,
+                          unsigned short *ximage,
+                          short *err,
+                          short *nerr,
+                          short *rtable,
+                          short *gtable,
+                          short *btable,
+                          int dr,
+                          int dg,
+                          int db,
+                          unsigned int roffs,
+                          unsigned int goffs, unsigned int boffs, int width, int height, int line_offset)
+{
+       union {
+               long long rrggbbaa;
+               struct {
+                       short int rr, gg, bb, aa;
+               } words;
+       } rrggbbaa;
+
+       union {
+               long long pixel;
+               struct {
+                       short int rr, gg, bb, aa;
+               } words;
+       } pixel;
+
+       short *tmp_err;
+       short *tmp_nerr;
+
+       int x;
+       int w1;
+       int w2;
+
+       asm volatile
+        ("pushl %%ebx                   \n\t" "movl %13, %%eax               \n\t"     // eax = width
+         "movl %%eax, %%ebx             \n\t" "shrl $2, %%eax                \n\t" "movl %%eax, %27               \n\t"        // w1 = width / 4
+         "andl $3, %%ebx                \n\t" "movl %%ebx, %28               \n"       // w2 = width %% 4
+          ".LoopYc:                               \n\t" "movl %13, %%eax               \n\t" "movl %%eax, %26               \n\t"      // x = width
+          "decl %14                      \n\t" // height--
+         "js .Endc                      \n\t"  // if height < 0 then end
+          "movl %14, %%eax               \n\t" "decl %%eax                    \n\t"    // y--
+         "movl %%eax, %14               \n\t" "js .Endc                      \n\t"     // if y < 0, goto end
+         "andl $1, %%eax                \n\t" "jz .LoopY_1c                  \n"       // if (y&1) goto LoopY_1
+          ".LoopY_0c:                             \n\t" "movl %2, %%ebx                \n\t"   // ebx = err
+         "movl %%ebx, %25               \n\t"  // [-36] = err
+         "movl %3, %%eax                \n\t"  //
+         "movl %%eax, %24               \n\t"  // [-32] = nerr
+          "jmp .LoopX_1c                 \n" ".LoopY_1c:                             \n\t" "movl %3, %%ebx                \n\t"        // ebx = nerr
+         "movl %%ebx, %25               \n\t"  // [-36] = nerr
+         "movl %2, %%eax                \n\t"  //
+         "movl %%eax, %24               \n\t"  // [-32] = eerr
+          ".align 16                     \n\t" "movl %%eax, %26               \n"      // x = w1
+         ".LoopX_1c:                             \n\t" "decl %26                      \n\t"    // x--
+         "js .Xend1_c                   \n\t"  // if x < 0 then end
+         // do conversion of 4 pixels
+         "movq %2, %%mm0                \n\t"  // mm0 = err
+          "jmp .LoopX_1c                 \n" ".Xend1_c:                              \n\t" "movl %28, %%eax               \n\t" "movl %%eax, %26               \n"     // x = w2
+         ".LoopX_2c:                             \n\t" "decl %26                      \n\t"    // x--
+         "js .Xend2_c                   \n\t"  //
+         // do conversion
+         "jmp .LoopX_2c                 \n" ".Xend2_c:                              \n\t" "movl %27, %%eax               \n\t" "jmp .LoopYc                   \n" ".Endc:                                 \n\t"        // THE END
+         "emms                          \n\t" "popl %%ebx                    \n\t":: "m" (image),      // %0
+         "m"(ximage),          // %1
+         "m"(err),             // %2
+         "m"(nerr),            // %3
+         "m"(rtable),          // %4
+         "m"(gtable),          // %5
+         "m"(btable),          // %6
+         "m"(dr),              // %7
+         "m"(dg),              // %8
+         "m"(db),              // %9
+         "m"(roffs),           // %10
+         "m"(goffs),           // %11
+         "m"(boffs),           // %12
+         "m"(width),           // %13
+         "m"(height),          // %14
+         "m"(line_offset),     // %15
+         "m"(rrggbbaa.words.rr),       // %16 (access to rr)
+         "m"(rrggbbaa.words.gg),       // %17 (access to gg)
+         "m"(rrggbbaa.words.bb),       // %18 (access to bb)
+         "m"(rrggbbaa.words.aa),       // %19 (access to aa)
+         "m"(pixel.words.rr),  // %20 (access to pixel.r)
+         "m"(pixel.words.gg),  // %21 (access to pixel.g)
+         "m"(pixel.words.bb),  // %22 (access to pixel.b)
+         "m"(pixel.words.aa),  // %23 (access to pixel.a)
+         "m"(tmp_err),         // %24
+         "m"(tmp_nerr),        // %25
+         "m"(x),               // %26
+         "m"(w1),              // %27
+         "m"(w2)               // %28
+         :"eax", "ecx", "edx", "esi", "edi");
+}
+
+#endif                         /* ASM_X86_MMX */
+
+void
+x86_PseudoColor_32_to_8(unsigned char *image,
+                       unsigned char *ximage,
+                       char *err,
+                       char *nerr,
+                       short *ctable,
+                       int dr,
+                       int dg,
+                       int db,
+                       unsigned long *pixels, int cpc, int width, int height, int bytesPerPixel, int line_offset)
+{
+       int x;
+       int cpcpc;
+
+       int rr;
+       int gg;
+       int bb;
+
+       char *tmp_err;
+       char *tmp_nerr;
+
+       char ndr;               // aparently not used
+       char ndg;               // aparently not used
+       char ndb;               // aparently not used
+
+       asm volatile
+        ("pushal                        \n\t" "movl %9, %%eax                \n\t" "mulb %9                       \n\t" "movl %%eax, %15               \n\t"   // cpcpc = cpc*cpc
+         // eax will always be <= 0xffff
+         // process 1 pixel / cycle, each component treated as 16bit
+         "movl %0, %%esi                \n"    // esi = image->data
+          ".LoopYb:                               \n\t" "movl %10, %%ecx               \n\t" "movl %%ecx, %14               \n\t"      // x = width
+          "movl %11, %%ecx               \n\t" "decl %%ecx                    \n\t"    // y--
+         "movl %%ecx, %11               \n\t" "js .Endb                      \n\t"     // if y < 0, goto end
+         "andl $1, %%ecx                \n\t" "jz .LoopY_1b                  \n"       // if (y&1) goto LoopY_1
+          ".LoopY_0b:                             \n\t" "movl %2, %%ebx                \n\t"   // ebx = err
+//useless "movl %%ebx, %20              \n\t" // [-36] = err
+         "movl %3, %%ecx                \n\t"  //
+         "movl %%ecx, %19               \n\t"  // [-32] = nerr
+          "movl $0, (%%ecx)              \n\t" // init error of nerr[0] to 0
+          "jmp .LoopXb                   \n" ".LoopY_1b:                             \n\t" "movl %3, %%ebx                \n\t"        // ebx = nerr
+//useless "movl %%ebx, %20              \n\t" // [-36] = nerr
+         "movl %2, %%ecx                \n\t"  //
+         "movl %%ecx, %19               \n\t"  // [-32] = err
+          "movl $0, (%%ecx)              \n\t" // init error of nerr[0] to 0
+          ".align 16                     \n" ".LoopXb:                               \n\t" "movl %4, %%edi                \n\t"        // edi = ctable
+         "xorl %%edx, %%edx             \n\t"  // zero the upper word on edx
+         // RED
+         // depends on ebx==err, esi==image->data, edi
+         "movzbw (%%esi), %%dx          \n\t"  // dx = image->data[0]
+         "movsbw (%%ebx), %%ax          \n\t"  // ax = error[0]
+         "addw %%ax, %%dx               \n\t"  // pixel.red = data[0] + error[0]
+          "testb %%dh, %%dh              \n\t" // test if pixel.red < 0 or > 255
+         "jz .OKRb                      \n\t"  // 0 <= pixel.red <= 255
+         "js .NEGRb                     \n\t"  // pixel.red < 0
+         "movw $0xff, %%dx              \n\t"  // pixel.red > 255
+         "jmp .OKRb                     \n"
+         ".NEGRb:                                \n\t"
+         "xorw %%dx, %%dx               \n" ".OKRb:                                 \n\t"
+         //partial reg
+         "leal (%%edi, %%edx, 2), %%ecx \n\t"  // ecx = &ctable[pixel.red]
+         //agi
+         "movl (%%ecx), %%eax           \n\t"  // ax = ctable[pixel.red]
+         "movw %%ax, %16                \n\t"  // save rr
+          "mulb %5                       \n\t" // ax = rr*dr
+         "subw %%ax, %%dx               \n\t"  // rer = dx = dx - rr*dr
+          "movswl %%dx, %%eax            \n\t" // save rer
+         // distribute error
+         "leal (, %%eax, 8), %%ecx      \n\t" "subw %%dx, %%cx               \n\t"     // cx = rer * 7
+         "sarw $4, %%cx                 \n\t"  // cx = rer * 7 / 16
+         "addb %%cl, 4(%%ebx)           \n\t"  // err[x+1] += rer * 7 / 16
+          "movl %19, %%ecx               \n\t" // ecx = nerr
+          "leaw (%%eax, %%eax, 4), %%dx  \n\t" // dx = rer * 5
+         "sarw $4, %%dx                 \n\t"  // dx = rer * 5 / 16
+         "addb %%dl, (%%ecx)            \n\t"  // nerr[x] += rer * 5 / 16
+          "leaw (%%eax, %%eax, 2), %%dx  \n\t" // dx = rer * 3
+         "sarw $4, %%dx                 \n\t"  // dx = rer * 3 / 16
+         "addb %%dl, -4(%%ecx)          \n\t"  // nerr[x-1] += rer * 3 / 16
+          "sarw $4, %%ax                 \n\t" // ax = rer / 16
+         "movb %%al, 4(%%ecx)           \n\t"  // nerr[x+1] = rer / 16
+         // GREEN
+         // depends on ebx, esi, edi
+         "movzbw 1(%%esi), %%dx         \n\t"  // dx = image->data[1]
+         "movsbw 1(%%ebx), %%ax         \n\t"  // ax = error[1]
+         "addw %%ax, %%dx               \n\t"  // pixel.grn = data[1] + error[1]
+          "testb %%dh, %%dh              \n\t" // test if pixel.grn < 0 or > 255
+         "jz .OKGb                      \n\t"  // 0 <= pixel.grn <= 255
+         "js .NEGGb                     \n\t"  // pixel.grn < 0
+         "movw $0xff, %%dx              \n\t"  // pixel.grn > 255
+         "jmp .OKGb                     \n"
+         ".NEGGb:                                \n\t"
+         "xorw %%dx, %%dx               \n" ".OKGb:                                 \n\t"
+         // partial reg
+         "leal (%%edi, %%edx, 2), %%ecx \n\t"  // ecx = &ctable[pixel.grn]
+         //agi
+         "movw (%%ecx), %%ax            \n\t"  // ax = ctable[pixel.grn]
+         "movw %%ax, %17                \n\t"  // save gg
+          "mulb %6                       \n\t" // ax = gg*dg
+         "subw %%ax, %%dx               \n\t"  // ger = dx = dx - gg*dg
+          "movswl %%dx, %%eax            \n\t" // save ger
+         // distribute error
+          "leal (, %%eax, 8), %%ecx      \n\t" "subw %%dx, %%cx               \n\t"    // cx = ger * 7
+         "sarw $4, %%cx                 \n\t"  // cx = ger * 7 / 16
+         "addb %%cl, 5(%%ebx)           \n\t"  // err[x+1] += ger * 7 / 16
+          "movl %19, %%ecx               \n\t" // ecx = nerr
+          "leaw (%%eax, %%eax, 4), %%dx  \n\t" // dx = ger * 5
+         "sarw $4, %%dx                 \n\t"  // dx = ger * 5 / 16
+         "addb %%dl, 1(%%ecx)           \n\t"  // nerr[x] += ger * 5 / 16
+          "leaw (%%eax, %%eax, 2), %%dx  \n\t" // dx = ger * 3
+         "sarw $4, %%dx                 \n\t"  // dx = ger * 3 / 16
+         "addb %%dl, -3(%%ecx)          \n\t"  // nerr[x-1] += ger * 3 / 16
+          "sarw $4, %%ax                 \n\t" // ax = ger / 16
+         "movb %%al, 5(%%ecx)           \n\t"  // nerr[x+1] = ger / 16
+         // BLUE
+         // depends on ebx, esi
+         "movzbw 2(%%esi), %%dx         \n\t"  // dx = image->data[2]
+         "movsbw 2(%%ebx), %%ax         \n\t"  // ax = error[2]
+         "addw %%ax, %%dx               \n\t"  // pixel.grn = data[2] + error[2]
+          "testb %%dh, %%dh              \n\t" // test if pixel.blu < 0 or > 255
+         "jz .OKBb                      \n\t"  // 0 <= pixel.blu <= 255
+         "js .NEGBb                     \n\t"  // pixel.blu < 0
+         "movw $0xff, %%dx              \n\t"  // pixel.blu > 255
+         "jmp .OKBb                     \n"
+         ".NEGBb:                                \n\t"
+         "xorw %%dx, %%dx               \n" ".OKBb:                                 \n\t"
+         //partial reg
+         "leal (%%edi, %%edx, 2), %%ecx \n\t"  // ecx = &ctable[pixel.blu]
+         //agi
+         "movw (%%ecx), %%ax            \n\t"  // ax = ctable[pixel.blu]
+         "movw %%ax, %18                \n\t"  // save bb
+          "mulb %7                       \n\t" // ax = bb*db
+         "subw %%ax, %%dx               \n\t"  // ber = dx = dx - bb*db
+         "movswl %%dx, %%eax            \n\t"  // save ber
+         // distribute error
+         "leal (, %%eax, 8), %%ecx      \n\t" "subw %%dx, %%cx               \n\t"     // cx = ber * 7
+         "sarw $4, %%cx                 \n\t"  // cx = ber * 7 / 16
+         "addb %%cl, 6(%%ebx)           \n\t"  // err[x+1] += ber * 7 / 16
+          "movl %19, %%ecx               \n\t" // ecx = nerr
+          "leaw (%%eax, %%eax, 4), %%dx  \n\t" // dx = ber * 5
+         "sarw $4, %%dx                 \n\t"  // dx = ber * 5 / 16
+         "addb %%dl, 2(%%ecx)           \n\t"  // nerr[x] += ber * 5 / 16
+          "leaw (%%eax, %%eax, 2), %%dx  \n\t" // dx = ber * 3
+         "sarw $4, %%dx                 \n\t"  // dx = ber * 3 / 16
+         "addb %%dl, -4(%%ecx)          \n\t"  // nerr[x-1] += ber * 3 / 16
+          "sarw $4, %%ax                 \n\t" // ax = ber / 16
+         "movb %%al, 6(%%ecx)           \n\t"  // nerr[x+1] = ber / 16
+          "andl $0xffff, %%eax           \n\t"
+         // depends on eax & 0xffff0000 == 0
+         // calculate the index of the value of the pixel
+         "movw %16, %%ax                \n\t"  // ax = rr
+         "mulb %15                      \n\t"  // ax = cpcpc*rr
+         "movw %%ax, %%cx               \n\t" "movw %17, %%ax                \n\t"     // ax = gg
+         "mulb %9                       \n\t"  // ax = cpc*gg
+         "addw %%cx, %%ax               \n\t"  // ax = cpc*gg + cpcpc*rr
+         "addw %18, %%ax                \n\t"  // ax = cpcpc*rr + cpc*gg + bb
+          "movl %8, %%ecx                \n\t"
+         //agi
+         "leal (%%ecx, %%eax, 4), %%edx \n\t"
+         //agi
+         "movb (%%edx), %%cl            \n\t"  // cl = pixels[ax]
+         // store the pixel
+         "movl %1, %%eax                \n\t" "movb %%cl, (%%eax)            \n\t"     // *ximage = cl
+         "incl %1                       \n\t"  // ximage++
+         // prepare for next iteration on X
+          "addl $4, %19                  \n\t" // nerr += 4
+         "addl $4, %%ebx                \n\t"  // err += 4
+          "addl %12, %%esi               \n\t" // image->data += bpp
+          "decl %14                      \n\t" // x--
+         "jnz .LoopXb                   \n\t"  // if x>0, goto .LoopX
+          "movl %13, %%eax               \n\t" "addl %%eax, %1                \n\t"    // add extra offset to ximage
+          "jmp .LoopYb                   \n" ".Endb:                                 \n\t" "emms                          \n\t" "popal                         \n\t":: "m" (image),    // %0
+         "m"(ximage),          // %1
+         "m"(err),             // %2
+         "m"(nerr),            // %3
+         "m"(ctable),          // %4
+         "m"(dr),              // %5
+         "m"(dg),              // %6
+         "m"(db),              // %7
+         "m"(pixels),          // %8
+         "m"(cpc),             // %9
+         "m"(width),           // %10
+         "m"(height),          // %11
+         "m"(bytesPerPixel),   // %12
+         "m"(line_offset),     // %13
+         "m"(x),               // %14
+         "m"(cpcpc),           // %15
+         "m"(rr),              // %16
+         "m"(gg),              // %17
+         "m"(bb),              // %18
+         "m"(tmp_err),         // %19
+         "m"(tmp_nerr),        // %20
+         "m"(ndr),             // %21
+         "m"(ndg),             // %22
+         "m"(ndb)              // %23
+           );
+}
+
+#endif                         /* ASM_X86 */