home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wvis0626.zip / warpvision_20020626.zip / libmpeg2 / motion_comp_mmx.c < prev    next >
C/C++ Source or Header  |  2002-06-19  |  26KB  |  1,018 lines

  1. /*
  2.  * motion_comp_mmx.c
  3.  * Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
  4.  *
  5.  * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
  6.  *
  7.  * mpeg2dec is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * mpeg2dec is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20.  */
  21.  
  22. #include "config.h"
  23.  
  24. #ifdef ARCH_X86
  25.  
  26. #include <inttypes.h>
  27.  
  28. #include "mpeg2_internal.h"
  29. #include "attributes.h"
  30. #include "mmx.h"
  31.  
  32. #define CPU_MMXEXT 0
  33. #define CPU_3DNOW 1
  34.  
  35.  
  36. /* MMX code - needs a rewrite */
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44. /* some rounding constants */
  45. mmx_t round1 = {0x0001000100010001LL};
  46. mmx_t round4 = {0x0002000200020002LL};
  47.  
  48. /*
  49.  * This code should probably be compiled with loop unrolling
  50.  * (ie, -funroll-loops in gcc)becuase some of the loops
  51.  * use a small static number of iterations. This was written
  52.  * with the assumption the compiler knows best about when
  53.  * unrolling will help
  54.  */
  55.  
  56. static inline void mmx_zero_reg ()
  57. {
  58.     /* load 0 into mm0 */
  59.     pxor_r2r (mm0, mm0);
  60. }
  61.  
  62. static inline void mmx_average_2_U8 (uint8_t * dest,
  63.                      uint8_t * src1, uint8_t * src2)
  64. {
  65.     /* *dest = (*src1 + *src2 + 1)/ 2; */
  66.  
  67.     movq_m2r (*src1, mm1);    // load 8 src1 bytes
  68.     movq_r2r (mm1, mm2);    // copy 8 src1 bytes
  69.  
  70.     movq_m2r (*src2, mm3);    // load 8 src2 bytes
  71.     movq_r2r (mm3, mm4);    // copy 8 src2 bytes
  72.  
  73.     punpcklbw_r2r (mm0, mm1);    // unpack low src1 bytes
  74.     punpckhbw_r2r (mm0, mm2);    // unpack high src1 bytes
  75.  
  76.     punpcklbw_r2r (mm0, mm3);    // unpack low src2 bytes
  77.     punpckhbw_r2r (mm0, mm4);    // unpack high src2 bytes
  78.  
  79.     paddw_r2r (mm3, mm1);    // add lows to mm1
  80.     paddw_m2r (round1, mm1);
  81.     psraw_i2r (1, mm1);        // /2
  82.  
  83.     paddw_r2r (mm4, mm2);    // add highs to mm2
  84.     paddw_m2r (round1, mm2);
  85.     psraw_i2r (1, mm2);        // /2
  86.  
  87.     packuswb_r2r (mm2, mm1);    // pack (w/ saturation)
  88.     movq_r2m (mm1, *dest);    // store result in dest
  89. }
  90.  
  91. static inline void mmx_interp_average_2_U8 (uint8_t * dest,
  92.                         uint8_t * src1, uint8_t * src2)
  93. {
  94.     /* *dest = (*dest + (*src1 + *src2 + 1)/ 2 + 1)/ 2; */
  95.  
  96.     movq_m2r (*dest, mm1);    // load 8 dest bytes
  97.     movq_r2r (mm1, mm2);    // copy 8 dest bytes
  98.  
  99.     movq_m2r (*src1, mm3);    // load 8 src1 bytes
  100.     movq_r2r (mm3, mm4);    // copy 8 src1 bytes
  101.  
  102.     movq_m2r (*src2, mm5);    // load 8 src2 bytes
  103.     movq_r2r (mm5, mm6);    // copy 8 src2 bytes
  104.  
  105.     punpcklbw_r2r (mm0, mm1);    // unpack low dest bytes
  106.     punpckhbw_r2r (mm0, mm2);    // unpack high dest bytes
  107.  
  108.     punpcklbw_r2r (mm0, mm3);    // unpack low src1 bytes
  109.     punpckhbw_r2r (mm0, mm4);    // unpack high src1 bytes
  110.  
  111.     punpcklbw_r2r (mm0, mm5);    // unpack low src2 bytes
  112.     punpckhbw_r2r (mm0, mm6);    // unpack high src2 bytes
  113.  
  114.     paddw_r2r (mm5, mm3);    // add lows
  115.     paddw_m2r (round1, mm3);
  116.     psraw_i2r (1, mm3);        // /2
  117.  
  118.     paddw_r2r (mm6, mm4);    // add highs
  119.     paddw_m2r (round1, mm4);
  120.     psraw_i2r (1, mm4);        // /2
  121.  
  122.     paddw_r2r (mm3, mm1);    // add lows
  123.     paddw_m2r (round1, mm1);
  124.     psraw_i2r (1, mm1);        // /2
  125.  
  126.     paddw_r2r (mm4, mm2);    // add highs
  127.     paddw_m2r (round1, mm2);
  128.     psraw_i2r (1, mm2);        // /2
  129.  
  130.     packuswb_r2r (mm2, mm1);    // pack (w/ saturation)
  131.     movq_r2m (mm1, *dest);    // store result in dest
  132. }
  133.  
  134. static inline void mmx_average_4_U8 (uint8_t * dest,
  135.                      uint8_t * src1, uint8_t * src2,
  136.                      uint8_t * src3, uint8_t * src4)
  137. {
  138.     /* *dest = (*src1 + *src2 + *src3 + *src4 + 2)/ 4; */
  139.  
  140.     movq_m2r (*src1, mm1);    // load 8 src1 bytes
  141.     movq_r2r (mm1, mm2);    // copy 8 src1 bytes
  142.  
  143.     punpcklbw_r2r (mm0, mm1);    // unpack low src1 bytes
  144.     punpckhbw_r2r (mm0, mm2);    // unpack high src1 bytes
  145.  
  146.     movq_m2r (*src2, mm3);    // load 8 src2 bytes
  147.     movq_r2r (mm3, mm4);    // copy 8 src2 bytes
  148.  
  149.     punpcklbw_r2r (mm0, mm3);    // unpack low src2 bytes
  150.     punpckhbw_r2r (mm0, mm4);    // unpack high src2 bytes
  151.  
  152.     paddw_r2r (mm3, mm1);    // add lows
  153.     paddw_r2r (mm4, mm2);    // add highs
  154.  
  155.     /* now have partials in mm1 and mm2 */
  156.  
  157.     movq_m2r (*src3, mm3);    // load 8 src3 bytes
  158.     movq_r2r (mm3, mm4);    // copy 8 src3 bytes
  159.  
  160.     punpcklbw_r2r (mm0, mm3);    // unpack low src3 bytes
  161.     punpckhbw_r2r (mm0, mm4);    // unpack high src3 bytes
  162.  
  163.     paddw_r2r (mm3, mm1);    // add lows
  164.     paddw_r2r (mm4, mm2);    // add highs
  165.  
  166.     movq_m2r (*src4, mm5);    // load 8 src4 bytes
  167.     movq_r2r (mm5, mm6);    // copy 8 src4 bytes
  168.  
  169.     punpcklbw_r2r (mm0, mm5);    // unpack low src4 bytes
  170.     punpckhbw_r2r (mm0, mm6);    // unpack high src4 bytes
  171.  
  172.     paddw_r2r (mm5, mm1);    // add lows
  173.     paddw_r2r (mm6, mm2);    // add highs
  174.  
  175.     /* now have subtotal in mm1 and mm2 */
  176.  
  177.     paddw_m2r (round4, mm1);
  178.     psraw_i2r (2, mm1);        // /4
  179.     paddw_m2r (round4, mm2);
  180.     psraw_i2r (2, mm2);        // /4
  181.  
  182.     packuswb_r2r (mm2, mm1);    // pack (w/ saturation)
  183.     movq_r2m (mm1, *dest);    // store result in dest
  184. }
  185.  
  186. static inline void mmx_interp_average_4_U8 (uint8_t * dest,
  187.                         uint8_t * src1, uint8_t * src2,
  188.                         uint8_t * src3, uint8_t * src4)
  189. {
  190.     /* *dest = (*dest + (*src1 + *src2 + *src3 + *src4 + 2)/ 4 + 1)/ 2; */
  191.  
  192.     movq_m2r (*src1, mm1);    // load 8 src1 bytes
  193.     movq_r2r (mm1, mm2);    // copy 8 src1 bytes
  194.  
  195.     punpcklbw_r2r (mm0, mm1);    // unpack low src1 bytes
  196.     punpckhbw_r2r (mm0, mm2);    // unpack high src1 bytes
  197.  
  198.     movq_m2r (*src2, mm3);    // load 8 src2 bytes
  199.     movq_r2r (mm3, mm4);    // copy 8 src2 bytes
  200.  
  201.     punpcklbw_r2r (mm0, mm3);    // unpack low src2 bytes
  202.     punpckhbw_r2r (mm0, mm4);    // unpack high src2 bytes
  203.  
  204.     paddw_r2r (mm3, mm1);    // add lows
  205.     paddw_r2r (mm4, mm2);    // add highs
  206.  
  207.     /* now have partials in mm1 and mm2 */
  208.  
  209.     movq_m2r (*src3, mm3);    // load 8 src3 bytes
  210.     movq_r2r (mm3, mm4);    // copy 8 src3 bytes
  211.  
  212.     punpcklbw_r2r (mm0, mm3);    // unpack low src3 bytes
  213.     punpckhbw_r2r (mm0, mm4);    // unpack high src3 bytes
  214.  
  215.     paddw_r2r (mm3, mm1);    // add lows
  216.     paddw_r2r (mm4, mm2);    // add highs
  217.  
  218.     movq_m2r (*src4, mm5);    // load 8 src4 bytes
  219.     movq_r2r (mm5, mm6);    // copy 8 src4 bytes
  220.  
  221.     punpcklbw_r2r (mm0, mm5);    // unpack low src4 bytes
  222.     punpckhbw_r2r (mm0, mm6);    // unpack high src4 bytes
  223.  
  224.     paddw_r2r (mm5, mm1);    // add lows
  225.     paddw_r2r (mm6, mm2);    // add highs
  226.  
  227.     paddw_m2r (round4, mm1);
  228.     psraw_i2r (2, mm1);        // /4
  229.     paddw_m2r (round4, mm2);
  230.     psraw_i2r (2, mm2);        // /4
  231.  
  232.     /* now have subtotal/4 in mm1 and mm2 */
  233.  
  234.     movq_m2r (*dest, mm3);    // load 8 dest bytes
  235.     movq_r2r (mm3, mm4);    // copy 8 dest bytes
  236.  
  237.     punpcklbw_r2r (mm0, mm3);    // unpack low dest bytes
  238.     punpckhbw_r2r (mm0, mm4);    // unpack high dest bytes
  239.  
  240.     paddw_r2r (mm3, mm1);    // add lows
  241.     paddw_r2r (mm4, mm2);    // add highs
  242.  
  243.     paddw_m2r (round1, mm1);
  244.     psraw_i2r (1, mm1);        // /2
  245.     paddw_m2r (round1, mm2);
  246.     psraw_i2r (1, mm2);        // /2
  247.  
  248.     /* now have end value in mm1 and mm2 */
  249.  
  250.     packuswb_r2r (mm2, mm1);    // pack (w/ saturation)
  251.     movq_r2m (mm1,*dest);    // store result in dest
  252. }
  253.  
  254. /*-----------------------------------------------------------------------*/
  255.  
  256. static inline void MC_avg_mmx (int width, int height,
  257.                    uint8_t * dest, uint8_t * ref, int stride)
  258. {
  259.     mmx_zero_reg ();
  260.  
  261.     do {
  262.     mmx_average_2_U8 (dest, dest, ref);
  263.  
  264.     if (width == 16)
  265.         mmx_average_2_U8 (dest+8, dest+8, ref+8);
  266.  
  267.     dest += stride;
  268.     ref += stride;
  269.     } while (--height);
  270. }
  271.  
  272. static void MC_avg_16_mmx (uint8_t * dest, uint8_t * ref,
  273.                int stride, int height)
  274. {
  275.     MC_avg_mmx (16, height, dest, ref, stride);
  276. }
  277.  
  278. static void MC_avg_8_mmx (uint8_t * dest, uint8_t * ref,
  279.               int stride, int height)
  280. {
  281.     MC_avg_mmx (8, height, dest, ref, stride);
  282. }
  283.  
  284. /*-----------------------------------------------------------------------*/
  285.  
  286. static inline void MC_put_mmx (int width, int height,
  287.                    uint8_t * dest, uint8_t * ref, int stride)
  288. {
  289.     mmx_zero_reg ();
  290.  
  291.     do {
  292.     movq_m2r (* ref, mm1);    // load 8 ref bytes
  293.     movq_r2m (mm1,* dest);    // store 8 bytes at curr
  294.  
  295.     if (width == 16)
  296.         {
  297.         movq_m2r (* (ref+8), mm1);    // load 8 ref bytes
  298.         movq_r2m (mm1,* (dest+8));    // store 8 bytes at curr
  299.         }
  300.  
  301.     dest += stride;
  302.     ref += stride;
  303.     } while (--height);
  304. }
  305.  
  306. static void MC_put_16_mmx (uint8_t * dest, uint8_t * ref,
  307.                int stride, int height)
  308. {
  309.     MC_put_mmx (16, height, dest, ref, stride);
  310. }
  311.  
  312. static void MC_put_8_mmx (uint8_t * dest, uint8_t * ref,
  313.               int stride, int height)
  314. {
  315.     MC_put_mmx (8, height, dest, ref, stride);
  316. }
  317.  
  318. /*-----------------------------------------------------------------------*/
  319.  
  320. /* Half pixel interpolation in the x direction */
  321. static inline void MC_avg_x_mmx (int width, int height,
  322.                  uint8_t * dest, uint8_t * ref, int stride)
  323. {
  324.     mmx_zero_reg ();
  325.  
  326.     do {
  327.     mmx_interp_average_2_U8 (dest, ref, ref+1);
  328.  
  329.     if (width == 16)
  330.         mmx_interp_average_2_U8 (dest+8, ref+8, ref+9);
  331.  
  332.     dest += stride;
  333.     ref += stride;
  334.     } while (--height);
  335. }
  336.  
  337. static void MC_avg_x16_mmx (uint8_t * dest, uint8_t * ref,
  338.                 int stride, int height)
  339. {
  340.     MC_avg_x_mmx (16, height, dest, ref, stride);
  341. }
  342.  
  343. static void MC_avg_x8_mmx (uint8_t * dest, uint8_t * ref,
  344.                int stride, int height)
  345. {
  346.     MC_avg_x_mmx (8, height, dest, ref, stride);
  347. }
  348.  
  349. /*-----------------------------------------------------------------------*/
  350.  
  351. static inline void MC_put_x_mmx (int width, int height,
  352.                  uint8_t * dest, uint8_t * ref, int stride)
  353. {
  354.     mmx_zero_reg ();
  355.  
  356.     do {
  357.     mmx_average_2_U8 (dest, ref, ref+1);
  358.  
  359.     if (width == 16)
  360.         mmx_average_2_U8 (dest+8, ref+8, ref+9);
  361.  
  362.     dest += stride;
  363.     ref += stride;
  364.     } while (--height);
  365. }
  366.  
  367. static void MC_put_x16_mmx (uint8_t * dest, uint8_t * ref,
  368.                 int stride, int height)
  369. {
  370.     MC_put_x_mmx (16, height, dest, ref, stride);
  371. }
  372.  
  373. static void MC_put_x8_mmx (uint8_t * dest, uint8_t * ref,
  374.                int stride, int height)
  375. {
  376.     MC_put_x_mmx (8, height, dest, ref, stride);
  377. }
  378.  
  379. /*-----------------------------------------------------------------------*/
  380.  
  381. static inline void MC_avg_xy_mmx (int width, int height,
  382.                   uint8_t * dest, uint8_t * ref, int stride)
  383. {
  384.     uint8_t * ref_next = ref+stride;
  385.  
  386.     mmx_zero_reg ();
  387.  
  388.     do {
  389.     mmx_interp_average_4_U8 (dest, ref, ref+1, ref_next, ref_next+1);
  390.  
  391.     if (width == 16)
  392.         mmx_interp_average_4_U8 (dest+8, ref+8, ref+9,
  393.                      ref_next+8, ref_next+9);
  394.  
  395.     dest += stride;
  396.     ref += stride;
  397.     ref_next += stride;
  398.     } while (--height);
  399. }
  400.  
  401. static void MC_avg_xy16_mmx (uint8_t * dest, uint8_t * ref,
  402.                  int stride, int height)
  403. {
  404.     MC_avg_xy_mmx (16, height, dest, ref, stride);
  405. }
  406.  
  407. static void MC_avg_xy8_mmx (uint8_t * dest, uint8_t * ref,
  408.                 int stride, int height)
  409. {
  410.     MC_avg_xy_mmx (8, height, dest, ref, stride);
  411. }
  412.  
  413. /*-----------------------------------------------------------------------*/
  414.  
  415. static inline void MC_put_xy_mmx (int width, int height,
  416.                   uint8_t * dest, uint8_t * ref, int stride)
  417. {
  418.     uint8_t * ref_next = ref+stride;
  419.  
  420.     mmx_zero_reg ();
  421.  
  422.     do {
  423.     mmx_average_4_U8 (dest, ref, ref+1, ref_next, ref_next+1);
  424.  
  425.     if (width == 16)
  426.         mmx_average_4_U8 (dest+8, ref+8, ref+9, ref_next+8, ref_next+9);
  427.  
  428.     dest += stride;
  429.     ref += stride;
  430.     ref_next += stride;
  431.     } while (--height);
  432. }
  433.  
  434. static void MC_put_xy16_mmx (uint8_t * dest, uint8_t * ref,
  435.                  int stride, int height)
  436. {
  437.     MC_put_xy_mmx (16, height, dest, ref, stride);
  438. }
  439.  
  440. static void MC_put_xy8_mmx (uint8_t * dest, uint8_t * ref,
  441.                 int stride, int height)
  442. {
  443.     MC_put_xy_mmx (8, height, dest, ref, stride);
  444. }
  445.  
  446. /*-----------------------------------------------------------------------*/
  447.  
  448. static inline void MC_avg_y_mmx (int width, int height,
  449.                  uint8_t * dest, uint8_t * ref, int stride)
  450. {
  451.     uint8_t * ref_next = ref+stride;
  452.  
  453.     mmx_zero_reg ();
  454.  
  455.     do {
  456.     mmx_interp_average_2_U8 (dest, ref, ref_next);
  457.  
  458.     if (width == 16)
  459.         mmx_interp_average_2_U8 (dest+8, ref+8, ref_next+8);
  460.  
  461.     dest += stride;
  462.     ref += stride;
  463.     ref_next += stride;
  464.     } while (--height);
  465. }
  466.  
  467. static void MC_avg_y16_mmx (uint8_t * dest, uint8_t * ref,
  468.                 int stride, int height)
  469. {
  470.     MC_avg_y_mmx (16, height, dest, ref, stride);
  471. }
  472.  
  473. static void MC_avg_y8_mmx (uint8_t * dest, uint8_t * ref,
  474.                int stride, int height)
  475. {
  476.     MC_avg_y_mmx (8, height, dest, ref, stride);
  477. }
  478.  
  479. /*-----------------------------------------------------------------------*/
  480.  
  481. static inline void MC_put_y_mmx (int width, int height,
  482.                  uint8_t * dest, uint8_t * ref, int stride)
  483. {
  484.     uint8_t * ref_next = ref+stride;
  485.  
  486.     mmx_zero_reg ();
  487.  
  488.     do {
  489.     mmx_average_2_U8 (dest, ref, ref_next);
  490.  
  491.     if (width == 16)
  492.         mmx_average_2_U8 (dest+8, ref+8, ref_next+8);
  493.  
  494.     dest += stride;
  495.     ref += stride;
  496.     ref_next += stride;
  497.     } while (--height);
  498. }
  499.  
  500. static void MC_put_y16_mmx (uint8_t * dest, uint8_t * ref,
  501.                 int stride, int height)
  502. {
  503.     MC_put_y_mmx (16, height, dest, ref, stride);
  504. }
  505.  
  506. static void MC_put_y8_mmx (uint8_t * dest, uint8_t * ref,
  507.                int stride, int height)
  508. {
  509.     MC_put_y_mmx (8, height, dest, ref, stride);
  510. }
  511.  
  512.  
  513. MOTION_COMP_EXTERN (mmx)
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521. /* CPU_MMXEXT/CPU_3DNOW adaptation layer */
  522.  
  523. #define pavg_r2r(src,dest)        \
  524. do {                    \
  525.     if (cpu == CPU_MMXEXT)        \
  526.     pavgb_r2r (src, dest);        \
  527.     else                \
  528.     pavgusb_r2r (src, dest);    \
  529. } while (0)
  530.  
  531. #define pavg_m2r(src,dest)        \
  532. do {                    \
  533.     if (cpu == CPU_MMXEXT)        \
  534.     pavgb_m2r (src, dest);        \
  535.     else                \
  536.     pavgusb_m2r (src, dest);    \
  537. } while (0)
  538.  
  539.  
  540. /* CPU_MMXEXT code */
  541.  
  542.  
  543. static inline void MC_put1_8 (int height, uint8_t * dest, uint8_t * ref,
  544.                   int stride)
  545. {
  546.     do {
  547.     movq_m2r (*ref, mm0);
  548.     movq_r2m (mm0, *dest);
  549.     ref += stride;
  550.     dest += stride;
  551.     } while (--height);
  552. }
  553.  
  554. static inline void MC_put1_16 (int height, uint8_t * dest, uint8_t * ref,
  555.                    int stride)
  556. {
  557.     do {
  558.     movq_m2r (*ref, mm0);
  559.     movq_m2r (*(ref+8), mm1);
  560.     ref += stride;
  561.     movq_r2m (mm0, *dest);
  562.     movq_r2m (mm1, *(dest+8));
  563.     dest += stride;
  564.     } while (--height);
  565. }
  566.  
  567. static inline void MC_avg1_8 (int height, uint8_t * dest, uint8_t * ref,
  568.                   int stride, int cpu)
  569. {
  570.     do {
  571.     movq_m2r (*ref, mm0);
  572.     pavg_m2r (*dest, mm0);
  573.     ref += stride;
  574.     movq_r2m (mm0, *dest);
  575.     dest += stride;
  576.     } while (--height);
  577. }
  578.  
  579. static inline void MC_avg1_16 (int height, uint8_t * dest, uint8_t * ref,
  580.                    int stride, int cpu)
  581. {
  582.     do {
  583.     movq_m2r (*ref, mm0);
  584.     movq_m2r (*(ref+8), mm1);
  585.     pavg_m2r (*dest, mm0);
  586.     pavg_m2r (*(dest+8), mm1);
  587.     movq_r2m (mm0, *dest);
  588.     ref += stride;
  589.     movq_r2m (mm1, *(dest+8));
  590.     dest += stride;
  591.     } while (--height);
  592. }
  593.  
  594. static inline void MC_put2_8 (int height, uint8_t * dest, uint8_t * ref,
  595.                   int stride, int offset, int cpu)
  596. {
  597.     do {
  598.     movq_m2r (*ref, mm0);
  599.     pavg_m2r (*(ref+offset), mm0);
  600.     ref += stride;
  601.     movq_r2m (mm0, *dest);
  602.     dest += stride;
  603.     } while (--height);
  604. }
  605.  
  606. static inline void MC_put2_16 (int height, uint8_t * dest, uint8_t * ref,
  607.                    int stride, int offset, int cpu)
  608. {
  609.     do {
  610.     movq_m2r (*ref, mm0);
  611.     movq_m2r (*(ref+8), mm1);
  612.     pavg_m2r (*(ref+offset), mm0);
  613.     pavg_m2r (*(ref+offset+8), mm1);
  614.     movq_r2m (mm0, *dest);
  615.     ref += stride;
  616.     movq_r2m (mm1, *(dest+8));
  617.     dest += stride;
  618.     } while (--height);
  619. }
  620.  
  621. static inline void MC_avg2_8 (int height, uint8_t * dest, uint8_t * ref,
  622.                   int stride, int offset, int cpu)
  623. {
  624.     do {
  625.     movq_m2r (*ref, mm0);
  626.     pavg_m2r (*(ref+offset), mm0);
  627.     pavg_m2r (*dest, mm0);
  628.     ref += stride;
  629.     movq_r2m (mm0, *dest);
  630.     dest += stride;
  631.     } while (--height);
  632. }
  633.  
  634. static inline void MC_avg2_16 (int height, uint8_t * dest, uint8_t * ref,
  635.                    int stride, int offset, int cpu)
  636. {
  637.     do {
  638.     movq_m2r (*ref, mm0);
  639.     movq_m2r (*(ref+8), mm1);
  640.     pavg_m2r (*(ref+offset), mm0);
  641.     pavg_m2r (*(ref+offset+8), mm1);
  642.     pavg_m2r (*dest, mm0);
  643.     pavg_m2r (*(dest+8), mm1);
  644.     ref += stride;
  645.     movq_r2m (mm0, *dest);
  646.     movq_r2m (mm1, *(dest+8));
  647.     dest += stride;
  648.     } while (--height);
  649. }
  650.  
  651. static mmx_t mask_one = {0x0101010101010101LL};
  652.  
  653. static inline void MC_put4_8 (int height, uint8_t * dest, uint8_t * ref,
  654.                   int stride, int cpu)
  655. {
  656.     movq_m2r (*ref, mm0);
  657.     movq_m2r (*(ref+1), mm1);
  658.     movq_r2r (mm0, mm7);
  659.     pxor_r2r (mm1, mm7);
  660.     pavg_r2r (mm1, mm0);
  661.     ref += stride;
  662.  
  663.     do {
  664.     movq_m2r (*ref, mm2);
  665.     movq_r2r (mm0, mm5);
  666.  
  667.     movq_m2r (*(ref+1), mm3);
  668.     movq_r2r (mm2, mm6);
  669.  
  670.     pxor_r2r (mm3, mm6);
  671.     pavg_r2r (mm3, mm2);
  672.  
  673.     por_r2r (mm6, mm7);
  674.     pxor_r2r (mm2, mm5);
  675.  
  676.     pand_r2r (mm5, mm7);
  677.     pavg_r2r (mm2, mm0);
  678.  
  679.     pand_m2r (mask_one, mm7);
  680.  
  681.     psubusb_r2r (mm7, mm0);
  682.  
  683.     ref += stride;
  684.     movq_r2m (mm0, *dest);
  685.     dest += stride;
  686.  
  687.     movq_r2r (mm6, mm7);    // unroll !
  688.     movq_r2r (mm2, mm0);    // unroll !
  689.     } while (--height);
  690. }
  691.  
  692. static inline void MC_put4_16 (int height, uint8_t * dest, uint8_t * ref,
  693.                    int stride, int cpu)
  694. {
  695.     do {
  696.     movq_m2r (*ref, mm0);
  697.     movq_m2r (*(ref+stride+1), mm1);
  698.     movq_r2r (mm0, mm7);
  699.     movq_m2r (*(ref+1), mm2);
  700.     pxor_r2r (mm1, mm7);
  701.     movq_m2r (*(ref+stride), mm3);
  702.     movq_r2r (mm2, mm6);
  703.     pxor_r2r (mm3, mm6);
  704.     pavg_r2r (mm1, mm0);
  705.     pavg_r2r (mm3, mm2);
  706.     por_r2r (mm6, mm7);
  707.     movq_r2r (mm0, mm6);
  708.     pxor_r2r (mm2, mm6);
  709.     pand_r2r (mm6, mm7);
  710.     pand_m2r (mask_one, mm7);
  711.     pavg_r2r (mm2, mm0);
  712.     psubusb_r2r (mm7, mm0);
  713.     movq_r2m (mm0, *dest);
  714.  
  715.     movq_m2r (*(ref+8), mm0);
  716.     movq_m2r (*(ref+stride+9), mm1);
  717.     movq_r2r (mm0, mm7);
  718.     movq_m2r (*(ref+9), mm2);
  719.     pxor_r2r (mm1, mm7);
  720.     movq_m2r (*(ref+stride+8), mm3);
  721.     movq_r2r (mm2, mm6);
  722.     pxor_r2r (mm3, mm6);
  723.     pavg_r2r (mm1, mm0);
  724.     pavg_r2r (mm3, mm2);
  725.     por_r2r (mm6, mm7);
  726.     movq_r2r (mm0, mm6);
  727.     pxor_r2r (mm2, mm6);
  728.     pand_r2r (mm6, mm7);
  729.     pand_m2r (mask_one, mm7);
  730.     pavg_r2r (mm2, mm0);
  731.     psubusb_r2r (mm7, mm0);
  732.     ref += stride;
  733.     movq_r2m (mm0, *(dest+8));
  734.     dest += stride;
  735.     } while (--height);
  736. }
  737.  
  738. static inline void MC_avg4_8 (int height, uint8_t * dest, uint8_t * ref,
  739.                   int stride, int cpu)
  740. {
  741.     do {
  742.     movq_m2r (*ref, mm0);
  743.     movq_m2r (*(ref+stride+1), mm1);
  744.     movq_r2r (mm0, mm7);
  745.     movq_m2r (*(ref+1), mm2);
  746.     pxor_r2r (mm1, mm7);
  747.     movq_m2r (*(ref+stride), mm3);
  748.     movq_r2r (mm2, mm6);
  749.     pxor_r2r (mm3, mm6);
  750.     pavg_r2r (mm1, mm0);
  751.     pavg_r2r (mm3, mm2);
  752.     por_r2r (mm6, mm7);
  753.     movq_r2r (mm0, mm6);
  754.     pxor_r2r (mm2, mm6);
  755.     pand_r2r (mm6, mm7);
  756.     pand_m2r (mask_one, mm7);
  757.     pavg_r2r (mm2, mm0);
  758.     psubusb_r2r (mm7, mm0);
  759.     movq_m2r (*dest, mm1);
  760.     pavg_r2r (mm1, mm0);
  761.     ref += stride;
  762.     movq_r2m (mm0, *dest);
  763.     dest += stride;
  764.     } while (--height);
  765. }
  766.  
  767. static inline void MC_avg4_16 (int height, uint8_t * dest, uint8_t * ref,
  768.                    int stride, int cpu)
  769. {
  770.     do {
  771.     movq_m2r (*ref, mm0);
  772.     movq_m2r (*(ref+stride+1), mm1);
  773.     movq_r2r (mm0, mm7);
  774.     movq_m2r (*(ref+1), mm2);
  775.     pxor_r2r (mm1, mm7);
  776.     movq_m2r (*(ref+stride), mm3);
  777.     movq_r2r (mm2, mm6);
  778.     pxor_r2r (mm3, mm6);
  779.     pavg_r2r (mm1, mm0);
  780.     pavg_r2r (mm3, mm2);
  781.     por_r2r (mm6, mm7);
  782.     movq_r2r (mm0, mm6);
  783.     pxor_r2r (mm2, mm6);
  784.     pand_r2r (mm6, mm7);
  785.     pand_m2r (mask_one, mm7);
  786.     pavg_r2r (mm2, mm0);
  787.     psubusb_r2r (mm7, mm0);
  788.     movq_m2r (*dest, mm1);
  789.     pavg_r2r (mm1, mm0);
  790.     movq_r2m (mm0, *dest);
  791.  
  792.     movq_m2r (*(ref+8), mm0);
  793.     movq_m2r (*(ref+stride+9), mm1);
  794.     movq_r2r (mm0, mm7);
  795.     movq_m2r (*(ref+9), mm2);
  796.     pxor_r2r (mm1, mm7);
  797.     movq_m2r (*(ref+stride+8), mm3);
  798.     movq_r2r (mm2, mm6);
  799.     pxor_r2r (mm3, mm6);
  800.     pavg_r2r (mm1, mm0);
  801.     pavg_r2r (mm3, mm2);
  802.     por_r2r (mm6, mm7);
  803.     movq_r2r (mm0, mm6);
  804.     pxor_r2r (mm2, mm6);
  805.     pand_r2r (mm6, mm7);
  806.     pand_m2r (mask_one, mm7);
  807.     pavg_r2r (mm2, mm0);
  808.     psubusb_r2r (mm7, mm0);
  809.     movq_m2r (*(dest+8), mm1);
  810.     pavg_r2r (mm1, mm0);
  811.     ref += stride;
  812.     movq_r2m (mm0, *(dest+8));
  813.     dest += stride;
  814.     } while (--height);
  815. }
  816.  
  817. static void MC_avg_16_mmxext (uint8_t * dest, uint8_t * ref,
  818.                   int stride, int height)
  819. {
  820.     MC_avg1_16 (height, dest, ref, stride, CPU_MMXEXT);
  821. }
  822.  
  823. static void MC_avg_8_mmxext (uint8_t * dest, uint8_t * ref,
  824.                  int stride, int height)
  825. {
  826.     MC_avg1_8 (height, dest, ref, stride, CPU_MMXEXT);
  827. }
  828.  
  829. static void MC_put_16_mmxext (uint8_t * dest, uint8_t * ref,
  830.                   int stride, int height)
  831. {
  832.     MC_put1_16 (height, dest, ref, stride);
  833. }
  834.  
  835. static void MC_put_8_mmxext (uint8_t * dest, uint8_t * ref,
  836.                  int stride, int height)
  837. {
  838.     MC_put1_8 (height, dest, ref, stride);
  839. }
  840.  
  841. static void MC_avg_x16_mmxext (uint8_t * dest, uint8_t * ref,
  842.                    int stride, int height)
  843. {
  844.     MC_avg2_16 (height, dest, ref, stride, 1, CPU_MMXEXT);
  845. }
  846.  
  847. static void MC_avg_x8_mmxext (uint8_t * dest, uint8_t * ref,
  848.                   int stride, int height)
  849. {
  850.     MC_avg2_8 (height, dest, ref, stride, 1, CPU_MMXEXT);
  851. }
  852.  
  853. static void MC_put_x16_mmxext (uint8_t * dest, uint8_t * ref,
  854.                    int stride, int height)
  855. {
  856.     MC_put2_16 (height, dest, ref, stride, 1, CPU_MMXEXT);
  857. }
  858.  
  859. static void MC_put_x8_mmxext (uint8_t * dest, uint8_t * ref,
  860.                   int stride, int height)
  861. {
  862.     MC_put2_8 (height, dest, ref, stride, 1, CPU_MMXEXT);
  863. }
  864.  
  865. static void MC_avg_y16_mmxext (uint8_t * dest, uint8_t * ref,
  866.                    int stride, int height)
  867. {
  868.     MC_avg2_16 (height, dest, ref, stride, stride, CPU_MMXEXT);
  869. }
  870.  
  871. static void MC_avg_y8_mmxext (uint8_t * dest, uint8_t * ref,
  872.                   int stride, int height)
  873. {
  874.     MC_avg2_8 (height, dest, ref, stride, stride, CPU_MMXEXT);
  875. }
  876.  
  877. static void MC_put_y16_mmxext (uint8_t * dest, uint8_t * ref,
  878.                    int stride, int height)
  879. {
  880.     MC_put2_16 (height, dest, ref, stride, stride, CPU_MMXEXT);
  881. }
  882.  
  883. static void MC_put_y8_mmxext (uint8_t * dest, uint8_t * ref,
  884.                   int stride, int height)
  885. {
  886.     MC_put2_8 (height, dest, ref, stride, stride, CPU_MMXEXT);
  887. }
  888.  
  889. static void MC_avg_xy16_mmxext (uint8_t * dest, uint8_t * ref,
  890.                 int stride, int height)
  891. {
  892.     MC_avg4_16 (height, dest, ref, stride, CPU_MMXEXT);
  893. }
  894.  
  895. static void MC_avg_xy8_mmxext (uint8_t * dest, uint8_t * ref,
  896.                    int stride, int height)
  897. {
  898.     MC_avg4_8 (height, dest, ref, stride, CPU_MMXEXT);
  899. }
  900.  
  901. static void MC_put_xy16_mmxext (uint8_t * dest, uint8_t * ref,
  902.                 int stride, int height)
  903. {
  904.     MC_put4_16 (height, dest, ref, stride, CPU_MMXEXT);
  905. }
  906.  
  907. static void MC_put_xy8_mmxext (uint8_t * dest, uint8_t * ref,
  908.                    int stride, int height)
  909. {
  910.     MC_put4_8 (height, dest, ref, stride, CPU_MMXEXT);
  911. }
  912.  
  913.  
  914. MOTION_COMP_EXTERN (mmxext)
  915.  
  916.  
  917.  
  918. static void MC_avg_16_3dnow (uint8_t * dest, uint8_t * ref,
  919.                   int stride, int height)
  920. {
  921.     MC_avg1_16 (height, dest, ref, stride, CPU_3DNOW);
  922. }
  923.  
  924. static void MC_avg_8_3dnow (uint8_t * dest, uint8_t * ref,
  925.                  int stride, int height)
  926. {
  927.     MC_avg1_8 (height, dest, ref, stride, CPU_3DNOW);
  928. }
  929.  
  930. static void MC_put_16_3dnow (uint8_t * dest, uint8_t * ref,
  931.                   int stride, int height)
  932. {
  933.     MC_put1_16 (height, dest, ref, stride);
  934. }
  935.  
  936. static void MC_put_8_3dnow (uint8_t * dest, uint8_t * ref,
  937.                  int stride, int height)
  938. {
  939.     MC_put1_8 (height, dest, ref, stride);
  940. }
  941.  
  942. static void MC_avg_x16_3dnow (uint8_t * dest, uint8_t * ref,
  943.                    int stride, int height)
  944. {
  945.     MC_avg2_16 (height, dest, ref, stride, 1, CPU_3DNOW);
  946. }
  947.  
  948. static void MC_avg_x8_3dnow (uint8_t * dest, uint8_t * ref,
  949.                   int stride, int height)
  950. {
  951.     MC_avg2_8 (height, dest, ref, stride, 1, CPU_3DNOW);
  952. }
  953.  
  954. static void MC_put_x16_3dnow (uint8_t * dest, uint8_t * ref,
  955.                    int stride, int height)
  956. {
  957.     MC_put2_16 (height, dest, ref, stride, 1, CPU_3DNOW);
  958. }
  959.  
  960. static void MC_put_x8_3dnow (uint8_t * dest, uint8_t * ref,
  961.                   int stride, int height)
  962. {
  963.     MC_put2_8 (height, dest, ref, stride, 1, CPU_3DNOW);
  964. }
  965.  
  966. static void MC_avg_y16_3dnow (uint8_t * dest, uint8_t * ref,
  967.                    int stride, int height)
  968. {
  969.     MC_avg2_16 (height, dest, ref, stride, stride, CPU_3DNOW);
  970. }
  971.  
  972. static void MC_avg_y8_3dnow (uint8_t * dest, uint8_t * ref,
  973.                   int stride, int height)
  974. {
  975.     MC_avg2_8 (height, dest, ref, stride, stride, CPU_3DNOW);
  976. }
  977.  
  978. static void MC_put_y16_3dnow (uint8_t * dest, uint8_t * ref,
  979.                    int stride, int height)
  980. {
  981.     MC_put2_16 (height, dest, ref, stride, stride, CPU_3DNOW);
  982. }
  983.  
  984. static void MC_put_y8_3dnow (uint8_t * dest, uint8_t * ref,
  985.                   int stride, int height)
  986. {
  987.     MC_put2_8 (height, dest, ref, stride, stride, CPU_3DNOW);
  988. }
  989.  
  990. static void MC_avg_xy16_3dnow (uint8_t * dest, uint8_t * ref,
  991.                 int stride, int height)
  992. {
  993.     MC_avg4_16 (height, dest, ref, stride, CPU_3DNOW);
  994. }
  995.  
  996. static void MC_avg_xy8_3dnow (uint8_t * dest, uint8_t * ref,
  997.                    int stride, int height)
  998. {
  999.     MC_avg4_8 (height, dest, ref, stride, CPU_3DNOW);
  1000. }
  1001.  
  1002. static void MC_put_xy16_3dnow (uint8_t * dest, uint8_t * ref,
  1003.                 int stride, int height)
  1004. {
  1005.     MC_put4_16 (height, dest, ref, stride, CPU_3DNOW);
  1006. }
  1007.  
  1008. static void MC_put_xy8_3dnow (uint8_t * dest, uint8_t * ref,
  1009.                    int stride, int height)
  1010. {
  1011.     MC_put4_8 (height, dest, ref, stride, CPU_3DNOW);
  1012. }
  1013.  
  1014.  
  1015. MOTION_COMP_EXTERN (3dnow)
  1016.  
  1017. #endif
  1018.