Change to the linux kernel coding style
[wmaker-crm.git] / wrlib / x86_specific.c
1 /* x86_convert.c - convert RImage to XImage with x86 optimizations
2  *
3  * Raster graphics library
4  *
5  * Copyright (c) 2000-2003 Alfredo K. Kojima
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Library General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Library General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Library General Public
18  *  License along with this library; if not, write to the Free
19  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include <config.h>
23
24 #ifdef ASM_X86
25
26 #ifdef ASM_X86_MMX
27
28 int x86_check_mmx()
29 {
30         static int result = -1;
31
32         if (result >= 0)
33                 return result;
34
35         result = 0;
36
37         asm volatile
38          ("pushal                \n\t"  // please dont forget this in any asm
39           "pushfl                \n\t"  // check whether cpuid supported
40           "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
41           // except reseting flags. is it needed?
42           "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
43           "movl $1, %0           \n\t"  // variable %0 may be kept in a register
44           "jmp .noPop            \n"
45           ".NotMMX:                       \n"
46           ".NotPentium:                   \n\t"
47           "popal                 \n" ".noPop:                        \n\t":"=m" (result));
48
49         return result;
50 }
51
52 /*
53  * TODO:
54  *              32/8    24/8    32/16   24/16   32/24   24/24
55  * PPlain       YES     YES
56  * MMX                          DONE
57  *
58  *
59  * - try to align stack (local variable space) into quadword boundary
60  */
61 void
62 x86_mmx_TrueColor_32_to_16(unsigned char *image,
63                            unsigned short *ximage,
64                            short *err,
65                            short *nerr,
66                            unsigned short *rtable,
67                            unsigned short *gtable,
68                            unsigned short *btable,
69                            int dr,
70                            int dg,
71                            int db,
72                            unsigned int roffs,
73                            unsigned int goffs, unsigned int boffs, int width, int height, int line_offset)
74 {
75         union {
76                 long long rrggbbaa;
77                 struct {
78                         short int rr, gg, bb, aa;
79                 } words;
80         } rrggbbaa;
81
82         union {
83                 long long pixel;
84                 struct {
85                         short int rr, gg, bb, aa;
86                 } words;
87         } pixel;
88
89         short *tmp_err;
90         short *tmp_nerr;
91         int x;
92
93         asm volatile
94          ("pushl %%ebx                   \n\t"
95           // pack dr, dg and db into mm6
96           "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
97           // pack 4|4|4|4 into mm7, for shifting (/16)
98           "movl $0x00040004, %16         \n\t"
99           "movl $0x00040004, %18         \n\t" "movq %16, %%mm7               \n\t"
100           // store constant values for using with mmx when dithering
101           "movl $0x00070007, %16         \n\t"
102           "movl $0x00070007, %18         \n\t"
103           "movq %16, %%mm5               \n\t"
104           "movl $0x00050005, %16         \n\t"
105           "movl $0x00050005, %18         \n\t"
106           "movq %16, %%mm4               \n\t"
107           "movl $0x00030003, %16         \n\t"
108           "movl $0x00030003, %18         \n\t" "movq %16, %%mm3               \n\t"
109           // process 1 pixel / cycle, each component treated as 16bit
110           "movl %0, %%esi                \n"    // esi = image->data
111            ".LoopYa:                               \n\t" "movl %13, %%eax               \n\t" "movl %%eax, %26               \n\t"      // x = width
112            "movl %14, %%eax               \n\t" "decl %%eax                    \n\t"    // y--
113           "movl %%eax, %14               \n\t" "js .Enda                      \n\t"     // if y < 0, goto end
114           "andl $1, %%eax                \n\t" "jz .LoopY_1a                  \n"       // if (y&1) goto LoopY_1
115            ".LoopY_0a:                             \n\t" "movl %2, %%ebx                \n\t"   // ebx = err
116           "movl %%ebx, %25               \n\t"  // [-36] = err
117           "movl %3, %%eax                \n\t"  //
118           "movl %%eax, %24               \n\t"  // [-32] = nerr
119            "jmp .LoopXa                   \n" ".LoopY_1a:                             \n\t" "movl %3, %%ebx                \n\t"        // ebx = nerr
120           "movl %%ebx, %25               \n\t"  // [-36] = nerr
121           "movl %2, %%eax                \n\t"  //
122           "movl %%eax, %24               \n\t"  // [-32] = eerr
123            ".align 16                     \n" ".LoopXa:                               \n\t"
124           // calculate errors and pixel components
125           // depend on ebx, esi, mm6
126           "movq (%%ebx), %%mm1           \n\t"  // mm1 = error[0..3]
127           "punpcklbw (%%esi), %%mm0      \n\t"  // mm0 = image->data[0..3]
128           "psrlw $8, %%mm0               \n\t"  // fixup mm0
129           "paddusb %%mm1, %%mm0          \n\t"  // mm0 = mm0 + mm1 (sat. to 255)
130           "movq %%mm0, %20               \n\t"  // save the pixel
131            "movzwl %20, %%ecx             \n\t" // ecx = pixel.red
132           "movl %4, %%edi                \n\t"  // edi = rtable
133           //agi
134           "leal (%%edi, %%ecx, 2), %%eax \n\t"  // eax = &rtable[pixel.red]
135           // agi
136           "movw (%%eax), %%dx            \n\t"  // dx = rtable[pixel.red]
137           "movw %%dx, %16                \n\t"  // save rr
138            "movzwl %21, %%ecx             \n\t" // ecx = pixel.green
139           "movl %5, %%edi                \n\t"  // edi = gtable
140           //agi
141           "leal (%%edi, %%ecx, 2), %%eax \n\t"  // eax = &gtable[pixel.green]
142           //agi
143           "movw (%%eax), %%dx            \n\t"  // dx = gtable[pixel.green]
144           "movw %%dx, %17                \n\t"  // save gg
145            "movzwl %22, %%ecx             \n\t" // ecx = pixel.blue
146           "movl %6, %%edi                \n\t"  // ebx = btable
147           //agi
148           "leal (%%edi, %%ecx, 2), %%eax \n\t"  // eax = &btable[pixel.blue]
149           //agi
150           "movw (%%eax), %%dx            \n\t"  // dx = btable[pixel.blue]
151           "movw %%dx, %18                \n\t"  // save bb
152            "movw $0, %19                  \n\t" // save dummy aa
153            "movq %16, %%mm1               \n\t" // load mm1 with rrggbbaa
154           "pmullw %%mm6, %%mm1           \n\t"  // mm1 = rr*dr|...
155           "psubsw %%mm1, %%mm0           \n\t"  // error = pixel - mm1
156           // distribute the error
157           // depend on mm0, mm7, mm3, mm4, mm5
158            "movl %25, %%ebx               \n\t" "movq %%mm0, %%mm1             \n\t" "pmullw %%mm5, %%mm1           \n\t"       // mm1 = mm1*7
159           "psrlw %%mm7, %%mm1            \n\t"  // mm1 = mm1/16
160           "paddw 8(%%ebx), %%mm1         \n\t" "movq %%mm1, 8(%%ebx)          \n\t"     // err[x+1,y] = rer*7/16
161            "movl %24, %%ebx               \n\t" "movq %%mm0, %%mm1             \n\t" "pmullw %%mm4, %%mm1           \n\t"       // mm1 = mm1*5
162           "psrlw %%mm7, %%mm1            \n\t"  // mm1 = mm1/16
163           "paddw -8(%%ebx), %%mm1        \n\t" "movq %%mm1, -8(%%ebx)         \n\t"     // err[x-1,y+1] += rer*3/16
164            "movq %%mm0, %%mm1             \n\t" "pmullw %%mm3, %%mm1           \n\t"    // mm1 = mm1*3
165           "psrlw %%mm7, %%mm1            \n\t"  // mm1 = mm1/16
166           "paddw 8(%%ebx), %%mm1         \n\t" "movq %%mm1, (%%ebx)           \n\t"     // err[x,y+1] += rer*5/16
167            "psrlw %%mm7, %%mm0            \n\t" // mm0 = mm0/16
168           "movq %%mm0, 8(%%ebx)          \n\t"  // err[x+1,y+1] = rer/16
169           // calculate final pixel value and store
170           "movl %10, %%ecx               \n\t" "movw %16, %%ax                \n\t" "shlw %%cl, %%ax               \n\t"        //NP* ax = r<<roffs
171            "movl %11, %%ecx               \n\t" "movw %17, %%bx                \n\t" "shlw %%cl, %%bx               \n\t"       //NP*
172           "orw %%bx, %%ax                \n\t" "movl %12, %%ecx               \n\t" "movw %18, %%bx                \n\t" "shlw %%cl, %%bx               \n\t"   //NP*
173           "orw %%bx, %%ax                \n\t" "movl %1, %%edx                \n\t" "movw %%ax, (%%edx)            \n\t" "addl $2, %%edx                \n\t"   // increment ximage
174           "movl %%edx, %1                \n\t"
175           // prepare for next iteration on X
176            "addl $8, %24                  \n\t" // nerr += 8
177            "movl %25, %%ebx               \n\t" "addl $8, %%ebx                \n\t" "movl %%ebx, %25               \n\t"       // ebx = err += 8
178           // Note: in the last pixel, this would cause an invalid memory access
179           // because, punpcklbw is used (which reads 8 bytes) and the last
180           // pixel is only 4 bytes. This is no problem because the image data
181           // was allocated with extra 4 bytes when created.
182           "addl $4, %%esi                \n\t"  // image->data += 4
183            "decl %26                      \n\t" // x--
184           "jnz .LoopXa                   \n\t"  // if x>0, goto .LoopX
185           // depend on edx
186           "addl %15, %%edx               \n\t"  // add extra offset to ximage
187           "movl %%edx, %1                \n\t" "jmp .LoopYa                   \n" ".Enda:                                 \n\t" // THE END
188           "emms                          \n\t" "popl %%ebx                    \n\t":: "m" (image),      // %0
189           "m"(ximage),          // %1
190           "m"(err),             // %2
191           "m"(nerr),            // %3
192           "m"(rtable),          // %4
193           "m"(gtable),          // %5
194           "m"(btable),          // %6
195           "m"(dr),              // %7
196           "m"(dg),              // %8
197           "m"(db),              // %9
198           "m"(roffs),           // %10
199           "m"(goffs),           // %11
200           "m"(boffs),           // %12
201           "m"(width),           // %13
202           "m"(height),          // %14
203           "m"(line_offset),     // %15
204           "m"(rrggbbaa.words.rr),       // %16 (access to rr)
205           "m"(rrggbbaa.words.gg),       // %17 (access to gg)
206           "m"(rrggbbaa.words.bb),       // %18 (access to bb)
207           "m"(rrggbbaa.words.aa),       // %19 (access to aa)
208           "m"(pixel.words.rr),  // %20 (access to pixel.r)
209           "m"(pixel.words.gg),  // %21 (access to pixel.g)
210           "m"(pixel.words.bb),  // %22 (access to pixel.b)
211           "m"(pixel.words.aa),  // %23 (access to pixel.a)
212           "m"(tmp_err),         // %24
213           "m"(tmp_nerr),        // %25
214           "m"(x)                // %26
215           :"eax", "ecx", "edx", "esi", "edi");
216 }
217
218 void
219 x86_mmx_TrueColor_24_to_16(unsigned char *image,
220                            unsigned short *ximage,
221                            short *err,
222                            short *nerr,
223                            short *rtable,
224                            short *gtable,
225                            short *btable,
226                            int dr,
227                            int dg,
228                            int db,
229                            unsigned int roffs,
230                            unsigned int goffs, unsigned int boffs, int width, int height, int line_offset)
231 {
232         union {
233                 long long rrggbbaa;
234                 struct {
235                         short int rr, gg, bb, aa;
236                 } words;
237         } rrggbbaa;
238
239         union {
240                 long long pixel;
241                 struct {
242                         short int rr, gg, bb, aa;
243                 } words;
244         } pixel;
245
246         short *tmp_err;
247         short *tmp_nerr;
248
249         int x;
250         int w1;
251         int w2;
252
253         asm volatile
254          ("pushl %%ebx                   \n\t" "movl %13, %%eax               \n\t"     // eax = width
255           "movl %%eax, %%ebx             \n\t" "shrl $2, %%eax                \n\t" "movl %%eax, %27               \n\t"        // w1 = width / 4
256           "andl $3, %%ebx                \n\t" "movl %%ebx, %28               \n"       // w2 = width %% 4
257            ".LoopYc:                               \n\t" "movl %13, %%eax               \n\t" "movl %%eax, %26               \n\t"      // x = width
258            "decl %14                      \n\t" // height--
259           "js .Endc                      \n\t"  // if height < 0 then end
260            "movl %14, %%eax               \n\t" "decl %%eax                    \n\t"    // y--
261           "movl %%eax, %14               \n\t" "js .Endc                      \n\t"     // if y < 0, goto end
262           "andl $1, %%eax                \n\t" "jz .LoopY_1c                  \n"       // if (y&1) goto LoopY_1
263            ".LoopY_0c:                             \n\t" "movl %2, %%ebx                \n\t"   // ebx = err
264           "movl %%ebx, %25               \n\t"  // [-36] = err
265           "movl %3, %%eax                \n\t"  //
266           "movl %%eax, %24               \n\t"  // [-32] = nerr
267            "jmp .LoopX_1c                 \n" ".LoopY_1c:                             \n\t" "movl %3, %%ebx                \n\t"        // ebx = nerr
268           "movl %%ebx, %25               \n\t"  // [-36] = nerr
269           "movl %2, %%eax                \n\t"  //
270           "movl %%eax, %24               \n\t"  // [-32] = eerr
271            ".align 16                     \n\t" "movl %%eax, %26               \n"      // x = w1
272           ".LoopX_1c:                             \n\t" "decl %26                      \n\t"    // x--
273           "js .Xend1_c                   \n\t"  // if x < 0 then end
274           // do conversion of 4 pixels
275           "movq %2, %%mm0                \n\t"  // mm0 = err
276            "jmp .LoopX_1c                 \n" ".Xend1_c:                              \n\t" "movl %28, %%eax               \n\t" "movl %%eax, %26               \n"     // x = w2
277           ".LoopX_2c:                             \n\t" "decl %26                      \n\t"    // x--
278           "js .Xend2_c                   \n\t"  //
279           // do conversion
280           "jmp .LoopX_2c                 \n" ".Xend2_c:                              \n\t" "movl %27, %%eax               \n\t" "jmp .LoopYc                   \n" ".Endc:                                 \n\t"        // THE END
281           "emms                          \n\t" "popl %%ebx                    \n\t":: "m" (image),      // %0
282           "m"(ximage),          // %1
283           "m"(err),             // %2
284           "m"(nerr),            // %3
285           "m"(rtable),          // %4
286           "m"(gtable),          // %5
287           "m"(btable),          // %6
288           "m"(dr),              // %7
289           "m"(dg),              // %8
290           "m"(db),              // %9
291           "m"(roffs),           // %10
292           "m"(goffs),           // %11
293           "m"(boffs),           // %12
294           "m"(width),           // %13
295           "m"(height),          // %14
296           "m"(line_offset),     // %15
297           "m"(rrggbbaa.words.rr),       // %16 (access to rr)
298           "m"(rrggbbaa.words.gg),       // %17 (access to gg)
299           "m"(rrggbbaa.words.bb),       // %18 (access to bb)
300           "m"(rrggbbaa.words.aa),       // %19 (access to aa)
301           "m"(pixel.words.rr),  // %20 (access to pixel.r)
302           "m"(pixel.words.gg),  // %21 (access to pixel.g)
303           "m"(pixel.words.bb),  // %22 (access to pixel.b)
304           "m"(pixel.words.aa),  // %23 (access to pixel.a)
305           "m"(tmp_err),         // %24
306           "m"(tmp_nerr),        // %25
307           "m"(x),               // %26
308           "m"(w1),              // %27
309           "m"(w2)               // %28
310           :"eax", "ecx", "edx", "esi", "edi");
311 }
312
313 #endif                          /* ASM_X86_MMX */
314
315 void
316 x86_PseudoColor_32_to_8(unsigned char *image,
317                         unsigned char *ximage,
318                         char *err,
319                         char *nerr,
320                         short *ctable,
321                         int dr,
322                         int dg,
323                         int db,
324                         unsigned long *pixels, int cpc, int width, int height, int bytesPerPixel, int line_offset)
325 {
326         int x;
327         int cpcpc;
328
329         int rr;
330         int gg;
331         int bb;
332
333         char *tmp_err;
334         char *tmp_nerr;
335
336         char ndr;               // aparently not used
337         char ndg;               // aparently not used
338         char ndb;               // aparently not used
339
340         asm volatile
341          ("pushal                        \n\t" "movl %9, %%eax                \n\t" "mulb %9                       \n\t" "movl %%eax, %15               \n\t"   // cpcpc = cpc*cpc
342           // eax will always be <= 0xffff
343           // process 1 pixel / cycle, each component treated as 16bit
344           "movl %0, %%esi                \n"    // esi = image->data
345            ".LoopYb:                               \n\t" "movl %10, %%ecx               \n\t" "movl %%ecx, %14               \n\t"      // x = width
346            "movl %11, %%ecx               \n\t" "decl %%ecx                    \n\t"    // y--
347           "movl %%ecx, %11               \n\t" "js .Endb                      \n\t"     // if y < 0, goto end
348           "andl $1, %%ecx                \n\t" "jz .LoopY_1b                  \n"       // if (y&1) goto LoopY_1
349            ".LoopY_0b:                             \n\t" "movl %2, %%ebx                \n\t"   // ebx = err
350 //useless "movl %%ebx, %20              \n\t" // [-36] = err
351           "movl %3, %%ecx                \n\t"  //
352           "movl %%ecx, %19               \n\t"  // [-32] = nerr
353            "movl $0, (%%ecx)              \n\t" // init error of nerr[0] to 0
354            "jmp .LoopXb                   \n" ".LoopY_1b:                             \n\t" "movl %3, %%ebx                \n\t"        // ebx = nerr
355 //useless "movl %%ebx, %20              \n\t" // [-36] = nerr
356           "movl %2, %%ecx                \n\t"  //
357           "movl %%ecx, %19               \n\t"  // [-32] = err
358            "movl $0, (%%ecx)              \n\t" // init error of nerr[0] to 0
359            ".align 16                     \n" ".LoopXb:                               \n\t" "movl %4, %%edi                \n\t"        // edi = ctable
360           "xorl %%edx, %%edx             \n\t"  // zero the upper word on edx
361           // RED
362           // depends on ebx==err, esi==image->data, edi
363           "movzbw (%%esi), %%dx          \n\t"  // dx = image->data[0]
364           "movsbw (%%ebx), %%ax          \n\t"  // ax = error[0]
365           "addw %%ax, %%dx               \n\t"  // pixel.red = data[0] + error[0]
366            "testb %%dh, %%dh              \n\t" // test if pixel.red < 0 or > 255
367           "jz .OKRb                      \n\t"  // 0 <= pixel.red <= 255
368           "js .NEGRb                     \n\t"  // pixel.red < 0
369           "movw $0xff, %%dx              \n\t"  // pixel.red > 255
370           "jmp .OKRb                     \n"
371           ".NEGRb:                                \n\t"
372           "xorw %%dx, %%dx               \n" ".OKRb:                                 \n\t"
373           //partial reg
374           "leal (%%edi, %%edx, 2), %%ecx \n\t"  // ecx = &ctable[pixel.red]
375           //agi
376           "movl (%%ecx), %%eax           \n\t"  // ax = ctable[pixel.red]
377           "movw %%ax, %16                \n\t"  // save rr
378            "mulb %5                       \n\t" // ax = rr*dr
379           "subw %%ax, %%dx               \n\t"  // rer = dx = dx - rr*dr
380            "movswl %%dx, %%eax            \n\t" // save rer
381           // distribute error
382           "leal (, %%eax, 8), %%ecx      \n\t" "subw %%dx, %%cx               \n\t"     // cx = rer * 7
383           "sarw $4, %%cx                 \n\t"  // cx = rer * 7 / 16
384           "addb %%cl, 4(%%ebx)           \n\t"  // err[x+1] += rer * 7 / 16
385            "movl %19, %%ecx               \n\t" // ecx = nerr
386            "leaw (%%eax, %%eax, 4), %%dx  \n\t" // dx = rer * 5
387           "sarw $4, %%dx                 \n\t"  // dx = rer * 5 / 16
388           "addb %%dl, (%%ecx)            \n\t"  // nerr[x] += rer * 5 / 16
389            "leaw (%%eax, %%eax, 2), %%dx  \n\t" // dx = rer * 3
390           "sarw $4, %%dx                 \n\t"  // dx = rer * 3 / 16
391           "addb %%dl, -4(%%ecx)          \n\t"  // nerr[x-1] += rer * 3 / 16
392            "sarw $4, %%ax                 \n\t" // ax = rer / 16
393           "movb %%al, 4(%%ecx)           \n\t"  // nerr[x+1] = rer / 16
394           // GREEN
395           // depends on ebx, esi, edi
396           "movzbw 1(%%esi), %%dx         \n\t"  // dx = image->data[1]
397           "movsbw 1(%%ebx), %%ax         \n\t"  // ax = error[1]
398           "addw %%ax, %%dx               \n\t"  // pixel.grn = data[1] + error[1]
399            "testb %%dh, %%dh              \n\t" // test if pixel.grn < 0 or > 255
400           "jz .OKGb                      \n\t"  // 0 <= pixel.grn <= 255
401           "js .NEGGb                     \n\t"  // pixel.grn < 0
402           "movw $0xff, %%dx              \n\t"  // pixel.grn > 255
403           "jmp .OKGb                     \n"
404           ".NEGGb:                                \n\t"
405           "xorw %%dx, %%dx               \n" ".OKGb:                                 \n\t"
406           // partial reg
407           "leal (%%edi, %%edx, 2), %%ecx \n\t"  // ecx = &ctable[pixel.grn]
408           //agi
409           "movw (%%ecx), %%ax            \n\t"  // ax = ctable[pixel.grn]
410           "movw %%ax, %17                \n\t"  // save gg
411            "mulb %6                       \n\t" // ax = gg*dg
412           "subw %%ax, %%dx               \n\t"  // ger = dx = dx - gg*dg
413            "movswl %%dx, %%eax            \n\t" // save ger
414           // distribute error
415            "leal (, %%eax, 8), %%ecx      \n\t" "subw %%dx, %%cx               \n\t"    // cx = ger * 7
416           "sarw $4, %%cx                 \n\t"  // cx = ger * 7 / 16
417           "addb %%cl, 5(%%ebx)           \n\t"  // err[x+1] += ger * 7 / 16
418            "movl %19, %%ecx               \n\t" // ecx = nerr
419            "leaw (%%eax, %%eax, 4), %%dx  \n\t" // dx = ger * 5
420           "sarw $4, %%dx                 \n\t"  // dx = ger * 5 / 16
421           "addb %%dl, 1(%%ecx)           \n\t"  // nerr[x] += ger * 5 / 16
422            "leaw (%%eax, %%eax, 2), %%dx  \n\t" // dx = ger * 3
423           "sarw $4, %%dx                 \n\t"  // dx = ger * 3 / 16
424           "addb %%dl, -3(%%ecx)          \n\t"  // nerr[x-1] += ger * 3 / 16
425            "sarw $4, %%ax                 \n\t" // ax = ger / 16
426           "movb %%al, 5(%%ecx)           \n\t"  // nerr[x+1] = ger / 16
427           // BLUE
428           // depends on ebx, esi
429           "movzbw 2(%%esi), %%dx         \n\t"  // dx = image->data[2]
430           "movsbw 2(%%ebx), %%ax         \n\t"  // ax = error[2]
431           "addw %%ax, %%dx               \n\t"  // pixel.grn = data[2] + error[2]
432            "testb %%dh, %%dh              \n\t" // test if pixel.blu < 0 or > 255
433           "jz .OKBb                      \n\t"  // 0 <= pixel.blu <= 255
434           "js .NEGBb                     \n\t"  // pixel.blu < 0
435           "movw $0xff, %%dx              \n\t"  // pixel.blu > 255
436           "jmp .OKBb                     \n"
437           ".NEGBb:                                \n\t"
438           "xorw %%dx, %%dx               \n" ".OKBb:                                 \n\t"
439           //partial reg
440           "leal (%%edi, %%edx, 2), %%ecx \n\t"  // ecx = &ctable[pixel.blu]
441           //agi
442           "movw (%%ecx), %%ax            \n\t"  // ax = ctable[pixel.blu]
443           "movw %%ax, %18                \n\t"  // save bb
444            "mulb %7                       \n\t" // ax = bb*db
445           "subw %%ax, %%dx               \n\t"  // ber = dx = dx - bb*db
446           "movswl %%dx, %%eax            \n\t"  // save ber
447           // distribute error
448           "leal (, %%eax, 8), %%ecx      \n\t" "subw %%dx, %%cx               \n\t"     // cx = ber * 7
449           "sarw $4, %%cx                 \n\t"  // cx = ber * 7 / 16
450           "addb %%cl, 6(%%ebx)           \n\t"  // err[x+1] += ber * 7 / 16
451            "movl %19, %%ecx               \n\t" // ecx = nerr
452            "leaw (%%eax, %%eax, 4), %%dx  \n\t" // dx = ber * 5
453           "sarw $4, %%dx                 \n\t"  // dx = ber * 5 / 16
454           "addb %%dl, 2(%%ecx)           \n\t"  // nerr[x] += ber * 5 / 16
455            "leaw (%%eax, %%eax, 2), %%dx  \n\t" // dx = ber * 3
456           "sarw $4, %%dx                 \n\t"  // dx = ber * 3 / 16
457           "addb %%dl, -4(%%ecx)          \n\t"  // nerr[x-1] += ber * 3 / 16
458            "sarw $4, %%ax                 \n\t" // ax = ber / 16
459           "movb %%al, 6(%%ecx)           \n\t"  // nerr[x+1] = ber / 16
460            "andl $0xffff, %%eax           \n\t"
461           // depends on eax & 0xffff0000 == 0
462           // calculate the index of the value of the pixel
463           "movw %16, %%ax                \n\t"  // ax = rr
464           "mulb %15                      \n\t"  // ax = cpcpc*rr
465           "movw %%ax, %%cx               \n\t" "movw %17, %%ax                \n\t"     // ax = gg
466           "mulb %9                       \n\t"  // ax = cpc*gg
467           "addw %%cx, %%ax               \n\t"  // ax = cpc*gg + cpcpc*rr
468           "addw %18, %%ax                \n\t"  // ax = cpcpc*rr + cpc*gg + bb
469            "movl %8, %%ecx                \n\t"
470           //agi
471           "leal (%%ecx, %%eax, 4), %%edx \n\t"
472           //agi
473           "movb (%%edx), %%cl            \n\t"  // cl = pixels[ax]
474           // store the pixel
475           "movl %1, %%eax                \n\t" "movb %%cl, (%%eax)            \n\t"     // *ximage = cl
476           "incl %1                       \n\t"  // ximage++
477           // prepare for next iteration on X
478            "addl $4, %19                  \n\t" // nerr += 4
479           "addl $4, %%ebx                \n\t"  // err += 4
480            "addl %12, %%esi               \n\t" // image->data += bpp
481            "decl %14                      \n\t" // x--
482           "jnz .LoopXb                   \n\t"  // if x>0, goto .LoopX
483            "movl %13, %%eax               \n\t" "addl %%eax, %1                \n\t"    // add extra offset to ximage
484            "jmp .LoopYb                   \n" ".Endb:                                 \n\t" "emms                          \n\t" "popal                         \n\t":: "m" (image),    // %0
485           "m"(ximage),          // %1
486           "m"(err),             // %2
487           "m"(nerr),            // %3
488           "m"(ctable),          // %4
489           "m"(dr),              // %5
490           "m"(dg),              // %6
491           "m"(db),              // %7
492           "m"(pixels),          // %8
493           "m"(cpc),             // %9
494           "m"(width),           // %10
495           "m"(height),          // %11
496           "m"(bytesPerPixel),   // %12
497           "m"(line_offset),     // %13
498           "m"(x),               // %14
499           "m"(cpcpc),           // %15
500           "m"(rr),              // %16
501           "m"(gg),              // %17
502           "m"(bb),              // %18
503           "m"(tmp_err),         // %19
504           "m"(tmp_nerr),        // %20
505           "m"(ndr),             // %21
506           "m"(ndg),             // %22
507           "m"(ndb)              // %23
508             );
509 }
510
511 #endif                          /* ASM_X86 */