A new fix, for some register restoral.
[wmaker-crm.git] / wrlib / x86_specific.c
blobdf8696dde4f467ff8662bb6508c4a9b3217914a1
1 /* x86_convert.c - convert RImage to XImage with x86 optimizations
2 *
3 * Raster graphics library
5 * Copyright (c) 2000 Alfredo K. Kojima
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.
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.
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.
22 #include <config.h>
24 #ifdef ASM_X86
27 #ifdef ASM_X86_MMX
29 int
30 x86_check_mmx()
32 static int result = -1;
34 if (result >= 0)
35 return result;
37 result = 0;
39 asm volatile
40 ("pushal \n" // please don't forget this in any asm
41 "pushfl \n" // check whether cpuid supported
42 "pop %%eax \n"
43 "movl %%eax, %%ebx \n"
44 "xorl $(1<<21), %%eax \n"
45 "pushl %%eax \n"
46 "popfl \n"
47 "pushfl \n"
48 "popl %%eax \n"
49 "xorl %%ebx, %%eax \n"
50 "andl $(1<<21), %%eax \n"
51 "jz .NotPentium \n"
52 "xorl %%eax, %%eax \n" // no eax effect because of the movl below
53 // except reseting flags. is it needed?
54 "movl $1, %%eax \n"
55 "cpuid \n"
56 "test $(1<<23), %%edx \n"
57 "jz .NotMMX \n"
59 "popal \n" // this is needed because the address of
60 "movl $1, %0 \n" // variable %0 may be kept in a register
61 "jmp .noPop \n"
63 ".NotMMX: \n"
64 ".Bye: \n"
65 ".NotPentium: \n"
66 "popal \n"
67 ".noPop: \n"
69 : "=rm" (result));
71 return result;
76 * TODO:
77 * 32/8 24/8 32/16 24/16 32/24 24/24
78 * PPlain YES YES
79 * MMX DONE
82 * - try to align stack (local variable space) into quadword boundary
88 void
89 x86_mmx_TrueColor_32_to_16(unsigned char *image, // 8
90 unsigned short *ximage, // 12
91 short *err, // 16
92 short *nerr, // 20
93 short *rtable, // 24
94 short *gtable, // 28
95 short *btable, // 32
96 int dr, // 36
97 int dg, // 40
98 int db, // 44
99 unsigned int roffs, // 48
100 unsigned int goffs, // 52
101 unsigned int boffs, // 56
102 int width, // 60
103 int height, // 64
104 int line_offset) // 68
107 int x; //-4
108 long long rrggbbaa;// -16
109 long long pixel; //-24
110 short *tmp_err; //-32
111 short *tmp_nerr; //-36
114 asm volatile
116 "subl $128, %esp \n" // alloc some more stack
118 "pushal \n"
120 // pack dr, dg and db into mm6
121 "movl 36(%ebp), %eax \n"
122 "movl 40(%ebp), %ebx \n"
123 "movw %ax, -16(%ebp) \n"
125 "movw %bx, -14(%ebp) \n"
126 "movl 44(%ebp), %eax \n"
127 "movw $0, -10(%ebp) \n"
128 "movw %ax, -12(%ebp) \n"
130 "movq -16(%ebp), %mm6 \n" // dr dg db 0
132 // pack 4|4|4|4 into mm7, for shifting (/16)
133 "movl $0x00040004, -16(%ebp) \n"
134 "movl $0x00040004, -12(%ebp) \n"
135 "movq -16(%ebp), %mm7 \n"
137 // store constant values for using with mmx when dithering
138 "movl $0x00070007, -16(%ebp) \n"
139 "movl $0x00070007, -12(%ebp) \n"
140 "movq -16(%ebp), %mm5 \n"
142 "movl $0x00050005, -16(%ebp) \n"
143 "movl $0x00050005, -12(%ebp) \n"
144 "movq -16(%ebp), %mm4 \n"
146 "movl $0x00030003, -16(%ebp) \n"
147 "movl $0x00030003, -12(%ebp) \n"
148 "movq -16(%ebp), %mm3 \n"
150 // process 1 pixel / cycle, each component treated as 16bit
151 "movl 8(%ebp), %esi \n" // esi = image->data
153 ".LoopYa: \n"
154 "movl 60(%ebp), %eax \n"
155 "movl %eax, -4(%ebp) \n" // x = width
157 "movl 64(%ebp), %eax \n"
158 "decl %eax \n" // y--
159 "movl %eax, 64(%ebp) \n"
160 "js .Enda \n" // if y < 0, goto end
161 "andl $1, %eax \n"
162 "jz .LoopY_1a \n" // if (y&1) goto LoopY_1
164 ".LoopY_0a: \n"
166 "movl 16(%ebp), %ebx \n" // ebx = err
167 "movl %ebx, -36(%ebp) \n" // [-36] = err
168 "movl 20(%ebp), %eax \n" //
169 "movl %eax, -32(%ebp) \n" // [-32] = nerr
171 "jmp .LoopXa \n"
173 ".LoopY_1a: \n"
175 "movl 20(%ebp), %ebx \n" // ebx = nerr
176 "movl %ebx, -36(%ebp) \n" // [-36] = nerr
177 "movl 16(%ebp), %eax \n" //
178 "movl %eax, -32(%ebp) \n" // [-32] = eerr
181 ".LoopXa: \n"
183 // calculate errors and pixel components
185 // depend on ebx, esi, mm6
186 "movq (%ebx), %mm1 \n" // mm1 = error[0..3]
187 "punpcklbw (%esi), %mm0 \n" // mm0 = image->data[0..3]
188 "psrlw $8, %mm0 \n" // fixup mm0
189 "paddusb %mm1, %mm0 \n" // mm0 = mm0 + mm1 (sat. to 255)
190 "movq %mm0, -24(%ebp) \n" // save the pixel
192 "movzwl -24(%ebp), %ecx \n" // ecx = pixel.red
193 "movl 24(%ebp), %edi \n" // edi = rtable
194 "leal (%edi, %ecx, 2), %eax \n" // eax = &rtable[pixel.red]
195 "movl (%eax), %edx \n" // edx = rtable[pixel.red]
196 "movw %dx, -16(%ebp) \n" // save rr
198 "movzwl -22(%ebp), %ecx \n" // ecx = pixel.green
199 "movl 28(%ebp), %edi \n" // edi = gtable
200 "leal (%edi, %ecx, 2), %eax \n" // eax = &gtable[pixel.green]
201 "movl (%eax), %edx \n" // ebx = gtable[pixel.green]
202 "movw %dx, -14(%ebp) \n" // save gg
204 "movzwl -20(%ebp), %ecx \n" // ecx = pixel.blue
205 "movl 32(%ebp), %edi \n" // ebx = btable
206 "leal (%edi, %ecx, 2), %eax \n" // eax = &btable[pixel.blue]
207 "movl (%eax), %edx \n" // ecx = btable[pixel.blue]
208 "movw %dx, -12(%ebp) \n" // save bb
210 "movw $0, -10(%ebp) \n" // save dummy aa
212 "movq -16(%ebp), %mm1 \n" // load mm1 with rrggbbaa
213 "pmullw %mm6, %mm1 \n" // mm1 = rr*dr|...
214 "psubsw %mm1, %mm0 \n" // error = pixel - mm1
217 // distribute the error
219 // depend on mm0, mm7, mm3, mm4, mm5
221 "movl -36(%ebp), %ebx \n"
223 "movq %mm0, %mm1 \n"
224 "pmullw %mm5, %mm1 \n" // mm1 = mm1*7
225 "psrlw %mm7, %mm1 \n" // mm1 = mm1/16
226 "paddw 8(%ebx), %mm1 \n"
227 "movq %mm1, 8(%ebx) \n" // err[x+1,y] = rer*7/16
230 "movl -32(%ebp), %ebx \n"
232 "movq %mm0, %mm1 \n"
233 "pmullw %mm4, %mm1 \n" // mm1 = mm1*5
234 "psrlw %mm7, %mm1 \n" // mm1 = mm1/16
235 "paddw -8(%ebx), %mm1 \n"
236 "movq %mm1, -8(%ebx) \n" // err[x-1,y+1] += rer*3/16
238 "movq %mm0, %mm1 \n"
239 "pmullw %mm3, %mm1 \n" // mm1 = mm1*3
240 "psrlw %mm7, %mm1 \n" // mm1 = mm1/16
241 "paddw 8(%ebx), %mm1 \n"
242 "movq %mm1, (%ebx) \n" // err[x,y+1] += rer*5/16
244 "psrlw %mm7, %mm0 \n" // mm0 = mm0/16
245 "movq %mm0, 8(%ebx) \n" // err[x+1,y+1] = rer/16
248 // calculate final pixel value and store
249 "movl 48(%ebp), %ecx \n"
250 "movw -16(%ebp), %ax \n"
251 "shlw %cl, %ax \n" //NP* ax = r<<roffs
253 "movl 52(%ebp), %ecx \n"
254 "movw -14(%ebp), %bx \n"
255 "shlw %cl, %bx \n" //NP*
256 "orw %bx, %ax \n"
258 "movl 56(%ebp), %ecx \n"
259 "movw -12(%ebp), %bx \n"
260 "shlw %cl, %bx \n" //NP*
261 "orw %bx, %ax \n"
263 "movl 12(%ebp), %edx \n"
264 "movw %ax, (%edx) \n"
265 "addl $2, %edx \n" // increment ximage
266 "movl %edx, 12(%ebp) \n"
268 // prepare for next iteration on X
270 "addl $8, -32(%ebp) \n" // nerr += 8
272 "movl -36(%ebp), %ebx \n"
273 "addl $8, %ebx \n"
274 "movl %ebx, -36(%ebp) \n" // ebx = err += 8
277 // Note: in the last pixel, this would cause an invalid memory access
278 // because, punpcklbw is used (which reads 8 bytes) and the last
279 // pixel is only 4 bytes. This is no problem because the image data
280 // was allocated with extra 4 bytes when created.
281 "addl $4, %esi \n" // image->data += 4
284 "decl -4(%ebp) \n" // x--
285 "jnz .LoopXa \n" // if x>0, goto .LoopX
288 // depend on edx
289 "addl 68(%ebp), %edx \n" // add extra offset to ximage
290 "movl %edx, 12(%ebp) \n"
293 "jmp .LoopYa \n"
295 ".Enda: \n" // THE END
297 "emms \n"
299 "popal \n"
304 #endif /* ASM_X86_MMX */
306 #if 0
308 /* convert and dither the image to XImage */
309 for (y=0; y<image->height; y++) {
310 nerr[0] = 0;
311 nerr[1] = 0;
312 nerr[2] = 0;
313 for (x=0; x<image->width*3; x+=3, ptr+=channels) {
315 /* reduce pixel */
316 pixel = *ptr + err[x];
317 if (pixel<0) pixel=0; else if (pixel>0xff) pixel=0xff;
318 r = rtable[pixel];
319 /* calc error */
320 rer = pixel - r*dr;
322 /* reduce pixel */
323 pixel = *(ptr+1) + err[x+1];
324 if (pixel<0) pixel=0; else if (pixel>0xff) pixel=0xff;
325 g = gtable[pixel];
326 /* calc error */
327 ger = pixel - g*dg;
329 /* reduce pixel */
330 pixel = *(ptr+2) + err[x+2];
331 if (pixel<0) pixel=0; else if (pixel>0xff) pixel=0xff;
332 b = btable[pixel];
333 /* calc error */
334 ber = pixel - b*db;
336 *optr++ = pixels[r*cpcpc + g*cpc + b];
338 /* distribute error */
339 r = (rer*3)/8;
340 g = (ger*3)/8;
341 b = (ber*3)/8;
342 /* x+1, y */
343 err[x+3*1]+=r;
344 err[x+1+3*1]+=g;
345 err[x+2+3*1]+=b;
346 /* x, y+1 */
347 nerr[x]+=r;
348 nerr[x+1]+=g;
349 nerr[x+2]+=b;
350 /* x+1, y+1 */
351 nerr[x+3*1]=rer-2*r;
352 nerr[x+1+3*1]=ger-2*g;
353 nerr[x+2+3*1]=ber-2*b;
355 /* skip to next line */
356 terr = err;
357 err = nerr;
358 nerr = terr;
360 optr += ximg->image->bytes_per_line - image->width;
363 #endif
366 void
367 x86_PseudoColor_32_to_8(unsigned char *image, // 8
368 unsigned char *ximage, // 12
369 char *err, // 16
370 char *nerr, // 20
371 short *rtable, // 24
372 short *gtable, // 28
373 short *btable, // 32
374 int dr, // 36
375 int dg, // 40
376 int db, // 44
377 unsigned long *pixels, // 48
378 int cpc, // 52
379 int width, // 56
380 int height, // 60
381 int line_offset) // 64
383 asm volatile
385 "andl $-8, %ebp \n"
386 "subl $128, %esp \n" // alloc some stack space
387 "pushal \n"
389 // process 1 pixel / cycle, each component treated as 16bit
390 "movl 8(%ebp), %esi \n" // esi = image->data
392 ".LoopYb: \n"
393 "movl 56(%ebp), %eax \n"
394 "movl %eax, -4(%ebp) \n" // x = width
396 "movl 60(%ebp), %eax \n"
397 "decl %eax \n" // y--
398 "movl %eax, 64(%ebp) \n"
399 "js .Endb \n" // if y < 0, goto end
400 "andl $1, %eax \n"
401 "jz .LoopY_1b \n" // if (y&1) goto LoopY_1
403 ".LoopY_0b: \n"
405 "movl 16(%ebp), %ebx \n" // ebx = err
406 "movl %ebx, -36(%ebp) \n" // [-36] = err
407 "movl 20(%ebp), %eax \n" //
408 "movl %eax, -32(%ebp) \n" // [-32] = nerr
410 "movl $0, -32(%ebp) \n" // init error of nerr[0] to 0
412 "jmp .LoopXb \n"
414 ".LoopY_1b: \n"
416 "movl 20(%ebp), %ebx \n" // ebx = nerr
417 "movl %ebx, -36(%ebp) \n" // [-36] = nerr
418 "movl 16(%ebp), %eax \n" //
419 "movl %eax, -32(%ebp) \n" // [-32] = err
421 "movl $0, -32(%ebp) \n" // init error of nerr[0] to 0
423 ".LoopXb: \n"
425 "movl (%esi), %edx \n" // fetch a pixel
427 // "movl \n"
431 ".Endb: \n"
433 "popal \n"
439 #endif /* ASM_X86 */