Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

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