pngvcrd.c
上传用户:jnfxsk
上传日期:2022-06-16
资源大小:3675k
文件大小:144k
源码类别:

游戏引擎

开发平台:

Visual C++

  1.          shr al, 1             // divide by 2
  2.          add al, [edi+ebx-1]   // Add Avg(x); -1 to offset inc ebx
  3.          cmp ebx, bpp
  4.          mov [edi+ebx-1], al    // Write back Raw(x);
  5.                             // mov does not affect flags; -1 to offset inc ebx
  6.          jb davgrlp
  7.          // get # of bytes to alignment
  8.          mov diff, edi         // take start of row
  9.          add diff, ebx         // add bpp
  10.          add diff, 0xf         // add 7 + 8 to incr past alignment boundary
  11.          and diff, 0xfffffff8  // mask to alignment boundary
  12.          sub diff, edi         // subtract from start ==> value ebx at alignment
  13.          jz davggo
  14.          // fix alignment
  15.          // Compute the Raw value for the bytes upto the alignment boundary
  16.          //    Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
  17.          xor ecx, ecx
  18. davglp1:
  19.          xor eax, eax
  20.          mov cl, [esi + ebx]        // load cl with Prior(x)
  21.          mov al, [edx + ebx]  // load al with Raw(x-bpp)
  22.          add ax, cx
  23.          inc ebx
  24.          shr ax, 1            // divide by 2
  25.          add al, [edi+ebx-1]  // Add Avg(x); -1 to offset inc ebx
  26.          cmp ebx, diff              // Check if at alignment boundary
  27.          mov [edi+ebx-1], al        // Write back Raw(x);
  28.                             // mov does not affect flags; -1 to offset inc ebx
  29.          jb davglp1               // Repeat until at alignment boundary
  30. davggo:
  31.          mov eax, FullLength
  32.          mov ecx, eax
  33.          sub eax, ebx          // subtract alignment fix
  34.          and eax, 0x00000007   // calc bytes over mult of 8
  35.          sub ecx, eax          // drop over bytes from original length
  36.          mov MMXLength, ecx
  37.    } // end _asm block
  38.    // Now do the math for the rest of the row
  39.    switch ( bpp )
  40.    {
  41.       case 3:
  42.       {
  43.          ActiveMask.use  = 0x0000000000ffffff;
  44.          ShiftBpp.use = 24;    // == 3 * 8
  45.          ShiftRem.use = 40;    // == 64 - 24
  46.          _asm {
  47.             // Re-init address pointers and offset
  48.             movq mm7, ActiveMask
  49.             mov ebx, diff      // ebx ==> x = offset to alignment boundary
  50.             movq mm5, LBCarryMask
  51.             mov edi, row       // edi ==> Avg(x)
  52.             movq mm4, HBClearMask
  53.             mov esi, prev_row        // esi ==> Prior(x)
  54.             // PRIME the pump (load the first Raw(x-bpp) data set
  55.             movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
  56.                                // (we correct position in loop below)
  57. davg3lp:
  58.             movq mm0, [edi + ebx]      // Load mm0 with Avg(x)
  59.             // Add (Prev_row/2) to Average
  60.             movq mm3, mm5
  61.             psrlq mm2, ShiftRem      // Correct position Raw(x-bpp) data
  62.             movq mm1, [esi + ebx]    // Load mm1 with Prior(x)
  63.             movq mm6, mm7
  64.             pand mm3, mm1      // get lsb for each prev_row byte
  65.             psrlq mm1, 1       // divide prev_row bytes by 2
  66.             pand  mm1, mm4     // clear invalid bit 7 of each byte
  67.             paddb mm0, mm1     // add (Prev_row/2) to Avg for each byte
  68.             // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
  69.             movq mm1, mm3      // now use mm1 for getting LBCarrys
  70.             pand mm1, mm2      // get LBCarrys for each byte where both
  71.                                // lsb's were == 1 (Only valid for active group)
  72.             psrlq mm2, 1       // divide raw bytes by 2
  73.             pand  mm2, mm4     // clear invalid bit 7 of each byte
  74.             paddb mm2, mm1     // add LBCarrys to (Raw(x-bpp)/2) for each byte
  75.             pand mm2, mm6      // Leave only Active Group 1 bytes to add to Avg
  76.             paddb mm0, mm2     // add (Raw/2) + LBCarrys to Avg for each Active
  77.                                //  byte
  78.             // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
  79.             psllq mm6, ShiftBpp  // shift the mm6 mask to cover bytes 3-5
  80.             movq mm2, mm0        // mov updated Raws to mm2
  81.             psllq mm2, ShiftBpp  // shift data to position correctly
  82.             movq mm1, mm3        // now use mm1 for getting LBCarrys
  83.             pand mm1, mm2      // get LBCarrys for each byte where both
  84.                                // lsb's were == 1 (Only valid for active group)
  85.             psrlq mm2, 1       // divide raw bytes by 2
  86.             pand  mm2, mm4     // clear invalid bit 7 of each byte
  87.             paddb mm2, mm1     // add LBCarrys to (Raw(x-bpp)/2) for each byte
  88.             pand mm2, mm6      // Leave only Active Group 2 bytes to add to Avg
  89.             paddb mm0, mm2     // add (Raw/2) + LBCarrys to Avg for each Active
  90.                                //  byte
  91.             // Add 3rd active group (Raw(x-bpp)/2) to Average with LBCarry
  92.             psllq mm6, ShiftBpp  // shift the mm6 mask to cover the last two
  93.                                  // bytes
  94.             movq mm2, mm0        // mov updated Raws to mm2
  95.             psllq mm2, ShiftBpp  // shift data to position correctly
  96.                               // Data only needs to be shifted once here to
  97.                               // get the correct x-bpp offset.
  98.             movq mm1, mm3     // now use mm1 for getting LBCarrys
  99.             pand mm1, mm2     // get LBCarrys for each byte where both
  100.                               // lsb's were == 1 (Only valid for active group)
  101.             psrlq mm2, 1      // divide raw bytes by 2
  102.             pand  mm2, mm4    // clear invalid bit 7 of each byte
  103.             paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
  104.             pand mm2, mm6     // Leave only Active Group 2 bytes to add to Avg
  105.             add ebx, 8
  106.             paddb mm0, mm2    // add (Raw/2) + LBCarrys to Avg for each Active
  107.                               // byte
  108.             // Now ready to write back to memory
  109.             movq [edi + ebx - 8], mm0
  110.             // Move updated Raw(x) to use as Raw(x-bpp) for next loop
  111.             cmp ebx, MMXLength
  112.             movq mm2, mm0     // mov updated Raw(x) to mm2
  113.             jb davg3lp
  114.          } // end _asm block
  115.       }
  116.       break;
  117.       case 6:
  118.       case 4:
  119.       case 7:
  120.       case 5:
  121.       {
  122.          ActiveMask.use  = 0xffffffffffffffff;  // use shift below to clear
  123.                                                 // appropriate inactive bytes
  124.          ShiftBpp.use = bpp << 3;
  125.          ShiftRem.use = 64 - ShiftBpp.use;
  126.          _asm {
  127.             movq mm4, HBClearMask
  128.             // Re-init address pointers and offset
  129.             mov ebx, diff       // ebx ==> x = offset to alignment boundary
  130.             // Load ActiveMask and clear all bytes except for 1st active group
  131.             movq mm7, ActiveMask
  132.             mov edi, row         // edi ==> Avg(x)
  133.             psrlq mm7, ShiftRem
  134.             mov esi, prev_row    // esi ==> Prior(x)
  135.             movq mm6, mm7
  136.             movq mm5, LBCarryMask
  137.             psllq mm6, ShiftBpp  // Create mask for 2nd active group
  138.             // PRIME the pump (load the first Raw(x-bpp) data set
  139.             movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
  140.                                  // (we correct position in loop below)
  141. davg4lp:
  142.             movq mm0, [edi + ebx]
  143.             psrlq mm2, ShiftRem  // shift data to position correctly
  144.             movq mm1, [esi + ebx]
  145.             // Add (Prev_row/2) to Average
  146.             movq mm3, mm5
  147.             pand mm3, mm1     // get lsb for each prev_row byte
  148.             psrlq mm1, 1      // divide prev_row bytes by 2
  149.             pand  mm1, mm4    // clear invalid bit 7 of each byte
  150.             paddb mm0, mm1    // add (Prev_row/2) to Avg for each byte
  151.             // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
  152.             movq mm1, mm3     // now use mm1 for getting LBCarrys
  153.             pand mm1, mm2     // get LBCarrys for each byte where both
  154.                               // lsb's were == 1 (Only valid for active group)
  155.             psrlq mm2, 1      // divide raw bytes by 2
  156.             pand  mm2, mm4    // clear invalid bit 7 of each byte
  157.             paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
  158.             pand mm2, mm7     // Leave only Active Group 1 bytes to add to Avg
  159.             paddb mm0, mm2    // add (Raw/2) + LBCarrys to Avg for each Active
  160.                               // byte
  161.             // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
  162.             movq mm2, mm0     // mov updated Raws to mm2
  163.             psllq mm2, ShiftBpp // shift data to position correctly
  164.             add ebx, 8
  165.             movq mm1, mm3     // now use mm1 for getting LBCarrys
  166.             pand mm1, mm2     // get LBCarrys for each byte where both
  167.                               // lsb's were == 1 (Only valid for active group)
  168.             psrlq mm2, 1      // divide raw bytes by 2
  169.             pand  mm2, mm4    // clear invalid bit 7 of each byte
  170.             paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
  171.             pand mm2, mm6     // Leave only Active Group 2 bytes to add to Avg
  172.             paddb mm0, mm2    // add (Raw/2) + LBCarrys to Avg for each Active
  173.                               // byte
  174.             cmp ebx, MMXLength
  175.             // Now ready to write back to memory
  176.             movq [edi + ebx - 8], mm0
  177.             // Prep Raw(x-bpp) for next loop
  178.             movq mm2, mm0     // mov updated Raws to mm2
  179.             jb davg4lp
  180.          } // end _asm block
  181.       }
  182.       break;
  183.       case 2:
  184.       {
  185.          ActiveMask.use  = 0x000000000000ffff;
  186.          ShiftBpp.use = 16;   // == 2 * 8     [BUGFIX]
  187.          ShiftRem.use = 48;   // == 64 - 16   [BUGFIX]
  188.          _asm {
  189.             // Load ActiveMask
  190.             movq mm7, ActiveMask
  191.             // Re-init address pointers and offset
  192.             mov ebx, diff     // ebx ==> x = offset to alignment boundary
  193.             movq mm5, LBCarryMask
  194.             mov edi, row      // edi ==> Avg(x)
  195.             movq mm4, HBClearMask
  196.             mov esi, prev_row  // esi ==> Prior(x)
  197.             // PRIME the pump (load the first Raw(x-bpp) data set
  198.             movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
  199.                               // (we correct position in loop below)
  200. davg2lp:
  201.             movq mm0, [edi + ebx]
  202.             psrlq mm2, ShiftRem  // shift data to position correctly   [BUGFIX]
  203.             movq mm1, [esi + ebx]
  204.             // Add (Prev_row/2) to Average
  205.             movq mm3, mm5
  206.             pand mm3, mm1     // get lsb for each prev_row byte
  207.             psrlq mm1, 1      // divide prev_row bytes by 2
  208.             pand  mm1, mm4    // clear invalid bit 7 of each byte
  209.             movq mm6, mm7
  210.             paddb mm0, mm1    // add (Prev_row/2) to Avg for each byte
  211.             // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
  212.             movq mm1, mm3     // now use mm1 for getting LBCarrys
  213.             pand mm1, mm2     // get LBCarrys for each byte where both
  214.                               // lsb's were == 1 (Only valid for active group)
  215.             psrlq mm2, 1      // divide raw bytes by 2
  216.             pand  mm2, mm4    // clear invalid bit 7 of each byte
  217.             paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
  218.             pand mm2, mm6     // Leave only Active Group 1 bytes to add to Avg
  219.             paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
  220.             // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
  221.             psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 2 & 3
  222.             movq mm2, mm0       // mov updated Raws to mm2
  223.             psllq mm2, ShiftBpp // shift data to position correctly
  224.             movq mm1, mm3       // now use mm1 for getting LBCarrys
  225.             pand mm1, mm2       // get LBCarrys for each byte where both
  226.                                 // lsb's were == 1 (Only valid for active group)
  227.             psrlq mm2, 1        // divide raw bytes by 2
  228.             pand  mm2, mm4      // clear invalid bit 7 of each byte
  229.             paddb mm2, mm1      // add LBCarrys to (Raw(x-bpp)/2) for each byte
  230.             pand mm2, mm6       // Leave only Active Group 2 bytes to add to Avg
  231.             paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
  232.             // Add rdd active group (Raw(x-bpp)/2) to Average with LBCarry
  233.             psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 4 & 5
  234.             movq mm2, mm0       // mov updated Raws to mm2
  235.             psllq mm2, ShiftBpp // shift data to position correctly
  236.                                 // Data only needs to be shifted once here to
  237.                                 // get the correct x-bpp offset.
  238.             movq mm1, mm3       // now use mm1 for getting LBCarrys
  239.             pand mm1, mm2       // get LBCarrys for each byte where both
  240.                                 // lsb's were == 1 (Only valid for active group)
  241.             psrlq mm2, 1        // divide raw bytes by 2
  242.             pand  mm2, mm4      // clear invalid bit 7 of each byte
  243.             paddb mm2, mm1      // add LBCarrys to (Raw(x-bpp)/2) for each byte
  244.             pand mm2, mm6       // Leave only Active Group 2 bytes to add to Avg
  245.             paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
  246.             // Add 4th active group (Raw(x-bpp)/2) to Average with LBCarry
  247.             psllq mm6, ShiftBpp  // shift the mm6 mask to cover bytes 6 & 7
  248.             movq mm2, mm0        // mov updated Raws to mm2
  249.             psllq mm2, ShiftBpp  // shift data to position correctly
  250.                                  // Data only needs to be shifted once here to
  251.                                  // get the correct x-bpp offset.
  252.             add ebx, 8
  253.             movq mm1, mm3    // now use mm1 for getting LBCarrys
  254.             pand mm1, mm2    // get LBCarrys for each byte where both
  255.                              // lsb's were == 1 (Only valid for active group)
  256.             psrlq mm2, 1     // divide raw bytes by 2
  257.             pand  mm2, mm4   // clear invalid bit 7 of each byte
  258.             paddb mm2, mm1   // add LBCarrys to (Raw(x-bpp)/2) for each byte
  259.             pand mm2, mm6    // Leave only Active Group 2 bytes to add to Avg
  260.             paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
  261.             cmp ebx, MMXLength
  262.             // Now ready to write back to memory
  263.             movq [edi + ebx - 8], mm0
  264.             // Prep Raw(x-bpp) for next loop
  265.             movq mm2, mm0    // mov updated Raws to mm2
  266.             jb davg2lp
  267.         } // end _asm block
  268.       }
  269.       break;
  270.       case 1:                 // bpp == 1
  271.       {
  272.          _asm {
  273.             // Re-init address pointers and offset
  274.             mov ebx, diff     // ebx ==> x = offset to alignment boundary
  275.             mov edi, row      // edi ==> Avg(x)
  276.             cmp ebx, FullLength  // Test if offset at end of array
  277.             jnb davg1end
  278.             // Do Paeth decode for remaining bytes
  279.             mov esi, prev_row    // esi ==> Prior(x)
  280.             mov edx, edi
  281.             xor ecx, ecx         // zero ecx before using cl & cx in loop below
  282.             sub edx, bpp         // edx ==> Raw(x-bpp)
  283. davg1lp:
  284.             // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
  285.             xor eax, eax
  286.             mov cl, [esi + ebx]  // load cl with Prior(x)
  287.             mov al, [edx + ebx]  // load al with Raw(x-bpp)
  288.             add ax, cx
  289.             inc ebx
  290.             shr ax, 1            // divide by 2
  291.             add al, [edi+ebx-1]  // Add Avg(x); -1 to offset inc ebx
  292.             cmp ebx, FullLength  // Check if at end of array
  293.             mov [edi+ebx-1], al  // Write back Raw(x);
  294.                          // mov does not affect flags; -1 to offset inc ebx
  295.             jb davg1lp
  296. davg1end:
  297.          } // end _asm block
  298.       }
  299.       return;
  300.       case 8:             // bpp == 8
  301.       {
  302.          _asm {
  303.             // Re-init address pointers and offset
  304.             mov ebx, diff           // ebx ==> x = offset to alignment boundary
  305.             movq mm5, LBCarryMask
  306.             mov edi, row            // edi ==> Avg(x)
  307.             movq mm4, HBClearMask
  308.             mov esi, prev_row       // esi ==> Prior(x)
  309.             // PRIME the pump (load the first Raw(x-bpp) data set
  310.             movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
  311.                                 // (NO NEED to correct position in loop below)
  312. davg8lp:
  313.             movq mm0, [edi + ebx]
  314.             movq mm3, mm5
  315.             movq mm1, [esi + ebx]
  316.             add ebx, 8
  317.             pand mm3, mm1       // get lsb for each prev_row byte
  318.             psrlq mm1, 1        // divide prev_row bytes by 2
  319.             pand mm3, mm2       // get LBCarrys for each byte where both
  320.                                 // lsb's were == 1
  321.             psrlq mm2, 1        // divide raw bytes by 2
  322.             pand  mm1, mm4      // clear invalid bit 7 of each byte
  323.             paddb mm0, mm3      // add LBCarrys to Avg for each byte
  324.             pand  mm2, mm4      // clear invalid bit 7 of each byte
  325.             paddb mm0, mm1      // add (Prev_row/2) to Avg for each byte
  326.             paddb mm0, mm2      // add (Raw/2) to Avg for each byte
  327.             cmp ebx, MMXLength
  328.             movq [edi + ebx - 8], mm0
  329.             movq mm2, mm0       // reuse as Raw(x-bpp)
  330.             jb davg8lp
  331.         } // end _asm block
  332.       }
  333.       break;
  334.       default:                  // bpp greater than 8
  335.       {
  336.         _asm {
  337.             movq mm5, LBCarryMask
  338.             // Re-init address pointers and offset
  339.             mov ebx, diff       // ebx ==> x = offset to alignment boundary
  340.             mov edi, row        // edi ==> Avg(x)
  341.             movq mm4, HBClearMask
  342.             mov edx, edi
  343.             mov esi, prev_row   // esi ==> Prior(x)
  344.             sub edx, bpp        // edx ==> Raw(x-bpp)
  345. davgAlp:
  346.             movq mm0, [edi + ebx]
  347.             movq mm3, mm5
  348.             movq mm1, [esi + ebx]
  349.             pand mm3, mm1       // get lsb for each prev_row byte
  350.             movq mm2, [edx + ebx]
  351.             psrlq mm1, 1        // divide prev_row bytes by 2
  352.             pand mm3, mm2       // get LBCarrys for each byte where both
  353.                                 // lsb's were == 1
  354.             psrlq mm2, 1        // divide raw bytes by 2
  355.             pand  mm1, mm4      // clear invalid bit 7 of each byte
  356.             paddb mm0, mm3      // add LBCarrys to Avg for each byte
  357.             pand  mm2, mm4      // clear invalid bit 7 of each byte
  358.             paddb mm0, mm1      // add (Prev_row/2) to Avg for each byte
  359.             add ebx, 8
  360.             paddb mm0, mm2      // add (Raw/2) to Avg for each byte
  361.             cmp ebx, MMXLength
  362.             movq [edi + ebx - 8], mm0
  363.             jb davgAlp
  364.         } // end _asm block
  365.       }
  366.       break;
  367.    }                         // end switch ( bpp )
  368.    _asm {
  369.          // MMX acceleration complete now do clean-up
  370.          // Check if any remaining bytes left to decode
  371.          mov ebx, MMXLength    // ebx ==> x = offset bytes remaining after MMX
  372.          mov edi, row          // edi ==> Avg(x)
  373.          cmp ebx, FullLength   // Test if offset at end of array
  374.          jnb davgend
  375.          // Do Paeth decode for remaining bytes
  376.          mov esi, prev_row     // esi ==> Prior(x)
  377.          mov edx, edi
  378.          xor ecx, ecx          // zero ecx before using cl & cx in loop below
  379.          sub edx, bpp          // edx ==> Raw(x-bpp)
  380. davglp2:
  381.          // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
  382.          xor eax, eax
  383.          mov cl, [esi + ebx]   // load cl with Prior(x)
  384.          mov al, [edx + ebx]   // load al with Raw(x-bpp)
  385.          add ax, cx
  386.          inc ebx
  387.          shr ax, 1              // divide by 2
  388.          add al, [edi+ebx-1]    // Add Avg(x); -1 to offset inc ebx
  389.          cmp ebx, FullLength    // Check if at end of array
  390.          mov [edi+ebx-1], al    // Write back Raw(x);
  391.                           // mov does not affect flags; -1 to offset inc ebx
  392.          jb davglp2
  393. davgend:
  394.          emms             // End MMX instructions; prep for possible FP instrs.
  395.    } // end _asm block
  396. }
  397. // Optimized code for PNG Paeth filter decoder
  398. void /* PRIVATE */
  399. png_read_filter_row_mmx_paeth(png_row_infop row_info, png_bytep row,
  400.                               png_bytep prev_row)
  401. {
  402.    png_uint_32 FullLength;
  403.    png_uint_32 MMXLength;
  404.    //png_uint_32 len;
  405.    int bpp;
  406.    int diff;
  407.    //int ptemp;
  408.    int patemp, pbtemp, pctemp;
  409.    bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
  410.    FullLength  = row_info->rowbytes; // # of bytes to filter
  411.    _asm
  412.    {
  413.          xor ebx, ebx        // ebx ==> x offset
  414.          mov edi, row
  415.          xor edx, edx        // edx ==> x-bpp offset
  416.          mov esi, prev_row
  417.          xor eax, eax
  418.          // Compute the Raw value for the first bpp bytes
  419.          // Note: the formula works out to be always
  420.          //   Paeth(x) = Raw(x) + Prior(x)      where x < bpp
  421. dpthrlp:
  422.          mov al, [edi + ebx]
  423.          add al, [esi + ebx]
  424.          inc ebx
  425.          cmp ebx, bpp
  426.          mov [edi + ebx - 1], al
  427.          jb dpthrlp
  428.          // get # of bytes to alignment
  429.          mov diff, edi         // take start of row
  430.          add diff, ebx         // add bpp
  431.          xor ecx, ecx
  432.          add diff, 0xf         // add 7 + 8 to incr past alignment boundary
  433.          and diff, 0xfffffff8  // mask to alignment boundary
  434.          sub diff, edi         // subtract from start ==> value ebx at alignment
  435.          jz dpthgo
  436.          // fix alignment
  437. dpthlp1:
  438.          xor eax, eax
  439.          // pav = p - a = (a + b - c) - a = b - c
  440.          mov al, [esi + ebx]   // load Prior(x) into al
  441.          mov cl, [esi + edx]   // load Prior(x-bpp) into cl
  442.          sub eax, ecx          // subtract Prior(x-bpp)
  443.          mov patemp, eax       // Save pav for later use
  444.          xor eax, eax
  445.          // pbv = p - b = (a + b - c) - b = a - c
  446.          mov al, [edi + edx]   // load Raw(x-bpp) into al
  447.          sub eax, ecx          // subtract Prior(x-bpp)
  448.          mov ecx, eax
  449.          // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  450.          add eax, patemp       // pcv = pav + pbv
  451.          // pc = abs(pcv)
  452.          test eax, 0x80000000
  453.          jz dpthpca
  454.          neg eax               // reverse sign of neg values
  455. dpthpca:
  456.          mov pctemp, eax       // save pc for later use
  457.          // pb = abs(pbv)
  458.          test ecx, 0x80000000
  459.          jz dpthpba
  460.          neg ecx               // reverse sign of neg values
  461. dpthpba:
  462.          mov pbtemp, ecx       // save pb for later use
  463.          // pa = abs(pav)
  464.          mov eax, patemp
  465.          test eax, 0x80000000
  466.          jz dpthpaa
  467.          neg eax               // reverse sign of neg values
  468. dpthpaa:
  469.          mov patemp, eax       // save pa for later use
  470.          // test if pa <= pb
  471.          cmp eax, ecx
  472.          jna dpthabb
  473.          // pa > pb; now test if pb <= pc
  474.          cmp ecx, pctemp
  475.          jna dpthbbc
  476.          // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
  477.          mov cl, [esi + edx]  // load Prior(x-bpp) into cl
  478.          jmp dpthpaeth
  479. dpthbbc:
  480.          // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
  481.          mov cl, [esi + ebx]   // load Prior(x) into cl
  482.          jmp dpthpaeth
  483. dpthabb:
  484.          // pa <= pb; now test if pa <= pc
  485.          cmp eax, pctemp
  486.          jna dpthabc
  487.          // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
  488.          mov cl, [esi + edx]  // load Prior(x-bpp) into cl
  489.          jmp dpthpaeth
  490. dpthabc:
  491.          // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
  492.          mov cl, [edi + edx]  // load Raw(x-bpp) into cl
  493. dpthpaeth:
  494.          inc ebx
  495.          inc edx
  496.          // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
  497.          add [edi + ebx - 1], cl
  498.          cmp ebx, diff
  499.          jb dpthlp1
  500. dpthgo:
  501.          mov ecx, FullLength
  502.          mov eax, ecx
  503.          sub eax, ebx          // subtract alignment fix
  504.          and eax, 0x00000007   // calc bytes over mult of 8
  505.          sub ecx, eax          // drop over bytes from original length
  506.          mov MMXLength, ecx
  507.    } // end _asm block
  508.    // Now do the math for the rest of the row
  509.    switch ( bpp )
  510.    {
  511.       case 3:
  512.       {
  513.          ActiveMask.use = 0x0000000000ffffff;
  514.          ActiveMaskEnd.use = 0xffff000000000000;
  515.          ShiftBpp.use = 24;    // == bpp(3) * 8
  516.          ShiftRem.use = 40;    // == 64 - 24
  517.          _asm
  518.          {
  519.             mov ebx, diff
  520.             mov edi, row
  521.             mov esi, prev_row
  522.             pxor mm0, mm0
  523.             // PRIME the pump (load the first Raw(x-bpp) data set
  524.             movq mm1, [edi+ebx-8]
  525. dpth3lp:
  526.             psrlq mm1, ShiftRem     // shift last 3 bytes to 1st 3 bytes
  527.             movq mm2, [esi + ebx]   // load b=Prior(x)
  528.             punpcklbw mm1, mm0      // Unpack High bytes of a
  529.             movq mm3, [esi+ebx-8]   // Prep c=Prior(x-bpp) bytes
  530.             punpcklbw mm2, mm0      // Unpack High bytes of b
  531.             psrlq mm3, ShiftRem     // shift last 3 bytes to 1st 3 bytes
  532.             // pav = p - a = (a + b - c) - a = b - c
  533.             movq mm4, mm2
  534.             punpcklbw mm3, mm0      // Unpack High bytes of c
  535.             // pbv = p - b = (a + b - c) - b = a - c
  536.             movq mm5, mm1
  537.             psubw mm4, mm3
  538.             pxor mm7, mm7
  539.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  540.             movq mm6, mm4
  541.             psubw mm5, mm3
  542.             // pa = abs(p-a) = abs(pav)
  543.             // pb = abs(p-b) = abs(pbv)
  544.             // pc = abs(p-c) = abs(pcv)
  545.             pcmpgtw mm0, mm4    // Create mask pav bytes < 0
  546.             paddw mm6, mm5
  547.             pand mm0, mm4       // Only pav bytes < 0 in mm7
  548.             pcmpgtw mm7, mm5    // Create mask pbv bytes < 0
  549.             psubw mm4, mm0
  550.             pand mm7, mm5       // Only pbv bytes < 0 in mm0
  551.             psubw mm4, mm0
  552.             psubw mm5, mm7
  553.             pxor mm0, mm0
  554.             pcmpgtw mm0, mm6    // Create mask pcv bytes < 0
  555.             pand mm0, mm6       // Only pav bytes < 0 in mm7
  556.             psubw mm5, mm7
  557.             psubw mm6, mm0
  558.             //  test pa <= pb
  559.             movq mm7, mm4
  560.             psubw mm6, mm0
  561.             pcmpgtw mm7, mm5    // pa > pb?
  562.             movq mm0, mm7
  563.             // use mm7 mask to merge pa & pb
  564.             pand mm5, mm7
  565.             // use mm0 mask copy to merge a & b
  566.             pand mm2, mm0
  567.             pandn mm7, mm4
  568.             pandn mm0, mm1
  569.             paddw mm7, mm5
  570.             paddw mm0, mm2
  571.             //  test  ((pa <= pb)? pa:pb) <= pc
  572.             pcmpgtw mm7, mm6       // pab > pc?
  573.             pxor mm1, mm1
  574.             pand mm3, mm7
  575.             pandn mm7, mm0
  576.             paddw mm7, mm3
  577.             pxor mm0, mm0
  578.             packuswb mm7, mm1
  579.             movq mm3, [esi + ebx]   // load c=Prior(x-bpp)
  580.             pand mm7, ActiveMask
  581.             movq mm2, mm3           // load b=Prior(x) step 1
  582.             paddb mm7, [edi + ebx]  // add Paeth predictor with Raw(x)
  583.             punpcklbw mm3, mm0      // Unpack High bytes of c
  584.             movq [edi + ebx], mm7   // write back updated value
  585.             movq mm1, mm7           // Now mm1 will be used as Raw(x-bpp)
  586.             // Now do Paeth for 2nd set of bytes (3-5)
  587.             psrlq mm2, ShiftBpp     // load b=Prior(x) step 2
  588.             punpcklbw mm1, mm0      // Unpack High bytes of a
  589.             pxor mm7, mm7
  590.             punpcklbw mm2, mm0      // Unpack High bytes of b
  591.             // pbv = p - b = (a + b - c) - b = a - c
  592.             movq mm5, mm1
  593.             // pav = p - a = (a + b - c) - a = b - c
  594.             movq mm4, mm2
  595.             psubw mm5, mm3
  596.             psubw mm4, mm3
  597.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) =
  598.             //       pav + pbv = pbv + pav
  599.             movq mm6, mm5
  600.             paddw mm6, mm4
  601.             // pa = abs(p-a) = abs(pav)
  602.             // pb = abs(p-b) = abs(pbv)
  603.             // pc = abs(p-c) = abs(pcv)
  604.             pcmpgtw mm0, mm5       // Create mask pbv bytes < 0
  605.             pcmpgtw mm7, mm4       // Create mask pav bytes < 0
  606.             pand mm0, mm5          // Only pbv bytes < 0 in mm0
  607.             pand mm7, mm4          // Only pav bytes < 0 in mm7
  608.             psubw mm5, mm0
  609.             psubw mm4, mm7
  610.             psubw mm5, mm0
  611.             psubw mm4, mm7
  612.             pxor mm0, mm0
  613.             pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
  614.             pand mm0, mm6          // Only pav bytes < 0 in mm7
  615.             psubw mm6, mm0
  616.             //  test pa <= pb
  617.             movq mm7, mm4
  618.             psubw mm6, mm0
  619.             pcmpgtw mm7, mm5       // pa > pb?
  620.             movq mm0, mm7
  621.             // use mm7 mask to merge pa & pb
  622.             pand mm5, mm7
  623.             // use mm0 mask copy to merge a & b
  624.             pand mm2, mm0
  625.             pandn mm7, mm4
  626.             pandn mm0, mm1
  627.             paddw mm7, mm5
  628.             paddw mm0, mm2
  629.             //  test  ((pa <= pb)? pa:pb) <= pc
  630.             pcmpgtw mm7, mm6       // pab > pc?
  631.             movq mm2, [esi + ebx]  // load b=Prior(x)
  632.             pand mm3, mm7
  633.             pandn mm7, mm0
  634.             pxor mm1, mm1
  635.             paddw mm7, mm3
  636.             pxor mm0, mm0
  637.             packuswb mm7, mm1
  638.             movq mm3, mm2           // load c=Prior(x-bpp) step 1
  639.             pand mm7, ActiveMask
  640.             punpckhbw mm2, mm0      // Unpack High bytes of b
  641.             psllq mm7, ShiftBpp     // Shift bytes to 2nd group of 3 bytes
  642.              // pav = p - a = (a + b - c) - a = b - c
  643.             movq mm4, mm2
  644.             paddb mm7, [edi + ebx]  // add Paeth predictor with Raw(x)
  645.             psllq mm3, ShiftBpp     // load c=Prior(x-bpp) step 2
  646.             movq [edi + ebx], mm7   // write back updated value
  647.             movq mm1, mm7
  648.             punpckhbw mm3, mm0      // Unpack High bytes of c
  649.             psllq mm1, ShiftBpp     // Shift bytes
  650.                                     // Now mm1 will be used as Raw(x-bpp)
  651.             // Now do Paeth for 3rd, and final, set of bytes (6-7)
  652.             pxor mm7, mm7
  653.             punpckhbw mm1, mm0      // Unpack High bytes of a
  654.             psubw mm4, mm3
  655.             // pbv = p - b = (a + b - c) - b = a - c
  656.             movq mm5, mm1
  657.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  658.             movq mm6, mm4
  659.             psubw mm5, mm3
  660.             pxor mm0, mm0
  661.             paddw mm6, mm5
  662.             // pa = abs(p-a) = abs(pav)
  663.             // pb = abs(p-b) = abs(pbv)
  664.             // pc = abs(p-c) = abs(pcv)
  665.             pcmpgtw mm0, mm4    // Create mask pav bytes < 0
  666.             pcmpgtw mm7, mm5    // Create mask pbv bytes < 0
  667.             pand mm0, mm4       // Only pav bytes < 0 in mm7
  668.             pand mm7, mm5       // Only pbv bytes < 0 in mm0
  669.             psubw mm4, mm0
  670.             psubw mm5, mm7
  671.             psubw mm4, mm0
  672.             psubw mm5, mm7
  673.             pxor mm0, mm0
  674.             pcmpgtw mm0, mm6    // Create mask pcv bytes < 0
  675.             pand mm0, mm6       // Only pav bytes < 0 in mm7
  676.             psubw mm6, mm0
  677.             //  test pa <= pb
  678.             movq mm7, mm4
  679.             psubw mm6, mm0
  680.             pcmpgtw mm7, mm5    // pa > pb?
  681.             movq mm0, mm7
  682.             // use mm0 mask copy to merge a & b
  683.             pand mm2, mm0
  684.             // use mm7 mask to merge pa & pb
  685.             pand mm5, mm7
  686.             pandn mm0, mm1
  687.             pandn mm7, mm4
  688.             paddw mm0, mm2
  689.             paddw mm7, mm5
  690.             //  test  ((pa <= pb)? pa:pb) <= pc
  691.             pcmpgtw mm7, mm6    // pab > pc?
  692.             pand mm3, mm7
  693.             pandn mm7, mm0
  694.             paddw mm7, mm3
  695.             pxor mm1, mm1
  696.             packuswb mm1, mm7
  697.             // Step ebx to next set of 8 bytes and repeat loop til done
  698.             add ebx, 8
  699.             pand mm1, ActiveMaskEnd
  700.             paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x)
  701.             cmp ebx, MMXLength
  702.             pxor mm0, mm0              // pxor does not affect flags
  703.             movq [edi + ebx - 8], mm1  // write back updated value
  704.                                  // mm1 will be used as Raw(x-bpp) next loop
  705.                            // mm3 ready to be used as Prior(x-bpp) next loop
  706.             jb dpth3lp
  707.          } // end _asm block
  708.       }
  709.       break;
  710.       case 6:
  711.       case 7:
  712.       case 5:
  713.       {
  714.          ActiveMask.use  = 0x00000000ffffffff;
  715.          ActiveMask2.use = 0xffffffff00000000;
  716.          ShiftBpp.use = bpp << 3;    // == bpp * 8
  717.          ShiftRem.use = 64 - ShiftBpp.use;
  718.          _asm
  719.          {
  720.             mov ebx, diff
  721.             mov edi, row
  722.             mov esi, prev_row
  723.             // PRIME the pump (load the first Raw(x-bpp) data set
  724.             movq mm1, [edi+ebx-8]
  725.             pxor mm0, mm0
  726. dpth6lp:
  727.             // Must shift to position Raw(x-bpp) data
  728.             psrlq mm1, ShiftRem
  729.             // Do first set of 4 bytes
  730.             movq mm3, [esi+ebx-8]      // read c=Prior(x-bpp) bytes
  731.             punpcklbw mm1, mm0      // Unpack Low bytes of a
  732.             movq mm2, [esi + ebx]   // load b=Prior(x)
  733.             punpcklbw mm2, mm0      // Unpack Low bytes of b
  734.             // Must shift to position Prior(x-bpp) data
  735.             psrlq mm3, ShiftRem
  736.             // pav = p - a = (a + b - c) - a = b - c
  737.             movq mm4, mm2
  738.             punpcklbw mm3, mm0      // Unpack Low bytes of c
  739.             // pbv = p - b = (a + b - c) - b = a - c
  740.             movq mm5, mm1
  741.             psubw mm4, mm3
  742.             pxor mm7, mm7
  743.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  744.             movq mm6, mm4
  745.             psubw mm5, mm3
  746.             // pa = abs(p-a) = abs(pav)
  747.             // pb = abs(p-b) = abs(pbv)
  748.             // pc = abs(p-c) = abs(pcv)
  749.             pcmpgtw mm0, mm4    // Create mask pav bytes < 0
  750.             paddw mm6, mm5
  751.             pand mm0, mm4       // Only pav bytes < 0 in mm7
  752.             pcmpgtw mm7, mm5    // Create mask pbv bytes < 0
  753.             psubw mm4, mm0
  754.             pand mm7, mm5       // Only pbv bytes < 0 in mm0
  755.             psubw mm4, mm0
  756.             psubw mm5, mm7
  757.             pxor mm0, mm0
  758.             pcmpgtw mm0, mm6    // Create mask pcv bytes < 0
  759.             pand mm0, mm6       // Only pav bytes < 0 in mm7
  760.             psubw mm5, mm7
  761.             psubw mm6, mm0
  762.             //  test pa <= pb
  763.             movq mm7, mm4
  764.             psubw mm6, mm0
  765.             pcmpgtw mm7, mm5    // pa > pb?
  766.             movq mm0, mm7
  767.             // use mm7 mask to merge pa & pb
  768.             pand mm5, mm7
  769.             // use mm0 mask copy to merge a & b
  770.             pand mm2, mm0
  771.             pandn mm7, mm4
  772.             pandn mm0, mm1
  773.             paddw mm7, mm5
  774.             paddw mm0, mm2
  775.             //  test  ((pa <= pb)? pa:pb) <= pc
  776.             pcmpgtw mm7, mm6    // pab > pc?
  777.             pxor mm1, mm1
  778.             pand mm3, mm7
  779.             pandn mm7, mm0
  780.             paddw mm7, mm3
  781.             pxor mm0, mm0
  782.             packuswb mm7, mm1
  783.             movq mm3, [esi + ebx - 8]  // load c=Prior(x-bpp)
  784.             pand mm7, ActiveMask
  785.             psrlq mm3, ShiftRem
  786.             movq mm2, [esi + ebx]      // load b=Prior(x) step 1
  787.             paddb mm7, [edi + ebx]     // add Paeth predictor with Raw(x)
  788.             movq mm6, mm2
  789.             movq [edi + ebx], mm7      // write back updated value
  790.             movq mm1, [edi+ebx-8]
  791.             psllq mm6, ShiftBpp
  792.             movq mm5, mm7
  793.             psrlq mm1, ShiftRem
  794.             por mm3, mm6
  795.             psllq mm5, ShiftBpp
  796.             punpckhbw mm3, mm0         // Unpack High bytes of c
  797.             por mm1, mm5
  798.             // Do second set of 4 bytes
  799.             punpckhbw mm2, mm0         // Unpack High bytes of b
  800.             punpckhbw mm1, mm0         // Unpack High bytes of a
  801.             // pav = p - a = (a + b - c) - a = b - c
  802.             movq mm4, mm2
  803.             // pbv = p - b = (a + b - c) - b = a - c
  804.             movq mm5, mm1
  805.             psubw mm4, mm3
  806.             pxor mm7, mm7
  807.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  808.             movq mm6, mm4
  809.             psubw mm5, mm3
  810.             // pa = abs(p-a) = abs(pav)
  811.             // pb = abs(p-b) = abs(pbv)
  812.             // pc = abs(p-c) = abs(pcv)
  813.             pcmpgtw mm0, mm4       // Create mask pav bytes < 0
  814.             paddw mm6, mm5
  815.             pand mm0, mm4          // Only pav bytes < 0 in mm7
  816.             pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
  817.             psubw mm4, mm0
  818.             pand mm7, mm5          // Only pbv bytes < 0 in mm0
  819.             psubw mm4, mm0
  820.             psubw mm5, mm7
  821.             pxor mm0, mm0
  822.             pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
  823.             pand mm0, mm6          // Only pav bytes < 0 in mm7
  824.             psubw mm5, mm7
  825.             psubw mm6, mm0
  826.             //  test pa <= pb
  827.             movq mm7, mm4
  828.             psubw mm6, mm0
  829.             pcmpgtw mm7, mm5       // pa > pb?
  830.             movq mm0, mm7
  831.             // use mm7 mask to merge pa & pb
  832.             pand mm5, mm7
  833.             // use mm0 mask copy to merge a & b
  834.             pand mm2, mm0
  835.             pandn mm7, mm4
  836.             pandn mm0, mm1
  837.             paddw mm7, mm5
  838.             paddw mm0, mm2
  839.             //  test  ((pa <= pb)? pa:pb) <= pc
  840.             pcmpgtw mm7, mm6           // pab > pc?
  841.             pxor mm1, mm1
  842.             pand mm3, mm7
  843.             pandn mm7, mm0
  844.             pxor mm1, mm1
  845.             paddw mm7, mm3
  846.             pxor mm0, mm0
  847.             // Step ex to next set of 8 bytes and repeat loop til done
  848.             add ebx, 8
  849.             packuswb mm1, mm7
  850.             paddb mm1, [edi + ebx - 8]     // add Paeth predictor with Raw(x)
  851.             cmp ebx, MMXLength
  852.             movq [edi + ebx - 8], mm1      // write back updated value
  853.                                 // mm1 will be used as Raw(x-bpp) next loop
  854.             jb dpth6lp
  855.          } // end _asm block
  856.       }
  857.       break;
  858.       case 4:
  859.       {
  860.          ActiveMask.use  = 0x00000000ffffffff;
  861.          _asm {
  862.             mov ebx, diff
  863.             mov edi, row
  864.             mov esi, prev_row
  865.             pxor mm0, mm0
  866.             // PRIME the pump (load the first Raw(x-bpp) data set
  867.             movq mm1, [edi+ebx-8]    // Only time should need to read
  868.                                      //  a=Raw(x-bpp) bytes
  869. dpth4lp:
  870.             // Do first set of 4 bytes
  871.             movq mm3, [esi+ebx-8]    // read c=Prior(x-bpp) bytes
  872.             punpckhbw mm1, mm0       // Unpack Low bytes of a
  873.             movq mm2, [esi + ebx]    // load b=Prior(x)
  874.             punpcklbw mm2, mm0       // Unpack High bytes of b
  875.             // pav = p - a = (a + b - c) - a = b - c
  876.             movq mm4, mm2
  877.             punpckhbw mm3, mm0       // Unpack High bytes of c
  878.             // pbv = p - b = (a + b - c) - b = a - c
  879.             movq mm5, mm1
  880.             psubw mm4, mm3
  881.             pxor mm7, mm7
  882.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  883.             movq mm6, mm4
  884.             psubw mm5, mm3
  885.             // pa = abs(p-a) = abs(pav)
  886.             // pb = abs(p-b) = abs(pbv)
  887.             // pc = abs(p-c) = abs(pcv)
  888.             pcmpgtw mm0, mm4       // Create mask pav bytes < 0
  889.             paddw mm6, mm5
  890.             pand mm0, mm4          // Only pav bytes < 0 in mm7
  891.             pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
  892.             psubw mm4, mm0
  893.             pand mm7, mm5          // Only pbv bytes < 0 in mm0
  894.             psubw mm4, mm0
  895.             psubw mm5, mm7
  896.             pxor mm0, mm0
  897.             pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
  898.             pand mm0, mm6          // Only pav bytes < 0 in mm7
  899.             psubw mm5, mm7
  900.             psubw mm6, mm0
  901.             //  test pa <= pb
  902.             movq mm7, mm4
  903.             psubw mm6, mm0
  904.             pcmpgtw mm7, mm5       // pa > pb?
  905.             movq mm0, mm7
  906.             // use mm7 mask to merge pa & pb
  907.             pand mm5, mm7
  908.             // use mm0 mask copy to merge a & b
  909.             pand mm2, mm0
  910.             pandn mm7, mm4
  911.             pandn mm0, mm1
  912.             paddw mm7, mm5
  913.             paddw mm0, mm2
  914.             //  test  ((pa <= pb)? pa:pb) <= pc
  915.             pcmpgtw mm7, mm6       // pab > pc?
  916.             pxor mm1, mm1
  917.             pand mm3, mm7
  918.             pandn mm7, mm0
  919.             paddw mm7, mm3
  920.             pxor mm0, mm0
  921.             packuswb mm7, mm1
  922.             movq mm3, [esi + ebx]      // load c=Prior(x-bpp)
  923.             pand mm7, ActiveMask
  924.             movq mm2, mm3              // load b=Prior(x) step 1
  925.             paddb mm7, [edi + ebx]     // add Paeth predictor with Raw(x)
  926.             punpcklbw mm3, mm0         // Unpack High bytes of c
  927.             movq [edi + ebx], mm7      // write back updated value
  928.             movq mm1, mm7              // Now mm1 will be used as Raw(x-bpp)
  929.             // Do second set of 4 bytes
  930.             punpckhbw mm2, mm0         // Unpack Low bytes of b
  931.             punpcklbw mm1, mm0         // Unpack Low bytes of a
  932.             // pav = p - a = (a + b - c) - a = b - c
  933.             movq mm4, mm2
  934.             // pbv = p - b = (a + b - c) - b = a - c
  935.             movq mm5, mm1
  936.             psubw mm4, mm3
  937.             pxor mm7, mm7
  938.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  939.             movq mm6, mm4
  940.             psubw mm5, mm3
  941.             // pa = abs(p-a) = abs(pav)
  942.             // pb = abs(p-b) = abs(pbv)
  943.             // pc = abs(p-c) = abs(pcv)
  944.             pcmpgtw mm0, mm4       // Create mask pav bytes < 0
  945.             paddw mm6, mm5
  946.             pand mm0, mm4          // Only pav bytes < 0 in mm7
  947.             pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
  948.             psubw mm4, mm0
  949.             pand mm7, mm5          // Only pbv bytes < 0 in mm0
  950.             psubw mm4, mm0
  951.             psubw mm5, mm7
  952.             pxor mm0, mm0
  953.             pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
  954.             pand mm0, mm6          // Only pav bytes < 0 in mm7
  955.             psubw mm5, mm7
  956.             psubw mm6, mm0
  957.             //  test pa <= pb
  958.             movq mm7, mm4
  959.             psubw mm6, mm0
  960.             pcmpgtw mm7, mm5       // pa > pb?
  961.             movq mm0, mm7
  962.             // use mm7 mask to merge pa & pb
  963.             pand mm5, mm7
  964.             // use mm0 mask copy to merge a & b
  965.             pand mm2, mm0
  966.             pandn mm7, mm4
  967.             pandn mm0, mm1
  968.             paddw mm7, mm5
  969.             paddw mm0, mm2
  970.             //  test  ((pa <= pb)? pa:pb) <= pc
  971.             pcmpgtw mm7, mm6       // pab > pc?
  972.             pxor mm1, mm1
  973.             pand mm3, mm7
  974.             pandn mm7, mm0
  975.             pxor mm1, mm1
  976.             paddw mm7, mm3
  977.             pxor mm0, mm0
  978.             // Step ex to next set of 8 bytes and repeat loop til done
  979.             add ebx, 8
  980.             packuswb mm1, mm7
  981.             paddb mm1, [edi + ebx - 8]     // add Paeth predictor with Raw(x)
  982.             cmp ebx, MMXLength
  983.             movq [edi + ebx - 8], mm1      // write back updated value
  984.                                 // mm1 will be used as Raw(x-bpp) next loop
  985.             jb dpth4lp
  986.          } // end _asm block
  987.       }
  988.       break;
  989.       case 8:                          // bpp == 8
  990.       {
  991.          ActiveMask.use  = 0x00000000ffffffff;
  992.          _asm {
  993.             mov ebx, diff
  994.             mov edi, row
  995.             mov esi, prev_row
  996.             pxor mm0, mm0
  997.             // PRIME the pump (load the first Raw(x-bpp) data set
  998.             movq mm1, [edi+ebx-8]      // Only time should need to read
  999.                                        //  a=Raw(x-bpp) bytes
  1000. dpth8lp:
  1001.             // Do first set of 4 bytes
  1002.             movq mm3, [esi+ebx-8]      // read c=Prior(x-bpp) bytes
  1003.             punpcklbw mm1, mm0         // Unpack Low bytes of a
  1004.             movq mm2, [esi + ebx]      // load b=Prior(x)
  1005.             punpcklbw mm2, mm0         // Unpack Low bytes of b
  1006.             // pav = p - a = (a + b - c) - a = b - c
  1007.             movq mm4, mm2
  1008.             punpcklbw mm3, mm0         // Unpack Low bytes of c
  1009.             // pbv = p - b = (a + b - c) - b = a - c
  1010.             movq mm5, mm1
  1011.             psubw mm4, mm3
  1012.             pxor mm7, mm7
  1013.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  1014.             movq mm6, mm4
  1015.             psubw mm5, mm3
  1016.             // pa = abs(p-a) = abs(pav)
  1017.             // pb = abs(p-b) = abs(pbv)
  1018.             // pc = abs(p-c) = abs(pcv)
  1019.             pcmpgtw mm0, mm4       // Create mask pav bytes < 0
  1020.             paddw mm6, mm5
  1021.             pand mm0, mm4          // Only pav bytes < 0 in mm7
  1022.             pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
  1023.             psubw mm4, mm0
  1024.             pand mm7, mm5          // Only pbv bytes < 0 in mm0
  1025.             psubw mm4, mm0
  1026.             psubw mm5, mm7
  1027.             pxor mm0, mm0
  1028.             pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
  1029.             pand mm0, mm6          // Only pav bytes < 0 in mm7
  1030.             psubw mm5, mm7
  1031.             psubw mm6, mm0
  1032.             //  test pa <= pb
  1033.             movq mm7, mm4
  1034.             psubw mm6, mm0
  1035.             pcmpgtw mm7, mm5       // pa > pb?
  1036.             movq mm0, mm7
  1037.             // use mm7 mask to merge pa & pb
  1038.             pand mm5, mm7
  1039.             // use mm0 mask copy to merge a & b
  1040.             pand mm2, mm0
  1041.             pandn mm7, mm4
  1042.             pandn mm0, mm1
  1043.             paddw mm7, mm5
  1044.             paddw mm0, mm2
  1045.             //  test  ((pa <= pb)? pa:pb) <= pc
  1046.             pcmpgtw mm7, mm6       // pab > pc?
  1047.             pxor mm1, mm1
  1048.             pand mm3, mm7
  1049.             pandn mm7, mm0
  1050.             paddw mm7, mm3
  1051.             pxor mm0, mm0
  1052.             packuswb mm7, mm1
  1053.             movq mm3, [esi+ebx-8]    // read c=Prior(x-bpp) bytes
  1054.             pand mm7, ActiveMask
  1055.             movq mm2, [esi + ebx]    // load b=Prior(x)
  1056.             paddb mm7, [edi + ebx]   // add Paeth predictor with Raw(x)
  1057.             punpckhbw mm3, mm0       // Unpack High bytes of c
  1058.             movq [edi + ebx], mm7    // write back updated value
  1059.             movq mm1, [edi+ebx-8]    // read a=Raw(x-bpp) bytes
  1060.             // Do second set of 4 bytes
  1061.             punpckhbw mm2, mm0       // Unpack High bytes of b
  1062.             punpckhbw mm1, mm0       // Unpack High bytes of a
  1063.             // pav = p - a = (a + b - c) - a = b - c
  1064.             movq mm4, mm2
  1065.             // pbv = p - b = (a + b - c) - b = a - c
  1066.             movq mm5, mm1
  1067.             psubw mm4, mm3
  1068.             pxor mm7, mm7
  1069.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  1070.             movq mm6, mm4
  1071.             psubw mm5, mm3
  1072.             // pa = abs(p-a) = abs(pav)
  1073.             // pb = abs(p-b) = abs(pbv)
  1074.             // pc = abs(p-c) = abs(pcv)
  1075.             pcmpgtw mm0, mm4       // Create mask pav bytes < 0
  1076.             paddw mm6, mm5
  1077.             pand mm0, mm4          // Only pav bytes < 0 in mm7
  1078.             pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
  1079.             psubw mm4, mm0
  1080.             pand mm7, mm5          // Only pbv bytes < 0 in mm0
  1081.             psubw mm4, mm0
  1082.             psubw mm5, mm7
  1083.             pxor mm0, mm0
  1084.             pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
  1085.             pand mm0, mm6          // Only pav bytes < 0 in mm7
  1086.             psubw mm5, mm7
  1087.             psubw mm6, mm0
  1088.             //  test pa <= pb
  1089.             movq mm7, mm4
  1090.             psubw mm6, mm0
  1091.             pcmpgtw mm7, mm5       // pa > pb?
  1092.             movq mm0, mm7
  1093.             // use mm7 mask to merge pa & pb
  1094.             pand mm5, mm7
  1095.             // use mm0 mask copy to merge a & b
  1096.             pand mm2, mm0
  1097.             pandn mm7, mm4
  1098.             pandn mm0, mm1
  1099.             paddw mm7, mm5
  1100.             paddw mm0, mm2
  1101.             //  test  ((pa <= pb)? pa:pb) <= pc
  1102.             pcmpgtw mm7, mm6       // pab > pc?
  1103.             pxor mm1, mm1
  1104.             pand mm3, mm7
  1105.             pandn mm7, mm0
  1106.             pxor mm1, mm1
  1107.             paddw mm7, mm3
  1108.             pxor mm0, mm0
  1109.             // Step ex to next set of 8 bytes and repeat loop til done
  1110.             add ebx, 8
  1111.             packuswb mm1, mm7
  1112.             paddb mm1, [edi + ebx - 8]     // add Paeth predictor with Raw(x)
  1113.             cmp ebx, MMXLength
  1114.             movq [edi + ebx - 8], mm1      // write back updated value
  1115.                             // mm1 will be used as Raw(x-bpp) next loop
  1116.             jb dpth8lp
  1117.          } // end _asm block
  1118.       }
  1119.       break;
  1120.       case 1:                // bpp = 1
  1121.       case 2:                // bpp = 2
  1122.       default:               // bpp > 8
  1123.       {
  1124.          _asm {
  1125.             mov ebx, diff
  1126.             cmp ebx, FullLength
  1127.             jnb dpthdend
  1128.             mov edi, row
  1129.             mov esi, prev_row
  1130.             // Do Paeth decode for remaining bytes
  1131.             mov edx, ebx
  1132.             xor ecx, ecx        // zero ecx before using cl & cx in loop below
  1133.             sub edx, bpp        // Set edx = ebx - bpp
  1134. dpthdlp:
  1135.             xor eax, eax
  1136.             // pav = p - a = (a + b - c) - a = b - c
  1137.             mov al, [esi + ebx]        // load Prior(x) into al
  1138.             mov cl, [esi + edx]        // load Prior(x-bpp) into cl
  1139.             sub eax, ecx                 // subtract Prior(x-bpp)
  1140.             mov patemp, eax                 // Save pav for later use
  1141.             xor eax, eax
  1142.             // pbv = p - b = (a + b - c) - b = a - c
  1143.             mov al, [edi + edx]        // load Raw(x-bpp) into al
  1144.             sub eax, ecx                 // subtract Prior(x-bpp)
  1145.             mov ecx, eax
  1146.             // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  1147.             add eax, patemp                 // pcv = pav + pbv
  1148.             // pc = abs(pcv)
  1149.             test eax, 0x80000000
  1150.             jz dpthdpca
  1151.             neg eax                     // reverse sign of neg values
  1152. dpthdpca:
  1153.             mov pctemp, eax             // save pc for later use
  1154.             // pb = abs(pbv)
  1155.             test ecx, 0x80000000
  1156.             jz dpthdpba
  1157.             neg ecx                     // reverse sign of neg values
  1158. dpthdpba:
  1159.             mov pbtemp, ecx             // save pb for later use
  1160.             // pa = abs(pav)
  1161.             mov eax, patemp
  1162.             test eax, 0x80000000
  1163.             jz dpthdpaa
  1164.             neg eax                     // reverse sign of neg values
  1165. dpthdpaa:
  1166.             mov patemp, eax             // save pa for later use
  1167.             // test if pa <= pb
  1168.             cmp eax, ecx
  1169.             jna dpthdabb
  1170.             // pa > pb; now test if pb <= pc
  1171.             cmp ecx, pctemp
  1172.             jna dpthdbbc
  1173.             // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
  1174.             mov cl, [esi + edx]  // load Prior(x-bpp) into cl
  1175.             jmp dpthdpaeth
  1176. dpthdbbc:
  1177.             // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
  1178.             mov cl, [esi + ebx]        // load Prior(x) into cl
  1179.             jmp dpthdpaeth
  1180. dpthdabb:
  1181.             // pa <= pb; now test if pa <= pc
  1182.             cmp eax, pctemp
  1183.             jna dpthdabc
  1184.             // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
  1185.             mov cl, [esi + edx]  // load Prior(x-bpp) into cl
  1186.             jmp dpthdpaeth
  1187. dpthdabc:
  1188.             // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
  1189.             mov cl, [edi + edx]  // load Raw(x-bpp) into cl
  1190. dpthdpaeth:
  1191.             inc ebx
  1192.             inc edx
  1193.             // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
  1194.             add [edi + ebx - 1], cl
  1195.             cmp ebx, FullLength
  1196.             jb dpthdlp
  1197. dpthdend:
  1198.          } // end _asm block
  1199.       }
  1200.       return;                   // No need to go further with this one
  1201.    }                         // end switch ( bpp )
  1202.    _asm
  1203.    {
  1204.          // MMX acceleration complete now do clean-up
  1205.          // Check if any remaining bytes left to decode
  1206.          mov ebx, MMXLength
  1207.          cmp ebx, FullLength
  1208.          jnb dpthend
  1209.          mov edi, row
  1210.          mov esi, prev_row
  1211.          // Do Paeth decode for remaining bytes
  1212.          mov edx, ebx
  1213.          xor ecx, ecx         // zero ecx before using cl & cx in loop below
  1214.          sub edx, bpp         // Set edx = ebx - bpp
  1215. dpthlp2:
  1216.          xor eax, eax
  1217.          // pav = p - a = (a + b - c) - a = b - c
  1218.          mov al, [esi + ebx]  // load Prior(x) into al
  1219.          mov cl, [esi + edx]  // load Prior(x-bpp) into cl
  1220.          sub eax, ecx         // subtract Prior(x-bpp)
  1221.          mov patemp, eax      // Save pav for later use
  1222.          xor eax, eax
  1223.          // pbv = p - b = (a + b - c) - b = a - c
  1224.          mov al, [edi + edx]  // load Raw(x-bpp) into al
  1225.          sub eax, ecx         // subtract Prior(x-bpp)
  1226.          mov ecx, eax
  1227.          // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
  1228.          add eax, patemp      // pcv = pav + pbv
  1229.          // pc = abs(pcv)
  1230.          test eax, 0x80000000
  1231.          jz dpthpca2
  1232.          neg eax              // reverse sign of neg values
  1233. dpthpca2:
  1234.          mov pctemp, eax      // save pc for later use
  1235.          // pb = abs(pbv)
  1236.          test ecx, 0x80000000
  1237.          jz dpthpba2
  1238.          neg ecx              // reverse sign of neg values
  1239. dpthpba2:
  1240.          mov pbtemp, ecx      // save pb for later use
  1241.          // pa = abs(pav)
  1242.          mov eax, patemp
  1243.          test eax, 0x80000000
  1244.          jz dpthpaa2
  1245.          neg eax              // reverse sign of neg values
  1246. dpthpaa2:
  1247.          mov patemp, eax      // save pa for later use
  1248.          // test if pa <= pb
  1249.          cmp eax, ecx
  1250.          jna dpthabb2
  1251.          // pa > pb; now test if pb <= pc
  1252.          cmp ecx, pctemp
  1253.          jna dpthbbc2
  1254.          // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
  1255.          mov cl, [esi + edx]  // load Prior(x-bpp) into cl
  1256.          jmp dpthpaeth2
  1257. dpthbbc2:
  1258.          // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
  1259.          mov cl, [esi + ebx]        // load Prior(x) into cl
  1260.          jmp dpthpaeth2
  1261. dpthabb2:
  1262.          // pa <= pb; now test if pa <= pc
  1263.          cmp eax, pctemp
  1264.          jna dpthabc2
  1265.          // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
  1266.          mov cl, [esi + edx]  // load Prior(x-bpp) into cl
  1267.          jmp dpthpaeth2
  1268. dpthabc2:
  1269.          // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
  1270.          mov cl, [edi + edx]  // load Raw(x-bpp) into cl
  1271. dpthpaeth2:
  1272.          inc ebx
  1273.          inc edx
  1274.          // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
  1275.          add [edi + ebx - 1], cl
  1276.          cmp ebx, FullLength
  1277.          jb dpthlp2
  1278. dpthend:
  1279.          emms             // End MMX instructions; prep for possible FP instrs.
  1280.    } // end _asm block
  1281. }
  1282. // Optimized code for PNG Sub filter decoder
  1283. void /* PRIVATE */
  1284. png_read_filter_row_mmx_sub(png_row_infop row_info, png_bytep row)
  1285. {
  1286.    //int test;
  1287.    int bpp;
  1288.    png_uint_32 FullLength;
  1289.    png_uint_32 MMXLength;
  1290.    int diff;
  1291.    bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
  1292.    FullLength  = row_info->rowbytes - bpp; // # of bytes to filter
  1293.    _asm {
  1294.         mov edi, row
  1295.         mov esi, edi               // lp = row
  1296.         add edi, bpp               // rp = row + bpp
  1297.         xor eax, eax
  1298.         // get # of bytes to alignment
  1299.         mov diff, edi               // take start of row
  1300.         add diff, 0xf               // add 7 + 8 to incr past
  1301.                                         // alignment boundary
  1302.         xor ebx, ebx
  1303.         and diff, 0xfffffff8        // mask to alignment boundary
  1304.         sub diff, edi               // subtract from start ==> value
  1305.                                         //  ebx at alignment
  1306.         jz dsubgo
  1307.         // fix alignment
  1308. dsublp1:
  1309.         mov al, [esi+ebx]
  1310.         add [edi+ebx], al
  1311.         inc ebx
  1312.         cmp ebx, diff
  1313.         jb dsublp1
  1314. dsubgo:
  1315.         mov ecx, FullLength
  1316.         mov edx, ecx
  1317.         sub edx, ebx                  // subtract alignment fix
  1318.         and edx, 0x00000007           // calc bytes over mult of 8
  1319.         sub ecx, edx                  // drop over bytes from length
  1320.         mov MMXLength, ecx
  1321.    } // end _asm block
  1322.    // Now do the math for the rest of the row
  1323.    switch ( bpp )
  1324.    {
  1325.         case 3:
  1326.         {
  1327.          ActiveMask.use  = 0x0000ffffff000000;
  1328.          ShiftBpp.use = 24;       // == 3 * 8
  1329.          ShiftRem.use  = 40;      // == 64 - 24
  1330.          _asm {
  1331.             mov edi, row
  1332.             movq mm7, ActiveMask  // Load ActiveMask for 2nd active byte group
  1333.             mov esi, edi              // lp = row
  1334.             add edi, bpp          // rp = row + bpp
  1335.             movq mm6, mm7
  1336.             mov ebx, diff
  1337.             psllq mm6, ShiftBpp   // Move mask in mm6 to cover 3rd active
  1338.                                   // byte group
  1339.             // PRIME the pump (load the first Raw(x-bpp) data set
  1340.             movq mm1, [edi+ebx-8]
  1341. dsub3lp:
  1342.             psrlq mm1, ShiftRem   // Shift data for adding 1st bpp bytes
  1343.                           // no need for mask; shift clears inactive bytes
  1344.             // Add 1st active group
  1345.             movq mm0, [edi+ebx]
  1346.             paddb mm0, mm1
  1347.             // Add 2nd active group
  1348.             movq mm1, mm0         // mov updated Raws to mm1
  1349.             psllq mm1, ShiftBpp   // shift data to position correctly
  1350.             pand mm1, mm7         // mask to use only 2nd active group
  1351.             paddb mm0, mm1
  1352.             // Add 3rd active group
  1353.             movq mm1, mm0         // mov updated Raws to mm1
  1354.             psllq mm1, ShiftBpp   // shift data to position correctly
  1355.             pand mm1, mm6         // mask to use only 3rd active group
  1356.             add ebx, 8
  1357.             paddb mm0, mm1
  1358.             cmp ebx, MMXLength
  1359.             movq [edi+ebx-8], mm0     // Write updated Raws back to array
  1360.             // Prep for doing 1st add at top of loop
  1361.             movq mm1, mm0
  1362.             jb dsub3lp
  1363.          } // end _asm block
  1364.       }
  1365.       break;
  1366.       case 1:
  1367.       {
  1368.          // Placed here just in case this is a duplicate of the
  1369.          // non-MMX code for the SUB filter in png_read_filter_row below
  1370.          //
  1371.          //         png_bytep rp;
  1372.          //         png_bytep lp;
  1373.          //         png_uint_32 i;
  1374.          //         bpp = (row_info->pixel_depth + 7) >> 3;
  1375.          //         for (i = (png_uint_32)bpp, rp = row + bpp, lp = row;
  1376.          //            i < row_info->rowbytes; i++, rp++, lp++)
  1377.          //      {
  1378.          //            *rp = (png_byte)(((int)(*rp) + (int)(*lp)) & 0xff);
  1379.          //      }
  1380.          _asm {
  1381.             mov ebx, diff
  1382.             mov edi, row
  1383.             cmp ebx, FullLength
  1384.             jnb dsub1end
  1385.             mov esi, edi          // lp = row
  1386.             xor eax, eax
  1387.             add edi, bpp      // rp = row + bpp
  1388. dsub1lp:
  1389.             mov al, [esi+ebx]
  1390.             add [edi+ebx], al
  1391.             inc ebx
  1392.             cmp ebx, FullLength
  1393.             jb dsub1lp
  1394. dsub1end:
  1395.          } // end _asm block
  1396.       }
  1397.       return;
  1398.       case 6:
  1399.       case 7:
  1400.       case 4:
  1401.       case 5:
  1402.       {
  1403.          ShiftBpp.use = bpp << 3;
  1404.          ShiftRem.use = 64 - ShiftBpp.use;
  1405.          _asm {
  1406.             mov edi, row
  1407.             mov ebx, diff
  1408.             mov esi, edi               // lp = row
  1409.             add edi, bpp           // rp = row + bpp
  1410.             // PRIME the pump (load the first Raw(x-bpp) data set
  1411.             movq mm1, [edi+ebx-8]
  1412. dsub4lp:
  1413.             psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes
  1414.                           // no need for mask; shift clears inactive bytes
  1415.             movq mm0, [edi+ebx]
  1416.             paddb mm0, mm1
  1417.             // Add 2nd active group
  1418.             movq mm1, mm0          // mov updated Raws to mm1
  1419.             psllq mm1, ShiftBpp    // shift data to position correctly
  1420.                                    // there is no need for any mask
  1421.                                    // since shift clears inactive bits/bytes
  1422.             add ebx, 8
  1423.             paddb mm0, mm1
  1424.             cmp ebx, MMXLength
  1425.             movq [edi+ebx-8], mm0
  1426.             movq mm1, mm0          // Prep for doing 1st add at top of loop
  1427.             jb dsub4lp
  1428.          } // end _asm block
  1429.       }
  1430.       break;
  1431.       case 2:
  1432.       {
  1433.          ActiveMask.use  = 0x00000000ffff0000;
  1434.          ShiftBpp.use = 16;       // == 2 * 8
  1435.          ShiftRem.use = 48;       // == 64 - 16
  1436.          _asm {
  1437.             movq mm7, ActiveMask  // Load ActiveMask for 2nd active byte group
  1438.             mov ebx, diff
  1439.             movq mm6, mm7
  1440.             mov edi, row
  1441.             psllq mm6, ShiftBpp     // Move mask in mm6 to cover 3rd active
  1442.                                     //  byte group
  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 */