]> git.saurik.com Git - wxWidgets.git/blob - src/png/pngvcrd.c
Implement mnemnic support for wxToggleButton.
[wxWidgets.git] / src / png / pngvcrd.c
1 /* pngvcrd.c - mixed C/assembler version of utilities to read a PNG file
2 *
3 * For Intel x86 CPU and Microsoft Visual C++ compiler
4 *
5 * libpng version 1.2.7 - September 12, 2004
6 * For conditions of distribution and use, see copyright notice in png.h
7 * Copyright (c) 1998-2004 Glenn Randers-Pehrson
8 * Copyright (c) 1998, Intel Corporation
9 *
10 * Contributed by Nirav Chhatrapati, Intel Corporation, 1998
11 * Interface to libpng contributed by Gilles Vollant, 1999
12 *
13 *
14 * In png_do_read_interlace() in libpng versions 1.0.3a through 1.0.4d,
15 * a sign error in the post-MMX cleanup code for each pixel_depth resulted
16 * in bad pixels at the beginning of some rows of some images, and also
17 * (due to out-of-range memory reads and writes) caused heap corruption
18 * when compiled with MSVC 6.0. The error was fixed in version 1.0.4e.
19 *
20 * [png_read_filter_row_mmx_avg() bpp == 2 bugfix, GRR 20000916]
21 *
22 * [runtime MMX configuration, GRR 20010102]
23 *
24 */
25
26 #define PNG_INTERNAL
27 #include "png.h"
28
29 #if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_USE_PNGVCRD)
30
31 static int mmx_supported=2;
32
33
34 int PNGAPI
35 png_mmx_support(void)
36 {
37 int mmx_supported_local = 0;
38 _asm {
39 push ebx /*CPUID will trash these */
40 push ecx
41 push edx
42
43 pushfd /*Save Eflag to stack */
44 pop eax /*Get Eflag from stack into eax */
45 mov ecx, eax /*Make another copy of Eflag in ecx */
46 xor eax, 0x200000 /*Toggle ID bit in Eflag [i.e. bit(21)] */
47 push eax /*Save modified Eflag back to stack */
48
49 popfd /*Restored modified value back to Eflag reg */
50 pushfd /*Save Eflag to stack */
51 pop eax /*Get Eflag from stack */
52 push ecx /* save original Eflag to stack */
53 popfd /* restore original Eflag */
54 xor eax, ecx /*Compare the new Eflag with the original Eflag */
55 jz NOT_SUPPORTED /*If the same, CPUID instruction is not supported, */
56 /*skip following instructions and jump to */
57 /*NOT_SUPPORTED label */
58
59 xor eax, eax /*Set eax to zero */
60
61 _asm _emit 0x0f /*CPUID instruction (two bytes opcode) */
62 _asm _emit 0xa2
63
64 cmp eax, 1 /*make sure eax return non-zero value */
65 jl NOT_SUPPORTED /*If eax is zero, mmx not supported */
66
67 xor eax, eax /*set eax to zero */
68 inc eax /*Now increment eax to 1. This instruction is */
69 /*faster than the instruction "mov eax, 1" */
70
71 _asm _emit 0x0f /*CPUID instruction */
72 _asm _emit 0xa2
73
74 and edx, 0x00800000 /*mask out all bits but mmx bit(24) */
75 cmp edx, 0 /* 0 = mmx not supported */
76 jz NOT_SUPPORTED /* non-zero = Yes, mmx IS supported */
77
78 mov mmx_supported_local, 1 /*set return value to 1 */
79
80 NOT_SUPPORTED:
81 mov eax, mmx_supported_local /*move return value to eax */
82 pop edx /*CPUID trashed these */
83 pop ecx
84 pop ebx
85 }
86
87 /*mmx_supported_local=0; // test code for force don't support MMX */
88 /*printf("MMX : %u (1=MMX supported)\n",mmx_supported_local); */
89
90 mmx_supported = mmx_supported_local;
91 return mmx_supported_local;
92 }
93
94 /* Combines the row recently read in with the previous row.
95 This routine takes care of alpha and transparency if requested.
96 This routine also handles the two methods of progressive display
97 of interlaced images, depending on the mask value.
98 The mask value describes which pixels are to be combined with
99 the row. The pattern always repeats every 8 pixels, so just 8
100 bits are needed. A one indicates the pixel is to be combined; a
101 zero indicates the pixel is to be skipped. This is in addition
102 to any alpha or transparency value associated with the pixel. If
103 you want all pixels to be combined, pass 0xff (255) in mask. */
104
105 /* Use this routine for x86 platform - uses faster MMX routine if machine
106 supports MMX */
107
108 void /* PRIVATE */
109 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
110 {
111 #ifdef PNG_USE_LOCAL_ARRAYS
112 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
113 #endif
114
115 png_debug(1,"in png_combine_row_asm\n");
116
117 if (mmx_supported == 2) {
118 #if !defined(PNG_1_0_X)
119 /* this should have happened in png_init_mmx_flags() already */
120 png_warning(png_ptr, "asm_flags may not have been initialized");
121 #endif
122 png_mmx_support();
123 }
124
125 if (mask == 0xff)
126 {
127 png_memcpy(row, png_ptr->row_buf + 1,
128 (png_size_t)PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
129 png_ptr->width));
130 }
131 /* GRR: add "else if (mask == 0)" case?
132 * or does png_combine_row() not even get called in that case? */
133 else
134 {
135 switch (png_ptr->row_info.pixel_depth)
136 {
137 case 1:
138 {
139 png_bytep sp;
140 png_bytep dp;
141 int s_inc, s_start, s_end;
142 int m;
143 int shift;
144 png_uint_32 i;
145
146 sp = png_ptr->row_buf + 1;
147 dp = row;
148 m = 0x80;
149 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
150 if (png_ptr->transformations & PNG_PACKSWAP)
151 {
152 s_start = 0;
153 s_end = 7;
154 s_inc = 1;
155 }
156 else
157 #endif
158 {
159 s_start = 7;
160 s_end = 0;
161 s_inc = -1;
162 }
163
164 shift = s_start;
165
166 for (i = 0; i < png_ptr->width; i++)
167 {
168 if (m & mask)
169 {
170 int value;
171
172 value = (*sp >> shift) & 0x1;
173 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
174 *dp |= (png_byte)(value << shift);
175 }
176
177 if (shift == s_end)
178 {
179 shift = s_start;
180 sp++;
181 dp++;
182 }
183 else
184 shift += s_inc;
185
186 if (m == 1)
187 m = 0x80;
188 else
189 m >>= 1;
190 }
191 break;
192 }
193
194 case 2:
195 {
196 png_bytep sp;
197 png_bytep dp;
198 int s_start, s_end, s_inc;
199 int m;
200 int shift;
201 png_uint_32 i;
202 int value;
203
204 sp = png_ptr->row_buf + 1;
205 dp = row;
206 m = 0x80;
207 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
208 if (png_ptr->transformations & PNG_PACKSWAP)
209 {
210 s_start = 0;
211 s_end = 6;
212 s_inc = 2;
213 }
214 else
215 #endif
216 {
217 s_start = 6;
218 s_end = 0;
219 s_inc = -2;
220 }
221
222 shift = s_start;
223
224 for (i = 0; i < png_ptr->width; i++)
225 {
226 if (m & mask)
227 {
228 value = (*sp >> shift) & 0x3;
229 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
230 *dp |= (png_byte)(value << shift);
231 }
232
233 if (shift == s_end)
234 {
235 shift = s_start;
236 sp++;
237 dp++;
238 }
239 else
240 shift += s_inc;
241 if (m == 1)
242 m = 0x80;
243 else
244 m >>= 1;
245 }
246 break;
247 }
248
249 case 4:
250 {
251 png_bytep sp;
252 png_bytep dp;
253 int s_start, s_end, s_inc;
254 int m;
255 int shift;
256 png_uint_32 i;
257 int value;
258
259 sp = png_ptr->row_buf + 1;
260 dp = row;
261 m = 0x80;
262 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
263 if (png_ptr->transformations & PNG_PACKSWAP)
264 {
265 s_start = 0;
266 s_end = 4;
267 s_inc = 4;
268 }
269 else
270 #endif
271 {
272 s_start = 4;
273 s_end = 0;
274 s_inc = -4;
275 }
276 shift = s_start;
277
278 for (i = 0; i < png_ptr->width; i++)
279 {
280 if (m & mask)
281 {
282 value = (*sp >> shift) & 0xf;
283 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
284 *dp |= (png_byte)(value << shift);
285 }
286
287 if (shift == s_end)
288 {
289 shift = s_start;
290 sp++;
291 dp++;
292 }
293 else
294 shift += s_inc;
295 if (m == 1)
296 m = 0x80;
297 else
298 m >>= 1;
299 }
300 break;
301 }
302
303 case 8:
304 {
305 png_bytep srcptr;
306 png_bytep dstptr;
307 png_uint_32 len;
308 int m;
309 int diff, unmask;
310
311 __int64 mask0=0x0102040810204080;
312
313 #if !defined(PNG_1_0_X)
314 if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
315 /* && mmx_supported */ )
316 #else
317 if (mmx_supported)
318 #endif
319 {
320 srcptr = png_ptr->row_buf + 1;
321 dstptr = row;
322 m = 0x80;
323 unmask = ~mask;
324 len = png_ptr->width &~7; /*reduce to multiple of 8 */
325 diff = png_ptr->width & 7; /*amount lost */
326
327 _asm
328 {
329 movd mm7, unmask /*load bit pattern */
330 psubb mm6,mm6 /*zero mm6 */
331 punpcklbw mm7,mm7
332 punpcklwd mm7,mm7
333 punpckldq mm7,mm7 /*fill register with 8 masks */
334
335 movq mm0,mask0
336
337 pand mm0,mm7 /*nonzero if keep byte */
338 pcmpeqb mm0,mm6 /*zeros->1s, v versa */
339
340 mov ecx,len /*load length of line (pixels) */
341 mov esi,srcptr /*load source */
342 mov ebx,dstptr /*load dest */
343 cmp ecx,0 /*lcr */
344 je mainloop8end
345
346 mainloop8:
347 movq mm4,[esi]
348 pand mm4,mm0
349 movq mm6,mm0
350 pandn mm6,[ebx]
351 por mm4,mm6
352 movq [ebx],mm4
353
354 add esi,8 /*inc by 8 bytes processed */
355 add ebx,8
356 sub ecx,8 /*dec by 8 pixels processed */
357
358 ja mainloop8
359 mainloop8end:
360
361 mov ecx,diff
362 cmp ecx,0
363 jz end8
364
365 mov edx,mask
366 sal edx,24 /*make low byte the high byte */
367
368 secondloop8:
369 sal edx,1 /*move high bit to CF */
370 jnc skip8 /*if CF = 0 */
371 mov al,[esi]
372 mov [ebx],al
373 skip8:
374 inc esi
375 inc ebx
376
377 dec ecx
378 jnz secondloop8
379 end8:
380 emms
381 }
382 }
383 else /* mmx not supported - use modified C routine */
384 {
385 register unsigned int incr1, initial_val, final_val;
386 png_size_t pixel_bytes;
387 png_uint_32 i;
388 register int disp = png_pass_inc[png_ptr->pass];
389 int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
390
391 pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
392 srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
393 pixel_bytes;
394 dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
395 initial_val = offset_table[png_ptr->pass]*pixel_bytes;
396 final_val = png_ptr->width*pixel_bytes;
397 incr1 = (disp)*pixel_bytes;
398 for (i = initial_val; i < final_val; i += incr1)
399 {
400 png_memcpy(dstptr, srcptr, pixel_bytes);
401 srcptr += incr1;
402 dstptr += incr1;
403 }
404 } /* end of else */
405
406 break;
407 } /* end 8 bpp */
408
409 case 16:
410 {
411 png_bytep srcptr;
412 png_bytep dstptr;
413 png_uint_32 len;
414 int unmask, diff;
415 __int64 mask1=0x0101020204040808,
416 mask0=0x1010202040408080;
417
418 #if !defined(PNG_1_0_X)
419 if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
420 /* && mmx_supported */ )
421 #else
422 if (mmx_supported)
423 #endif
424 {
425 srcptr = png_ptr->row_buf + 1;
426 dstptr = row;
427
428 unmask = ~mask;
429 len = (png_ptr->width)&~7;
430 diff = (png_ptr->width)&7;
431 _asm
432 {
433 movd mm7, unmask /*load bit pattern */
434 psubb mm6,mm6 /*zero mm6 */
435 punpcklbw mm7,mm7
436 punpcklwd mm7,mm7
437 punpckldq mm7,mm7 /*fill register with 8 masks */
438
439 movq mm0,mask0
440 movq mm1,mask1
441
442 pand mm0,mm7
443 pand mm1,mm7
444
445 pcmpeqb mm0,mm6
446 pcmpeqb mm1,mm6
447
448 mov ecx,len /*load length of line */
449 mov esi,srcptr /*load source */
450 mov ebx,dstptr /*load dest */
451 cmp ecx,0 /*lcr */
452 jz mainloop16end
453
454 mainloop16:
455 movq mm4,[esi]
456 pand mm4,mm0
457 movq mm6,mm0
458 movq mm7,[ebx]
459 pandn mm6,mm7
460 por mm4,mm6
461 movq [ebx],mm4
462
463 movq mm5,[esi+8]
464 pand mm5,mm1
465 movq mm7,mm1
466 movq mm6,[ebx+8]
467 pandn mm7,mm6
468 por mm5,mm7
469 movq [ebx+8],mm5
470
471 add esi,16 /*inc by 16 bytes processed */
472 add ebx,16
473 sub ecx,8 /*dec by 8 pixels processed */
474
475 ja mainloop16
476
477 mainloop16end:
478 mov ecx,diff
479 cmp ecx,0
480 jz end16
481
482 mov edx,mask
483 sal edx,24 /*make low byte the high byte */
484 secondloop16:
485 sal edx,1 /*move high bit to CF */
486 jnc skip16 /*if CF = 0 */
487 mov ax,[esi]
488 mov [ebx],ax
489 skip16:
490 add esi,2
491 add ebx,2
492
493 dec ecx
494 jnz secondloop16
495 end16:
496 emms
497 }
498 }
499 else /* mmx not supported - use modified C routine */
500 {
501 register unsigned int incr1, initial_val, final_val;
502 png_size_t pixel_bytes;
503 png_uint_32 i;
504 register int disp = png_pass_inc[png_ptr->pass];
505 int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
506
507 pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
508 srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
509 pixel_bytes;
510 dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
511 initial_val = offset_table[png_ptr->pass]*pixel_bytes;
512 final_val = png_ptr->width*pixel_bytes;
513 incr1 = (disp)*pixel_bytes;
514 for (i = initial_val; i < final_val; i += incr1)
515 {
516 png_memcpy(dstptr, srcptr, pixel_bytes);
517 srcptr += incr1;
518 dstptr += incr1;
519 }
520 } /* end of else */
521
522 break;
523 } /* end 16 bpp */
524
525 case 24:
526 {
527 png_bytep srcptr;
528 png_bytep dstptr;
529 png_uint_32 len;
530 int unmask, diff;
531
532 __int64 mask2=0x0101010202020404, /*24bpp */
533 mask1=0x0408080810101020,
534 mask0=0x2020404040808080;
535
536 srcptr = png_ptr->row_buf + 1;
537 dstptr = row;
538
539 unmask = ~mask;
540 len = (png_ptr->width)&~7;
541 diff = (png_ptr->width)&7;
542
543 #if !defined(PNG_1_0_X)
544 if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
545 /* && mmx_supported */ )
546 #else
547 if (mmx_supported)
548 #endif
549 {
550 _asm
551 {
552 movd mm7, unmask /*load bit pattern */
553 psubb mm6,mm6 /*zero mm6 */
554 punpcklbw mm7,mm7
555 punpcklwd mm7,mm7
556 punpckldq mm7,mm7 /*fill register with 8 masks */
557
558 movq mm0,mask0
559 movq mm1,mask1
560 movq mm2,mask2
561
562 pand mm0,mm7
563 pand mm1,mm7
564 pand mm2,mm7
565
566 pcmpeqb mm0,mm6
567 pcmpeqb mm1,mm6
568 pcmpeqb mm2,mm6
569
570 mov ecx,len /*load length of line */
571 mov esi,srcptr /*load source */
572 mov ebx,dstptr /*load dest */
573 cmp ecx,0
574 jz mainloop24end
575
576 mainloop24:
577 movq mm4,[esi]
578 pand mm4,mm0
579 movq mm6,mm0
580 movq mm7,[ebx]
581 pandn mm6,mm7
582 por mm4,mm6
583 movq [ebx],mm4
584
585
586 movq mm5,[esi+8]
587 pand mm5,mm1
588 movq mm7,mm1
589 movq mm6,[ebx+8]
590 pandn mm7,mm6
591 por mm5,mm7
592 movq [ebx+8],mm5
593
594 movq mm6,[esi+16]
595 pand mm6,mm2
596 movq mm4,mm2
597 movq mm7,[ebx+16]
598 pandn mm4,mm7
599 por mm6,mm4
600 movq [ebx+16],mm6
601
602 add esi,24 /*inc by 24 bytes processed */
603 add ebx,24
604 sub ecx,8 /*dec by 8 pixels processed */
605
606 ja mainloop24
607
608 mainloop24end:
609 mov ecx,diff
610 cmp ecx,0
611 jz end24
612
613 mov edx,mask
614 sal edx,24 /*make low byte the high byte */
615 secondloop24:
616 sal edx,1 /*move high bit to CF */
617 jnc skip24 /*if CF = 0 */
618 mov ax,[esi]
619 mov [ebx],ax
620 xor eax,eax
621 mov al,[esi+2]
622 mov [ebx+2],al
623 skip24:
624 add esi,3
625 add ebx,3
626
627 dec ecx
628 jnz secondloop24
629
630 end24:
631 emms
632 }
633 }
634 else /* mmx not supported - use modified C routine */
635 {
636 register unsigned int incr1, initial_val, final_val;
637 png_size_t pixel_bytes;
638 png_uint_32 i;
639 register int disp = png_pass_inc[png_ptr->pass];
640 int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
641
642 pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
643 srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
644 pixel_bytes;
645 dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
646 initial_val = offset_table[png_ptr->pass]*pixel_bytes;
647 final_val = png_ptr->width*pixel_bytes;
648 incr1 = (disp)*pixel_bytes;
649 for (i = initial_val; i < final_val; i += incr1)
650 {
651 png_memcpy(dstptr, srcptr, pixel_bytes);
652 srcptr += incr1;
653 dstptr += incr1;
654 }
655 } /* end of else */
656
657 break;
658 } /* end 24 bpp */
659
660 case 32:
661 {
662 png_bytep srcptr;
663 png_bytep dstptr;
664 png_uint_32 len;
665 int unmask, diff;
666
667 __int64 mask3=0x0101010102020202, /*32bpp */
668 mask2=0x0404040408080808,
669 mask1=0x1010101020202020,
670 mask0=0x4040404080808080;
671
672 srcptr = png_ptr->row_buf + 1;
673 dstptr = row;
674
675 unmask = ~mask;
676 len = (png_ptr->width)&~7;
677 diff = (png_ptr->width)&7;
678
679 #if !defined(PNG_1_0_X)
680 if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
681 /* && mmx_supported */ )
682 #else
683 if (mmx_supported)
684 #endif
685 {
686 _asm
687 {
688 movd mm7, unmask /*load bit pattern */
689 psubb mm6,mm6 /*zero mm6 */
690 punpcklbw mm7,mm7
691 punpcklwd mm7,mm7
692 punpckldq mm7,mm7 /*fill register with 8 masks */
693
694 movq mm0,mask0
695 movq mm1,mask1
696 movq mm2,mask2
697 movq mm3,mask3
698
699 pand mm0,mm7
700 pand mm1,mm7
701 pand mm2,mm7
702 pand mm3,mm7
703
704 pcmpeqb mm0,mm6
705 pcmpeqb mm1,mm6
706 pcmpeqb mm2,mm6
707 pcmpeqb mm3,mm6
708
709 mov ecx,len /*load length of line */
710 mov esi,srcptr /*load source */
711 mov ebx,dstptr /*load dest */
712
713 cmp ecx,0 /*lcr */
714 jz mainloop32end
715
716 mainloop32:
717 movq mm4,[esi]
718 pand mm4,mm0
719 movq mm6,mm0
720 movq mm7,[ebx]
721 pandn mm6,mm7
722 por mm4,mm6
723 movq [ebx],mm4
724
725 movq mm5,[esi+8]
726 pand mm5,mm1
727 movq mm7,mm1
728 movq mm6,[ebx+8]
729 pandn mm7,mm6
730 por mm5,mm7
731 movq [ebx+8],mm5
732
733 movq mm6,[esi+16]
734 pand mm6,mm2
735 movq mm4,mm2
736 movq mm7,[ebx+16]
737 pandn mm4,mm7
738 por mm6,mm4
739 movq [ebx+16],mm6
740
741 movq mm7,[esi+24]
742 pand mm7,mm3
743 movq mm5,mm3
744 movq mm4,[ebx+24]
745 pandn mm5,mm4
746 por mm7,mm5
747 movq [ebx+24],mm7
748
749 add esi,32 /*inc by 32 bytes processed */
750 add ebx,32
751 sub ecx,8 /*dec by 8 pixels processed */
752
753 ja mainloop32
754
755 mainloop32end:
756 mov ecx,diff
757 cmp ecx,0
758 jz end32
759
760 mov edx,mask
761 sal edx,24 /*make low byte the high byte */
762 secondloop32:
763 sal edx,1 /*move high bit to CF */
764 jnc skip32 /*if CF = 0 */
765 mov eax,[esi]
766 mov [ebx],eax
767 skip32:
768 add esi,4
769 add ebx,4
770
771 dec ecx
772 jnz secondloop32
773
774 end32:
775 emms
776 }
777 }
778 else /* mmx _not supported - Use modified C routine */
779 {
780 register unsigned int incr1, initial_val, final_val;
781 png_size_t pixel_bytes;
782 png_uint_32 i;
783 register int disp = png_pass_inc[png_ptr->pass];
784 int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
785
786 pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
787 srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
788 pixel_bytes;
789 dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
790 initial_val = offset_table[png_ptr->pass]*pixel_bytes;
791 final_val = png_ptr->width*pixel_bytes;
792 incr1 = (disp)*pixel_bytes;
793 for (i = initial_val; i < final_val; i += incr1)
794 {
795 png_memcpy(dstptr, srcptr, pixel_bytes);
796 srcptr += incr1;
797 dstptr += incr1;
798 }
799 } /* end of else */
800
801 break;
802 } /* end 32 bpp */
803
804 case 48:
805 {
806 png_bytep srcptr;
807 png_bytep dstptr;
808 png_uint_32 len;
809 int unmask, diff;
810
811 __int64 mask5=0x0101010101010202,
812 mask4=0x0202020204040404,
813 mask3=0x0404080808080808,
814 mask2=0x1010101010102020,
815 mask1=0x2020202040404040,
816 mask0=0x4040808080808080;
817
818 #if !defined(PNG_1_0_X)
819 if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
820 /* && mmx_supported */ )
821 #else
822 if (mmx_supported)
823 #endif
824 {
825 srcptr = png_ptr->row_buf + 1;
826 dstptr = row;
827
828 unmask = ~mask;
829 len = (png_ptr->width)&~7;
830 diff = (png_ptr->width)&7;
831 _asm
832 {
833 movd mm7, unmask /*load bit pattern */
834 psubb mm6,mm6 /*zero mm6 */
835 punpcklbw mm7,mm7
836 punpcklwd mm7,mm7
837 punpckldq mm7,mm7 /*fill register with 8 masks */
838
839 movq mm0,mask0
840 movq mm1,mask1
841 movq mm2,mask2
842 movq mm3,mask3
843 movq mm4,mask4
844 movq mm5,mask5
845
846 pand mm0,mm7
847 pand mm1,mm7
848 pand mm2,mm7
849 pand mm3,mm7
850 pand mm4,mm7
851 pand mm5,mm7
852
853 pcmpeqb mm0,mm6
854 pcmpeqb mm1,mm6
855 pcmpeqb mm2,mm6
856 pcmpeqb mm3,mm6
857 pcmpeqb mm4,mm6
858 pcmpeqb mm5,mm6
859
860 mov ecx,len /*load length of line */
861 mov esi,srcptr /*load source */
862 mov ebx,dstptr /*load dest */
863
864 cmp ecx,0
865 jz mainloop48end
866
867 mainloop48:
868 movq mm7,[esi]
869 pand mm7,mm0
870 movq mm6,mm0
871 pandn mm6,[ebx]
872 por mm7,mm6
873 movq [ebx],mm7
874
875 movq mm6,[esi+8]
876 pand mm6,mm1
877 movq mm7,mm1
878 pandn mm7,[ebx+8]
879 por mm6,mm7
880 movq [ebx+8],mm6
881
882 movq mm6,[esi+16]
883 pand mm6,mm2
884 movq mm7,mm2
885 pandn mm7,[ebx+16]
886 por mm6,mm7
887 movq [ebx+16],mm6
888
889 movq mm7,[esi+24]
890 pand mm7,mm3
891 movq mm6,mm3
892 pandn mm6,[ebx+24]
893 por mm7,mm6
894 movq [ebx+24],mm7
895
896 movq mm6,[esi+32]
897 pand mm6,mm4
898 movq mm7,mm4
899 pandn mm7,[ebx+32]
900 por mm6,mm7
901 movq [ebx+32],mm6
902
903 movq mm7,[esi+40]
904 pand mm7,mm5
905 movq mm6,mm5
906 pandn mm6,[ebx+40]
907 por mm7,mm6
908 movq [ebx+40],mm7
909
910 add esi,48 /*inc by 32 bytes processed */
911 add ebx,48
912 sub ecx,8 /*dec by 8 pixels processed */
913
914 ja mainloop48
915 mainloop48end:
916
917 mov ecx,diff
918 cmp ecx,0
919 jz end48
920
921 mov edx,mask
922 sal edx,24 /*make low byte the high byte */
923
924 secondloop48:
925 sal edx,1 /*move high bit to CF */
926 jnc skip48 /*if CF = 0 */
927 mov eax,[esi]
928 mov [ebx],eax
929 skip48:
930 add esi,4
931 add ebx,4
932
933 dec ecx
934 jnz secondloop48
935
936 end48:
937 emms
938 }
939 }
940 else /* mmx _not supported - Use modified C routine */
941 {
942 register unsigned int incr1, initial_val, final_val;
943 png_size_t pixel_bytes;
944 png_uint_32 i;
945 register int disp = png_pass_inc[png_ptr->pass];
946 int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
947
948 pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
949 srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
950 pixel_bytes;
951 dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
952 initial_val = offset_table[png_ptr->pass]*pixel_bytes;
953 final_val = png_ptr->width*pixel_bytes;
954 incr1 = (disp)*pixel_bytes;
955 for (i = initial_val; i < final_val; i += incr1)
956 {
957 png_memcpy(dstptr, srcptr, pixel_bytes);
958 srcptr += incr1;
959 dstptr += incr1;
960 }
961 } /* end of else */
962
963 break;
964 } /* end 48 bpp */
965
966 default:
967 {
968 png_bytep sptr;
969 png_bytep dp;
970 png_size_t pixel_bytes;
971 int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
972 unsigned int i;
973 register int disp = png_pass_inc[png_ptr->pass]; /* get the offset */
974 register unsigned int incr1, initial_val, final_val;
975
976 pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
977 sptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
978 pixel_bytes;
979 dp = row + offset_table[png_ptr->pass]*pixel_bytes;
980 initial_val = offset_table[png_ptr->pass]*pixel_bytes;
981 final_val = png_ptr->width*pixel_bytes;
982 incr1 = (disp)*pixel_bytes;
983 for (i = initial_val; i < final_val; i += incr1)
984 {
985 png_memcpy(dp, sptr, pixel_bytes);
986 sptr += incr1;
987 dp += incr1;
988 }
989 break;
990 }
991 } /* end switch (png_ptr->row_info.pixel_depth) */
992 } /* end if (non-trivial mask) */
993
994 } /* end png_combine_row() */
995
996
997 #if defined(PNG_READ_INTERLACING_SUPPORTED)
998
999 void /* PRIVATE */
1000 png_do_read_interlace(png_structp png_ptr)
1001 {
1002 png_row_infop row_info = &(png_ptr->row_info);
1003 png_bytep row = png_ptr->row_buf + 1;
1004 int pass = png_ptr->pass;
1005 png_uint_32 transformations = png_ptr->transformations;
1006 #ifdef PNG_USE_LOCAL_ARRAYS
1007 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
1008 #endif
1009
1010 png_debug(1,"in png_do_read_interlace\n");
1011
1012 if (mmx_supported == 2) {
1013 #if !defined(PNG_1_0_X)
1014 /* this should have happened in png_init_mmx_flags() already */
1015 png_warning(png_ptr, "asm_flags may not have been initialized");
1016 #endif
1017 png_mmx_support();
1018 }
1019
1020 if (row != NULL && row_info != NULL)
1021 {
1022 png_uint_32 final_width;
1023
1024 final_width = row_info->width * png_pass_inc[pass];
1025
1026 switch (row_info->pixel_depth)
1027 {
1028 case 1:
1029 {
1030 png_bytep sp, dp;
1031 int sshift, dshift;
1032 int s_start, s_end, s_inc;
1033 png_byte v;
1034 png_uint_32 i;
1035 int j;
1036
1037 sp = row + (png_size_t)((row_info->width - 1) >> 3);
1038 dp = row + (png_size_t)((final_width - 1) >> 3);
1039 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
1040 if (transformations & PNG_PACKSWAP)
1041 {
1042 sshift = (int)((row_info->width + 7) & 7);
1043 dshift = (int)((final_width + 7) & 7);
1044 s_start = 7;
1045 s_end = 0;
1046 s_inc = -1;
1047 }
1048 else
1049 #endif
1050 {
1051 sshift = 7 - (int)((row_info->width + 7) & 7);
1052 dshift = 7 - (int)((final_width + 7) & 7);
1053 s_start = 0;
1054 s_end = 7;
1055 s_inc = 1;
1056 }
1057
1058 for (i = row_info->width; i; i--)
1059 {
1060 v = (png_byte)((*sp >> sshift) & 0x1);
1061 for (j = 0; j < png_pass_inc[pass]; j++)
1062 {
1063 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
1064 *dp |= (png_byte)(v << dshift);
1065 if (dshift == s_end)
1066 {
1067 dshift = s_start;
1068 dp--;
1069 }
1070 else
1071 dshift += s_inc;
1072 }
1073 if (sshift == s_end)
1074 {
1075 sshift = s_start;
1076 sp--;
1077 }
1078 else
1079 sshift += s_inc;
1080 }
1081 break;
1082 }
1083
1084 case 2:
1085 {
1086 png_bytep sp, dp;
1087 int sshift, dshift;
1088 int s_start, s_end, s_inc;
1089 png_uint_32 i;
1090
1091 sp = row + (png_size_t)((row_info->width - 1) >> 2);
1092 dp = row + (png_size_t)((final_width - 1) >> 2);
1093 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
1094 if (transformations & PNG_PACKSWAP)
1095 {
1096 sshift = (png_size_t)(((row_info->width + 3) & 3) << 1);
1097 dshift = (png_size_t)(((final_width + 3) & 3) << 1);
1098 s_start = 6;
1099 s_end = 0;
1100 s_inc = -2;
1101 }
1102 else
1103 #endif
1104 {
1105 sshift = (png_size_t)((3 - ((row_info->width + 3) & 3)) << 1);
1106 dshift = (png_size_t)((3 - ((final_width + 3) & 3)) << 1);
1107 s_start = 0;
1108 s_end = 6;
1109 s_inc = 2;
1110 }
1111
1112 for (i = row_info->width; i; i--)
1113 {
1114 png_byte v;
1115 int j;
1116
1117 v = (png_byte)((*sp >> sshift) & 0x3);
1118 for (j = 0; j < png_pass_inc[pass]; j++)
1119 {
1120 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
1121 *dp |= (png_byte)(v << dshift);
1122 if (dshift == s_end)
1123 {
1124 dshift = s_start;
1125 dp--;
1126 }
1127 else
1128 dshift += s_inc;
1129 }
1130 if (sshift == s_end)
1131 {
1132 sshift = s_start;
1133 sp--;
1134 }
1135 else
1136 sshift += s_inc;
1137 }
1138 break;
1139 }
1140
1141 case 4:
1142 {
1143 png_bytep sp, dp;
1144 int sshift, dshift;
1145 int s_start, s_end, s_inc;
1146 png_uint_32 i;
1147
1148 sp = row + (png_size_t)((row_info->width - 1) >> 1);
1149 dp = row + (png_size_t)((final_width - 1) >> 1);
1150 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
1151 if (transformations & PNG_PACKSWAP)
1152 {
1153 sshift = (png_size_t)(((row_info->width + 1) & 1) << 2);
1154 dshift = (png_size_t)(((final_width + 1) & 1) << 2);
1155 s_start = 4;
1156 s_end = 0;
1157 s_inc = -4;
1158 }
1159 else
1160 #endif
1161 {
1162 sshift = (png_size_t)((1 - ((row_info->width + 1) & 1)) << 2);
1163 dshift = (png_size_t)((1 - ((final_width + 1) & 1)) << 2);
1164 s_start = 0;
1165 s_end = 4;
1166 s_inc = 4;
1167 }
1168
1169 for (i = row_info->width; i; i--)
1170 {
1171 png_byte v;
1172 int j;
1173
1174 v = (png_byte)((*sp >> sshift) & 0xf);
1175 for (j = 0; j < png_pass_inc[pass]; j++)
1176 {
1177 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
1178 *dp |= (png_byte)(v << dshift);
1179 if (dshift == s_end)
1180 {
1181 dshift = s_start;
1182 dp--;
1183 }
1184 else
1185 dshift += s_inc;
1186 }
1187 if (sshift == s_end)
1188 {
1189 sshift = s_start;
1190 sp--;
1191 }
1192 else
1193 sshift += s_inc;
1194 }
1195 break;
1196 }
1197
1198 default: /* This is the place where the routine is modified */
1199 {
1200 __int64 const4 = 0x0000000000FFFFFF;
1201 /* __int64 const5 = 0x000000FFFFFF0000; // unused... */
1202 __int64 const6 = 0x00000000000000FF;
1203 png_bytep sptr, dp;
1204 png_uint_32 i;
1205 png_size_t pixel_bytes;
1206 int width = row_info->width;
1207
1208 pixel_bytes = (row_info->pixel_depth >> 3);
1209
1210 sptr = row + (width - 1) * pixel_bytes;
1211 dp = row + (final_width - 1) * pixel_bytes;
1212 /* New code by Nirav Chhatrapati - Intel Corporation */
1213 /* sign fix by GRR */
1214 /* NOTE: there is NO MMX code for 48-bit and 64-bit images */
1215
1216 // use MMX routine if machine supports it
1217 #if !defined(PNG_1_0_X)
1218 if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_INTERLACE)
1219 /* && mmx_supported */ )
1220 #else
1221 if (mmx_supported)
1222 #endif
1223 {
1224 if (pixel_bytes == 3)
1225 {
1226 if (((pass == 0) || (pass == 1)) && width)
1227 {
1228 _asm
1229 {
1230 mov esi, sptr
1231 mov edi, dp
1232 mov ecx, width
1233 sub edi, 21 /* (png_pass_inc[pass] - 1)*pixel_bytes */
1234 loop_pass0:
1235 movd mm0, [esi] ; X X X X X v2 v1 v0
1236 pand mm0, const4 ; 0 0 0 0 0 v2 v1 v0
1237 movq mm1, mm0 ; 0 0 0 0 0 v2 v1 v0
1238 psllq mm0, 16 ; 0 0 0 v2 v1 v0 0 0
1239 movq mm2, mm0 ; 0 0 0 v2 v1 v0 0 0
1240 psllq mm0, 24 ; v2 v1 v0 0 0 0 0 0
1241 psrlq mm1, 8 ; 0 0 0 0 0 0 v2 v1
1242 por mm0, mm2 ; v2 v1 v0 v2 v1 v0 0 0
1243 por mm0, mm1 ; v2 v1 v0 v2 v1 v0 v2 v1
1244 movq mm3, mm0 ; v2 v1 v0 v2 v1 v0 v2 v1
1245 psllq mm0, 16 ; v0 v2 v1 v0 v2 v1 0 0
1246 movq mm4, mm3 ; v2 v1 v0 v2 v1 v0 v2 v1
1247 punpckhdq mm3, mm0 ; v0 v2 v1 v0 v2 v1 v0 v2
1248 movq [edi+16] , mm4
1249 psrlq mm0, 32 ; 0 0 0 0 v0 v2 v1 v0
1250 movq [edi+8] , mm3
1251 punpckldq mm0, mm4 ; v1 v0 v2 v1 v0 v2 v1 v0
1252 sub esi, 3
1253 movq [edi], mm0
1254 sub edi, 24
1255 /*sub esi, 3 */
1256 dec ecx
1257 jnz loop_pass0
1258 EMMS
1259 }
1260 }
1261 else if (((pass == 2) || (pass == 3)) && width)
1262 {
1263 _asm
1264 {
1265 mov esi, sptr
1266 mov edi, dp
1267 mov ecx, width
1268 sub edi, 9 /* (png_pass_inc[pass] - 1)*pixel_bytes */
1269 loop_pass2:
1270 movd mm0, [esi] ; X X X X X v2 v1 v0
1271 pand mm0, const4 ; 0 0 0 0 0 v2 v1 v0
1272 movq mm1, mm0 ; 0 0 0 0 0 v2 v1 v0
1273 psllq mm0, 16 ; 0 0 0 v2 v1 v0 0 0
1274 movq mm2, mm0 ; 0 0 0 v2 v1 v0 0 0
1275 psllq mm0, 24 ; v2 v1 v0 0 0 0 0 0
1276 psrlq mm1, 8 ; 0 0 0 0 0 0 v2 v1
1277 por mm0, mm2 ; v2 v1 v0 v2 v1 v0 0 0
1278 por mm0, mm1 ; v2 v1 v0 v2 v1 v0 v2 v1
1279 movq [edi+4], mm0 ; move to memory
1280 psrlq mm0, 16 ; 0 0 v2 v1 v0 v2 v1 v0
1281 movd [edi], mm0 ; move to memory
1282 sub esi, 3
1283 sub edi, 12
1284 dec ecx
1285 jnz loop_pass2
1286 EMMS
1287 }
1288 }
1289 else if (width) /* && ((pass == 4) || (pass == 5)) */
1290 {
1291 int width_mmx = ((width >> 1) << 1) - 8;
1292 if (width_mmx < 0)
1293 width_mmx = 0;
1294 width -= width_mmx; /* 8 or 9 pix, 24 or 27 bytes */
1295 if (width_mmx)
1296 {
1297 _asm
1298 {
1299 mov esi, sptr
1300 mov edi, dp
1301 mov ecx, width_mmx
1302 sub esi, 3
1303 sub edi, 9
1304 loop_pass4:
1305 movq mm0, [esi] ; X X v2 v1 v0 v5 v4 v3
1306 movq mm7, mm0 ; X X v2 v1 v0 v5 v4 v3
1307 movq mm6, mm0 ; X X v2 v1 v0 v5 v4 v3
1308 psllq mm0, 24 ; v1 v0 v5 v4 v3 0 0 0
1309 pand mm7, const4 ; 0 0 0 0 0 v5 v4 v3
1310 psrlq mm6, 24 ; 0 0 0 X X v2 v1 v0
1311 por mm0, mm7 ; v1 v0 v5 v4 v3 v5 v4 v3
1312 movq mm5, mm6 ; 0 0 0 X X v2 v1 v0
1313 psllq mm6, 8 ; 0 0 X X v2 v1 v0 0
1314 movq [edi], mm0 ; move quad to memory
1315 psrlq mm5, 16 ; 0 0 0 0 0 X X v2
1316 pand mm5, const6 ; 0 0 0 0 0 0 0 v2
1317 por mm6, mm5 ; 0 0 X X v2 v1 v0 v2
1318 movd [edi+8], mm6 ; move double to memory
1319 sub esi, 6
1320 sub edi, 12
1321 sub ecx, 2
1322 jnz loop_pass4
1323 EMMS
1324 }
1325 }
1326
1327 sptr -= width_mmx*3;
1328 dp -= width_mmx*6;
1329 for (i = width; i; i--)
1330 {
1331 png_byte v[8];
1332 int j;
1333
1334 png_memcpy(v, sptr, 3);
1335 for (j = 0; j < png_pass_inc[pass]; j++)
1336 {
1337 png_memcpy(dp, v, 3);
1338 dp -= 3;
1339 }
1340 sptr -= 3;
1341 }
1342 }
1343 } /* end of pixel_bytes == 3 */
1344
1345 else if (pixel_bytes == 1)
1346 {
1347 if (((pass == 0) || (pass == 1)) && width)
1348 {
1349 int width_mmx = ((width >> 2) << 2);
1350 width -= width_mmx;
1351 if (width_mmx)
1352 {
1353 _asm
1354 {
1355 mov esi, sptr
1356 mov edi, dp
1357 mov ecx, width_mmx
1358 sub edi, 31
1359 sub esi, 3
1360 loop1_pass0:
1361 movd mm0, [esi] ; X X X X v0 v1 v2 v3
1362 movq mm1, mm0 ; X X X X v0 v1 v2 v3
1363 punpcklbw mm0, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3
1364 movq mm2, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3
1365 punpcklwd mm0, mm0 ; v2 v2 v2 v2 v3 v3 v3 v3
1366 movq mm3, mm0 ; v2 v2 v2 v2 v3 v3 v3 v3
1367 punpckldq mm0, mm0 ; v3 v3 v3 v3 v3 v3 v3 v3
1368 punpckhdq mm3, mm3 ; v2 v2 v2 v2 v2 v2 v2 v2
1369 movq [edi], mm0 ; move to memory v3
1370 punpckhwd mm2, mm2 ; v0 v0 v0 v0 v1 v1 v1 v1
1371 movq [edi+8], mm3 ; move to memory v2
1372 movq mm4, mm2 ; v0 v0 v0 v0 v1 v1 v1 v1
1373 punpckldq mm2, mm2 ; v1 v1 v1 v1 v1 v1 v1 v1
1374 punpckhdq mm4, mm4 ; v0 v0 v0 v0 v0 v0 v0 v0
1375 movq [edi+16], mm2 ; move to memory v1
1376 movq [edi+24], mm4 ; move to memory v0
1377 sub esi, 4
1378 sub edi, 32
1379 sub ecx, 4
1380 jnz loop1_pass0
1381 EMMS
1382 }
1383 }
1384
1385 sptr -= width_mmx;
1386 dp -= width_mmx*8;
1387 for (i = width; i; i--)
1388 {
1389 int j;
1390
1391 /* I simplified this part in version 1.0.4e
1392 * here and in several other instances where
1393 * pixel_bytes == 1 -- GR-P
1394 *
1395 * Original code:
1396 *
1397 * png_byte v[8];
1398 * png_memcpy(v, sptr, pixel_bytes);
1399 * for (j = 0; j < png_pass_inc[pass]; j++)
1400 * {
1401 * png_memcpy(dp, v, pixel_bytes);
1402 * dp -= pixel_bytes;
1403 * }
1404 * sptr -= pixel_bytes;
1405 *
1406 * Replacement code is in the next three lines:
1407 */
1408
1409 for (j = 0; j < png_pass_inc[pass]; j++)
1410 *dp-- = *sptr;
1411 sptr--;
1412 }
1413 }
1414 else if (((pass == 2) || (pass == 3)) && width)
1415 {
1416 int width_mmx = ((width >> 2) << 2);
1417 width -= width_mmx;
1418 if (width_mmx)
1419 {
1420 _asm
1421 {
1422 mov esi, sptr
1423 mov edi, dp
1424 mov ecx, width_mmx
1425 sub edi, 15
1426 sub esi, 3
1427 loop1_pass2:
1428 movd mm0, [esi] ; X X X X v0 v1 v2 v3
1429 punpcklbw mm0, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3
1430 movq mm1, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3
1431 punpcklwd mm0, mm0 ; v2 v2 v2 v2 v3 v3 v3 v3
1432 punpckhwd mm1, mm1 ; v0 v0 v0 v0 v1 v1 v1 v1
1433 movq [edi], mm0 ; move to memory v2 and v3
1434 sub esi, 4
1435 movq [edi+8], mm1 ; move to memory v1 and v0
1436 sub edi, 16
1437 sub ecx, 4
1438 jnz loop1_pass2
1439 EMMS
1440 }
1441 }
1442
1443 sptr -= width_mmx;
1444 dp -= width_mmx*4;
1445 for (i = width; i; i--)
1446 {
1447 int j;
1448
1449 for (j = 0; j < png_pass_inc[pass]; j++)
1450 {
1451 *dp-- = *sptr;
1452 }
1453 sptr --;
1454 }
1455 }
1456 else if (width) /* && ((pass == 4) || (pass == 5))) */
1457 {
1458 int width_mmx = ((width >> 3) << 3);
1459 width -= width_mmx;
1460 if (width_mmx)
1461 {
1462 _asm
1463 {
1464 mov esi, sptr
1465 mov edi, dp
1466 mov ecx, width_mmx
1467 sub edi, 15
1468 sub esi, 7
1469 loop1_pass4:
1470 movq mm0, [esi] ; v0 v1 v2 v3 v4 v5 v6 v7
1471 movq mm1, mm0 ; v0 v1 v2 v3 v4 v5 v6 v7
1472 punpcklbw mm0, mm0 ; v4 v4 v5 v5 v6 v6 v7 v7
1473 /*movq mm1, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3 */
1474 punpckhbw mm1, mm1 ;v0 v0 v1 v1 v2 v2 v3 v3
1475 movq [edi+8], mm1 ; move to memory v0 v1 v2 and v3
1476 sub esi, 8
1477 movq [edi], mm0 ; move to memory v4 v5 v6 and v7
1478 /*sub esi, 4 */
1479 sub edi, 16
1480 sub ecx, 8
1481 jnz loop1_pass4
1482 EMMS
1483 }
1484 }
1485
1486 sptr -= width_mmx;
1487 dp -= width_mmx*2;
1488 for (i = width; i; i--)
1489 {
1490 int j;
1491
1492 for (j = 0; j < png_pass_inc[pass]; j++)
1493 {
1494 *dp-- = *sptr;
1495 }
1496 sptr --;
1497 }
1498 }
1499 } /* end of pixel_bytes == 1 */
1500
1501 else if (pixel_bytes == 2)
1502 {
1503 if (((pass == 0) || (pass == 1)) && width)
1504 {
1505 int width_mmx = ((width >> 1) << 1);
1506 width -= width_mmx;
1507 if (width_mmx)
1508 {
1509 _asm
1510 {
1511 mov esi, sptr
1512 mov edi, dp
1513 mov ecx, width_mmx
1514 sub esi, 2
1515 sub edi, 30
1516 loop2_pass0:
1517 movd mm0, [esi] ; X X X X v1 v0 v3 v2
1518 punpcklwd mm0, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2
1519 movq mm1, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2
1520 punpckldq mm0, mm0 ; v3 v2 v3 v2 v3 v2 v3 v2
1521 punpckhdq mm1, mm1 ; v1 v0 v1 v0 v1 v0 v1 v0
1522 movq [edi], mm0
1523 movq [edi + 8], mm0
1524 movq [edi + 16], mm1
1525 movq [edi + 24], mm1
1526 sub esi, 4
1527 sub edi, 32
1528 sub ecx, 2
1529 jnz loop2_pass0
1530 EMMS
1531 }
1532 }
1533
1534 sptr -= (width_mmx*2 - 2); /* sign fixed */
1535 dp -= (width_mmx*16 - 2); /* sign fixed */
1536 for (i = width; i; i--)
1537 {
1538 png_byte v[8];
1539 int j;
1540 sptr -= 2;
1541 png_memcpy(v, sptr, 2);
1542 for (j = 0; j < png_pass_inc[pass]; j++)
1543 {
1544 dp -= 2;
1545 png_memcpy(dp, v, 2);
1546 }
1547 }
1548 }
1549 else if (((pass == 2) || (pass == 3)) && width)
1550 {
1551 int width_mmx = ((width >> 1) << 1) ;
1552 width -= width_mmx;
1553 if (width_mmx)
1554 {
1555 _asm
1556 {
1557 mov esi, sptr
1558 mov edi, dp
1559 mov ecx, width_mmx
1560 sub esi, 2
1561 sub edi, 14
1562 loop2_pass2:
1563 movd mm0, [esi] ; X X X X v1 v0 v3 v2
1564 punpcklwd mm0, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2
1565 movq mm1, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2
1566 punpckldq mm0, mm0 ; v3 v2 v3 v2 v3 v2 v3 v2
1567 punpckhdq mm1, mm1 ; v1 v0 v1 v0 v1 v0 v1 v0
1568 movq [edi], mm0
1569 sub esi, 4
1570 movq [edi + 8], mm1
1571 /*sub esi, 4 */
1572 sub edi, 16
1573 sub ecx, 2
1574 jnz loop2_pass2
1575 EMMS
1576 }
1577 }
1578
1579 sptr -= (width_mmx*2 - 2); /* sign fixed */
1580 dp -= (width_mmx*8 - 2); /* sign fixed */
1581 for (i = width; i; i--)
1582 {
1583 png_byte v[8];
1584 int j;
1585 sptr -= 2;
1586 png_memcpy(v, sptr, 2);
1587 for (j = 0; j < png_pass_inc[pass]; j++)
1588 {
1589 dp -= 2;
1590 png_memcpy(dp, v, 2);
1591 }
1592 }
1593 }
1594 else if (width) /* pass == 4 or 5 */
1595 {
1596 int width_mmx = ((width >> 1) << 1) ;
1597 width -= width_mmx;
1598 if (width_mmx)
1599 {
1600 _asm
1601 {
1602 mov esi, sptr
1603 mov edi, dp
1604 mov ecx, width_mmx
1605 sub esi, 2
1606 sub edi, 6
1607 loop2_pass4:
1608 movd mm0, [esi] ; X X X X v1 v0 v3 v2
1609 punpcklwd mm0, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2
1610 sub esi, 4
1611 movq [edi], mm0
1612 sub edi, 8
1613 sub ecx, 2
1614 jnz loop2_pass4
1615 EMMS
1616 }
1617 }
1618
1619 sptr -= (width_mmx*2 - 2); /* sign fixed */
1620 dp -= (width_mmx*4 - 2); /* sign fixed */
1621 for (i = width; i; i--)
1622 {
1623 png_byte v[8];
1624 int j;
1625 sptr -= 2;
1626 png_memcpy(v, sptr, 2);
1627 for (j = 0; j < png_pass_inc[pass]; j++)
1628 {
1629 dp -= 2;
1630 png_memcpy(dp, v, 2);
1631 }
1632 }
1633 }
1634 } /* end of pixel_bytes == 2 */
1635
1636 else if (pixel_bytes == 4)
1637 {
1638 if (((pass == 0) || (pass == 1)) && width)
1639 {
1640 int width_mmx = ((width >> 1) << 1) ;
1641 width -= width_mmx;
1642 if (width_mmx)
1643 {
1644 _asm
1645 {
1646 mov esi, sptr
1647 mov edi, dp
1648 mov ecx, width_mmx
1649 sub esi, 4
1650 sub edi, 60
1651 loop4_pass0:
1652 movq mm0, [esi] ; v3 v2 v1 v0 v7 v6 v5 v4
1653 movq mm1, mm0 ; v3 v2 v1 v0 v7 v6 v5 v4
1654 punpckldq mm0, mm0 ; v7 v6 v5 v4 v7 v6 v5 v4
1655 punpckhdq mm1, mm1 ; v3 v2 v1 v0 v3 v2 v1 v0
1656 movq [edi], mm0
1657 movq [edi + 8], mm0
1658 movq [edi + 16], mm0
1659 movq [edi + 24], mm0
1660 movq [edi+32], mm1
1661 movq [edi + 40], mm1
1662 movq [edi+ 48], mm1
1663 sub esi, 8
1664 movq [edi + 56], mm1
1665 sub edi, 64
1666 sub ecx, 2
1667 jnz loop4_pass0
1668 EMMS
1669 }
1670 }
1671
1672 sptr -= (width_mmx*4 - 4); /* sign fixed */
1673 dp -= (width_mmx*32 - 4); /* sign fixed */
1674 for (i = width; i; i--)
1675 {
1676 png_byte v[8];
1677 int j;
1678 sptr -= 4;
1679 png_memcpy(v, sptr, 4);
1680 for (j = 0; j < png_pass_inc[pass]; j++)
1681 {
1682 dp -= 4;
1683 png_memcpy(dp, v, 4);
1684 }
1685 }
1686 }
1687 else if (((pass == 2) || (pass == 3)) && width)
1688 {
1689 int width_mmx = ((width >> 1) << 1) ;
1690 width -= width_mmx;
1691 if (width_mmx)
1692 {
1693 _asm
1694 {
1695 mov esi, sptr
1696 mov edi, dp
1697 mov ecx, width_mmx
1698 sub esi, 4
1699 sub edi, 28
1700 loop4_pass2:
1701 movq mm0, [esi] ; v3 v2 v1 v0 v7 v6 v5 v4
1702 movq mm1, mm0 ; v3 v2 v1 v0 v7 v6 v5 v4
1703 punpckldq mm0, mm0 ; v7 v6 v5 v4 v7 v6 v5 v4
1704 punpckhdq mm1, mm1 ; v3 v2 v1 v0 v3 v2 v1 v0
1705 movq [edi], mm0
1706 movq [edi + 8], mm0
1707 movq [edi+16], mm1
1708 movq [edi + 24], mm1
1709 sub esi, 8
1710 sub edi, 32
1711 sub ecx, 2
1712 jnz loop4_pass2
1713 EMMS
1714 }
1715 }
1716
1717 sptr -= (width_mmx*4 - 4); /* sign fixed */
1718 dp -= (width_mmx*16 - 4); /* sign fixed */
1719 for (i = width; i; i--)
1720 {
1721 png_byte v[8];
1722 int j;
1723 sptr -= 4;
1724 png_memcpy(v, sptr, 4);
1725 for (j = 0; j < png_pass_inc[pass]; j++)
1726 {
1727 dp -= 4;
1728 png_memcpy(dp, v, 4);
1729 }
1730 }
1731 }
1732 else if (width) /* pass == 4 or 5 */
1733 {
1734 int width_mmx = ((width >> 1) << 1) ;
1735 width -= width_mmx;
1736 if (width_mmx)
1737 {
1738 _asm
1739 {
1740 mov esi, sptr
1741 mov edi, dp
1742 mov ecx, width_mmx
1743 sub esi, 4
1744 sub edi, 12
1745 loop4_pass4:
1746 movq mm0, [esi] ; v3 v2 v1 v0 v7 v6 v5 v4
1747 movq mm1, mm0 ; v3 v2 v1 v0 v7 v6 v5 v4
1748 punpckldq mm0, mm0 ; v7 v6 v5 v4 v7 v6 v5 v4
1749 punpckhdq mm1, mm1 ; v3 v2 v1 v0 v3 v2 v1 v0
1750 movq [edi], mm0
1751 sub esi, 8
1752 movq [edi + 8], mm1
1753 sub edi, 16
1754 sub ecx, 2
1755 jnz loop4_pass4
1756 EMMS
1757 }
1758 }
1759
1760 sptr -= (width_mmx*4 - 4); /* sign fixed */
1761 dp -= (width_mmx*8 - 4); /* sign fixed */
1762 for (i = width; i; i--)
1763 {
1764 png_byte v[8];
1765 int j;
1766 sptr -= 4;
1767 png_memcpy(v, sptr, 4);
1768 for (j = 0; j < png_pass_inc[pass]; j++)
1769 {
1770 dp -= 4;
1771 png_memcpy(dp, v, 4);
1772 }
1773 }
1774 }
1775
1776 } /* end of pixel_bytes == 4 */
1777
1778 else if (pixel_bytes == 6)
1779 {
1780 for (i = width; i; i--)
1781 {
1782 png_byte v[8];
1783 int j;
1784 png_memcpy(v, sptr, 6);
1785 for (j = 0; j < png_pass_inc[pass]; j++)
1786 {
1787 png_memcpy(dp, v, 6);
1788 dp -= 6;
1789 }
1790 sptr -= 6;
1791 }
1792 } /* end of pixel_bytes == 6 */
1793
1794 else
1795 {
1796 for (i = width; i; i--)
1797 {
1798 png_byte v[8];
1799 int j;
1800 png_memcpy(v, sptr, pixel_bytes);
1801 for (j = 0; j < png_pass_inc[pass]; j++)
1802 {
1803 png_memcpy(dp, v, pixel_bytes);
1804 dp -= pixel_bytes;
1805 }
1806 sptr-= pixel_bytes;
1807 }
1808 }
1809 } /* end of mmx_supported */
1810
1811 else /* MMX not supported: use modified C code - takes advantage
1812 * of inlining of memcpy for a constant */
1813 {
1814 if (pixel_bytes == 1)
1815 {
1816 for (i = width; i; i--)
1817 {
1818 int j;
1819 for (j = 0; j < png_pass_inc[pass]; j++)
1820 *dp-- = *sptr;
1821 sptr--;
1822 }
1823 }
1824 else if (pixel_bytes == 3)
1825 {
1826 for (i = width; i; i--)
1827 {
1828 png_byte v[8];
1829 int j;
1830 png_memcpy(v, sptr, pixel_bytes);
1831 for (j = 0; j < png_pass_inc[pass]; j++)
1832 {
1833 png_memcpy(dp, v, pixel_bytes);
1834 dp -= pixel_bytes;
1835 }
1836 sptr -= pixel_bytes;
1837 }
1838 }
1839 else if (pixel_bytes == 2)
1840 {
1841 for (i = width; i; i--)
1842 {
1843 png_byte v[8];
1844 int j;
1845 png_memcpy(v, sptr, pixel_bytes);
1846 for (j = 0; j < png_pass_inc[pass]; j++)
1847 {
1848 png_memcpy(dp, v, pixel_bytes);
1849 dp -= pixel_bytes;
1850 }
1851 sptr -= pixel_bytes;
1852 }
1853 }
1854 else if (pixel_bytes == 4)
1855 {
1856 for (i = width; i; i--)
1857 {
1858 png_byte v[8];
1859 int j;
1860 png_memcpy(v, sptr, pixel_bytes);
1861 for (j = 0; j < png_pass_inc[pass]; j++)
1862 {
1863 png_memcpy(dp, v, pixel_bytes);
1864 dp -= pixel_bytes;
1865 }
1866 sptr -= pixel_bytes;
1867 }
1868 }
1869 else if (pixel_bytes == 6)
1870 {
1871 for (i = width; i; i--)
1872 {
1873 png_byte v[8];
1874 int j;
1875 png_memcpy(v, sptr, pixel_bytes);
1876 for (j = 0; j < png_pass_inc[pass]; j++)
1877 {
1878 png_memcpy(dp, v, pixel_bytes);
1879 dp -= pixel_bytes;
1880 }
1881 sptr -= pixel_bytes;
1882 }
1883 }
1884 else
1885 {
1886 for (i = width; i; i--)
1887 {
1888 png_byte v[8];
1889 int j;
1890 png_memcpy(v, sptr, pixel_bytes);
1891 for (j = 0; j < png_pass_inc[pass]; j++)
1892 {
1893 png_memcpy(dp, v, pixel_bytes);
1894 dp -= pixel_bytes;
1895 }
1896 sptr -= pixel_bytes;
1897 }
1898 }
1899
1900 } /* end of MMX not supported */
1901 break;
1902 }
1903 } /* end switch (row_info->pixel_depth) */
1904
1905 row_info->width = final_width;
1906
1907 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
1908 }
1909
1910 }
1911
1912 #endif /* PNG_READ_INTERLACING_SUPPORTED */
1913
1914
1915 /* These variables are utilized in the functions below. They are declared */
1916 /* globally here to ensure alignment on 8-byte boundaries. */
1917
1918 union uAll {
1919 __int64 use;
1920 double align;
1921 } LBCarryMask = {0x0101010101010101},
1922 HBClearMask = {0x7f7f7f7f7f7f7f7f},
1923 ActiveMask, ActiveMask2, ActiveMaskEnd, ShiftBpp, ShiftRem;
1924
1925
1926 /* Optimized code for PNG Average filter decoder */
1927 void /* PRIVATE */
1928 png_read_filter_row_mmx_avg(png_row_infop row_info, png_bytep row
1929 , png_bytep prev_row)
1930 {
1931 int bpp;
1932 png_uint_32 FullLength;
1933 png_uint_32 MMXLength;
1934 /*png_uint_32 len; */
1935 int diff;
1936
1937 bpp = (row_info->pixel_depth + 7) >> 3; /* Get # bytes per pixel */
1938 FullLength = row_info->rowbytes; /* # of bytes to filter */
1939 _asm {
1940 /* Init address pointers and offset */
1941 mov edi, row /* edi ==> Avg(x) */
1942 xor ebx, ebx /* ebx ==> x */
1943 mov edx, edi
1944 mov esi, prev_row /* esi ==> Prior(x) */
1945 sub edx, bpp /* edx ==> Raw(x-bpp) */
1946
1947 xor eax, eax
1948 /* Compute the Raw value for the first bpp bytes */
1949 /* Raw(x) = Avg(x) + (Prior(x)/2) */
1950 davgrlp:
1951 mov al, [esi + ebx] /* Load al with Prior(x) */
1952 inc ebx
1953 shr al, 1 /* divide by 2 */
1954 add al, [edi+ebx-1] /* Add Avg(x); -1 to offset inc ebx */
1955 cmp ebx, bpp
1956 mov [edi+ebx-1], al /* Write back Raw(x); */
1957 /* mov does not affect flags; -1 to offset inc ebx */
1958 jb davgrlp
1959 /* get # of bytes to alignment */
1960 mov diff, edi /* take start of row */
1961 add diff, ebx /* add bpp */
1962 add diff, 0xf /* add 7 + 8 to incr past alignment boundary */
1963 and diff, 0xfffffff8 /* mask to alignment boundary */
1964 sub diff, edi /* subtract from start ==> value ebx at alignment */
1965 jz davggo
1966 /* fix alignment */
1967 /* Compute the Raw value for the bytes upto the alignment boundary */
1968 /* Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2) */
1969 xor ecx, ecx
1970 davglp1:
1971 xor eax, eax
1972 mov cl, [esi + ebx] /* load cl with Prior(x) */
1973 mov al, [edx + ebx] /* load al with Raw(x-bpp) */
1974 add ax, cx
1975 inc ebx
1976 shr ax, 1 /* divide by 2 */
1977 add al, [edi+ebx-1] /* Add Avg(x); -1 to offset inc ebx */
1978 cmp ebx, diff /* Check if at alignment boundary */
1979 mov [edi+ebx-1], al /* Write back Raw(x); */
1980 /* mov does not affect flags; -1 to offset inc ebx */
1981 jb davglp1 /* Repeat until at alignment boundary */
1982 davggo:
1983 mov eax, FullLength
1984 mov ecx, eax
1985 sub eax, ebx /* subtract alignment fix */
1986 and eax, 0x00000007 /* calc bytes over mult of 8 */
1987 sub ecx, eax /* drop over bytes from original length */
1988 mov MMXLength, ecx
1989 } /* end _asm block */
1990 /* Now do the math for the rest of the row */
1991 switch ( bpp )
1992 {
1993 case 3:
1994 {
1995 ActiveMask.use = 0x0000000000ffffff;
1996 ShiftBpp.use = 24; /* == 3 * 8 */
1997 ShiftRem.use = 40; /* == 64 - 24 */
1998 _asm {
1999 /* Re-init address pointers and offset */
2000 movq mm7, ActiveMask
2001 mov ebx, diff /* ebx ==> x = offset to alignment boundary */
2002 movq mm5, LBCarryMask
2003 mov edi, row /* edi ==> Avg(x) */
2004 movq mm4, HBClearMask
2005 mov esi, prev_row /* esi ==> Prior(x) */
2006 /* PRIME the pump (load the first Raw(x-bpp) data set */
2007 movq mm2, [edi + ebx - 8] /* Load previous aligned 8 bytes */
2008 /* (we correct position in loop below) */
2009 davg3lp:
2010 movq mm0, [edi + ebx] /* Load mm0 with Avg(x) */
2011 /* Add (Prev_row/2) to Average */
2012 movq mm3, mm5
2013 psrlq mm2, ShiftRem /* Correct position Raw(x-bpp) data */
2014 movq mm1, [esi + ebx] /* Load mm1 with Prior(x) */
2015 movq mm6, mm7
2016 pand mm3, mm1 /* get lsb for each prev_row byte */
2017 psrlq mm1, 1 /* divide prev_row bytes by 2 */
2018 pand mm1, mm4 /* clear invalid bit 7 of each byte */
2019 paddb mm0, mm1 /* add (Prev_row/2) to Avg for each byte */
2020 /* Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry */
2021 movq mm1, mm3 /* now use mm1 for getting LBCarrys */
2022 pand mm1, mm2 /* get LBCarrys for each byte where both */
2023 /* lsb's were == 1 (Only valid for active group) */
2024 psrlq mm2, 1 /* divide raw bytes by 2 */
2025 pand mm2, mm4 /* clear invalid bit 7 of each byte */
2026 paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
2027 pand mm2, mm6 /* Leave only Active Group 1 bytes to add to Avg */
2028 paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active */
2029 /* byte */
2030 /* Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry */
2031 psllq mm6, ShiftBpp /* shift the mm6 mask to cover bytes 3-5 */
2032 movq mm2, mm0 /* mov updated Raws to mm2 */
2033 psllq mm2, ShiftBpp /* shift data to position correctly */
2034 movq mm1, mm3 /* now use mm1 for getting LBCarrys */
2035 pand mm1, mm2 /* get LBCarrys for each byte where both */
2036 /* lsb's were == 1 (Only valid for active group) */
2037 psrlq mm2, 1 /* divide raw bytes by 2 */
2038 pand mm2, mm4 /* clear invalid bit 7 of each byte */
2039 paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
2040 pand mm2, mm6 /* Leave only Active Group 2 bytes to add to Avg */
2041 paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active */
2042 /* byte */
2043
2044 /* Add 3rd active group (Raw(x-bpp)/2) to Average with LBCarry */
2045 psllq mm6, ShiftBpp /* shift the mm6 mask to cover the last two */
2046 /* bytes */
2047 movq mm2, mm0 /* mov updated Raws to mm2 */
2048 psllq mm2, ShiftBpp /* shift data to position correctly */
2049 /* Data only needs to be shifted once here to */
2050 /* get the correct x-bpp offset. */
2051 movq mm1, mm3 /* now use mm1 for getting LBCarrys */
2052 pand mm1, mm2 /* get LBCarrys for each byte where both */
2053 /* lsb's were == 1 (Only valid for active group) */
2054 psrlq mm2, 1 /* divide raw bytes by 2 */
2055 pand mm2, mm4 /* clear invalid bit 7 of each byte */
2056 paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
2057 pand mm2, mm6 /* Leave only Active Group 2 bytes to add to Avg */
2058 add ebx, 8
2059 paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active */
2060 /* byte */
2061
2062 /* Now ready to write back to memory */
2063 movq [edi + ebx - 8], mm0
2064 /* Move updated Raw(x) to use as Raw(x-bpp) for next loop */
2065 cmp ebx, MMXLength
2066 movq mm2, mm0 /* mov updated Raw(x) to mm2 */
2067 jb davg3lp
2068 } /* end _asm block */
2069 }
2070 break;
2071
2072 case 6:
2073 case 4:
2074 case 7:
2075 case 5:
2076 {
2077 ActiveMask.use = 0xffffffffffffffff; /* use shift below to clear */
2078 /* appropriate inactive bytes */
2079 ShiftBpp.use = bpp << 3;
2080 ShiftRem.use = 64 - ShiftBpp.use;
2081 _asm {
2082 movq mm4, HBClearMask
2083 /* Re-init address pointers and offset */
2084 mov ebx, diff /* ebx ==> x = offset to alignment boundary */
2085 /* Load ActiveMask and clear all bytes except for 1st active group */
2086 movq mm7, ActiveMask
2087 mov edi, row /* edi ==> Avg(x) */
2088 psrlq mm7, ShiftRem
2089 mov esi, prev_row /* esi ==> Prior(x) */
2090 movq mm6, mm7
2091 movq mm5, LBCarryMask
2092 psllq mm6, ShiftBpp /* Create mask for 2nd active group */
2093 /* PRIME the pump (load the first Raw(x-bpp) data set */
2094 movq mm2, [edi + ebx - 8] /* Load previous aligned 8 bytes */
2095 /* (we correct position in loop below) */
2096 davg4lp:
2097 movq mm0, [edi + ebx]
2098 psrlq mm2, ShiftRem /* shift data to position correctly */
2099 movq mm1, [esi + ebx]
2100 /* Add (Prev_row/2) to Average */
2101 movq mm3, mm5
2102 pand mm3, mm1 /* get lsb for each prev_row byte */
2103 psrlq mm1, 1 /* divide prev_row bytes by 2 */
2104 pand mm1, mm4 /* clear invalid bit 7 of each byte */
2105 paddb mm0, mm1 /* add (Prev_row/2) to Avg for each byte */
2106 /* Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry */
2107 movq mm1, mm3 /* now use mm1 for getting LBCarrys */
2108 pand mm1, mm2 /* get LBCarrys for each byte where both */
2109 /* lsb's were == 1 (Only valid for active group) */
2110 psrlq mm2, 1 /* divide raw bytes by 2 */
2111 pand mm2, mm4 /* clear invalid bit 7 of each byte */
2112 paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
2113 pand mm2, mm7 /* Leave only Active Group 1 bytes to add to Avg */
2114 paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active */
2115 /* byte */
2116 /* Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry */
2117 movq mm2, mm0 /* mov updated Raws to mm2 */
2118 psllq mm2, ShiftBpp /* shift data to position correctly */
2119 add ebx, 8
2120 movq mm1, mm3 /* now use mm1 for getting LBCarrys */
2121 pand mm1, mm2 /* get LBCarrys for each byte where both */
2122 /* lsb's were == 1 (Only valid for active group) */
2123 psrlq mm2, 1 /* divide raw bytes by 2 */
2124 pand mm2, mm4 /* clear invalid bit 7 of each byte */
2125 paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
2126 pand mm2, mm6 /* Leave only Active Group 2 bytes to add to Avg */
2127 paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active */
2128 /* byte */
2129 cmp ebx, MMXLength
2130 /* Now ready to write back to memory */
2131 movq [edi + ebx - 8], mm0
2132 /* Prep Raw(x-bpp) for next loop */
2133 movq mm2, mm0 /* mov updated Raws to mm2 */
2134 jb davg4lp
2135 } /* end _asm block */
2136 }
2137 break;
2138 case 2:
2139 {
2140 ActiveMask.use = 0x000000000000ffff;
2141 ShiftBpp.use = 16; /* == 2 * 8 [BUGFIX] */
2142 ShiftRem.use = 48; /* == 64 - 16 [BUGFIX] */
2143 _asm {
2144 /* Load ActiveMask */
2145 movq mm7, ActiveMask
2146 /* Re-init address pointers and offset */
2147 mov ebx, diff /* ebx ==> x = offset to alignment boundary */
2148 movq mm5, LBCarryMask
2149 mov edi, row /* edi ==> Avg(x) */
2150 movq mm4, HBClearMask
2151 mov esi, prev_row /* esi ==> Prior(x) */
2152 /* PRIME the pump (load the first Raw(x-bpp) data set */
2153 movq mm2, [edi + ebx - 8] /* Load previous aligned 8 bytes */
2154 /* (we correct position in loop below) */
2155 davg2lp:
2156 movq mm0, [edi + ebx]
2157 psrlq mm2, ShiftRem /* shift data to position correctly [BUGFIX] */
2158 movq mm1, [esi + ebx]
2159 /* Add (Prev_row/2) to Average */
2160 movq mm3, mm5
2161 pand mm3, mm1 /* get lsb for each prev_row byte */
2162 psrlq mm1, 1 /* divide prev_row bytes by 2 */
2163 pand mm1, mm4 /* clear invalid bit 7 of each byte */
2164 movq mm6, mm7
2165 paddb mm0, mm1 /* add (Prev_row/2) to Avg for each byte */
2166 /* Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry */
2167 movq mm1, mm3 /* now use mm1 for getting LBCarrys */
2168 pand mm1, mm2 /* get LBCarrys for each byte where both */
2169 /* lsb's were == 1 (Only valid for active group) */
2170 psrlq mm2, 1 /* divide raw bytes by 2 */
2171 pand mm2, mm4 /* clear invalid bit 7 of each byte */
2172 paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
2173 pand mm2, mm6 /* Leave only Active Group 1 bytes to add to Avg */
2174 paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active byte */
2175 /* Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry */
2176 psllq mm6, ShiftBpp /* shift the mm6 mask to cover bytes 2 & 3 */
2177 movq mm2, mm0 /* mov updated Raws to mm2 */
2178 psllq mm2, ShiftBpp /* shift data to position correctly */
2179 movq mm1, mm3 /* now use mm1 for getting LBCarrys */
2180 pand mm1, mm2 /* get LBCarrys for each byte where both */
2181 /* lsb's were == 1 (Only valid for active group) */
2182 psrlq mm2, 1 /* divide raw bytes by 2 */
2183 pand mm2, mm4 /* clear invalid bit 7 of each byte */
2184 paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
2185 pand mm2, mm6 /* Leave only Active Group 2 bytes to add to Avg */
2186 paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active byte */
2187
2188 /* Add rdd active group (Raw(x-bpp)/2) to Average with LBCarry */
2189 psllq mm6, ShiftBpp /* shift the mm6 mask to cover bytes 4 & 5 */
2190 movq mm2, mm0 /* mov updated Raws to mm2 */
2191 psllq mm2, ShiftBpp /* shift data to position correctly */
2192 /* Data only needs to be shifted once here to */
2193 /* get the correct x-bpp offset. */
2194 movq mm1, mm3 /* now use mm1 for getting LBCarrys */
2195 pand mm1, mm2 /* get LBCarrys for each byte where both */
2196 /* lsb's were == 1 (Only valid for active group) */
2197 psrlq mm2, 1 /* divide raw bytes by 2 */
2198 pand mm2, mm4 /* clear invalid bit 7 of each byte */
2199 paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
2200 pand mm2, mm6 /* Leave only Active Group 2 bytes to add to Avg */
2201 paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active byte */
2202
2203 /* Add 4th active group (Raw(x-bpp)/2) to Average with LBCarry */
2204 psllq mm6, ShiftBpp /* shift the mm6 mask to cover bytes 6 & 7 */
2205 movq mm2, mm0 /* mov updated Raws to mm2 */
2206 psllq mm2, ShiftBpp /* shift data to position correctly */
2207 /* Data only needs to be shifted once here to */
2208 /* get the correct x-bpp offset. */
2209 add ebx, 8
2210 movq mm1, mm3 /* now use mm1 for getting LBCarrys */
2211 pand mm1, mm2 /* get LBCarrys for each byte where both */
2212 /* lsb's were == 1 (Only valid for active group) */
2213 psrlq mm2, 1 /* divide raw bytes by 2 */
2214 pand mm2, mm4 /* clear invalid bit 7 of each byte */
2215 paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
2216 pand mm2, mm6 /* Leave only Active Group 2 bytes to add to Avg */
2217 paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active byte */
2218
2219 cmp ebx, MMXLength
2220 /* Now ready to write back to memory */
2221 movq [edi + ebx - 8], mm0
2222 /* Prep Raw(x-bpp) for next loop */
2223 movq mm2, mm0 /* mov updated Raws to mm2 */
2224 jb davg2lp
2225 } /* end _asm block */
2226 }
2227 break;
2228
2229 case 1: /* bpp == 1 */
2230 {
2231 _asm {
2232 /* Re-init address pointers and offset */
2233 mov ebx, diff /* ebx ==> x = offset to alignment boundary */
2234 mov edi, row /* edi ==> Avg(x) */
2235 cmp ebx, FullLength /* Test if offset at end of array */
2236 jnb davg1end
2237 /* Do Paeth decode for remaining bytes */
2238 mov esi, prev_row /* esi ==> Prior(x) */
2239 mov edx, edi
2240 xor ecx, ecx /* zero ecx before using cl & cx in loop below */
2241 sub edx, bpp /* edx ==> Raw(x-bpp) */
2242 davg1lp:
2243 /* Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2) */
2244 xor eax, eax
2245 mov cl, [esi + ebx] /* load cl with Prior(x) */
2246 mov al, [edx + ebx] /* load al with Raw(x-bpp) */
2247 add ax, cx
2248 inc ebx
2249 shr ax, 1 /* divide by 2 */
2250 add al, [edi+ebx-1] /* Add Avg(x); -1 to offset inc ebx */
2251 cmp ebx, FullLength /* Check if at end of array */
2252 mov [edi+ebx-1], al /* Write back Raw(x); */
2253 /* mov does not affect flags; -1 to offset inc ebx */
2254 jb davg1lp
2255 davg1end:
2256 } /* end _asm block */
2257 }
2258 return;
2259
2260 case 8: /* bpp == 8 */
2261 {
2262 _asm {
2263 /* Re-init address pointers and offset */
2264 mov ebx, diff /* ebx ==> x = offset to alignment boundary */
2265 movq mm5, LBCarryMask
2266 mov edi, row /* edi ==> Avg(x) */
2267 movq mm4, HBClearMask
2268 mov esi, prev_row /* esi ==> Prior(x) */
2269 /* PRIME the pump (load the first Raw(x-bpp) data set */
2270 movq mm2, [edi + ebx - 8] /* Load previous aligned 8 bytes */
2271 /* (NO NEED to correct position in loop below) */
2272 davg8lp:
2273 movq mm0, [edi + ebx]
2274 movq mm3, mm5
2275 movq mm1, [esi + ebx]
2276 add ebx, 8
2277 pand mm3, mm1 /* get lsb for each prev_row byte */
2278 psrlq mm1, 1 /* divide prev_row bytes by 2 */
2279 pand mm3, mm2 /* get LBCarrys for each byte where both */
2280 /* lsb's were == 1 */
2281 psrlq mm2, 1 /* divide raw bytes by 2 */
2282 pand mm1, mm4 /* clear invalid bit 7 of each byte */
2283 paddb mm0, mm3 /* add LBCarrys to Avg for each byte */
2284 pand mm2, mm4 /* clear invalid bit 7 of each byte */
2285 paddb mm0, mm1 /* add (Prev_row/2) to Avg for each byte */
2286 paddb mm0, mm2 /* add (Raw/2) to Avg for each byte */
2287 cmp ebx, MMXLength
2288 movq [edi + ebx - 8], mm0
2289 movq mm2, mm0 /* reuse as Raw(x-bpp) */
2290 jb davg8lp
2291 } /* end _asm block */
2292 }
2293 break;
2294 default: /* bpp greater than 8 */
2295 {
2296 _asm {
2297 movq mm5, LBCarryMask
2298 /* Re-init address pointers and offset */
2299 mov ebx, diff /* ebx ==> x = offset to alignment boundary */
2300 mov edi, row /* edi ==> Avg(x) */
2301 movq mm4, HBClearMask
2302 mov edx, edi
2303 mov esi, prev_row /* esi ==> Prior(x) */
2304 sub edx, bpp /* edx ==> Raw(x-bpp) */
2305 davgAlp:
2306 movq mm0, [edi + ebx]
2307 movq mm3, mm5
2308 movq mm1, [esi + ebx]
2309 pand mm3, mm1 /* get lsb for each prev_row byte */
2310 movq mm2, [edx + ebx]
2311 psrlq mm1, 1 /* divide prev_row bytes by 2 */
2312 pand mm3, mm2 /* get LBCarrys for each byte where both */
2313 /* lsb's were == 1 */
2314 psrlq mm2, 1 /* divide raw bytes by 2 */
2315 pand mm1, mm4 /* clear invalid bit 7 of each byte */
2316 paddb mm0, mm3 /* add LBCarrys to Avg for each byte */
2317 pand mm2, mm4 /* clear invalid bit 7 of each byte */
2318 paddb mm0, mm1 /* add (Prev_row/2) to Avg for each byte */
2319 add ebx, 8
2320 paddb mm0, mm2 /* add (Raw/2) to Avg for each byte */
2321 cmp ebx, MMXLength
2322 movq [edi + ebx - 8], mm0
2323 jb davgAlp
2324 } /* end _asm block */
2325 }
2326 break;
2327 } /* end switch ( bpp ) */
2328
2329 _asm {
2330 /* MMX acceleration complete now do clean-up */
2331 /* Check if any remaining bytes left to decode */
2332 mov ebx, MMXLength /* ebx ==> x = offset bytes remaining after MMX */
2333 mov edi, row /* edi ==> Avg(x) */
2334 cmp ebx, FullLength /* Test if offset at end of array */
2335 jnb davgend
2336 /* Do Paeth decode for remaining bytes */
2337 mov esi, prev_row /* esi ==> Prior(x) */
2338 mov edx, edi
2339 xor ecx, ecx /* zero ecx before using cl & cx in loop below */
2340 sub edx, bpp /* edx ==> Raw(x-bpp) */
2341 davglp2:
2342 /* Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2) */
2343 xor eax, eax
2344 mov cl, [esi + ebx] /* load cl with Prior(x) */
2345 mov al, [edx + ebx] /* load al with Raw(x-bpp) */
2346 add ax, cx
2347 inc ebx
2348 shr ax, 1 /* divide by 2 */
2349 add al, [edi+ebx-1] /* Add Avg(x); -1 to offset inc ebx */
2350 cmp ebx, FullLength /* Check if at end of array */
2351 mov [edi+ebx-1], al /* Write back Raw(x); */
2352 /* mov does not affect flags; -1 to offset inc ebx */
2353 jb davglp2
2354 davgend:
2355 emms /* End MMX instructions; prep for possible FP instrs. */
2356 } /* end _asm block */
2357 }
2358
2359 /* Optimized code for PNG Paeth filter decoder */
2360 void /* PRIVATE */
2361 png_read_filter_row_mmx_paeth(png_row_infop row_info, png_bytep row,
2362 png_bytep prev_row)
2363 {
2364 png_uint_32 FullLength;
2365 png_uint_32 MMXLength;
2366 /*png_uint_32 len; */
2367 int bpp;
2368 int diff;
2369 /*int ptemp; */
2370 int patemp, pbtemp, pctemp;
2371
2372 bpp = (row_info->pixel_depth + 7) >> 3; /* Get # bytes per pixel */
2373 FullLength = row_info->rowbytes; /* # of bytes to filter */
2374 _asm
2375 {
2376 xor ebx, ebx /* ebx ==> x offset */
2377 mov edi, row
2378 xor edx, edx /* edx ==> x-bpp offset */
2379 mov esi, prev_row
2380 xor eax, eax
2381
2382 /* Compute the Raw value for the first bpp bytes */
2383 /* Note: the formula works out to be always */
2384 /* Paeth(x) = Raw(x) + Prior(x) where x < bpp */
2385 dpthrlp:
2386 mov al, [edi + ebx]
2387 add al, [esi + ebx]
2388 inc ebx
2389 cmp ebx, bpp
2390 mov [edi + ebx - 1], al
2391 jb dpthrlp
2392 /* get # of bytes to alignment */
2393 mov diff, edi /* take start of row */
2394 add diff, ebx /* add bpp */
2395 xor ecx, ecx
2396 add diff, 0xf /* add 7 + 8 to incr past alignment boundary */
2397 and diff, 0xfffffff8 /* mask to alignment boundary */
2398 sub diff, edi /* subtract from start ==> value ebx at alignment */
2399 jz dpthgo
2400 /* fix alignment */
2401 dpthlp1:
2402 xor eax, eax
2403 /* pav = p - a = (a + b - c) - a = b - c */
2404 mov al, [esi + ebx] /* load Prior(x) into al */
2405 mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
2406 sub eax, ecx /* subtract Prior(x-bpp) */
2407 mov patemp, eax /* Save pav for later use */
2408 xor eax, eax
2409 /* pbv = p - b = (a + b - c) - b = a - c */
2410 mov al, [edi + edx] /* load Raw(x-bpp) into al */
2411 sub eax, ecx /* subtract Prior(x-bpp) */
2412 mov ecx, eax
2413 /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
2414 add eax, patemp /* pcv = pav + pbv */
2415 /* pc = abs(pcv) */
2416 test eax, 0x80000000
2417 jz dpthpca
2418 neg eax /* reverse sign of neg values */
2419 dpthpca:
2420 mov pctemp, eax /* save pc for later use */
2421 /* pb = abs(pbv) */
2422 test ecx, 0x80000000
2423 jz dpthpba
2424 neg ecx /* reverse sign of neg values */
2425 dpthpba:
2426 mov pbtemp, ecx /* save pb for later use */
2427 /* pa = abs(pav) */
2428 mov eax, patemp
2429 test eax, 0x80000000
2430 jz dpthpaa
2431 neg eax /* reverse sign of neg values */
2432 dpthpaa:
2433 mov patemp, eax /* save pa for later use */
2434 /* test if pa <= pb */
2435 cmp eax, ecx
2436 jna dpthabb
2437 /* pa > pb; now test if pb <= pc */
2438 cmp ecx, pctemp
2439 jna dpthbbc
2440 /* pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp) */
2441 mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
2442 jmp dpthpaeth
2443 dpthbbc:
2444 /* pb <= pc; Raw(x) = Paeth(x) + Prior(x) */
2445 mov cl, [esi + ebx] /* load Prior(x) into cl */
2446 jmp dpthpaeth
2447 dpthabb:
2448 /* pa <= pb; now test if pa <= pc */
2449 cmp eax, pctemp
2450 jna dpthabc
2451 /* pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp) */
2452 mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
2453 jmp dpthpaeth
2454 dpthabc:
2455 /* pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp) */
2456 mov cl, [edi + edx] /* load Raw(x-bpp) into cl */
2457 dpthpaeth:
2458 inc ebx
2459 inc edx
2460 /* Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256 */
2461 add [edi + ebx - 1], cl
2462 cmp ebx, diff
2463 jb dpthlp1
2464 dpthgo:
2465 mov ecx, FullLength
2466 mov eax, ecx
2467 sub eax, ebx /* subtract alignment fix */
2468 and eax, 0x00000007 /* calc bytes over mult of 8 */
2469 sub ecx, eax /* drop over bytes from original length */
2470 mov MMXLength, ecx
2471 } /* end _asm block */
2472 /* Now do the math for the rest of the row */
2473 switch ( bpp )
2474 {
2475 case 3:
2476 {
2477 ActiveMask.use = 0x0000000000ffffff;
2478 ActiveMaskEnd.use = 0xffff000000000000;
2479 ShiftBpp.use = 24; /* == bpp(3) * 8 */
2480 ShiftRem.use = 40; /* == 64 - 24 */
2481 _asm
2482 {
2483 mov ebx, diff
2484 mov edi, row
2485 mov esi, prev_row
2486 pxor mm0, mm0
2487 /* PRIME the pump (load the first Raw(x-bpp) data set */
2488 movq mm1, [edi+ebx-8]
2489 dpth3lp:
2490 psrlq mm1, ShiftRem /* shift last 3 bytes to 1st 3 bytes */
2491 movq mm2, [esi + ebx] /* load b=Prior(x) */
2492 punpcklbw mm1, mm0 /* Unpack High bytes of a */
2493 movq mm3, [esi+ebx-8] /* Prep c=Prior(x-bpp) bytes */
2494 punpcklbw mm2, mm0 /* Unpack High bytes of b */
2495 psrlq mm3, ShiftRem /* shift last 3 bytes to 1st 3 bytes */
2496 /* pav = p - a = (a + b - c) - a = b - c */
2497 movq mm4, mm2
2498 punpcklbw mm3, mm0 /* Unpack High bytes of c */
2499 /* pbv = p - b = (a + b - c) - b = a - c */
2500 movq mm5, mm1
2501 psubw mm4, mm3
2502 pxor mm7, mm7
2503 /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
2504 movq mm6, mm4
2505 psubw mm5, mm3
2506
2507 /* pa = abs(p-a) = abs(pav) */
2508 /* pb = abs(p-b) = abs(pbv) */
2509 /* pc = abs(p-c) = abs(pcv) */
2510 pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
2511 paddw mm6, mm5
2512 pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
2513 pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
2514 psubw mm4, mm0
2515 pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
2516 psubw mm4, mm0
2517 psubw mm5, mm7
2518 pxor mm0, mm0
2519 pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
2520 pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
2521 psubw mm5, mm7
2522 psubw mm6, mm0
2523 /* test pa <= pb */
2524 movq mm7, mm4
2525 psubw mm6, mm0
2526 pcmpgtw mm7, mm5 /* pa > pb? */
2527 movq mm0, mm7
2528 /* use mm7 mask to merge pa & pb */
2529 pand mm5, mm7
2530 /* use mm0 mask copy to merge a & b */
2531 pand mm2, mm0
2532 pandn mm7, mm4
2533 pandn mm0, mm1
2534 paddw mm7, mm5
2535 paddw mm0, mm2
2536 /* test ((pa <= pb)? pa:pb) <= pc */
2537 pcmpgtw mm7, mm6 /* pab > pc? */
2538 pxor mm1, mm1
2539 pand mm3, mm7
2540 pandn mm7, mm0
2541 paddw mm7, mm3
2542 pxor mm0, mm0
2543 packuswb mm7, mm1
2544 movq mm3, [esi + ebx] /* load c=Prior(x-bpp) */
2545 pand mm7, ActiveMask
2546 movq mm2, mm3 /* load b=Prior(x) step 1 */
2547 paddb mm7, [edi + ebx] /* add Paeth predictor with Raw(x) */
2548 punpcklbw mm3, mm0 /* Unpack High bytes of c */
2549 movq [edi + ebx], mm7 /* write back updated value */
2550 movq mm1, mm7 /* Now mm1 will be used as Raw(x-bpp) */
2551 /* Now do Paeth for 2nd set of bytes (3-5) */
2552 psrlq mm2, ShiftBpp /* load b=Prior(x) step 2 */
2553 punpcklbw mm1, mm0 /* Unpack High bytes of a */
2554 pxor mm7, mm7
2555 punpcklbw mm2, mm0 /* Unpack High bytes of b */
2556 /* pbv = p - b = (a + b - c) - b = a - c */
2557 movq mm5, mm1
2558 /* pav = p - a = (a + b - c) - a = b - c */
2559 movq mm4, mm2
2560 psubw mm5, mm3
2561 psubw mm4, mm3
2562 /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = */
2563 /* pav + pbv = pbv + pav */
2564 movq mm6, mm5
2565 paddw mm6, mm4
2566
2567 /* pa = abs(p-a) = abs(pav) */
2568 /* pb = abs(p-b) = abs(pbv) */
2569 /* pc = abs(p-c) = abs(pcv) */
2570 pcmpgtw mm0, mm5 /* Create mask pbv bytes < 0 */
2571 pcmpgtw mm7, mm4 /* Create mask pav bytes < 0 */
2572 pand mm0, mm5 /* Only pbv bytes < 0 in mm0 */
2573 pand mm7, mm4 /* Only pav bytes < 0 in mm7 */
2574 psubw mm5, mm0
2575 psubw mm4, mm7
2576 psubw mm5, mm0
2577 psubw mm4, mm7
2578 pxor mm0, mm0
2579 pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
2580 pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
2581 psubw mm6, mm0
2582 /* test pa <= pb */
2583 movq mm7, mm4
2584 psubw mm6, mm0
2585 pcmpgtw mm7, mm5 /* pa > pb? */
2586 movq mm0, mm7
2587 /* use mm7 mask to merge pa & pb */
2588 pand mm5, mm7
2589 /* use mm0 mask copy to merge a & b */
2590 pand mm2, mm0
2591 pandn mm7, mm4
2592 pandn mm0, mm1
2593 paddw mm7, mm5
2594 paddw mm0, mm2
2595 /* test ((pa <= pb)? pa:pb) <= pc */
2596 pcmpgtw mm7, mm6 /* pab > pc? */
2597 movq mm2, [esi + ebx] /* load b=Prior(x) */
2598 pand mm3, mm7
2599 pandn mm7, mm0
2600 pxor mm1, mm1
2601 paddw mm7, mm3
2602 pxor mm0, mm0
2603 packuswb mm7, mm1
2604 movq mm3, mm2 /* load c=Prior(x-bpp) step 1 */
2605 pand mm7, ActiveMask
2606 punpckhbw mm2, mm0 /* Unpack High bytes of b */
2607 psllq mm7, ShiftBpp /* Shift bytes to 2nd group of 3 bytes */
2608 /* pav = p - a = (a + b - c) - a = b - c */
2609 movq mm4, mm2
2610 paddb mm7, [edi + ebx] /* add Paeth predictor with Raw(x) */
2611 psllq mm3, ShiftBpp /* load c=Prior(x-bpp) step 2 */
2612 movq [edi + ebx], mm7 /* write back updated value */
2613 movq mm1, mm7
2614 punpckhbw mm3, mm0 /* Unpack High bytes of c */
2615 psllq mm1, ShiftBpp /* Shift bytes */
2616 /* Now mm1 will be used as Raw(x-bpp) */
2617 /* Now do Paeth for 3rd, and final, set of bytes (6-7) */
2618 pxor mm7, mm7
2619 punpckhbw mm1, mm0 /* Unpack High bytes of a */
2620 psubw mm4, mm3
2621 /* pbv = p - b = (a + b - c) - b = a - c */
2622 movq mm5, mm1
2623 /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
2624 movq mm6, mm4
2625 psubw mm5, mm3
2626 pxor mm0, mm0
2627 paddw mm6, mm5
2628
2629 /* pa = abs(p-a) = abs(pav) */
2630 /* pb = abs(p-b) = abs(pbv) */
2631 /* pc = abs(p-c) = abs(pcv) */
2632 pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
2633 pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
2634 pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
2635 pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
2636 psubw mm4, mm0
2637 psubw mm5, mm7
2638 psubw mm4, mm0
2639 psubw mm5, mm7
2640 pxor mm0, mm0
2641 pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
2642 pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
2643 psubw mm6, mm0
2644 /* test pa <= pb */
2645 movq mm7, mm4
2646 psubw mm6, mm0
2647 pcmpgtw mm7, mm5 /* pa > pb? */
2648 movq mm0, mm7
2649 /* use mm0 mask copy to merge a & b */
2650 pand mm2, mm0
2651 /* use mm7 mask to merge pa & pb */
2652 pand mm5, mm7
2653 pandn mm0, mm1
2654 pandn mm7, mm4
2655 paddw mm0, mm2
2656 paddw mm7, mm5
2657 /* test ((pa <= pb)? pa:pb) <= pc */
2658 pcmpgtw mm7, mm6 /* pab > pc? */
2659 pand mm3, mm7
2660 pandn mm7, mm0
2661 paddw mm7, mm3
2662 pxor mm1, mm1
2663 packuswb mm1, mm7
2664 /* Step ebx to next set of 8 bytes and repeat loop til done */
2665 add ebx, 8
2666 pand mm1, ActiveMaskEnd
2667 paddb mm1, [edi + ebx - 8] /* add Paeth predictor with Raw(x) */
2668
2669 cmp ebx, MMXLength
2670 pxor mm0, mm0 /* pxor does not affect flags */
2671 movq [edi + ebx - 8], mm1 /* write back updated value */
2672 /* mm1 will be used as Raw(x-bpp) next loop */
2673 /* mm3 ready to be used as Prior(x-bpp) next loop */
2674 jb dpth3lp
2675 } /* end _asm block */
2676 }
2677 break;
2678
2679 case 6:
2680 case 7:
2681 case 5:
2682 {
2683 ActiveMask.use = 0x00000000ffffffff;
2684 ActiveMask2.use = 0xffffffff00000000;
2685 ShiftBpp.use = bpp << 3; /* == bpp * 8 */
2686 ShiftRem.use = 64 - ShiftBpp.use;
2687 _asm
2688 {
2689 mov ebx, diff
2690 mov edi, row
2691 mov esi, prev_row
2692 /* PRIME the pump (load the first Raw(x-bpp) data set */
2693 movq mm1, [edi+ebx-8]
2694 pxor mm0, mm0
2695 dpth6lp:
2696 /* Must shift to position Raw(x-bpp) data */
2697 psrlq mm1, ShiftRem
2698 /* Do first set of 4 bytes */
2699 movq mm3, [esi+ebx-8] /* read c=Prior(x-bpp) bytes */
2700 punpcklbw mm1, mm0 /* Unpack Low bytes of a */
2701 movq mm2, [esi + ebx] /* load b=Prior(x) */
2702 punpcklbw mm2, mm0 /* Unpack Low bytes of b */
2703 /* Must shift to position Prior(x-bpp) data */
2704 psrlq mm3, ShiftRem
2705 /* pav = p - a = (a + b - c) - a = b - c */
2706 movq mm4, mm2
2707 punpcklbw mm3, mm0 /* Unpack Low bytes of c */
2708 /* pbv = p - b = (a + b - c) - b = a - c */
2709 movq mm5, mm1
2710 psubw mm4, mm3
2711 pxor mm7, mm7
2712 /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
2713 movq mm6, mm4
2714 psubw mm5, mm3
2715 /* pa = abs(p-a) = abs(pav) */
2716 /* pb = abs(p-b) = abs(pbv) */
2717 /* pc = abs(p-c) = abs(pcv) */
2718 pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
2719 paddw mm6, mm5
2720 pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
2721 pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
2722 psubw mm4, mm0
2723 pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
2724 psubw mm4, mm0
2725 psubw mm5, mm7
2726 pxor mm0, mm0
2727 pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
2728 pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
2729 psubw mm5, mm7
2730 psubw mm6, mm0
2731 /* test pa <= pb */
2732 movq mm7, mm4
2733 psubw mm6, mm0
2734 pcmpgtw mm7, mm5 /* pa > pb? */
2735 movq mm0, mm7
2736 /* use mm7 mask to merge pa & pb */
2737 pand mm5, mm7
2738 /* use mm0 mask copy to merge a & b */
2739 pand mm2, mm0
2740 pandn mm7, mm4
2741 pandn mm0, mm1
2742 paddw mm7, mm5
2743 paddw mm0, mm2
2744 /* test ((pa <= pb)? pa:pb) <= pc */
2745 pcmpgtw mm7, mm6 /* pab > pc? */
2746 pxor mm1, mm1
2747 pand mm3, mm7
2748 pandn mm7, mm0
2749 paddw mm7, mm3
2750 pxor mm0, mm0
2751 packuswb mm7, mm1
2752 movq mm3, [esi + ebx - 8] /* load c=Prior(x-bpp) */
2753 pand mm7, ActiveMask
2754 psrlq mm3, ShiftRem
2755 movq mm2, [esi + ebx] /* load b=Prior(x) step 1 */
2756 paddb mm7, [edi + ebx] /* add Paeth predictor with Raw(x) */
2757 movq mm6, mm2
2758 movq [edi + ebx], mm7 /* write back updated value */
2759 movq mm1, [edi+ebx-8]
2760 psllq mm6, ShiftBpp
2761 movq mm5, mm7
2762 psrlq mm1, ShiftRem
2763 por mm3, mm6
2764 psllq mm5, ShiftBpp
2765 punpckhbw mm3, mm0 /* Unpack High bytes of c */
2766 por mm1, mm5
2767 /* Do second set of 4 bytes */
2768 punpckhbw mm2, mm0 /* Unpack High bytes of b */
2769 punpckhbw mm1, mm0 /* Unpack High bytes of a */
2770 /* pav = p - a = (a + b - c) - a = b - c */
2771 movq mm4, mm2
2772 /* pbv = p - b = (a + b - c) - b = a - c */
2773 movq mm5, mm1
2774 psubw mm4, mm3
2775 pxor mm7, mm7
2776 /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
2777 movq mm6, mm4
2778 psubw mm5, mm3
2779 /* pa = abs(p-a) = abs(pav) */
2780 /* pb = abs(p-b) = abs(pbv) */
2781 /* pc = abs(p-c) = abs(pcv) */
2782 pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
2783 paddw mm6, mm5
2784 pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
2785 pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
2786 psubw mm4, mm0
2787 pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
2788 psubw mm4, mm0
2789 psubw mm5, mm7
2790 pxor mm0, mm0
2791 pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
2792 pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
2793 psubw mm5, mm7
2794 psubw mm6, mm0
2795 /* test pa <= pb */
2796 movq mm7, mm4
2797 psubw mm6, mm0
2798 pcmpgtw mm7, mm5 /* pa > pb? */
2799 movq mm0, mm7
2800 /* use mm7 mask to merge pa & pb */
2801 pand mm5, mm7
2802 /* use mm0 mask copy to merge a & b */
2803 pand mm2, mm0
2804 pandn mm7, mm4
2805 pandn mm0, mm1
2806 paddw mm7, mm5
2807 paddw mm0, mm2
2808 /* test ((pa <= pb)? pa:pb) <= pc */
2809 pcmpgtw mm7, mm6 /* pab > pc? */
2810 pxor mm1, mm1
2811 pand mm3, mm7
2812 pandn mm7, mm0
2813 pxor mm1, mm1
2814 paddw mm7, mm3
2815 pxor mm0, mm0
2816 /* Step ex to next set of 8 bytes and repeat loop til done */
2817 add ebx, 8
2818 packuswb mm1, mm7
2819 paddb mm1, [edi + ebx - 8] /* add Paeth predictor with Raw(x) */
2820 cmp ebx, MMXLength
2821 movq [edi + ebx - 8], mm1 /* write back updated value */
2822 /* mm1 will be used as Raw(x-bpp) next loop */
2823 jb dpth6lp
2824 } /* end _asm block */
2825 }
2826 break;
2827
2828 case 4:
2829 {
2830 ActiveMask.use = 0x00000000ffffffff;
2831 _asm {
2832 mov ebx, diff
2833 mov edi, row
2834 mov esi, prev_row
2835 pxor mm0, mm0
2836 /* PRIME the pump (load the first Raw(x-bpp) data set */
2837 movq mm1, [edi+ebx-8] /* Only time should need to read */
2838 /* a=Raw(x-bpp) bytes */
2839 dpth4lp:
2840 /* Do first set of 4 bytes */
2841 movq mm3, [esi+ebx-8] /* read c=Prior(x-bpp) bytes */
2842 punpckhbw mm1, mm0 /* Unpack Low bytes of a */
2843 movq mm2, [esi + ebx] /* load b=Prior(x) */
2844 punpcklbw mm2, mm0 /* Unpack High bytes of b */
2845 /* pav = p - a = (a + b - c) - a = b - c */
2846 movq mm4, mm2
2847 punpckhbw mm3, mm0 /* Unpack High bytes of c */
2848 /* pbv = p - b = (a + b - c) - b = a - c */
2849 movq mm5, mm1
2850 psubw mm4, mm3
2851 pxor mm7, mm7
2852 /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
2853 movq mm6, mm4
2854 psubw mm5, mm3
2855 /* pa = abs(p-a) = abs(pav) */
2856 /* pb = abs(p-b) = abs(pbv) */
2857 /* pc = abs(p-c) = abs(pcv) */
2858 pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
2859 paddw mm6, mm5
2860 pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
2861 pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
2862 psubw mm4, mm0
2863 pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
2864 psubw mm4, mm0
2865 psubw mm5, mm7
2866 pxor mm0, mm0
2867 pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
2868 pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
2869 psubw mm5, mm7
2870 psubw mm6, mm0
2871 /* test pa <= pb */
2872 movq mm7, mm4
2873 psubw mm6, mm0
2874 pcmpgtw mm7, mm5 /* pa > pb? */
2875 movq mm0, mm7
2876 /* use mm7 mask to merge pa & pb */
2877 pand mm5, mm7
2878 /* use mm0 mask copy to merge a & b */
2879 pand mm2, mm0
2880 pandn mm7, mm4
2881 pandn mm0, mm1
2882 paddw mm7, mm5
2883 paddw mm0, mm2
2884 /* test ((pa <= pb)? pa:pb) <= pc */
2885 pcmpgtw mm7, mm6 /* pab > pc? */
2886 pxor mm1, mm1
2887 pand mm3, mm7
2888 pandn mm7, mm0
2889 paddw mm7, mm3
2890 pxor mm0, mm0
2891 packuswb mm7, mm1
2892 movq mm3, [esi + ebx] /* load c=Prior(x-bpp) */
2893 pand mm7, ActiveMask
2894 movq mm2, mm3 /* load b=Prior(x) step 1 */
2895 paddb mm7, [edi + ebx] /* add Paeth predictor with Raw(x) */
2896 punpcklbw mm3, mm0 /* Unpack High bytes of c */
2897 movq [edi + ebx], mm7 /* write back updated value */
2898 movq mm1, mm7 /* Now mm1 will be used as Raw(x-bpp) */
2899 /* Do second set of 4 bytes */
2900 punpckhbw mm2, mm0 /* Unpack Low bytes of b */
2901 punpcklbw mm1, mm0 /* Unpack Low bytes of a */
2902 /* pav = p - a = (a + b - c) - a = b - c */
2903 movq mm4, mm2
2904 /* pbv = p - b = (a + b - c) - b = a - c */
2905 movq mm5, mm1
2906 psubw mm4, mm3
2907 pxor mm7, mm7
2908 /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
2909 movq mm6, mm4
2910 psubw mm5, mm3
2911 /* pa = abs(p-a) = abs(pav) */
2912 /* pb = abs(p-b) = abs(pbv) */
2913 /* pc = abs(p-c) = abs(pcv) */
2914 pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
2915 paddw mm6, mm5
2916 pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
2917 pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
2918 psubw mm4, mm0
2919 pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
2920 psubw mm4, mm0
2921 psubw mm5, mm7
2922 pxor mm0, mm0
2923 pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
2924 pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
2925 psubw mm5, mm7
2926 psubw mm6, mm0
2927 /* test pa <= pb */
2928 movq mm7, mm4
2929 psubw mm6, mm0
2930 pcmpgtw mm7, mm5 /* pa > pb? */
2931 movq mm0, mm7
2932 /* use mm7 mask to merge pa & pb */
2933 pand mm5, mm7
2934 /* use mm0 mask copy to merge a & b */
2935 pand mm2, mm0
2936 pandn mm7, mm4
2937 pandn mm0, mm1
2938 paddw mm7, mm5
2939 paddw mm0, mm2
2940 /* test ((pa <= pb)? pa:pb) <= pc */
2941 pcmpgtw mm7, mm6 /* pab > pc? */
2942 pxor mm1, mm1
2943 pand mm3, mm7
2944 pandn mm7, mm0
2945 pxor mm1, mm1
2946 paddw mm7, mm3
2947 pxor mm0, mm0
2948 /* Step ex to next set of 8 bytes and repeat loop til done */
2949 add ebx, 8
2950 packuswb mm1, mm7
2951 paddb mm1, [edi + ebx - 8] /* add Paeth predictor with Raw(x) */
2952 cmp ebx, MMXLength
2953 movq [edi + ebx - 8], mm1 /* write back updated value */
2954 /* mm1 will be used as Raw(x-bpp) next loop */
2955 jb dpth4lp
2956 } /* end _asm block */
2957 }
2958 break;
2959 case 8: /* bpp == 8 */
2960 {
2961 ActiveMask.use = 0x00000000ffffffff;
2962 _asm {
2963 mov ebx, diff
2964 mov edi, row
2965 mov esi, prev_row
2966 pxor mm0, mm0
2967 /* PRIME the pump (load the first Raw(x-bpp) data set */
2968 movq mm1, [edi+ebx-8] /* Only time should need to read */
2969 /* a=Raw(x-bpp) bytes */
2970 dpth8lp:
2971 /* Do first set of 4 bytes */
2972 movq mm3, [esi+ebx-8] /* read c=Prior(x-bpp) bytes */
2973 punpcklbw mm1, mm0 /* Unpack Low bytes of a */
2974 movq mm2, [esi + ebx] /* load b=Prior(x) */
2975 punpcklbw mm2, mm0 /* Unpack Low bytes of b */
2976 /* pav = p - a = (a + b - c) - a = b - c */
2977 movq mm4, mm2
2978 punpcklbw mm3, mm0 /* Unpack Low bytes of c */
2979 /* pbv = p - b = (a + b - c) - b = a - c */
2980 movq mm5, mm1
2981 psubw mm4, mm3
2982 pxor mm7, mm7
2983 /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
2984 movq mm6, mm4
2985 psubw mm5, mm3
2986 /* pa = abs(p-a) = abs(pav) */
2987 /* pb = abs(p-b) = abs(pbv) */
2988 /* pc = abs(p-c) = abs(pcv) */
2989 pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
2990 paddw mm6, mm5
2991 pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
2992 pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
2993 psubw mm4, mm0
2994 pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
2995 psubw mm4, mm0
2996 psubw mm5, mm7
2997 pxor mm0, mm0
2998 pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
2999 pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
3000 psubw mm5, mm7
3001 psubw mm6, mm0
3002 /* test pa <= pb */
3003 movq mm7, mm4
3004 psubw mm6, mm0
3005 pcmpgtw mm7, mm5 /* pa > pb? */
3006 movq mm0, mm7
3007 /* use mm7 mask to merge pa & pb */
3008 pand mm5, mm7
3009 /* use mm0 mask copy to merge a & b */
3010 pand mm2, mm0
3011 pandn mm7, mm4
3012 pandn mm0, mm1
3013 paddw mm7, mm5
3014 paddw mm0, mm2
3015 /* test ((pa <= pb)? pa:pb) <= pc */
3016 pcmpgtw mm7, mm6 /* pab > pc? */
3017 pxor mm1, mm1
3018 pand mm3, mm7
3019 pandn mm7, mm0
3020 paddw mm7, mm3
3021 pxor mm0, mm0
3022 packuswb mm7, mm1
3023 movq mm3, [esi+ebx-8] /* read c=Prior(x-bpp) bytes */
3024 pand mm7, ActiveMask
3025 movq mm2, [esi + ebx] /* load b=Prior(x) */
3026 paddb mm7, [edi + ebx] /* add Paeth predictor with Raw(x) */
3027 punpckhbw mm3, mm0 /* Unpack High bytes of c */
3028 movq [edi + ebx], mm7 /* write back updated value */
3029 movq mm1, [edi+ebx-8] /* read a=Raw(x-bpp) bytes */
3030
3031 /* Do second set of 4 bytes */
3032 punpckhbw mm2, mm0 /* Unpack High bytes of b */
3033 punpckhbw mm1, mm0 /* Unpack High bytes of a */
3034 /* pav = p - a = (a + b - c) - a = b - c */
3035 movq mm4, mm2
3036 /* pbv = p - b = (a + b - c) - b = a - c */
3037 movq mm5, mm1
3038 psubw mm4, mm3
3039 pxor mm7, mm7
3040 /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
3041 movq mm6, mm4
3042 psubw mm5, mm3
3043 /* pa = abs(p-a) = abs(pav) */
3044 /* pb = abs(p-b) = abs(pbv) */
3045 /* pc = abs(p-c) = abs(pcv) */
3046 pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
3047 paddw mm6, mm5
3048 pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
3049 pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
3050 psubw mm4, mm0
3051 pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
3052 psubw mm4, mm0
3053 psubw mm5, mm7
3054 pxor mm0, mm0
3055 pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
3056 pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
3057 psubw mm5, mm7
3058 psubw mm6, mm0
3059 /* test pa <= pb */
3060 movq mm7, mm4
3061 psubw mm6, mm0
3062 pcmpgtw mm7, mm5 /* pa > pb? */
3063 movq mm0, mm7
3064 /* use mm7 mask to merge pa & pb */
3065 pand mm5, mm7
3066 /* use mm0 mask copy to merge a & b */
3067 pand mm2, mm0
3068 pandn mm7, mm4
3069 pandn mm0, mm1
3070 paddw mm7, mm5
3071 paddw mm0, mm2
3072 /* test ((pa <= pb)? pa:pb) <= pc */
3073 pcmpgtw mm7, mm6 /* pab > pc? */
3074 pxor mm1, mm1
3075 pand mm3, mm7
3076 pandn mm7, mm0
3077 pxor mm1, mm1
3078 paddw mm7, mm3
3079 pxor mm0, mm0
3080 /* Step ex to next set of 8 bytes and repeat loop til done */
3081 add ebx, 8
3082 packuswb mm1, mm7
3083 paddb mm1, [edi + ebx - 8] /* add Paeth predictor with Raw(x) */
3084 cmp ebx, MMXLength
3085 movq [edi + ebx - 8], mm1 /* write back updated value */
3086 /* mm1 will be used as Raw(x-bpp) next loop */
3087 jb dpth8lp
3088 } /* end _asm block */
3089 }
3090 break;
3091
3092 case 1: /* bpp = 1 */
3093 case 2: /* bpp = 2 */
3094 default: /* bpp > 8 */
3095 {
3096 _asm {
3097 mov ebx, diff
3098 cmp ebx, FullLength
3099 jnb dpthdend
3100 mov edi, row
3101 mov esi, prev_row
3102 /* Do Paeth decode for remaining bytes */
3103 mov edx, ebx
3104 xor ecx, ecx /* zero ecx before using cl & cx in loop below */
3105 sub edx, bpp /* Set edx = ebx - bpp */
3106 dpthdlp:
3107 xor eax, eax
3108 /* pav = p - a = (a + b - c) - a = b - c */
3109 mov al, [esi + ebx] /* load Prior(x) into al */
3110 mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
3111 sub eax, ecx /* subtract Prior(x-bpp) */
3112 mov patemp, eax /* Save pav for later use */
3113 xor eax, eax
3114 /* pbv = p - b = (a + b - c) - b = a - c */
3115 mov al, [edi + edx] /* load Raw(x-bpp) into al */
3116 sub eax, ecx /* subtract Prior(x-bpp) */
3117 mov ecx, eax
3118 /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
3119 add eax, patemp /* pcv = pav + pbv */
3120 /* pc = abs(pcv) */
3121 test eax, 0x80000000
3122 jz dpthdpca
3123 neg eax /* reverse sign of neg values */
3124 dpthdpca:
3125 mov pctemp, eax /* save pc for later use */
3126 /* pb = abs(pbv) */
3127 test ecx, 0x80000000
3128 jz dpthdpba
3129 neg ecx /* reverse sign of neg values */
3130 dpthdpba:
3131 mov pbtemp, ecx /* save pb for later use */
3132 /* pa = abs(pav) */
3133 mov eax, patemp
3134 test eax, 0x80000000
3135 jz dpthdpaa
3136 neg eax /* reverse sign of neg values */
3137 dpthdpaa:
3138 mov patemp, eax /* save pa for later use */
3139 /* test if pa <= pb */
3140 cmp eax, ecx
3141 jna dpthdabb
3142 /* pa > pb; now test if pb <= pc */
3143 cmp ecx, pctemp
3144 jna dpthdbbc
3145 /* pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp) */
3146 mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
3147 jmp dpthdpaeth
3148 dpthdbbc:
3149 /* pb <= pc; Raw(x) = Paeth(x) + Prior(x) */
3150 mov cl, [esi + ebx] /* load Prior(x) into cl */
3151 jmp dpthdpaeth
3152 dpthdabb:
3153 /* pa <= pb; now test if pa <= pc */
3154 cmp eax, pctemp
3155 jna dpthdabc
3156 /* pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp) */
3157 mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
3158 jmp dpthdpaeth
3159 dpthdabc:
3160 /* pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp) */
3161 mov cl, [edi + edx] /* load Raw(x-bpp) into cl */
3162 dpthdpaeth:
3163 inc ebx
3164 inc edx
3165 /* Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256 */
3166 add [edi + ebx - 1], cl
3167 cmp ebx, FullLength
3168 jb dpthdlp
3169 dpthdend:
3170 } /* end _asm block */
3171 }
3172 return; /* No need to go further with this one */
3173 } /* end switch ( bpp ) */
3174 _asm
3175 {
3176 /* MMX acceleration complete now do clean-up */
3177 /* Check if any remaining bytes left to decode */
3178 mov ebx, MMXLength
3179 cmp ebx, FullLength
3180 jnb dpthend
3181 mov edi, row
3182 mov esi, prev_row
3183 /* Do Paeth decode for remaining bytes */
3184 mov edx, ebx
3185 xor ecx, ecx /* zero ecx before using cl & cx in loop below */
3186 sub edx, bpp /* Set edx = ebx - bpp */
3187 dpthlp2:
3188 xor eax, eax
3189 /* pav = p - a = (a + b - c) - a = b - c */
3190 mov al, [esi + ebx] /* load Prior(x) into al */
3191 mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
3192 sub eax, ecx /* subtract Prior(x-bpp) */
3193 mov patemp, eax /* Save pav for later use */
3194 xor eax, eax
3195 /* pbv = p - b = (a + b - c) - b = a - c */
3196 mov al, [edi + edx] /* load Raw(x-bpp) into al */
3197 sub eax, ecx /* subtract Prior(x-bpp) */
3198 mov ecx, eax
3199 /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
3200 add eax, patemp /* pcv = pav + pbv */
3201 /* pc = abs(pcv) */
3202 test eax, 0x80000000
3203 jz dpthpca2
3204 neg eax /* reverse sign of neg values */
3205 dpthpca2:
3206 mov pctemp, eax /* save pc for later use */
3207 /* pb = abs(pbv) */
3208 test ecx, 0x80000000
3209 jz dpthpba2
3210 neg ecx /* reverse sign of neg values */
3211 dpthpba2:
3212 mov pbtemp, ecx /* save pb for later use */
3213 /* pa = abs(pav) */
3214 mov eax, patemp
3215 test eax, 0x80000000
3216 jz dpthpaa2
3217 neg eax /* reverse sign of neg values */
3218 dpthpaa2:
3219 mov patemp, eax /* save pa for later use */
3220 /* test if pa <= pb */
3221 cmp eax, ecx
3222 jna dpthabb2
3223 /* pa > pb; now test if pb <= pc */
3224 cmp ecx, pctemp
3225 jna dpthbbc2
3226 /* pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp) */
3227 mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
3228 jmp dpthpaeth2
3229 dpthbbc2:
3230 /* pb <= pc; Raw(x) = Paeth(x) + Prior(x) */
3231 mov cl, [esi + ebx] /* load Prior(x) into cl */
3232 jmp dpthpaeth2
3233 dpthabb2:
3234 /* pa <= pb; now test if pa <= pc */
3235 cmp eax, pctemp
3236 jna dpthabc2
3237 /* pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp) */
3238 mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
3239 jmp dpthpaeth2
3240 dpthabc2:
3241 /* pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp) */
3242 mov cl, [edi + edx] /* load Raw(x-bpp) into cl */
3243 dpthpaeth2:
3244 inc ebx
3245 inc edx
3246 /* Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256 */
3247 add [edi + ebx - 1], cl
3248 cmp ebx, FullLength
3249 jb dpthlp2
3250 dpthend:
3251 emms /* End MMX instructions; prep for possible FP instrs. */
3252 } /* end _asm block */
3253 }
3254
3255 /* Optimized code for PNG Sub filter decoder */
3256 void /* PRIVATE */
3257 png_read_filter_row_mmx_sub(png_row_infop row_info, png_bytep row)
3258 {
3259 /*int test; */
3260 int bpp;
3261 png_uint_32 FullLength;
3262 png_uint_32 MMXLength;
3263 int diff;
3264
3265 bpp = (row_info->pixel_depth + 7) >> 3; /* Get # bytes per pixel */
3266 FullLength = row_info->rowbytes - bpp; /* # of bytes to filter */
3267 _asm {
3268 mov edi, row
3269 mov esi, edi /* lp = row */
3270 add edi, bpp /* rp = row + bpp */
3271 xor eax, eax
3272 /* get # of bytes to alignment */
3273 mov diff, edi /* take start of row */
3274 add diff, 0xf /* add 7 + 8 to incr past */
3275 /* alignment boundary */
3276 xor ebx, ebx
3277 and diff, 0xfffffff8 /* mask to alignment boundary */
3278 sub diff, edi /* subtract from start ==> value */
3279 /* ebx at alignment */
3280 jz dsubgo
3281 /* fix alignment */
3282 dsublp1:
3283 mov al, [esi+ebx]
3284 add [edi+ebx], al
3285 inc ebx
3286 cmp ebx, diff
3287 jb dsublp1
3288 dsubgo:
3289 mov ecx, FullLength
3290 mov edx, ecx
3291 sub edx, ebx /* subtract alignment fix */
3292 and edx, 0x00000007 /* calc bytes over mult of 8 */
3293 sub ecx, edx /* drop over bytes from length */
3294 mov MMXLength, ecx
3295 } /* end _asm block */
3296
3297 /* Now do the math for the rest of the row */
3298 switch ( bpp )
3299 {
3300 case 3:
3301 {
3302 ActiveMask.use = 0x0000ffffff000000;
3303 ShiftBpp.use = 24; /* == 3 * 8 */
3304 ShiftRem.use = 40; /* == 64 - 24 */
3305 _asm {
3306 mov edi, row
3307 movq mm7, ActiveMask /* Load ActiveMask for 2nd active byte group */
3308 mov esi, edi /* lp = row */
3309 add edi, bpp /* rp = row + bpp */
3310 movq mm6, mm7
3311 mov ebx, diff
3312 psllq mm6, ShiftBpp /* Move mask in mm6 to cover 3rd active */
3313 /* byte group */
3314 /* PRIME the pump (load the first Raw(x-bpp) data set */
3315 movq mm1, [edi+ebx-8]
3316 dsub3lp:
3317 psrlq mm1, ShiftRem /* Shift data for adding 1st bpp bytes */
3318 /* no need for mask; shift clears inactive bytes */
3319 /* Add 1st active group */
3320 movq mm0, [edi+ebx]
3321 paddb mm0, mm1
3322 /* Add 2nd active group */
3323 movq mm1, mm0 /* mov updated Raws to mm1 */
3324 psllq mm1, ShiftBpp /* shift data to position correctly */
3325 pand mm1, mm7 /* mask to use only 2nd active group */
3326 paddb mm0, mm1
3327 /* Add 3rd active group */
3328 movq mm1, mm0 /* mov updated Raws to mm1 */
3329 psllq mm1, ShiftBpp /* shift data to position correctly */
3330 pand mm1, mm6 /* mask to use only 3rd active group */
3331 add ebx, 8
3332 paddb mm0, mm1
3333 cmp ebx, MMXLength
3334 movq [edi+ebx-8], mm0 /* Write updated Raws back to array */
3335 /* Prep for doing 1st add at top of loop */
3336 movq mm1, mm0
3337 jb dsub3lp
3338 } /* end _asm block */
3339 }
3340 break;
3341
3342 case 1:
3343 {
3344 /* Placed here just in case this is a duplicate of the */
3345 /* non-MMX code for the SUB filter in png_read_filter_row below */
3346 //
3347 /* png_bytep rp; */
3348 /* png_bytep lp; */
3349 /* png_uint_32 i; */
3350 /* bpp = (row_info->pixel_depth + 7) >> 3; */
3351 /* for (i = (png_uint_32)bpp, rp = row + bpp, lp = row; */
3352 /* i < row_info->rowbytes; i++, rp++, lp++) */
3353 /* { */
3354 /* *rp = (png_byte)(((int)(*rp) + (int)(*lp)) & 0xff); */
3355 /* } */
3356 _asm {
3357 mov ebx, diff
3358 mov edi, row
3359 cmp ebx, FullLength
3360 jnb dsub1end
3361 mov esi, edi /* lp = row */
3362 xor eax, eax
3363 add edi, bpp /* rp = row + bpp */
3364 dsub1lp:
3365 mov al, [esi+ebx]
3366 add [edi+ebx], al
3367 inc ebx
3368 cmp ebx, FullLength
3369 jb dsub1lp
3370 dsub1end:
3371 } /* end _asm block */
3372 }
3373 return;
3374
3375 case 6:
3376 case 7:
3377 case 4:
3378 case 5:
3379 {
3380 ShiftBpp.use = bpp << 3;
3381 ShiftRem.use = 64 - ShiftBpp.use;
3382 _asm {
3383 mov edi, row
3384 mov ebx, diff
3385 mov esi, edi /* lp = row */
3386 add edi, bpp /* rp = row + bpp */
3387 /* PRIME the pump (load the first Raw(x-bpp) data set */
3388 movq mm1, [edi+ebx-8]
3389 dsub4lp:
3390 psrlq mm1, ShiftRem /* Shift data for adding 1st bpp bytes */
3391 /* no need for mask; shift clears inactive bytes */
3392 movq mm0, [edi+ebx]
3393 paddb mm0, mm1
3394 /* Add 2nd active group */
3395 movq mm1, mm0 /* mov updated Raws to mm1 */
3396 psllq mm1, ShiftBpp /* shift data to position correctly */
3397 /* there is no need for any mask */
3398 /* since shift clears inactive bits/bytes */
3399 add ebx, 8
3400 paddb mm0, mm1
3401 cmp ebx, MMXLength
3402 movq [edi+ebx-8], mm0
3403 movq mm1, mm0 /* Prep for doing 1st add at top of loop */
3404 jb dsub4lp
3405 } /* end _asm block */
3406 }
3407 break;
3408
3409 case 2:
3410 {
3411 ActiveMask.use = 0x00000000ffff0000;
3412 ShiftBpp.use = 16; /* == 2 * 8 */
3413 ShiftRem.use = 48; /* == 64 - 16 */
3414 _asm {
3415 movq mm7, ActiveMask /* Load ActiveMask for 2nd active byte group */
3416 mov ebx, diff
3417 movq mm6, mm7
3418 mov edi, row
3419 psllq mm6, ShiftBpp /* Move mask in mm6 to cover 3rd active */
3420 /* byte group */
3421 mov esi, edi /* lp = row */
3422 movq mm5, mm6
3423 add edi, bpp /* rp = row + bpp */
3424 psllq mm5, ShiftBpp /* Move mask in mm5 to cover 4th active */
3425 /* byte group */
3426 /* PRIME the pump (load the first Raw(x-bpp) data set */
3427 movq mm1, [edi+ebx-8]
3428 dsub2lp:
3429 /* Add 1st active group */
3430 psrlq mm1, ShiftRem /* Shift data for adding 1st bpp bytes */
3431 /* no need for mask; shift clears inactive */
3432 /* bytes */
3433 movq mm0, [edi+ebx]
3434 paddb mm0, mm1
3435 /* Add 2nd active group */
3436 movq mm1, mm0 /* mov updated Raws to mm1 */
3437 psllq mm1, ShiftBpp /* shift data to position correctly */
3438 pand mm1, mm7 /* mask to use only 2nd active group */
3439 paddb mm0, mm1
3440 /* Add 3rd active group */
3441 movq mm1, mm0 /* mov updated Raws to mm1 */
3442 psllq mm1, ShiftBpp /* shift data to position correctly */
3443 pand mm1, mm6 /* mask to use only 3rd active group */
3444 paddb mm0, mm1
3445 /* Add 4th active group */
3446 movq mm1, mm0 /* mov updated Raws to mm1 */
3447 psllq mm1, ShiftBpp /* shift data to position correctly */
3448 pand mm1, mm5 /* mask to use only 4th active group */
3449 add ebx, 8
3450 paddb mm0, mm1
3451 cmp ebx, MMXLength
3452 movq [edi+ebx-8], mm0 /* Write updated Raws back to array */
3453 movq mm1, mm0 /* Prep for doing 1st add at top of loop */
3454 jb dsub2lp
3455 } /* end _asm block */
3456 }
3457 break;
3458 case 8:
3459 {
3460 _asm {
3461 mov edi, row
3462 mov ebx, diff
3463 mov esi, edi /* lp = row */
3464 add edi, bpp /* rp = row + bpp */
3465 mov ecx, MMXLength
3466 movq mm7, [edi+ebx-8] /* PRIME the pump (load the first */
3467 /* Raw(x-bpp) data set */
3468 and ecx, 0x0000003f /* calc bytes over mult of 64 */
3469 dsub8lp:
3470 movq mm0, [edi+ebx] /* Load Sub(x) for 1st 8 bytes */
3471 paddb mm0, mm7
3472 movq mm1, [edi+ebx+8] /* Load Sub(x) for 2nd 8 bytes */
3473 movq [edi+ebx], mm0 /* Write Raw(x) for 1st 8 bytes */
3474 /* Now mm0 will be used as Raw(x-bpp) for */
3475 /* the 2nd group of 8 bytes. This will be */
3476 /* repeated for each group of 8 bytes with */
3477 /* the 8th group being used as the Raw(x-bpp) */
3478 /* for the 1st group of the next loop. */
3479 paddb mm1, mm0
3480 movq mm2, [edi+ebx+16] /* Load Sub(x) for 3rd 8 bytes */
3481 movq [edi+ebx+8], mm1 /* Write Raw(x) for 2nd 8 bytes */
3482 paddb mm2, mm1
3483 movq mm3, [edi+ebx+24] /* Load Sub(x) for 4th 8 bytes */
3484 movq [edi+ebx+16], mm2 /* Write Raw(x) for 3rd 8 bytes */
3485 paddb mm3, mm2
3486 movq mm4, [edi+ebx+32] /* Load Sub(x) for 5th 8 bytes */
3487 movq [edi+ebx+24], mm3 /* Write Raw(x) for 4th 8 bytes */
3488 paddb mm4, mm3
3489 movq mm5, [edi+ebx+40] /* Load Sub(x) for 6th 8 bytes */
3490 movq [edi+ebx+32], mm4 /* Write Raw(x) for 5th 8 bytes */
3491 paddb mm5, mm4
3492 movq mm6, [edi+ebx+48] /* Load Sub(x) for 7th 8 bytes */
3493 movq [edi+ebx+40], mm5 /* Write Raw(x) for 6th 8 bytes */
3494 paddb mm6, mm5
3495 movq mm7, [edi+ebx+56] /* Load Sub(x) for 8th 8 bytes */
3496 movq [edi+ebx+48], mm6 /* Write Raw(x) for 7th 8 bytes */
3497 add ebx, 64
3498 paddb mm7, mm6
3499 cmp ebx, ecx
3500 movq [edi+ebx-8], mm7 /* Write Raw(x) for 8th 8 bytes */
3501 jb dsub8lp
3502 cmp ebx, MMXLength
3503 jnb dsub8lt8
3504 dsub8lpA:
3505 movq mm0, [edi+ebx]
3506 add ebx, 8
3507 paddb mm0, mm7
3508 cmp ebx, MMXLength
3509 movq [edi+ebx-8], mm0 /* use -8 to offset early add to ebx */
3510 movq mm7, mm0 /* Move calculated Raw(x) data to mm1 to */
3511 /* be the new Raw(x-bpp) for the next loop */
3512 jb dsub8lpA
3513 dsub8lt8:
3514 } /* end _asm block */
3515 }
3516 break;
3517
3518 default: /* bpp greater than 8 bytes */
3519 {
3520 _asm {
3521 mov ebx, diff
3522 mov edi, row
3523 mov esi, edi /* lp = row */
3524 add edi, bpp /* rp = row + bpp */
3525 dsubAlp:
3526 movq mm0, [edi+ebx]
3527 movq mm1, [esi+ebx]
3528 add ebx, 8
3529 paddb mm0, mm1
3530 cmp ebx, MMXLength
3531 movq [edi+ebx-8], mm0 /* mov does not affect flags; -8 to offset */
3532 /* add ebx */
3533 jb dsubAlp
3534 } /* end _asm block */
3535 }
3536 break;
3537
3538 } /* end switch ( bpp ) */
3539
3540 _asm {
3541 mov ebx, MMXLength
3542 mov edi, row
3543 cmp ebx, FullLength
3544 jnb dsubend
3545 mov esi, edi /* lp = row */
3546 xor eax, eax
3547 add edi, bpp /* rp = row + bpp */
3548 dsublp2:
3549 mov al, [esi+ebx]
3550 add [edi+ebx], al
3551 inc ebx
3552 cmp ebx, FullLength
3553 jb dsublp2
3554 dsubend:
3555 emms /* End MMX instructions; prep for possible FP instrs. */
3556 } /* end _asm block */
3557 }
3558
3559 /* Optimized code for PNG Up filter decoder */
3560 void /* PRIVATE */
3561 png_read_filter_row_mmx_up(png_row_infop row_info, png_bytep row,
3562 png_bytep prev_row)
3563 {
3564 png_uint_32 len;
3565 len = row_info->rowbytes; /* # of bytes to filter */
3566 _asm {
3567 mov edi, row
3568 /* get # of bytes to alignment */
3569 mov ecx, edi
3570 xor ebx, ebx
3571 add ecx, 0x7
3572 xor eax, eax
3573 and ecx, 0xfffffff8
3574 mov esi, prev_row
3575 sub ecx, edi
3576 jz dupgo
3577 /* fix alignment */
3578 duplp1:
3579 mov al, [edi+ebx]
3580 add al, [esi+ebx]
3581 inc ebx
3582 cmp ebx, ecx
3583 mov [edi + ebx-1], al /* mov does not affect flags; -1 to offset inc ebx */
3584 jb duplp1
3585 dupgo:
3586 mov ecx, len
3587 mov edx, ecx
3588 sub edx, ebx /* subtract alignment fix */
3589 and edx, 0x0000003f /* calc bytes over mult of 64 */
3590 sub ecx, edx /* drop over bytes from length */
3591 /* Unrolled loop - use all MMX registers and interleave to reduce */
3592 /* number of branch instructions (loops) and reduce partial stalls */
3593 duploop:
3594 movq mm1, [esi+ebx]
3595 movq mm0, [edi+ebx]
3596 movq mm3, [esi+ebx+8]
3597 paddb mm0, mm1
3598 movq mm2, [edi+ebx+8]
3599 movq [edi+ebx], mm0
3600 paddb mm2, mm3
3601 movq mm5, [esi+ebx+16]
3602 movq [edi+ebx+8], mm2
3603 movq mm4, [edi+ebx+16]
3604 movq mm7, [esi+ebx+24]
3605 paddb mm4, mm5
3606 movq mm6, [edi+ebx+24]
3607 movq [edi+ebx+16], mm4
3608 paddb mm6, mm7
3609 movq mm1, [esi+ebx+32]
3610 movq [edi+ebx+24], mm6
3611 movq mm0, [edi+ebx+32]
3612 movq mm3, [esi+ebx+40]
3613 paddb mm0, mm1
3614 movq mm2, [edi+ebx+40]
3615 movq [edi+ebx+32], mm0
3616 paddb mm2, mm3
3617 movq mm5, [esi+ebx+48]
3618 movq [edi+ebx+40], mm2
3619 movq mm4, [edi+ebx+48]
3620 movq mm7, [esi+ebx+56]
3621 paddb mm4, mm5
3622 movq mm6, [edi+ebx+56]
3623 movq [edi+ebx+48], mm4
3624 add ebx, 64
3625 paddb mm6, mm7
3626 cmp ebx, ecx
3627 movq [edi+ebx-8], mm6 /* (+56)movq does not affect flags; */
3628 /* -8 to offset add ebx */
3629 jb duploop
3630
3631 cmp edx, 0 /* Test for bytes over mult of 64 */
3632 jz dupend
3633
3634
3635 /* 2 lines added by lcreeve@netins.net */
3636 /* (mail 11 Jul 98 in png-implement list) */
3637 cmp edx, 8 /*test for less than 8 bytes */
3638 jb duplt8
3639
3640
3641 add ecx, edx
3642 and edx, 0x00000007 /* calc bytes over mult of 8 */
3643 sub ecx, edx /* drop over bytes from length */
3644 jz duplt8
3645 /* Loop using MMX registers mm0 & mm1 to update 8 bytes simultaneously */
3646 duplpA:
3647 movq mm1, [esi+ebx]
3648 movq mm0, [edi+ebx]
3649 add ebx, 8
3650 paddb mm0, mm1
3651 cmp ebx, ecx
3652 movq [edi+ebx-8], mm0 /* movq does not affect flags; -8 to offset add ebx */
3653 jb duplpA
3654 cmp edx, 0 /* Test for bytes over mult of 8 */
3655 jz dupend
3656 duplt8:
3657 xor eax, eax
3658 add ecx, edx /* move over byte count into counter */
3659 /* Loop using x86 registers to update remaining bytes */
3660 duplp2:
3661 mov al, [edi + ebx]
3662 add al, [esi + ebx]
3663 inc ebx
3664 cmp ebx, ecx
3665 mov [edi + ebx-1], al /* mov does not affect flags; -1 to offset inc ebx */
3666 jb duplp2
3667 dupend:
3668 /* Conversion of filtered row completed */
3669 emms /* End MMX instructions; prep for possible FP instrs. */
3670 } /* end _asm block */
3671 }
3672
3673
3674 /* Optimized png_read_filter_row routines */
3675 void /* PRIVATE */
3676 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep
3677 row, png_bytep prev_row, int filter)
3678 {
3679 #ifdef PNG_DEBUG
3680 char filnm[10];
3681 #endif
3682
3683 if (mmx_supported == 2) {
3684 #if !defined(PNG_1_0_X)
3685 /* this should have happened in png_init_mmx_flags() already */
3686 png_warning(png_ptr, "asm_flags may not have been initialized");
3687 #endif
3688 png_mmx_support();
3689 }
3690
3691 #ifdef PNG_DEBUG
3692 png_debug(1, "in png_read_filter_row\n");
3693 switch (filter)
3694 {
3695 case 0: sprintf(filnm, "none");
3696 break;
3697 #if !defined(PNG_1_0_X)
3698 case 1: sprintf(filnm, "sub-%s",
3699 (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB)? "MMX" : "x86");
3700 break;
3701 case 2: sprintf(filnm, "up-%s",
3702 (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP)? "MMX" : "x86");
3703 break;
3704 case 3: sprintf(filnm, "avg-%s",
3705 (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG)? "MMX" : "x86");
3706 break;
3707 case 4: sprintf(filnm, "Paeth-%s",
3708 (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH)? "MMX":"x86");
3709 break;
3710 #else
3711 case 1: sprintf(filnm, "sub");
3712 break;
3713 case 2: sprintf(filnm, "up");
3714 break;
3715 case 3: sprintf(filnm, "avg");
3716 break;
3717 case 4: sprintf(filnm, "Paeth");
3718 break;
3719 #endif
3720 default: sprintf(filnm, "unknw");
3721 break;
3722 }
3723 png_debug2(0,"row=%5d, %s, ", png_ptr->row_number, filnm);
3724 png_debug2(0, "pd=%2d, b=%d, ", (int)row_info->pixel_depth,
3725 (int)((row_info->pixel_depth + 7) >> 3));
3726 png_debug1(0,"len=%8d, ", row_info->rowbytes);
3727 #endif /* PNG_DEBUG */
3728
3729 switch (filter)
3730 {
3731 case PNG_FILTER_VALUE_NONE:
3732 break;
3733
3734 case PNG_FILTER_VALUE_SUB:
3735 {
3736 #if !defined(PNG_1_0_X)
3737 if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB) &&
3738 (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
3739 (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
3740 #else
3741 if (mmx_supported)
3742 #endif
3743 {
3744 png_read_filter_row_mmx_sub(row_info, row);
3745 }
3746 else
3747 {
3748 png_uint_32 i;
3749 png_uint_32 istop = row_info->rowbytes;
3750 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
3751 png_bytep rp = row + bpp;
3752 png_bytep lp = row;
3753
3754 for (i = bpp; i < istop; i++)
3755 {
3756 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
3757 rp++;
3758 }
3759 }
3760 break;
3761 }
3762
3763 case PNG_FILTER_VALUE_UP:
3764 {
3765 #if !defined(PNG_1_0_X)
3766 if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP) &&
3767 (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
3768 (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
3769 #else
3770 if (mmx_supported)
3771 #endif
3772 {
3773 png_read_filter_row_mmx_up(row_info, row, prev_row);
3774 }
3775 else
3776 {
3777 png_uint_32 i;
3778 png_uint_32 istop = row_info->rowbytes;
3779 png_bytep rp = row;
3780 png_bytep pp = prev_row;
3781
3782 for (i = 0; i < istop; ++i)
3783 {
3784 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
3785 rp++;
3786 }
3787 }
3788 break;
3789 }
3790
3791 case PNG_FILTER_VALUE_AVG:
3792 {
3793 #if !defined(PNG_1_0_X)
3794 if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG) &&
3795 (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
3796 (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
3797 #else
3798 if (mmx_supported)
3799 #endif
3800 {
3801 png_read_filter_row_mmx_avg(row_info, row, prev_row);
3802 }
3803 else
3804 {
3805 png_uint_32 i;
3806 png_bytep rp = row;
3807 png_bytep pp = prev_row;
3808 png_bytep lp = row;
3809 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
3810 png_uint_32 istop = row_info->rowbytes - bpp;
3811
3812 for (i = 0; i < bpp; i++)
3813 {
3814 *rp = (png_byte)(((int)(*rp) +
3815 ((int)(*pp++) >> 1)) & 0xff);
3816 rp++;
3817 }
3818
3819 for (i = 0; i < istop; i++)
3820 {
3821 *rp = (png_byte)(((int)(*rp) +
3822 ((int)(*pp++ + *lp++) >> 1)) & 0xff);
3823 rp++;
3824 }
3825 }
3826 break;
3827 }
3828
3829 case PNG_FILTER_VALUE_PAETH:
3830 {
3831 #if !defined(PNG_1_0_X)
3832 if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH) &&
3833 (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
3834 (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
3835 #else
3836 if (mmx_supported)
3837 #endif
3838 {
3839 png_read_filter_row_mmx_paeth(row_info, row, prev_row);
3840 }
3841 else
3842 {
3843 png_uint_32 i;
3844 png_bytep rp = row;
3845 png_bytep pp = prev_row;
3846 png_bytep lp = row;
3847 png_bytep cp = prev_row;
3848 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
3849 png_uint_32 istop=row_info->rowbytes - bpp;
3850
3851 for (i = 0; i < bpp; i++)
3852 {
3853 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
3854 rp++;
3855 }
3856
3857 for (i = 0; i < istop; i++) /* use leftover rp,pp */
3858 {
3859 int a, b, c, pa, pb, pc, p;
3860
3861 a = *lp++;
3862 b = *pp++;
3863 c = *cp++;
3864
3865 p = b - c;
3866 pc = a - c;
3867
3868 #ifdef PNG_USE_ABS
3869 pa = abs(p);
3870 pb = abs(pc);
3871 pc = abs(p + pc);
3872 #else
3873 pa = p < 0 ? -p : p;
3874 pb = pc < 0 ? -pc : pc;
3875 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
3876 #endif
3877
3878 /*
3879 if (pa <= pb && pa <= pc)
3880 p = a;
3881 else if (pb <= pc)
3882 p = b;
3883 else
3884 p = c;
3885 */
3886
3887 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
3888
3889 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
3890 rp++;
3891 }
3892 }
3893 break;
3894 }
3895
3896 default:
3897 png_warning(png_ptr, "Ignoring bad row filter type");
3898 *row=0;
3899 break;
3900 }
3901 }
3902
3903 #endif /* PNG_ASSEMBLER_CODE_SUPPORTED && PNG_USE_PNGVCRD */