pngvcrd.c
上传用户:looem2003
上传日期:2014-07-20
资源大小:13733k
文件大小:140k
源码类别:

打印编程

开发平台:

Visual C++

  1.          inc ebx
  2.          shr al, 1             // divide by 2
  3.          add al, [edi+ebx-1]   // Add Avg(x); -1 to offset inc ebx
  4.          cmp ebx, bpp
  5.          mov [edi+ebx-1], al    // Write back Raw(x);
  6.                             // mov does not affect flags; -1 to offset inc ebx
  7.          jb davgrlp
  8.          // get # of bytes to alignment
  9.          mov diff, edi         // take start of row
  10.          add diff, ebx         // add bpp
  11.          add diff, 0xf         // add 7 + 8 to incr past alignment boundary
  12.          and diff, 0xfffffff8  // mask to alignment boundary
  13.          sub diff, edi         // subtract from start ==> value ebx at alignment
  14.          jz davggo
  15.          // fix alignment
  16.          // Compute the Raw value for the bytes upto the alignment boundary
  17.          //    Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
  18.          xor ecx, ecx
  19. davglp1:
  20.          xor eax, eax
  21.          mov cl, [esi + ebx]        // load cl with Prior(x)
  22.          mov al, [edx + ebx]  // load al with Raw(x-bpp)
  23.          add ax, cx
  24.          inc ebx
  25.          shr ax, 1            // divide by 2
  26.          add al, [edi+ebx-1]  // Add Avg(x); -1 to offset inc ebx
  27.          cmp ebx, diff              // Check if at alignment boundary
  28.          mov [edi+ebx-1], al        // Write back Raw(x);
  29.                             // mov does not affect flags; -1 to offset inc ebx
  30.          jb davglp1               // Repeat until at alignment boundary
  31. davggo:
  32.          mov eax, FullLength
  33.          mov ecx, eax
  34.          sub eax, ebx          // subtract alignment fix
  35.          and eax, 0x00000007   // calc bytes over mult of 8
  36.          sub ecx, eax          // drop over bytes from original length
  37.          mov MMXLength, ecx
  38.    } // end _asm block
  39.    // Now do the math for the rest of the row
  40.    switch ( bpp )
  41.    {
  42.       case 3:
  43.       {
  44.          ActiveMask.use  = 0x0000000000ffffff;
  45.          ShiftBpp.use = 24;    // == 3 * 8
  46.          ShiftRem.use = 40;    // == 64 - 24
  47.          _asm {
  48.             // Re-init address pointers and offset
  49.             movq mm7, ActiveMask
  50.             mov ebx, diff      // ebx ==> x = offset to alignment boundary
  51.             movq mm5, LBCarryMask
  52.             mov edi, row       // edi ==> Avg(x)
  53.             movq mm4, HBClearMask
  54.             mov esi, prev_row        // esi ==> Prior(x)
  55.             // PRIME the pump (load the first Raw(x-bpp) data set
  56.             movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
  57.                                // (we correct position in loop below)
  58. davg3lp:
  59.             movq mm0, [edi + ebx]      // Load mm0 with Avg(x)
  60.             // Add (Prev_row/2) to Average
  61.             movq mm3, mm5
  62.             psrlq mm2, ShiftRem      // Correct position Raw(x-bpp) data
  63.             movq mm1, [esi + ebx]    // Load mm1 with Prior(x)
  64.             movq mm6, mm7
  65.             pand mm3, mm1      // get lsb for each prev_row byte
  66.             psrlq mm1, 1       // divide prev_row bytes by 2
  67.             pand  mm1, mm4     // clear invalid bit 7 of each byte
  68.             paddb mm0, mm1     // add (Prev_row/2) to Avg for each byte
  69.             // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
  70.             movq mm1, mm3      // now use mm1 for getting LBCarrys
  71.             pand mm1, mm2      // get LBCarrys for each byte where both
  72.                                // lsb's were == 1 (Only valid for active group)
  73.             psrlq mm2, 1       // divide raw bytes by 2
  74.             pand  mm2, mm4     // clear invalid bit 7 of each byte
  75.             paddb mm2, mm1     // add LBCarrys to (Raw(x-bpp)/2) for each byte
  76.             pand mm2, mm6      // Leave only Active Group 1 bytes to add to Avg
  77.             paddb mm0, mm2     // add (Raw/2) + LBCarrys to Avg for each Active
  78.                                //  byte
  79.             // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
  80.             psllq mm6, ShiftBpp  // shift the mm6 mask to cover bytes 3-5
  81.             movq mm2, mm0        // mov updated Raws to mm2
  82.             psllq mm2, ShiftBpp  // shift data to position correctly
  83.             movq mm1, mm3        // now use mm1 for getting LBCarrys
  84.             pand mm1, mm2      // get LBCarrys for each byte where both
  85.                                // lsb's were == 1 (Only valid for active group)
  86.             psrlq mm2, 1       // divide raw bytes by 2
  87.             pand  mm2, mm4     // clear invalid bit 7 of each byte
  88.             paddb mm2, mm1     // add LBCarrys to (Raw(x-bpp)/2) for each byte
  89.             pand mm2, mm6      // Leave only Active Group 2 bytes to add to Avg
  90.             paddb mm0, mm2     // add (Raw/2) + LBCarrys to Avg for each Active
  91.                                //  byte
  92.             // Add 3rd active group (Raw(x-bpp)/2) to Average with LBCarry
  93.             psllq mm6, ShiftBpp  // shift the mm6 mask to cover the last two
  94.                                  // bytes
  95.             movq mm2, mm0        // mov updated Raws to mm2
  96.             psllq mm2, ShiftBpp  // shift data to position correctly
  97.                               // Data only needs to be shifted once here to
  98.                               // get the correct x-bpp offset.
  99.             movq mm1, mm3     // now use mm1 for getting LBCarrys
  100.             pand mm1, mm2     // get LBCarrys for each byte where both
  101.                               // lsb's were == 1 (Only valid for active group)
  102.             psrlq mm2, 1      // divide raw bytes by 2
  103.             pand  mm2, mm4    // clear invalid bit 7 of each byte
  104.             paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
  105.             pand mm2, mm6     // Leave only Active Group 2 bytes to add to Avg
  106.             add ebx, 8
  107.             paddb mm0, mm2    // add (Raw/2) + LBCarrys to Avg for each Active
  108.                               // byte
  109.             // Now ready to write back to memory
  110.             movq [edi + ebx - 8], mm0
  111.             // Move updated Raw(x) to use as Raw(x-bpp) for next loop
  112.             cmp ebx, MMXLength
  113.             movq mm2, mm0     // mov updated Raw(x) to mm2
  114.             jb davg3lp
  115.          } // end _asm block
  116.       }
  117.       break;
  118.       case 6:
  119.       case 4:
  120.       case 7:
  121.       case 5:
  122.       {
  123.          ActiveMask.use  = 0xffffffffffffffff;  // use shift below to clear
  124.                                                 // appropriate inactive bytes
  125.          ShiftBpp.use = bpp << 3;
  126.          ShiftRem.use = 64 - ShiftBpp.use;
  127.          _asm {
  128.             movq mm4, HBClearMask
  129.             // Re-init address pointers and offset
  130.             mov ebx, diff       // ebx ==> x = offset to alignment boundary
  131.             // Load ActiveMask and clear all bytes except for 1st active group
  132.             movq mm7, ActiveMask
  133.             mov edi, row         // edi ==> Avg(x)
  134.             psrlq mm7, ShiftRem
  135.             mov esi, prev_row    // esi ==> Prior(x)
  136.             movq mm6, mm7
  137.             movq mm5, LBCarryMask
  138.             psllq mm6, ShiftBpp  // Create mask for 2nd active group
  139.             // PRIME the pump (load the first Raw(x-bpp) data set
  140.             movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
  141.                                  // (we correct position in loop below)
  142. davg4lp:
  143.             movq mm0, [edi + ebx]
  144.             psrlq mm2, ShiftRem  // shift data to position correctly
  145.             movq mm1, [esi + ebx]
  146.             // Add (Prev_row/2) to Average
  147.             movq mm3, mm5
  148.             pand mm3, mm1     // get lsb for each prev_row byte
  149.             psrlq mm1, 1      // divide prev_row bytes by 2
  150.             pand  mm1, mm4    // clear invalid bit 7 of each byte
  151.             paddb mm0, mm1    // add (Prev_row/2) to Avg for each byte
  152.             // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
  153.             movq mm1, mm3     // now use mm1 for getting LBCarrys
  154.             pand mm1, mm2     // get LBCarrys for each byte where both
  155.                               // lsb's were == 1 (Only valid for active group)
  156.             psrlq mm2, 1      // divide raw bytes by 2
  157.             pand  mm2, mm4    // clear invalid bit 7 of each byte
  158.             paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
  159.             pand mm2, mm7     // Leave only Active Group 1 bytes to add to Avg
  160.             paddb mm0, mm2    // add (Raw/2) + LBCarrys to Avg for each Active
  161.                               // byte
  162.             // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
  163.             movq mm2, mm0     // mov updated Raws to mm2
  164.             psllq mm2, ShiftBpp // shift data to position correctly
  165.             add ebx, 8
  166.             movq mm1, mm3     // now use mm1 for getting LBCarrys
  167.             pand mm1, mm2     // get LBCarrys for each byte where both
  168.                               // lsb's were == 1 (Only valid for active group)
  169.             psrlq mm2, 1      // divide raw bytes by 2
  170.             pand  mm2, mm4    // clear invalid bit 7 of each byte
  171.             paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
  172.             pand mm2, mm6     // Leave only Active Group 2 bytes to add to Avg
  173.             paddb mm0, mm2    // add (Raw/2) + LBCarrys to Avg for each Active
  174.                               // byte
  175.             cmp ebx, MMXLength
  176.             // Now ready to write back to memory
  177.             movq [edi + ebx - 8], mm0
  178.             // Prep Raw(x-bpp) for next loop
  179.             movq mm2, mm0     // mov updated Raws to mm2
  180.             jb davg4lp
  181.          } // end _asm block
  182.       }
  183.       break;
  184.       case 2:
  185.       {
  186.          ActiveMask.use  = 0x000000000000ffff;
  187.          ShiftBpp.use = 16;   // == 2 * 8     [BUGFIX]
  188.          ShiftRem.use = 48;   // == 64 - 16   [BUGFIX]
  189.          _asm {
  190.             // Load ActiveMask
  191.             movq mm7, ActiveMask
  192.             // Re-init address pointers and offset
  193.             mov ebx, diff     // ebx ==> x = offset to alignment boundary
  194.             movq mm5, LBCarryMask
  195.             mov edi, row      // edi ==> Avg(x)
  196.             movq mm4, HBClearMask
  197.             mov esi, prev_row  // esi ==> Prior(x)
  198.             // PRIME the pump (load the first Raw(x-bpp) data set
  199.             movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
  200.                               // (we correct position in loop below)
  201. davg2lp:
  202.             movq mm0, [edi + ebx]
  203.             psrlq mm2, ShiftRem  // shift data to position correctly   [BUGFIX]
  204.             movq mm1, [esi + ebx]
  205.             // Add (Prev_row/2) to Average
  206.             movq mm3, mm5
  207.             pand mm3, mm1     // get lsb for each prev_row byte
  208.             psrlq mm1, 1      // divide prev_row bytes by 2
  209.             pand  mm1, mm4    // clear invalid bit 7 of each byte
  210.             movq mm6, mm7
  211.             paddb mm0, mm1    // add (Prev_row/2) to Avg for each byte
  212.             // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
  213.             movq mm1, mm3     // now use mm1 for getting LBCarrys
  214.             pand mm1, mm2     // get LBCarrys for each byte where both
  215.                               // lsb's were == 1 (Only valid for active group)
  216.             psrlq mm2, 1      // divide raw bytes by 2
  217.             pand  mm2, mm4    // clear invalid bit 7 of each byte
  218.             paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
  219.             pand mm2, mm6     // Leave only Active Group 1 bytes to add to Avg
  220.             paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
  221.             // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
  222.             psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 2 & 3
  223.             movq mm2, mm0       // mov updated Raws to mm2
  224.             psllq mm2, ShiftBpp // shift data to position correctly
  225.             movq mm1, mm3       // now use mm1 for getting LBCarrys
  226.             pand mm1, mm2       // get LBCarrys for each byte where both
  227.                                 // lsb's were == 1 (Only valid for active group)
  228.             psrlq mm2, 1        // divide raw bytes by 2
  229.             pand  mm2, mm4      // clear invalid bit 7 of each byte
  230.             paddb mm2, mm1      // add LBCarrys to (Raw(x-bpp)/2) for each byte
  231.             pand mm2, mm6       // Leave only Active Group 2 bytes to add to Avg
  232.             paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
  233.             // Add rdd active group (Raw(x-bpp)/2) to Average with LBCarry
  234.             psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 4 & 5
  235.             movq mm2, mm0       // mov updated Raws to mm2
  236.             psllq mm2, ShiftBpp // shift data to position correctly
  237.                                 // Data only needs to be shifted once here to
  238.                                 // get the correct x-bpp offset.
  239.             movq mm1, mm3       // now use mm1 for getting LBCarrys
  240.             pand mm1, mm2       // get LBCarrys for each byte where both
  241.                                 // lsb's were == 1 (Only valid for active group)
  242.             psrlq mm2, 1        // divide raw bytes by 2
  243.             pand  mm2, mm4      // clear invalid bit 7 of each byte
  244.             paddb mm2, mm1      // add LBCarrys to (Raw(x-bpp)/2) for each byte
  245.             pand mm2, mm6       // Leave only Active Group 2 bytes to add to Avg
  246.             paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
  247.             // Add 4th active group (Raw(x-bpp)/2) to Average with LBCarry
  248.             psllq mm6, ShiftBpp  // shift the mm6 mask to cover bytes 6 & 7
  249.             movq mm2, mm0        // mov updated Raws to mm2
  250.             psllq mm2, ShiftBpp  // shift data to position correctly
  251.                                  // Data only needs to be shifted once here to
  252.                                  // get the correct x-bpp offset.
  253.             add ebx, 8
  254.             movq mm1, mm3    // now use mm1 for getting LBCarrys
  255.             pand mm1, mm2    // get LBCarrys for each byte where both
  256.                              // lsb's were == 1 (Only valid for active group)
  257.             psrlq mm2, 1     // divide raw bytes by 2
  258.             pand  mm2, mm4   // clear invalid bit 7 of each byte
  259.             paddb mm2, mm1   // add LBCarrys to (Raw(x-bpp)/2) for each byte
  260.             pand mm2, mm6    // Leave only Active Group 2 bytes to add to Avg
  261.             paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
  262.             cmp ebx, MMXLength
  263.             // Now ready to write back to memory
  264.             movq [edi + ebx - 8], mm0
  265.             // Prep Raw(x-bpp) for next loop
  266.             movq mm2, mm0    // mov updated Raws to mm2
  267.             jb davg2lp
  268.         } // end _asm block
  269.       }
  270.       break;
  271.       case 1:                 // bpp == 1
  272.       {
  273.          _asm {
  274.             // Re-init address pointers and offset
  275.             mov ebx, diff     // ebx ==> x = offset to alignment boundary
  276.             mov edi, row      // edi ==> Avg(x)
  277.             cmp ebx, FullLength  // Test if offset at end of array
  278.             jnb davg1end
  279.             // Do Paeth decode for remaining bytes
  280.             mov esi, prev_row    // esi ==> Prior(x)
  281.             mov edx, edi
  282.             xor ecx, ecx         // zero ecx before using cl & cx in loop below
  283.             sub edx, bpp         // edx ==> Raw(x-bpp)
  284. davg1lp:
  285.             // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
  286.             xor eax, eax
  287.             mov cl, [esi + ebx]  // load cl with Prior(x)
  288.             mov al, [edx + ebx]  // load al with Raw(x-bpp)
  289.             add ax, cx
  290.             inc ebx
  291.             shr ax, 1            // divide by 2
  292.             add al, [edi+ebx-1]  // Add Avg(x); -1 to offset inc ebx
  293.             cmp ebx, FullLength  // Check if at end of array
  294.             mov [edi+ebx-1], al  // Write back Raw(x);
  295.                          // mov does not affect flags; -1 to offset inc ebx
  296.             jb davg1lp
  297. davg1end:
  298.          } // end _asm block
  299.       }
  300.       return;
  301.       case 8:             // bpp == 8
  302.       {
  303.          _asm {
  304.             // Re-init address pointers and offset
  305.             mov ebx, diff           // ebx ==> x = offset to alignment boundary
  306.             movq mm5, LBCarryMask
  307.             mov edi, row            // edi ==> Avg(x)
  308.             movq mm4, HBClearMask
  309.             mov esi, prev_row       // esi ==> Prior(x)
  310.             // PRIME the pump (load the first Raw(x-bpp) data set
  311.             movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
  312.                                 // (NO NEED to correct position in loop below)
  313. davg8lp:
  314.             movq mm0, [edi + ebx]
  315.             movq mm3, mm5
  316.             movq mm1, [esi + ebx]
  317.             add ebx, 8
  318.             pand mm3, mm1       // get lsb for each prev_row byte
  319.             psrlq mm1, 1        // divide prev_row bytes by 2
  320.             pand mm3, mm2       // get LBCarrys for each byte where both
  321.                                 // lsb's were == 1
  322.             psrlq mm2, 1        // divide raw bytes by 2
  323.             pand  mm1, mm4      // clear invalid bit 7 of each byte
  324.             paddb mm0, mm3      // add LBCarrys to Avg for each byte
  325.             pand  mm2, mm4      // clear invalid bit 7 of each byte
  326.             paddb mm0, mm1      // add (Prev_row/2) to Avg for each byte
  327.             paddb mm0, mm2      // add (Raw/2) to Avg for each byte
  328.             cmp ebx, MMXLength
  329.             movq [edi + ebx - 8], mm0
  330.             movq mm2, mm0       // reuse as Raw(x-bpp)
  331.             jb davg8lp
  332.         } // end _asm block
  333.       }
  334.       break;
  335.       default:                  // bpp greater than 8
  336.       {
  337.         _asm {
  338.             movq mm5, LBCarryMask
  339.             // Re-init address pointers and offset
  340.             mov ebx, diff       // ebx ==> x = offset to alignment boundary
  341.             mov edi, row        // edi ==> Avg(x)
  342.             movq mm4, HBClearMask
  343.             mov edx, edi
  344.             mov esi, prev_row   // esi ==> Prior(x)
  345.             sub edx, bpp        // edx ==> Raw(x-bpp)
  346. davgAlp:
  347.             movq mm0, [edi + ebx]
  348.             movq mm3, mm5
  349.             movq mm1, [esi + ebx]
  350.             pand mm3, mm1       // get lsb for each prev_row byte
  351.             movq mm2, [edx + ebx]
  352.             psrlq mm1, 1        // divide prev_row bytes by 2
  353.             pand mm3, mm2       // get LBCarrys for each byte where both
  354.                                 // lsb's were == 1
  355.             psrlq mm2, 1        // divide raw bytes by 2
  356.             pand  mm1, mm4      // clear invalid bit 7 of each byte
  357.             paddb mm0, mm3      // add LBCarrys to Avg for each byte
  358.             pand  mm2, mm4      // clear invalid bit 7 of each byte
  359.             paddb mm0, mm1      // add (Prev_row/2) to Avg for each byte
  360.             add ebx, 8
  361.             paddb mm0, mm2      // add (Raw/2) to Avg for each byte
  362.             cmp ebx, MMXLength
  363.             movq [edi + ebx - 8], mm0
  364.             jb davgAlp
  365.         } // end _asm block
  366.       }
  367.       break;
  368.    }                         // end switch ( bpp )
  369.    _asm {
  370.          // MMX acceleration complete now do clean-up
  371.          // Check if any remaining bytes left to decode
  372.          mov ebx, MMXLength    // ebx ==> x = offset bytes remaining after MMX
  373.          mov edi, row          // edi ==> Avg(x)
  374.          cmp ebx, FullLength   // Test if offset at end of array
  375.          jnb davgend
  376.          // Do Paeth decode for remaining bytes
  377.          mov esi, prev_row     // esi ==> Prior(x)
  378.          mov edx, edi
  379.          xor ecx, ecx          // zero ecx before using cl & cx in loop below
  380.          sub edx, bpp          // edx ==> Raw(x-bpp)
  381. davglp2:
  382.          // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
  383.          xor eax, eax
  384.          mov cl, [esi + ebx]   // load cl with Prior(x)
  385.          mov al, [edx + ebx]   // load al with Raw(x-bpp)
  386.          add ax, cx
  387.          inc ebx
  388.          shr ax, 1              // divide by 2
  389.          add al, [edi+ebx-1]    // Add Avg(x); -1 to offset inc ebx
  390.          cmp ebx, FullLength    // Check if at end of array
  391.          mov [edi+ebx-1], al    // Write back Raw(x);
  392.                           // mov does not affect flags; -1 to offset inc ebx
  393.          jb davglp2
  394. davgend:
  395.          emms             // End MMX instructions; prep for possible FP instrs.
  396.    } // end _asm block
  397. }
  398. // Optimized code for PNG Paeth filter decoder
  399. void /* PRIVATE */
  400. png_read_filter_row_mmx_paeth(png_row_infop row_info, png_bytep row,
  401.                               png_bytep prev_row)
  402. {
  403.    png_uint_32 FullLength;
  404.    png_uint_32 MMXLength;
  405.    //png_uint_32 len;
  406.    int bpp;
  407.    int diff;
  408.    //int ptemp;
  409.    int patemp, pbtemp, pctemp;
  410.    bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
  411.    FullLength  = row_info->rowbytes; // # of bytes to filter
  412.    _asm
  413.    {
  414.          xor ebx, ebx        // ebx ==> x offset
  415.          mov edi, row
  416.          xor edx, edx        // edx ==> x-bpp offset
  417.          mov esi, prev_row
  418.          xor eax, eax
  419.          // Compute the Raw value for the first bpp bytes
  420.          // Note: the formula works out to be always
  421.          //   Paeth(x) = Raw(x) + Prior(x)      where x < bpp
  422. dpthrlp:
  423.          mov al, [edi + ebx]
  424.          add al, [esi + ebx]
  425.          inc ebx
  426.          cmp ebx, bpp
  427.          mov [edi + ebx - 1], al
  428.          jb dpthrlp
  429.          // get # of bytes to alignment
  430.          mov diff, edi         // take start of row
  431.          add diff, ebx         // add bpp
  432.          xor ecx, ecx
  433.          add diff, 0xf         // add 7 + 8 to incr past alignment boundary
  434.          and diff, 0xfffffff8  // mask to alignment boundary
  435.          sub diff, edi         // subtract from start ==> value ebx at alignment
  436.          jz dpthgo
  437.          // fix alignment
  438. dpthlp1:
  439.          xor eax, eax
  440.          // pav = p - a = (a + b - c) - a = b - c
  441.          mov al, [esi + ebx]   // load Prior(x) into al
  442.          mov cl, [esi + edx]   // load Prior(x-bpp) into cl
  443.          sub eax, ecx          // subtract Prior(x-bpp)
  444.          mov patemp, eax       // Save pav for later use
  445.          xor eax, eax
  446.          // pbv = p - b = (a + b - c) - b = a - c
  447.          mov al, [edi + edx]   // load Raw(x-bpp) into al
  448.          sub eax, ecx          // subtract Prior(x-bpp)
  449.          mov ecx, eax
  450.          // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  451.          add eax, patemp       // pcv = pav + pbv
  452.          // pc = abs(pcv)
  453.          test eax, 0x80000000
  454.          jz dpthpca
  455.          neg eax               // reverse sign of neg values
  456. dpthpca:
  457.          mov pctemp, eax       // save pc for later use
  458.          // pb = abs(pbv)
  459.          test ecx, 0x80000000
  460.          jz dpthpba
  461.          neg ecx               // reverse sign of neg values
  462. dpthpba:
  463.          mov pbtemp, ecx       // save pb for later use
  464.          // pa = abs(pav)
  465.          mov eax, patemp
  466.          test eax, 0x80000000
  467.          jz dpthpaa
  468.          neg eax               // reverse sign of neg values
  469. dpthpaa:
  470.          mov patemp, eax       // save pa for later use
  471.          // test if pa <= pb
  472.          cmp eax, ecx
  473.          jna dpthabb
  474.          // pa > pb; now test if pb <= pc
  475.          cmp ecx, pctemp
  476.          jna dpthbbc
  477.          // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
  478.          mov cl, [esi + edx]  // load Prior(x-bpp) into cl
  479.          jmp dpthpaeth
  480. dpthbbc:
  481.          // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
  482.          mov cl, [esi + ebx]   // load Prior(x) into cl
  483.          jmp dpthpaeth
  484. dpthabb:
  485.          // pa <= pb; now test if pa <= pc
  486.          cmp eax, pctemp
  487.          jna dpthabc
  488.          // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
  489.          mov cl, [esi + edx]  // load Prior(x-bpp) into cl
  490.          jmp dpthpaeth
  491. dpthabc:
  492.          // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
  493.          mov cl, [edi + edx]  // load Raw(x-bpp) into cl
  494. dpthpaeth:
  495.          inc ebx
  496.          inc edx
  497.          // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
  498.          add [edi + ebx - 1], cl
  499.          cmp ebx, diff
  500.          jb dpthlp1
  501. dpthgo:
  502.          mov ecx, FullLength
  503.          mov eax, ecx
  504.          sub eax, ebx          // subtract alignment fix
  505.          and eax, 0x00000007   // calc bytes over mult of 8
  506.          sub ecx, eax          // drop over bytes from original length
  507.          mov MMXLength, ecx
  508.    } // end _asm block
  509.    // Now do the math for the rest of the row
  510.    switch ( bpp )
  511.    {
  512.       case 3:
  513.       {
  514.          ActiveMask.use = 0x0000000000ffffff;
  515.          ActiveMaskEnd.use = 0xffff000000000000;
  516.          ShiftBpp.use = 24;    // == bpp(3) * 8
  517.          ShiftRem.use = 40;    // == 64 - 24
  518.          _asm
  519.          {
  520.             mov ebx, diff
  521.             mov edi, row
  522.             mov esi, prev_row
  523.             pxor mm0, mm0
  524.             // PRIME the pump (load the first Raw(x-bpp) data set
  525.             movq mm1, [edi+ebx-8]
  526. dpth3lp:
  527.             psrlq mm1, ShiftRem     // shift last 3 bytes to 1st 3 bytes
  528.             movq mm2, [esi + ebx]   // load b=Prior(x)
  529.             punpcklbw mm1, mm0      // Unpack High bytes of a
  530.             movq mm3, [esi+ebx-8]   // Prep c=Prior(x-bpp) bytes
  531.             punpcklbw mm2, mm0      // Unpack High bytes of b
  532.             psrlq mm3, ShiftRem     // shift last 3 bytes to 1st 3 bytes
  533.             // pav = p - a = (a + b - c) - a = b - c
  534.             movq mm4, mm2
  535.             punpcklbw mm3, mm0      // Unpack High bytes of c
  536.             // pbv = p - b = (a + b - c) - b = a - c
  537.             movq mm5, mm1
  538.             psubw mm4, mm3
  539.             pxor mm7, mm7
  540.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  541.             movq mm6, mm4
  542.             psubw mm5, mm3
  543.             // pa = abs(p-a) = abs(pav)
  544.             // pb = abs(p-b) = abs(pbv)
  545.             // pc = abs(p-c) = abs(pcv)
  546.             pcmpgtw mm0, mm4    // Create mask pav bytes < 0
  547.             paddw mm6, mm5
  548.             pand mm0, mm4       // Only pav bytes < 0 in mm7
  549.             pcmpgtw mm7, mm5    // Create mask pbv bytes < 0
  550.             psubw mm4, mm0
  551.             pand mm7, mm5       // Only pbv bytes < 0 in mm0
  552.             psubw mm4, mm0
  553.             psubw mm5, mm7
  554.             pxor mm0, mm0
  555.             pcmpgtw mm0, mm6    // Create mask pcv bytes < 0
  556.             pand mm0, mm6       // Only pav bytes < 0 in mm7
  557.             psubw mm5, mm7
  558.             psubw mm6, mm0
  559.             //  test pa <= pb
  560.             movq mm7, mm4
  561.             psubw mm6, mm0
  562.             pcmpgtw mm7, mm5    // pa > pb?
  563.             movq mm0, mm7
  564.             // use mm7 mask to merge pa & pb
  565.             pand mm5, mm7
  566.             // use mm0 mask copy to merge a & b
  567.             pand mm2, mm0
  568.             pandn mm7, mm4
  569.             pandn mm0, mm1
  570.             paddw mm7, mm5
  571.             paddw mm0, mm2
  572.             //  test  ((pa <= pb)? pa:pb) <= pc
  573.             pcmpgtw mm7, mm6       // pab > pc?
  574.             pxor mm1, mm1
  575.             pand mm3, mm7
  576.             pandn mm7, mm0
  577.             paddw mm7, mm3
  578.             pxor mm0, mm0
  579.             packuswb mm7, mm1
  580.             movq mm3, [esi + ebx]   // load c=Prior(x-bpp)
  581.             pand mm7, ActiveMask
  582.             movq mm2, mm3           // load b=Prior(x) step 1
  583.             paddb mm7, [edi + ebx]  // add Paeth predictor with Raw(x)
  584.             punpcklbw mm3, mm0      // Unpack High bytes of c
  585.             movq [edi + ebx], mm7   // write back updated value
  586.             movq mm1, mm7           // Now mm1 will be used as Raw(x-bpp)
  587.             // Now do Paeth for 2nd set of bytes (3-5)
  588.             psrlq mm2, ShiftBpp     // load b=Prior(x) step 2
  589.             punpcklbw mm1, mm0      // Unpack High bytes of a
  590.             pxor mm7, mm7
  591.             punpcklbw mm2, mm0      // Unpack High bytes of b
  592.             // pbv = p - b = (a + b - c) - b = a - c
  593.             movq mm5, mm1
  594.             // pav = p - a = (a + b - c) - a = b - c
  595.             movq mm4, mm2
  596.             psubw mm5, mm3
  597.             psubw mm4, mm3
  598.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) =
  599.             //       pav + pbv = pbv + pav
  600.             movq mm6, mm5
  601.             paddw mm6, mm4
  602.             // pa = abs(p-a) = abs(pav)
  603.             // pb = abs(p-b) = abs(pbv)
  604.             // pc = abs(p-c) = abs(pcv)
  605.             pcmpgtw mm0, mm5       // Create mask pbv bytes < 0
  606.             pcmpgtw mm7, mm4       // Create mask pav bytes < 0
  607.             pand mm0, mm5          // Only pbv bytes < 0 in mm0
  608.             pand mm7, mm4          // Only pav bytes < 0 in mm7
  609.             psubw mm5, mm0
  610.             psubw mm4, mm7
  611.             psubw mm5, mm0
  612.             psubw mm4, mm7
  613.             pxor mm0, mm0
  614.             pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
  615.             pand mm0, mm6          // Only pav bytes < 0 in mm7
  616.             psubw mm6, mm0
  617.             //  test pa <= pb
  618.             movq mm7, mm4
  619.             psubw mm6, mm0
  620.             pcmpgtw mm7, mm5       // pa > pb?
  621.             movq mm0, mm7
  622.             // use mm7 mask to merge pa & pb
  623.             pand mm5, mm7
  624.             // use mm0 mask copy to merge a & b
  625.             pand mm2, mm0
  626.             pandn mm7, mm4
  627.             pandn mm0, mm1
  628.             paddw mm7, mm5
  629.             paddw mm0, mm2
  630.             //  test  ((pa <= pb)? pa:pb) <= pc
  631.             pcmpgtw mm7, mm6       // pab > pc?
  632.             movq mm2, [esi + ebx]  // load b=Prior(x)
  633.             pand mm3, mm7
  634.             pandn mm7, mm0
  635.             pxor mm1, mm1
  636.             paddw mm7, mm3
  637.             pxor mm0, mm0
  638.             packuswb mm7, mm1
  639.             movq mm3, mm2           // load c=Prior(x-bpp) step 1
  640.             pand mm7, ActiveMask
  641.             punpckhbw mm2, mm0      // Unpack High bytes of b
  642.             psllq mm7, ShiftBpp     // Shift bytes to 2nd group of 3 bytes
  643.              // pav = p - a = (a + b - c) - a = b - c
  644.             movq mm4, mm2
  645.             paddb mm7, [edi + ebx]  // add Paeth predictor with Raw(x)
  646.             psllq mm3, ShiftBpp     // load c=Prior(x-bpp) step 2
  647.             movq [edi + ebx], mm7   // write back updated value
  648.             movq mm1, mm7
  649.             punpckhbw mm3, mm0      // Unpack High bytes of c
  650.             psllq mm1, ShiftBpp     // Shift bytes
  651.                                     // Now mm1 will be used as Raw(x-bpp)
  652.             // Now do Paeth for 3rd, and final, set of bytes (6-7)
  653.             pxor mm7, mm7
  654.             punpckhbw mm1, mm0      // Unpack High bytes of a
  655.             psubw mm4, mm3
  656.             // pbv = p - b = (a + b - c) - b = a - c
  657.             movq mm5, mm1
  658.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  659.             movq mm6, mm4
  660.             psubw mm5, mm3
  661.             pxor mm0, mm0
  662.             paddw mm6, mm5
  663.             // pa = abs(p-a) = abs(pav)
  664.             // pb = abs(p-b) = abs(pbv)
  665.             // pc = abs(p-c) = abs(pcv)
  666.             pcmpgtw mm0, mm4    // Create mask pav bytes < 0
  667.             pcmpgtw mm7, mm5    // Create mask pbv bytes < 0
  668.             pand mm0, mm4       // Only pav bytes < 0 in mm7
  669.             pand mm7, mm5       // Only pbv bytes < 0 in mm0
  670.             psubw mm4, mm0
  671.             psubw mm5, mm7
  672.             psubw mm4, mm0
  673.             psubw mm5, mm7
  674.             pxor mm0, mm0
  675.             pcmpgtw mm0, mm6    // Create mask pcv bytes < 0
  676.             pand mm0, mm6       // Only pav bytes < 0 in mm7
  677.             psubw mm6, mm0
  678.             //  test pa <= pb
  679.             movq mm7, mm4
  680.             psubw mm6, mm0
  681.             pcmpgtw mm7, mm5    // pa > pb?
  682.             movq mm0, mm7
  683.             // use mm0 mask copy to merge a & b
  684.             pand mm2, mm0
  685.             // use mm7 mask to merge pa & pb
  686.             pand mm5, mm7
  687.             pandn mm0, mm1
  688.             pandn mm7, mm4
  689.             paddw mm0, mm2
  690.             paddw mm7, mm5
  691.             //  test  ((pa <= pb)? pa:pb) <= pc
  692.             pcmpgtw mm7, mm6    // pab > pc?
  693.             pand mm3, mm7
  694.             pandn mm7, mm0
  695.             paddw mm7, mm3
  696.             pxor mm1, mm1
  697.             packuswb mm1, mm7
  698.             // Step ebx to next set of 8 bytes and repeat loop til done
  699.             add ebx, 8
  700.             pand mm1, ActiveMaskEnd
  701.             paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x)
  702.             cmp ebx, MMXLength
  703.             pxor mm0, mm0              // pxor does not affect flags
  704.             movq [edi + ebx - 8], mm1  // write back updated value
  705.                                  // mm1 will be used as Raw(x-bpp) next loop
  706.                            // mm3 ready to be used as Prior(x-bpp) next loop
  707.             jb dpth3lp
  708.          } // end _asm block
  709.       }
  710.       break;
  711.       case 6:
  712.       case 7:
  713.       case 5:
  714.       {
  715.          ActiveMask.use  = 0x00000000ffffffff;
  716.          ActiveMask2.use = 0xffffffff00000000;
  717.          ShiftBpp.use = bpp << 3;    // == bpp * 8
  718.          ShiftRem.use = 64 - ShiftBpp.use;
  719.          _asm
  720.          {
  721.             mov ebx, diff
  722.             mov edi, row
  723.             mov esi, prev_row
  724.             // PRIME the pump (load the first Raw(x-bpp) data set
  725.             movq mm1, [edi+ebx-8]
  726.             pxor mm0, mm0
  727. dpth6lp:
  728.             // Must shift to position Raw(x-bpp) data
  729.             psrlq mm1, ShiftRem
  730.             // Do first set of 4 bytes
  731.             movq mm3, [esi+ebx-8]      // read c=Prior(x-bpp) bytes
  732.             punpcklbw mm1, mm0      // Unpack Low bytes of a
  733.             movq mm2, [esi + ebx]   // load b=Prior(x)
  734.             punpcklbw mm2, mm0      // Unpack Low bytes of b
  735.             // Must shift to position Prior(x-bpp) data
  736.             psrlq mm3, ShiftRem
  737.             // pav = p - a = (a + b - c) - a = b - c
  738.             movq mm4, mm2
  739.             punpcklbw mm3, mm0      // Unpack Low bytes of c
  740.             // pbv = p - b = (a + b - c) - b = a - c
  741.             movq mm5, mm1
  742.             psubw mm4, mm3
  743.             pxor mm7, mm7
  744.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  745.             movq mm6, mm4
  746.             psubw mm5, mm3
  747.             // pa = abs(p-a) = abs(pav)
  748.             // pb = abs(p-b) = abs(pbv)
  749.             // pc = abs(p-c) = abs(pcv)
  750.             pcmpgtw mm0, mm4    // Create mask pav bytes < 0
  751.             paddw mm6, mm5
  752.             pand mm0, mm4       // Only pav bytes < 0 in mm7
  753.             pcmpgtw mm7, mm5    // Create mask pbv bytes < 0
  754.             psubw mm4, mm0
  755.             pand mm7, mm5       // Only pbv bytes < 0 in mm0
  756.             psubw mm4, mm0
  757.             psubw mm5, mm7
  758.             pxor mm0, mm0
  759.             pcmpgtw mm0, mm6    // Create mask pcv bytes < 0
  760.             pand mm0, mm6       // Only pav bytes < 0 in mm7
  761.             psubw mm5, mm7
  762.             psubw mm6, mm0
  763.             //  test pa <= pb
  764.             movq mm7, mm4
  765.             psubw mm6, mm0
  766.             pcmpgtw mm7, mm5    // pa > pb?
  767.             movq mm0, mm7
  768.             // use mm7 mask to merge pa & pb
  769.             pand mm5, mm7
  770.             // use mm0 mask copy to merge a & b
  771.             pand mm2, mm0
  772.             pandn mm7, mm4
  773.             pandn mm0, mm1
  774.             paddw mm7, mm5
  775.             paddw mm0, mm2
  776.             //  test  ((pa <= pb)? pa:pb) <= pc
  777.             pcmpgtw mm7, mm6    // pab > pc?
  778.             pxor mm1, mm1
  779.             pand mm3, mm7
  780.             pandn mm7, mm0
  781.             paddw mm7, mm3
  782.             pxor mm0, mm0
  783.             packuswb mm7, mm1
  784.             movq mm3, [esi + ebx - 8]  // load c=Prior(x-bpp)
  785.             pand mm7, ActiveMask
  786.             psrlq mm3, ShiftRem
  787.             movq mm2, [esi + ebx]      // load b=Prior(x) step 1
  788.             paddb mm7, [edi + ebx]     // add Paeth predictor with Raw(x)
  789.             movq mm6, mm2
  790.             movq [edi + ebx], mm7      // write back updated value
  791.             movq mm1, [edi+ebx-8]
  792.             psllq mm6, ShiftBpp
  793.             movq mm5, mm7
  794.             psrlq mm1, ShiftRem
  795.             por mm3, mm6
  796.             psllq mm5, ShiftBpp
  797.             punpckhbw mm3, mm0         // Unpack High bytes of c
  798.             por mm1, mm5
  799.             // Do second set of 4 bytes
  800.             punpckhbw mm2, mm0         // Unpack High bytes of b
  801.             punpckhbw mm1, mm0         // Unpack High bytes of a
  802.             // pav = p - a = (a + b - c) - a = b - c
  803.             movq mm4, mm2
  804.             // pbv = p - b = (a + b - c) - b = a - c
  805.             movq mm5, mm1
  806.             psubw mm4, mm3
  807.             pxor mm7, mm7
  808.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  809.             movq mm6, mm4
  810.             psubw mm5, mm3
  811.             // pa = abs(p-a) = abs(pav)
  812.             // pb = abs(p-b) = abs(pbv)
  813.             // pc = abs(p-c) = abs(pcv)
  814.             pcmpgtw mm0, mm4       // Create mask pav bytes < 0
  815.             paddw mm6, mm5
  816.             pand mm0, mm4          // Only pav bytes < 0 in mm7
  817.             pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
  818.             psubw mm4, mm0
  819.             pand mm7, mm5          // Only pbv bytes < 0 in mm0
  820.             psubw mm4, mm0
  821.             psubw mm5, mm7
  822.             pxor mm0, mm0
  823.             pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
  824.             pand mm0, mm6          // Only pav bytes < 0 in mm7
  825.             psubw mm5, mm7
  826.             psubw mm6, mm0
  827.             //  test pa <= pb
  828.             movq mm7, mm4
  829.             psubw mm6, mm0
  830.             pcmpgtw mm7, mm5       // pa > pb?
  831.             movq mm0, mm7
  832.             // use mm7 mask to merge pa & pb
  833.             pand mm5, mm7
  834.             // use mm0 mask copy to merge a & b
  835.             pand mm2, mm0
  836.             pandn mm7, mm4
  837.             pandn mm0, mm1
  838.             paddw mm7, mm5
  839.             paddw mm0, mm2
  840.             //  test  ((pa <= pb)? pa:pb) <= pc
  841.             pcmpgtw mm7, mm6           // pab > pc?
  842.             pxor mm1, mm1
  843.             pand mm3, mm7
  844.             pandn mm7, mm0
  845.             pxor mm1, mm1
  846.             paddw mm7, mm3
  847.             pxor mm0, mm0
  848.             // Step ex to next set of 8 bytes and repeat loop til done
  849.             add ebx, 8
  850.             packuswb mm1, mm7
  851.             paddb mm1, [edi + ebx - 8]     // add Paeth predictor with Raw(x)
  852.             cmp ebx, MMXLength
  853.             movq [edi + ebx - 8], mm1      // write back updated value
  854.                                 // mm1 will be used as Raw(x-bpp) next loop
  855.             jb dpth6lp
  856.          } // end _asm block
  857.       }
  858.       break;
  859.       case 4:
  860.       {
  861.          ActiveMask.use  = 0x00000000ffffffff;
  862.          _asm {
  863.             mov ebx, diff
  864.             mov edi, row
  865.             mov esi, prev_row
  866.             pxor mm0, mm0
  867.             // PRIME the pump (load the first Raw(x-bpp) data set
  868.             movq mm1, [edi+ebx-8]    // Only time should need to read
  869.                                      //  a=Raw(x-bpp) bytes
  870. dpth4lp:
  871.             // Do first set of 4 bytes
  872.             movq mm3, [esi+ebx-8]    // read c=Prior(x-bpp) bytes
  873.             punpckhbw mm1, mm0       // Unpack Low bytes of a
  874.             movq mm2, [esi + ebx]    // load b=Prior(x)
  875.             punpcklbw mm2, mm0       // Unpack High bytes of b
  876.             // pav = p - a = (a + b - c) - a = b - c
  877.             movq mm4, mm2
  878.             punpckhbw mm3, mm0       // Unpack High bytes of c
  879.             // pbv = p - b = (a + b - c) - b = a - c
  880.             movq mm5, mm1
  881.             psubw mm4, mm3
  882.             pxor mm7, mm7
  883.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  884.             movq mm6, mm4
  885.             psubw mm5, mm3
  886.             // pa = abs(p-a) = abs(pav)
  887.             // pb = abs(p-b) = abs(pbv)
  888.             // pc = abs(p-c) = abs(pcv)
  889.             pcmpgtw mm0, mm4       // Create mask pav bytes < 0
  890.             paddw mm6, mm5
  891.             pand mm0, mm4          // Only pav bytes < 0 in mm7
  892.             pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
  893.             psubw mm4, mm0
  894.             pand mm7, mm5          // Only pbv bytes < 0 in mm0
  895.             psubw mm4, mm0
  896.             psubw mm5, mm7
  897.             pxor mm0, mm0
  898.             pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
  899.             pand mm0, mm6          // Only pav bytes < 0 in mm7
  900.             psubw mm5, mm7
  901.             psubw mm6, mm0
  902.             //  test pa <= pb
  903.             movq mm7, mm4
  904.             psubw mm6, mm0
  905.             pcmpgtw mm7, mm5       // pa > pb?
  906.             movq mm0, mm7
  907.             // use mm7 mask to merge pa & pb
  908.             pand mm5, mm7
  909.             // use mm0 mask copy to merge a & b
  910.             pand mm2, mm0
  911.             pandn mm7, mm4
  912.             pandn mm0, mm1
  913.             paddw mm7, mm5
  914.             paddw mm0, mm2
  915.             //  test  ((pa <= pb)? pa:pb) <= pc
  916.             pcmpgtw mm7, mm6       // pab > pc?
  917.             pxor mm1, mm1
  918.             pand mm3, mm7
  919.             pandn mm7, mm0
  920.             paddw mm7, mm3
  921.             pxor mm0, mm0
  922.             packuswb mm7, mm1
  923.             movq mm3, [esi + ebx]      // load c=Prior(x-bpp)
  924.             pand mm7, ActiveMask
  925.             movq mm2, mm3              // load b=Prior(x) step 1
  926.             paddb mm7, [edi + ebx]     // add Paeth predictor with Raw(x)
  927.             punpcklbw mm3, mm0         // Unpack High bytes of c
  928.             movq [edi + ebx], mm7      // write back updated value
  929.             movq mm1, mm7              // Now mm1 will be used as Raw(x-bpp)
  930.             // Do second set of 4 bytes
  931.             punpckhbw mm2, mm0         // Unpack Low bytes of b
  932.             punpcklbw mm1, mm0         // Unpack Low bytes of a
  933.             // pav = p - a = (a + b - c) - a = b - c
  934.             movq mm4, mm2
  935.             // pbv = p - b = (a + b - c) - b = a - c
  936.             movq mm5, mm1
  937.             psubw mm4, mm3
  938.             pxor mm7, mm7
  939.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  940.             movq mm6, mm4
  941.             psubw mm5, mm3
  942.             // pa = abs(p-a) = abs(pav)
  943.             // pb = abs(p-b) = abs(pbv)
  944.             // pc = abs(p-c) = abs(pcv)
  945.             pcmpgtw mm0, mm4       // Create mask pav bytes < 0
  946.             paddw mm6, mm5
  947.             pand mm0, mm4          // Only pav bytes < 0 in mm7
  948.             pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
  949.             psubw mm4, mm0
  950.             pand mm7, mm5          // Only pbv bytes < 0 in mm0
  951.             psubw mm4, mm0
  952.             psubw mm5, mm7
  953.             pxor mm0, mm0
  954.             pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
  955.             pand mm0, mm6          // Only pav bytes < 0 in mm7
  956.             psubw mm5, mm7
  957.             psubw mm6, mm0
  958.             //  test pa <= pb
  959.             movq mm7, mm4
  960.             psubw mm6, mm0
  961.             pcmpgtw mm7, mm5       // pa > pb?
  962.             movq mm0, mm7
  963.             // use mm7 mask to merge pa & pb
  964.             pand mm5, mm7
  965.             // use mm0 mask copy to merge a & b
  966.             pand mm2, mm0
  967.             pandn mm7, mm4
  968.             pandn mm0, mm1
  969.             paddw mm7, mm5
  970.             paddw mm0, mm2
  971.             //  test  ((pa <= pb)? pa:pb) <= pc
  972.             pcmpgtw mm7, mm6       // pab > pc?
  973.             pxor mm1, mm1
  974.             pand mm3, mm7
  975.             pandn mm7, mm0
  976.             pxor mm1, mm1
  977.             paddw mm7, mm3
  978.             pxor mm0, mm0
  979.             // Step ex to next set of 8 bytes and repeat loop til done
  980.             add ebx, 8
  981.             packuswb mm1, mm7
  982.             paddb mm1, [edi + ebx - 8]     // add Paeth predictor with Raw(x)
  983.             cmp ebx, MMXLength
  984.             movq [edi + ebx - 8], mm1      // write back updated value
  985.                                 // mm1 will be used as Raw(x-bpp) next loop
  986.             jb dpth4lp
  987.          } // end _asm block
  988.       }
  989.       break;
  990.       case 8:                          // bpp == 8
  991.       {
  992.          ActiveMask.use  = 0x00000000ffffffff;
  993.          _asm {
  994.             mov ebx, diff
  995.             mov edi, row
  996.             mov esi, prev_row
  997.             pxor mm0, mm0
  998.             // PRIME the pump (load the first Raw(x-bpp) data set
  999.             movq mm1, [edi+ebx-8]      // Only time should need to read
  1000.                                        //  a=Raw(x-bpp) bytes
  1001. dpth8lp:
  1002.             // Do first set of 4 bytes
  1003.             movq mm3, [esi+ebx-8]      // read c=Prior(x-bpp) bytes
  1004.             punpcklbw mm1, mm0         // Unpack Low bytes of a
  1005.             movq mm2, [esi + ebx]      // load b=Prior(x)
  1006.             punpcklbw mm2, mm0         // Unpack Low bytes of b
  1007.             // pav = p - a = (a + b - c) - a = b - c
  1008.             movq mm4, mm2
  1009.             punpcklbw mm3, mm0         // Unpack Low bytes of c
  1010.             // pbv = p - b = (a + b - c) - b = a - c
  1011.             movq mm5, mm1
  1012.             psubw mm4, mm3
  1013.             pxor mm7, mm7
  1014.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  1015.             movq mm6, mm4
  1016.             psubw mm5, mm3
  1017.             // pa = abs(p-a) = abs(pav)
  1018.             // pb = abs(p-b) = abs(pbv)
  1019.             // pc = abs(p-c) = abs(pcv)
  1020.             pcmpgtw mm0, mm4       // Create mask pav bytes < 0
  1021.             paddw mm6, mm5
  1022.             pand mm0, mm4          // Only pav bytes < 0 in mm7
  1023.             pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
  1024.             psubw mm4, mm0
  1025.             pand mm7, mm5          // Only pbv bytes < 0 in mm0
  1026.             psubw mm4, mm0
  1027.             psubw mm5, mm7
  1028.             pxor mm0, mm0
  1029.             pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
  1030.             pand mm0, mm6          // Only pav bytes < 0 in mm7
  1031.             psubw mm5, mm7
  1032.             psubw mm6, mm0
  1033.             //  test pa <= pb
  1034.             movq mm7, mm4
  1035.             psubw mm6, mm0
  1036.             pcmpgtw mm7, mm5       // pa > pb?
  1037.             movq mm0, mm7
  1038.             // use mm7 mask to merge pa & pb
  1039.             pand mm5, mm7
  1040.             // use mm0 mask copy to merge a & b
  1041.             pand mm2, mm0
  1042.             pandn mm7, mm4
  1043.             pandn mm0, mm1
  1044.             paddw mm7, mm5
  1045.             paddw mm0, mm2
  1046.             //  test  ((pa <= pb)? pa:pb) <= pc
  1047.             pcmpgtw mm7, mm6       // pab > pc?
  1048.             pxor mm1, mm1
  1049.             pand mm3, mm7
  1050.             pandn mm7, mm0
  1051.             paddw mm7, mm3
  1052.             pxor mm0, mm0
  1053.             packuswb mm7, mm1
  1054.             movq mm3, [esi+ebx-8]    // read c=Prior(x-bpp) bytes
  1055.             pand mm7, ActiveMask
  1056.             movq mm2, [esi + ebx]    // load b=Prior(x)
  1057.             paddb mm7, [edi + ebx]   // add Paeth predictor with Raw(x)
  1058.             punpckhbw mm3, mm0       // Unpack High bytes of c
  1059.             movq [edi + ebx], mm7    // write back updated value
  1060.             movq mm1, [edi+ebx-8]    // read a=Raw(x-bpp) bytes
  1061.             // Do second set of 4 bytes
  1062.             punpckhbw mm2, mm0       // Unpack High bytes of b
  1063.             punpckhbw mm1, mm0       // Unpack High bytes of a
  1064.             // pav = p - a = (a + b - c) - a = b - c
  1065.             movq mm4, mm2
  1066.             // pbv = p - b = (a + b - c) - b = a - c
  1067.             movq mm5, mm1
  1068.             psubw mm4, mm3
  1069.             pxor mm7, mm7
  1070.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  1071.             movq mm6, mm4
  1072.             psubw mm5, mm3
  1073.             // pa = abs(p-a) = abs(pav)
  1074.             // pb = abs(p-b) = abs(pbv)
  1075.             // pc = abs(p-c) = abs(pcv)
  1076.             pcmpgtw mm0, mm4       // Create mask pav bytes < 0
  1077.             paddw mm6, mm5
  1078.             pand mm0, mm4          // Only pav bytes < 0 in mm7
  1079.             pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
  1080.             psubw mm4, mm0
  1081.             pand mm7, mm5          // Only pbv bytes < 0 in mm0
  1082.             psubw mm4, mm0
  1083.             psubw mm5, mm7
  1084.             pxor mm0, mm0
  1085.             pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
  1086.             pand mm0, mm6          // Only pav bytes < 0 in mm7
  1087.             psubw mm5, mm7
  1088.             psubw mm6, mm0
  1089.             //  test pa <= pb
  1090.             movq mm7, mm4
  1091.             psubw mm6, mm0
  1092.             pcmpgtw mm7, mm5       // pa > pb?
  1093.             movq mm0, mm7
  1094.             // use mm7 mask to merge pa & pb
  1095.             pand mm5, mm7
  1096.             // use mm0 mask copy to merge a & b
  1097.             pand mm2, mm0
  1098.             pandn mm7, mm4
  1099.             pandn mm0, mm1
  1100.             paddw mm7, mm5
  1101.             paddw mm0, mm2
  1102.             //  test  ((pa <= pb)? pa:pb) <= pc
  1103.             pcmpgtw mm7, mm6       // pab > pc?
  1104.             pxor mm1, mm1
  1105.             pand mm3, mm7
  1106.             pandn mm7, mm0
  1107.             pxor mm1, mm1
  1108.             paddw mm7, mm3
  1109.             pxor mm0, mm0
  1110.             // Step ex to next set of 8 bytes and repeat loop til done
  1111.             add ebx, 8
  1112.             packuswb mm1, mm7
  1113.             paddb mm1, [edi + ebx - 8]     // add Paeth predictor with Raw(x)
  1114.             cmp ebx, MMXLength
  1115.             movq [edi + ebx - 8], mm1      // write back updated value
  1116.                             // mm1 will be used as Raw(x-bpp) next loop
  1117.             jb dpth8lp
  1118.          } // end _asm block
  1119.       }
  1120.       break;
  1121.       case 1:                // bpp = 1
  1122.       case 2:                // bpp = 2
  1123.       default:               // bpp > 8
  1124.       {
  1125.          _asm {
  1126.             mov ebx, diff
  1127.             cmp ebx, FullLength
  1128.             jnb dpthdend
  1129.             mov edi, row
  1130.             mov esi, prev_row
  1131.             // Do Paeth decode for remaining bytes
  1132.             mov edx, ebx
  1133.             xor ecx, ecx        // zero ecx before using cl & cx in loop below
  1134.             sub edx, bpp        // Set edx = ebx - bpp
  1135. dpthdlp:
  1136.             xor eax, eax
  1137.             // pav = p - a = (a + b - c) - a = b - c
  1138.             mov al, [esi + ebx]        // load Prior(x) into al
  1139.             mov cl, [esi + edx]        // load Prior(x-bpp) into cl
  1140.             sub eax, ecx                 // subtract Prior(x-bpp)
  1141.             mov patemp, eax                 // Save pav for later use
  1142.             xor eax, eax
  1143.             // pbv = p - b = (a + b - c) - b = a - c
  1144.             mov al, [edi + edx]        // load Raw(x-bpp) into al
  1145.             sub eax, ecx                 // subtract Prior(x-bpp)
  1146.             mov ecx, eax
  1147.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  1148.             add eax, patemp                 // pcv = pav + pbv
  1149.             // pc = abs(pcv)
  1150.             test eax, 0x80000000
  1151.             jz dpthdpca
  1152.             neg eax                     // reverse sign of neg values
  1153. dpthdpca:
  1154.             mov pctemp, eax             // save pc for later use
  1155.             // pb = abs(pbv)
  1156.             test ecx, 0x80000000
  1157.             jz dpthdpba
  1158.             neg ecx                     // reverse sign of neg values
  1159. dpthdpba:
  1160.             mov pbtemp, ecx             // save pb for later use
  1161.             // pa = abs(pav)
  1162.             mov eax, patemp
  1163.             test eax, 0x80000000
  1164.             jz dpthdpaa
  1165.             neg eax                     // reverse sign of neg values
  1166. dpthdpaa:
  1167.             mov patemp, eax             // save pa for later use
  1168.             // test if pa <= pb
  1169.             cmp eax, ecx
  1170.             jna dpthdabb
  1171.             // pa > pb; now test if pb <= pc
  1172.             cmp ecx, pctemp
  1173.             jna dpthdbbc
  1174.             // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
  1175.             mov cl, [esi + edx]  // load Prior(x-bpp) into cl
  1176.             jmp dpthdpaeth
  1177. dpthdbbc:
  1178.             // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
  1179.             mov cl, [esi + ebx]        // load Prior(x) into cl
  1180.             jmp dpthdpaeth
  1181. dpthdabb:
  1182.             // pa <= pb; now test if pa <= pc
  1183.             cmp eax, pctemp
  1184.             jna dpthdabc
  1185.             // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
  1186.             mov cl, [esi + edx]  // load Prior(x-bpp) into cl
  1187.             jmp dpthdpaeth
  1188. dpthdabc:
  1189.             // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
  1190.             mov cl, [edi + edx]  // load Raw(x-bpp) into cl
  1191. dpthdpaeth:
  1192.             inc ebx
  1193.             inc edx
  1194.             // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
  1195.             add [edi + ebx - 1], cl
  1196.             cmp ebx, FullLength
  1197.             jb dpthdlp
  1198. dpthdend:
  1199.          } // end _asm block
  1200.       }
  1201.       return;                   // No need to go further with this one
  1202.    }                         // end switch ( bpp )
  1203.    _asm
  1204.    {
  1205.          // MMX acceleration complete now do clean-up
  1206.          // Check if any remaining bytes left to decode
  1207.          mov ebx, MMXLength
  1208.          cmp ebx, FullLength
  1209.          jnb dpthend
  1210.          mov edi, row
  1211.          mov esi, prev_row
  1212.          // Do Paeth decode for remaining bytes
  1213.          mov edx, ebx
  1214.          xor ecx, ecx         // zero ecx before using cl & cx in loop below
  1215.          sub edx, bpp         // Set edx = ebx - bpp
  1216. dpthlp2:
  1217.          xor eax, eax
  1218.          // pav = p - a = (a + b - c) - a = b - c
  1219.          mov al, [esi + ebx]  // load Prior(x) into al
  1220.          mov cl, [esi + edx]  // load Prior(x-bpp) into cl
  1221.          sub eax, ecx         // subtract Prior(x-bpp)
  1222.          mov patemp, eax      // Save pav for later use
  1223.          xor eax, eax
  1224.          // pbv = p - b = (a + b - c) - b = a - c
  1225.          mov al, [edi + edx]  // load Raw(x-bpp) into al
  1226.          sub eax, ecx         // subtract Prior(x-bpp)
  1227.          mov ecx, eax
  1228.          // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  1229.          add eax, patemp      // pcv = pav + pbv
  1230.          // pc = abs(pcv)
  1231.          test eax, 0x80000000
  1232.          jz dpthpca2
  1233.          neg eax              // reverse sign of neg values
  1234. dpthpca2:
  1235.          mov pctemp, eax      // save pc for later use
  1236.          // pb = abs(pbv)
  1237.          test ecx, 0x80000000
  1238.          jz dpthpba2
  1239.          neg ecx              // reverse sign of neg values
  1240. dpthpba2:
  1241.          mov pbtemp, ecx      // save pb for later use
  1242.          // pa = abs(pav)
  1243.          mov eax, patemp
  1244.          test eax, 0x80000000
  1245.          jz dpthpaa2
  1246.          neg eax              // reverse sign of neg values
  1247. dpthpaa2:
  1248.          mov patemp, eax      // save pa for later use
  1249.          // test if pa <= pb
  1250.          cmp eax, ecx
  1251.          jna dpthabb2
  1252.          // pa > pb; now test if pb <= pc
  1253.          cmp ecx, pctemp
  1254.          jna dpthbbc2
  1255.          // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
  1256.          mov cl, [esi + edx]  // load Prior(x-bpp) into cl
  1257.          jmp dpthpaeth2
  1258. dpthbbc2:
  1259.          // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
  1260.          mov cl, [esi + ebx]        // load Prior(x) into cl
  1261.          jmp dpthpaeth2
  1262. dpthabb2:
  1263.          // pa <= pb; now test if pa <= pc
  1264.          cmp eax, pctemp
  1265.          jna dpthabc2
  1266.          // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
  1267.          mov cl, [esi + edx]  // load Prior(x-bpp) into cl
  1268.          jmp dpthpaeth2
  1269. dpthabc2:
  1270.          // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
  1271.          mov cl, [edi + edx]  // load Raw(x-bpp) into cl
  1272. dpthpaeth2:
  1273.          inc ebx
  1274.          inc edx
  1275.          // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
  1276.          add [edi + ebx - 1], cl
  1277.          cmp ebx, FullLength
  1278.          jb dpthlp2
  1279. dpthend:
  1280.          emms             // End MMX instructions; prep for possible FP instrs.
  1281.    } // end _asm block
  1282. }
  1283. // Optimized code for PNG Sub filter decoder
  1284. void /* PRIVATE */
  1285. png_read_filter_row_mmx_sub(png_row_infop row_info, png_bytep row)
  1286. {
  1287.    //int test;
  1288.    int bpp;
  1289.    png_uint_32 FullLength;
  1290.    png_uint_32 MMXLength;
  1291.    int diff;
  1292.    bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
  1293.    FullLength  = row_info->rowbytes - bpp; // # of bytes to filter
  1294.    _asm {
  1295.         mov edi, row
  1296.         mov esi, edi               // lp = row
  1297.         add edi, bpp               // rp = row + bpp
  1298.         xor eax, eax
  1299.         // get # of bytes to alignment
  1300.         mov diff, edi               // take start of row
  1301.         add diff, 0xf               // add 7 + 8 to incr past
  1302.                                         // alignment boundary
  1303.         xor ebx, ebx
  1304.         and diff, 0xfffffff8        // mask to alignment boundary
  1305.         sub diff, edi               // subtract from start ==> value
  1306.                                         //  ebx at alignment
  1307.         jz dsubgo
  1308.         // fix alignment
  1309. dsublp1:
  1310.         mov al, [esi+ebx]
  1311.         add [edi+ebx], al
  1312.         inc ebx
  1313.         cmp ebx, diff
  1314.         jb dsublp1
  1315. dsubgo:
  1316.         mov ecx, FullLength
  1317.         mov edx, ecx
  1318.         sub edx, ebx                  // subtract alignment fix
  1319.         and edx, 0x00000007           // calc bytes over mult of 8
  1320.         sub ecx, edx                  // drop over bytes from length
  1321.         mov MMXLength, ecx
  1322.    } // end _asm block
  1323.    // Now do the math for the rest of the row
  1324.    switch ( bpp )
  1325.    {
  1326.         case 3:
  1327.         {
  1328.          ActiveMask.use  = 0x0000ffffff000000;
  1329.          ShiftBpp.use = 24;       // == 3 * 8
  1330.          ShiftRem.use  = 40;      // == 64 - 24
  1331.          _asm {
  1332.             mov edi, row
  1333.             movq mm7, ActiveMask  // Load ActiveMask for 2nd active byte group
  1334.             mov esi, edi              // lp = row
  1335.             add edi, bpp          // rp = row + bpp
  1336.             movq mm6, mm7
  1337.             mov ebx, diff
  1338.             psllq mm6, ShiftBpp   // Move mask in mm6 to cover 3rd active
  1339.                                   // byte group
  1340.             // PRIME the pump (load the first Raw(x-bpp) data set
  1341.             movq mm1, [edi+ebx-8]
  1342. dsub3lp:
  1343.             psrlq mm1, ShiftRem   // Shift data for adding 1st bpp bytes
  1344.                           // no need for mask; shift clears inactive bytes
  1345.             // Add 1st active group
  1346.             movq mm0, [edi+ebx]
  1347.             paddb mm0, mm1
  1348.             // Add 2nd active group
  1349.             movq mm1, mm0         // mov updated Raws to mm1
  1350.             psllq mm1, ShiftBpp   // shift data to position correctly
  1351.             pand mm1, mm7         // mask to use only 2nd active group
  1352.             paddb mm0, mm1
  1353.             // Add 3rd active group
  1354.             movq mm1, mm0         // mov updated Raws to mm1
  1355.             psllq mm1, ShiftBpp   // shift data to position correctly
  1356.             pand mm1, mm6         // mask to use only 3rd active group
  1357.             add ebx, 8
  1358.             paddb mm0, mm1
  1359.             cmp ebx, MMXLength
  1360.             movq [edi+ebx-8], mm0     // Write updated Raws back to array
  1361.             // Prep for doing 1st add at top of loop
  1362.             movq mm1, mm0
  1363.             jb dsub3lp
  1364.          } // end _asm block
  1365.       }
  1366.       break;
  1367.       case 1:
  1368.       {
  1369.          // Placed here just in case this is a duplicate of the
  1370.          // non-MMX code for the SUB filter in png_read_filter_row below
  1371.          //
  1372.          //         png_bytep rp;
  1373.          //         png_bytep lp;
  1374.          //         png_uint_32 i;
  1375.          //         bpp = (row_info->pixel_depth + 7) >> 3;
  1376.          //         for (i = (png_uint_32)bpp, rp = row + bpp, lp = row;
  1377.          //            i < row_info->rowbytes; i++, rp++, lp++)
  1378.          //      {
  1379.          //            *rp = (png_byte)(((int)(*rp) + (int)(*lp)) & 0xff);
  1380.          //      }
  1381.          _asm {
  1382.             mov ebx, diff
  1383.             mov edi, row
  1384.             cmp ebx, FullLength
  1385.             jnb dsub1end
  1386.             mov esi, edi          // lp = row
  1387.             xor eax, eax
  1388.             add edi, bpp      // rp = row + bpp
  1389. dsub1lp:
  1390.             mov al, [esi+ebx]
  1391.             add [edi+ebx], al
  1392.             inc ebx
  1393.             cmp ebx, FullLength
  1394.             jb dsub1lp
  1395. dsub1end:
  1396.          } // end _asm block
  1397.       }
  1398.       return;
  1399.       case 6:
  1400.       case 7:
  1401.       case 4:
  1402.       case 5:
  1403.       {
  1404.          ShiftBpp.use = bpp << 3;
  1405.          ShiftRem.use = 64 - ShiftBpp.use;
  1406.          _asm {
  1407.             mov edi, row
  1408.             mov ebx, diff
  1409.             mov esi, edi               // lp = row
  1410.             add edi, bpp           // rp = row + bpp
  1411.             // PRIME the pump (load the first Raw(x-bpp) data set
  1412.             movq mm1, [edi+ebx-8]
  1413. dsub4lp:
  1414.             psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes
  1415.                           // no need for mask; shift clears inactive bytes
  1416.             movq mm0, [edi+ebx]
  1417.             paddb mm0, mm1
  1418.             // Add 2nd active group
  1419.             movq mm1, mm0          // mov updated Raws to mm1
  1420.             psllq mm1, ShiftBpp    // shift data to position correctly
  1421.                                    // there is no need for any mask
  1422.                                    // since shift clears inactive bits/bytes
  1423.             add ebx, 8
  1424.             paddb mm0, mm1
  1425.             cmp ebx, MMXLength
  1426.             movq [edi+ebx-8], mm0
  1427.             movq mm1, mm0          // Prep for doing 1st add at top of loop
  1428.             jb dsub4lp
  1429.          } // end _asm block
  1430.       }
  1431.       break;
  1432.       case 2:
  1433.       {
  1434.          ActiveMask.use  = 0x00000000ffff0000;
  1435.          ShiftBpp.use = 16;       // == 2 * 8
  1436.          ShiftRem.use = 48;       // == 64 - 16
  1437.          _asm {
  1438.             movq mm7, ActiveMask  // Load ActiveMask for 2nd active byte group
  1439.             mov ebx, diff
  1440.             movq mm6, mm7
  1441.             mov edi, row
  1442.             psllq mm6, ShiftBpp     // Move mask in mm6 to cover 3rd active
  1443.             mov esi, edi            // lp = row
  1444.             movq mm5, mm6
  1445.             add edi, bpp            // rp = row + bpp
  1446.             psllq mm5, ShiftBpp     // Move mask in mm5 to cover 4th active
  1447.                                     //  byte group
  1448.             // PRIME the pump (load the first Raw(x-bpp) data set
  1449.             movq mm1, [edi+ebx-8]
  1450. dsub2lp:
  1451.             // Add 1st active group
  1452.             psrlq mm1, ShiftRem     // Shift data for adding 1st bpp bytes
  1453.                                     // no need for mask; shift clears inactive
  1454.                                     //  bytes
  1455.             movq mm0, [edi+ebx]
  1456.             paddb mm0, mm1
  1457.             // Add 2nd active group
  1458.             movq mm1, mm0           // mov updated Raws to mm1
  1459.             psllq mm1, ShiftBpp     // shift data to position correctly
  1460.             pand mm1, mm7           // mask to use only 2nd active group
  1461.             paddb mm0, mm1
  1462.             // Add 3rd active group
  1463.             movq mm1, mm0           // mov updated Raws to mm1
  1464.             psllq mm1, ShiftBpp     // shift data to position correctly
  1465.             pand mm1, mm6           // mask to use only 3rd active group
  1466.             paddb mm0, mm1
  1467.             // Add 4th active group
  1468.             movq mm1, mm0           // mov updated Raws to mm1
  1469.             psllq mm1, ShiftBpp     // shift data to position correctly
  1470.             pand mm1, mm5           // mask to use only 4th active group
  1471.             add ebx, 8
  1472.             paddb mm0, mm1
  1473.             cmp ebx, MMXLength
  1474.             movq [edi+ebx-8], mm0   // Write updated Raws back to array
  1475.             movq mm1, mm0           // Prep for doing 1st add at top of loop
  1476.             jb dsub2lp
  1477.          } // end _asm block
  1478.       }
  1479.       break;
  1480.       case 8:
  1481.       {
  1482.          _asm {
  1483.             mov edi, row
  1484.             mov ebx, diff
  1485.             mov esi, edi            // lp = row
  1486.             add edi, bpp            // rp = row + bpp
  1487.             mov ecx, MMXLength
  1488.             movq mm7, [edi+ebx-8]   // PRIME the pump (load the first
  1489.                                     // Raw(x-bpp) data set
  1490.             and ecx, 0x0000003f     // calc bytes over mult of 64
  1491. dsub8lp:
  1492.             movq mm0, [edi+ebx]     // Load Sub(x) for 1st 8 bytes
  1493.             paddb mm0, mm7
  1494.             movq mm1, [edi+ebx+8]   // Load Sub(x) for 2nd 8 bytes
  1495.             movq [edi+ebx], mm0    // Write Raw(x) for 1st 8 bytes
  1496.                                    // Now mm0 will be used as Raw(x-bpp) for
  1497.                                    // the 2nd group of 8 bytes.  This will be
  1498.                                    // repeated for each group of 8 bytes with
  1499.                                    // the 8th group being used as the Raw(x-bpp)
  1500.                                    // for the 1st group of the next loop.
  1501.             paddb mm1, mm0
  1502.             movq mm2, [edi+ebx+16]  // Load Sub(x) for 3rd 8 bytes
  1503.             movq [edi+ebx+8], mm1   // Write Raw(x) for 2nd 8 bytes
  1504.             paddb mm2, mm1
  1505.             movq mm3, [edi+ebx+24]  // Load Sub(x) for 4th 8 bytes
  1506.             movq [edi+ebx+16], mm2  // Write Raw(x) for 3rd 8 bytes
  1507.             paddb mm3, mm2
  1508.             movq mm4, [edi+ebx+32]  // Load Sub(x) for 5th 8 bytes
  1509.             movq [edi+ebx+24], mm3  // Write Raw(x) for 4th 8 bytes
  1510.             paddb mm4, mm3
  1511.             movq mm5, [edi+ebx+40]  // Load Sub(x) for 6th 8 bytes
  1512.             movq [edi+ebx+32], mm4  // Write Raw(x) for 5th 8 bytes
  1513.             paddb mm5, mm4
  1514.             movq mm6, [edi+ebx+48]  // Load Sub(x) for 7th 8 bytes
  1515.             movq [edi+ebx+40], mm5  // Write Raw(x) for 6th 8 bytes
  1516.             paddb mm6, mm5
  1517.             movq mm7, [edi+ebx+56]  // Load Sub(x) for 8th 8 bytes
  1518.             movq [edi+ebx+48], mm6  // Write Raw(x) for 7th 8 bytes
  1519.             add ebx, 64
  1520.             paddb mm7, mm6
  1521.             cmp ebx, ecx
  1522.             movq [edi+ebx-8], mm7   // Write Raw(x) for 8th 8 bytes
  1523.             jb dsub8lp
  1524.             cmp ebx, MMXLength
  1525.             jnb dsub8lt8
  1526. dsub8lpA:
  1527.             movq mm0, [edi+ebx]
  1528.             add ebx, 8
  1529.             paddb mm0, mm7
  1530.             cmp ebx, MMXLength
  1531.             movq [edi+ebx-8], mm0   // use -8 to offset early add to ebx
  1532.             movq mm7, mm0           // Move calculated Raw(x) data to mm1 to
  1533.                                     // be the new Raw(x-bpp) for the next loop
  1534.             jb dsub8lpA
  1535. dsub8lt8:
  1536.          } // end _asm block
  1537.       }
  1538.       break;
  1539.       default:                // bpp greater than 8 bytes
  1540.       {
  1541.          _asm {
  1542.             mov ebx, diff
  1543.             mov edi, row
  1544.             mov esi, edi           // lp = row
  1545.             add edi, bpp           // rp = row + bpp
  1546. dsubAlp:
  1547.             movq mm0, [edi+ebx]
  1548.             movq mm1, [esi+ebx]
  1549.             add ebx, 8
  1550.             paddb mm0, mm1
  1551.             cmp ebx, MMXLength
  1552.             movq [edi+ebx-8], mm0  // mov does not affect flags; -8 to offset
  1553.                                    //  add ebx
  1554.             jb dsubAlp
  1555.          } // end _asm block
  1556.       }
  1557.       break;
  1558.    } // end switch ( bpp )
  1559.    _asm {
  1560.         mov ebx, MMXLength
  1561.         mov edi, row
  1562.         cmp ebx, FullLength
  1563.         jnb dsubend
  1564.         mov esi, edi               // lp = row
  1565.         xor eax, eax
  1566.         add edi, bpp               // rp = row + bpp
  1567. dsublp2:
  1568.         mov al, [esi+ebx]
  1569.         add [edi+ebx], al
  1570.         inc ebx
  1571.         cmp ebx, FullLength
  1572.         jb dsublp2
  1573. dsubend:
  1574.         emms             // End MMX instructions; prep for possible FP instrs.
  1575.    } // end _asm block
  1576. }
  1577. // Optimized code for PNG Up filter decoder
  1578. void /* PRIVATE */
  1579. png_read_filter_row_mmx_up(png_row_infop row_info, png_bytep row,
  1580.    png_bytep prev_row)
  1581. {
  1582.    png_uint_32 len;
  1583.    len  = row_info->rowbytes;       // # of bytes to filter
  1584.    _asm {
  1585.       mov edi, row
  1586.       // get # of bytes to alignment
  1587.       mov ecx, edi
  1588.       xor ebx, ebx
  1589.       add ecx, 0x7
  1590.       xor eax, eax
  1591.       and ecx, 0xfffffff8
  1592.       mov esi, prev_row
  1593.       sub ecx, edi
  1594.       jz dupgo
  1595.       // fix alignment
  1596. duplp1:
  1597.       mov al, [edi+ebx]
  1598.       add al, [esi+ebx]
  1599.       inc ebx
  1600.       cmp ebx, ecx
  1601.       mov [edi + ebx-1], al  // mov does not affect flags; -1 to offset inc ebx
  1602.       jb duplp1
  1603. dupgo:
  1604.       mov ecx, len
  1605.       mov edx, ecx
  1606.       sub edx, ebx                  // subtract alignment fix
  1607.       and edx, 0x0000003f           // calc bytes over mult of 64
  1608.       sub ecx, edx                  // drop over bytes from length
  1609.       // Unrolled loop - use all MMX registers and interleave to reduce
  1610.       // number of branch instructions (loops) and reduce partial stalls
  1611. duploop:
  1612.       movq mm1, [esi+ebx]
  1613.       movq mm0, [edi+ebx]
  1614.       movq mm3, [esi+ebx+8]
  1615.       paddb mm0, mm1
  1616.       movq mm2, [edi+ebx+8]
  1617.       movq [edi+ebx], mm0
  1618.       paddb mm2, mm3
  1619.       movq mm5, [esi+ebx+16]
  1620.       movq [edi+ebx+8], mm2
  1621.       movq mm4, [edi+ebx+16]
  1622.       movq mm7, [esi+ebx+24]
  1623.       paddb mm4, mm5
  1624.       movq mm6, [edi+ebx+24]
  1625.       movq [edi+ebx+16], mm4
  1626.       paddb mm6, mm7
  1627.       movq mm1, [esi+ebx+32]
  1628.       movq [edi+ebx+24], mm6
  1629.       movq mm0, [edi+ebx+32]
  1630.       movq mm3, [esi+ebx+40]
  1631.       paddb mm0, mm1
  1632.       movq mm2, [edi+ebx+40]
  1633.       movq [edi+ebx+32], mm0
  1634.       paddb mm2, mm3
  1635.       movq mm5, [esi+ebx+48]
  1636.       movq [edi+ebx+40], mm2
  1637.       movq mm4, [edi+ebx+48]
  1638.       movq mm7, [esi+ebx+56]
  1639.       paddb mm4, mm5
  1640.       movq mm6, [edi+ebx+56]
  1641.       movq [edi+ebx+48], mm4
  1642.       add ebx, 64
  1643.       paddb mm6, mm7
  1644.       cmp ebx, ecx
  1645.       movq [edi+ebx-8], mm6 // (+56)movq does not affect flags;
  1646.                                      // -8 to offset add ebx
  1647.       jb duploop
  1648.       cmp edx, 0                     // Test for bytes over mult of 64
  1649.       jz dupend
  1650.       // 2 lines added by lcreeve at netins.net
  1651.       // (mail 11 Jul 98 in png-implement list)
  1652.       cmp edx, 8 //test for less than 8 bytes
  1653.       jb duplt8
  1654.       add ecx, edx
  1655.       and edx, 0x00000007           // calc bytes over mult of 8
  1656.       sub ecx, edx                  // drop over bytes from length
  1657.       jz duplt8
  1658.       // Loop using MMX registers mm0 & mm1 to update 8 bytes simultaneously
  1659. duplpA:
  1660.       movq mm1, [esi+ebx]
  1661.       movq mm0, [edi+ebx]
  1662.       add ebx, 8
  1663.       paddb mm0, mm1
  1664.       cmp ebx, ecx
  1665.       movq [edi+ebx-8], mm0 // movq does not affect flags; -8 to offset add ebx
  1666.       jb duplpA
  1667.       cmp edx, 0            // Test for bytes over mult of 8
  1668.       jz dupend
  1669. duplt8:
  1670.       xor eax, eax
  1671.       add ecx, edx          // move over byte count into counter
  1672.       // Loop using x86 registers to update remaining bytes
  1673. duplp2:
  1674.       mov al, [edi + ebx]
  1675.       add al, [esi + ebx]
  1676.       inc ebx
  1677.       cmp ebx, ecx
  1678.       mov [edi + ebx-1], al // mov does not affect flags; -1 to offset inc ebx
  1679.       jb duplp2
  1680. dupend:
  1681.       // Conversion of filtered row completed
  1682.       emms          // End MMX instructions; prep for possible FP instrs.
  1683.    } // end _asm block
  1684. }
  1685. // Optimized png_read_filter_row routines
  1686. void /* PRIVATE */
  1687. png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep
  1688.    row, png_bytep prev_row, int filter)
  1689. {
  1690. #ifdef PNG_DEBUG
  1691.    char filnm[10];
  1692. #endif
  1693.    if (mmx_supported == 2) {
  1694. #if !defined(PNG_1_0_X)
  1695.        /* this should have happened in png_init_mmx_flags() already */
  1696.        png_warning(png_ptr, "asm_flags may not have been initialized");
  1697. #endif
  1698.        png_mmx_support();
  1699.    }
  1700. #ifdef PNG_DEBUG
  1701.    png_debug(1, "in png_read_filter_rown");
  1702.    switch (filter)
  1703.    {
  1704.       case 0: sprintf(filnm, "none");
  1705.          break;
  1706. #if !defined(PNG_1_0_X)
  1707.       case 1: sprintf(filnm, "sub-%s",
  1708.         (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB)? "MMX" : "x86");
  1709.          break;
  1710.       case 2: sprintf(filnm, "up-%s",
  1711.         (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP)? "MMX" : "x86");
  1712.          break;
  1713.       case 3: sprintf(filnm, "avg-%s",
  1714.         (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG)? "MMX" : "x86");
  1715.          break;
  1716.       case 4: sprintf(filnm, "Paeth-%s",
  1717.         (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH)? "MMX":"x86");
  1718.          break;
  1719. #else
  1720.       case 1: sprintf(filnm, "sub");
  1721.          break;
  1722.       case 2: sprintf(filnm, "up");
  1723.          break;
  1724.       case 3: sprintf(filnm, "avg");
  1725.          break;
  1726.       case 4: sprintf(filnm, "Paeth");
  1727.          break;
  1728. #endif
  1729.       default: sprintf(filnm, "unknw");
  1730.          break;
  1731.    }
  1732.    png_debug2(0,"row=%5d, %s, ", png_ptr->row_number, filnm);
  1733.    png_debug2(0, "pd=%2d, b=%d, ", (int)row_info->pixel_depth,
  1734.       (int)((row_info->pixel_depth + 7) >> 3));
  1735.    png_debug1(0,"len=%8d, ", row_info->rowbytes);
  1736. #endif /* PNG_DEBUG */
  1737.    switch (filter)
  1738.    {
  1739.       case PNG_FILTER_VALUE_NONE:
  1740.          break;
  1741.       case PNG_FILTER_VALUE_SUB:
  1742.       {
  1743. #if !defined(PNG_1_0_X)
  1744.          if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB) &&
  1745.              (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
  1746.              (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
  1747. #else
  1748.          if (mmx_supported)
  1749. #endif
  1750.          {
  1751.             png_read_filter_row_mmx_sub(row_info, row);
  1752.          }
  1753.          else
  1754.          {
  1755.             png_uint_32 i;
  1756.             png_uint_32 istop = row_info->rowbytes;
  1757.             png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
  1758.             png_bytep rp = row + bpp;
  1759.             png_bytep lp = row;
  1760.             for (i = bpp; i < istop; i++)
  1761.             {
  1762.                *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
  1763.                rp++;
  1764.             }
  1765.          }
  1766.          break;
  1767.       }
  1768.       case PNG_FILTER_VALUE_UP:
  1769.       {
  1770. #if !defined(PNG_1_0_X)
  1771.          if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP) &&
  1772.              (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
  1773.              (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
  1774. #else
  1775.          if (mmx_supported)
  1776. #endif
  1777.          {
  1778.             png_read_filter_row_mmx_up(row_info, row, prev_row);
  1779.          }
  1780.          else
  1781.          {
  1782.             png_uint_32 i;
  1783.             png_uint_32 istop = row_info->rowbytes;
  1784.             png_bytep rp = row;
  1785.             png_bytep pp = prev_row;
  1786.             for (i = 0; i < istop; ++i)
  1787.             {
  1788.                *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
  1789.                rp++;
  1790.             }
  1791.          }
  1792.          break;
  1793.       }
  1794.       case PNG_FILTER_VALUE_AVG:
  1795.       {
  1796. #if !defined(PNG_1_0_X)
  1797.          if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG) &&
  1798.              (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
  1799.              (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
  1800. #else
  1801.          if (mmx_supported)
  1802. #endif
  1803.          {
  1804.             png_read_filter_row_mmx_avg(row_info, row, prev_row);
  1805.          }
  1806.          else
  1807.          {
  1808.             png_uint_32 i;
  1809.             png_bytep rp = row;
  1810.             png_bytep pp = prev_row;
  1811.             png_bytep lp = row;
  1812.             png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
  1813.             png_uint_32 istop = row_info->rowbytes - bpp;
  1814.             for (i = 0; i < bpp; i++)
  1815.             {
  1816.                *rp = (png_byte)(((int)(*rp) +
  1817.                   ((int)(*pp++) >> 1)) & 0xff);
  1818.                rp++;
  1819.             }
  1820.             for (i = 0; i < istop; i++)
  1821.             {
  1822.                *rp = (png_byte)(((int)(*rp) +
  1823.                   ((int)(*pp++ + *lp++) >> 1)) & 0xff);
  1824.                rp++;
  1825.             }
  1826.          }
  1827.          break;
  1828.       }
  1829.       case PNG_FILTER_VALUE_PAETH:
  1830.       {
  1831. #if !defined(PNG_1_0_X)
  1832.          if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH) &&
  1833.              (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
  1834.              (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
  1835. #else
  1836.          if (mmx_supported)
  1837. #endif
  1838.          {
  1839.             png_read_filter_row_mmx_paeth(row_info, row, prev_row);
  1840.          }
  1841.          else
  1842.          {
  1843.             png_uint_32 i;
  1844.             png_bytep rp = row;
  1845.             png_bytep pp = prev_row;
  1846.             png_bytep lp = row;
  1847.             png_bytep cp = prev_row;
  1848.             png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
  1849.             png_uint_32 istop=row_info->rowbytes - bpp;
  1850.             for (i = 0; i < bpp; i++)
  1851.             {
  1852.                *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
  1853.                rp++;
  1854.             }
  1855.             for (i = 0; i < istop; i++)   // use leftover rp,pp
  1856.             {
  1857.                int a, b, c, pa, pb, pc, p;
  1858.                a = *lp++;
  1859.                b = *pp++;
  1860.                c = *cp++;
  1861.                p = b - c;
  1862.                pc = a - c;
  1863. #ifdef PNG_USE_ABS
  1864.                pa = abs(p);
  1865.                pb = abs(pc);
  1866.                pc = abs(p + pc);
  1867. #else
  1868.                pa = p < 0 ? -p : p;
  1869.                pb = pc < 0 ? -pc : pc;
  1870.                pc = (p + pc) < 0 ? -(p + pc) : p + pc;
  1871. #endif
  1872.                /*
  1873.                   if (pa <= pb && pa <= pc)
  1874.                      p = a;
  1875.                   else if (pb <= pc)
  1876.                      p = b;
  1877.                   else
  1878.                      p = c;
  1879.                 */
  1880.                p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
  1881.                *rp = (png_byte)(((int)(*rp) + p) & 0xff);
  1882.                rp++;
  1883.             }
  1884.          }
  1885.          break;
  1886.       }
  1887.       default:
  1888.          png_warning(png_ptr, "Ignoring bad row filter type");
  1889.          *row=0;
  1890.          break;
  1891.    }
  1892. }
  1893. #endif /* PNG_ASSEMBLER_CODE_SUPPORTED && PNG_USE_PNGVCRD */