home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wvis0626.zip / warpvision_20020626.zip / libavcodec / i386 / dsputil_mmx.c < prev    next >
C/C++ Source or Header  |  2002-06-24  |  17KB  |  549 lines

  1. /*
  2.  * MMX optimized DSP utils
  3.  * Copyright (c) 2000, 2001 Fabrice Bellard.
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Lesser General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public
  16.  * License along with this library; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  * MMX optimization by Nick Kurshev <nickols_k@mail.ru>
  20.  */
  21.  
  22. #include "../dsputil.h"
  23. #include "../simple_idct.h"
  24.  
  25. int mm_flags; /* multimedia extension flags */
  26.  
  27. int pix_abs16x16_mmx(UINT8 *blk1, UINT8 *blk2, int lx);
  28. int pix_abs16x16_x2_mmx(UINT8 *blk1, UINT8 *blk2, int lx);
  29. int pix_abs16x16_y2_mmx(UINT8 *blk1, UINT8 *blk2, int lx);
  30. int pix_abs16x16_xy2_mmx(UINT8 *blk1, UINT8 *blk2, int lx);
  31.  
  32. int pix_abs16x16_mmx2(UINT8 *blk1, UINT8 *blk2, int lx);
  33. int pix_abs16x16_x2_mmx2(UINT8 *blk1, UINT8 *blk2, int lx);
  34. int pix_abs16x16_y2_mmx2(UINT8 *blk1, UINT8 *blk2, int lx);
  35. int pix_abs16x16_xy2_mmx2(UINT8 *blk1, UINT8 *blk2, int lx);
  36.  
  37. int pix_abs8x8_mmx(UINT8 *blk1, UINT8 *blk2, int lx);
  38. int pix_abs8x8_x2_mmx(UINT8 *blk1, UINT8 *blk2, int lx);
  39. int pix_abs8x8_y2_mmx(UINT8 *blk1, UINT8 *blk2, int lx);
  40. int pix_abs8x8_xy2_mmx(UINT8 *blk1, UINT8 *blk2, int lx);
  41.  
  42. int pix_abs8x8_mmx2(UINT8 *blk1, UINT8 *blk2, int lx);
  43. int pix_abs8x8_x2_mmx2(UINT8 *blk1, UINT8 *blk2, int lx);
  44. int pix_abs8x8_y2_mmx2(UINT8 *blk1, UINT8 *blk2, int lx);
  45. int pix_abs8x8_xy2_mmx2(UINT8 *blk1, UINT8 *blk2, int lx);
  46.  
  47. /* external functions, from idct_mmx.c */
  48. void ff_mmx_idct(DCTELEM *block);
  49. void ff_mmxext_idct(DCTELEM *block);
  50.  
  51. /* pixel operations */
  52. static const uint64_t mm_bone __attribute__ ((aligned(8))) = 0x0101010101010101ULL;
  53. static const uint64_t mm_wone __attribute__ ((aligned(8))) = 0x0001000100010001ULL;
  54. static const uint64_t mm_wtwo __attribute__ ((aligned(8))) = 0x0002000200020002ULL;
  55.  
  56. #define JUMPALIGN() __asm __volatile (".balign 8"::)
  57. #define MOVQ_ZERO(regd)  __asm __volatile ("pxor %%" #regd ", %%" #regd ::)
  58.  
  59. #define MOVQ_WONE(regd) \
  60.     __asm __volatile ( \
  61.     "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
  62.     "psrlw $15, %%" #regd ::)
  63.  
  64. #define MOVQ_BFE(regd) \
  65.     __asm __volatile ( \
  66.     "pcmpeqd %%" #regd ", %%" #regd " \n\t"\
  67.     "paddb %%" #regd ", %%" #regd " \n\t" ::)
  68.  
  69. #ifndef PIC
  70. #define MOVQ_BONE(regd)  __asm __volatile ("movq %0, %%" #regd " \n\t" ::"m"(mm_bone))
  71. #define MOVQ_WTWO(regd)  __asm __volatile ("movq %0, %%" #regd " \n\t" ::"m"(mm_wtwo))
  72. #else
  73. // for shared library it's better to use this way for accessing constants
  74. // pcmpeqd -> -1
  75. #define MOVQ_BONE(regd) \
  76.     __asm __volatile ( \
  77.     "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
  78.     "psrlw $15, %%" #regd " \n\t" \
  79.     "packuswb %%" #regd ", %%" #regd " \n\t" ::)
  80.  
  81. #define MOVQ_WTWO(regd) \
  82.     __asm __volatile ( \
  83.     "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
  84.     "psrlw $15, %%" #regd " \n\t" \
  85.     "psllw $1, %%" #regd " \n\t"::)
  86.  
  87. #endif
  88.  
  89. // using regr as temporary and for the output result
  90. // first argument is unmodifed and second is trashed
  91. // regfe is supposed to contain 0xfefefefefefefefe
  92. #define PAVGB_MMX_NO_RND(rega, regb, regr, regfe) \
  93.     "movq " #rega ", " #regr "    \n\t"\
  94.     "pand " #regb ", " #regr "    \n\t"\
  95.     "pxor " #rega ", " #regb "    \n\t"\
  96.     "pand " #regfe "," #regb "    \n\t"\
  97.     "psrlq $1, " #regb "     \n\t"\
  98.     "paddb " #regb ", " #regr "    \n\t"
  99.  
  100. #define PAVGB_MMX(rega, regb, regr, regfe) \
  101.     "movq " #rega ", " #regr "    \n\t"\
  102.     "por  " #regb ", " #regr "    \n\t"\
  103.     "pxor " #rega ", " #regb "    \n\t"\
  104.     "pand " #regfe "," #regb "    \n\t"\
  105.     "psrlq $1, " #regb "    \n\t"\
  106.     "psubb " #regb ", " #regr "    \n\t"
  107.  
  108. // mm6 is supposed to contain 0xfefefefefefefefe
  109. #define PAVGBP_MMX_NO_RND(rega, regb, regr,  regc, regd, regp) \
  110.     "movq " #rega ", " #regr "    \n\t"\
  111.     "movq " #regc ", " #regp "    \n\t"\
  112.     "pand " #regb ", " #regr "    \n\t"\
  113.     "pand " #regd ", " #regp "    \n\t"\
  114.     "pxor " #rega ", " #regb "    \n\t"\
  115.     "pxor " #regc ", " #regd "    \n\t"\
  116.     "pand %%mm6, " #regb "    \n\t"\
  117.     "pand %%mm6, " #regd "    \n\t"\
  118.     "psrlq $1, " #regb "     \n\t"\
  119.     "psrlq $1, " #regd "     \n\t"\
  120.     "paddb " #regb ", " #regr "    \n\t"\
  121.     "paddb " #regd ", " #regp "    \n\t"
  122.  
  123. #define PAVGBP_MMX(rega, regb, regr, regc, regd, regp) \
  124.     "movq " #rega ", " #regr "    \n\t"\
  125.     "movq " #regc ", " #regp "    \n\t"\
  126.     "por  " #regb ", " #regr "    \n\t"\
  127.     "por  " #regd ", " #regp "    \n\t"\
  128.     "pxor " #rega ", " #regb "    \n\t"\
  129.     "pxor " #regc ", " #regd "    \n\t"\
  130.     "pand %%mm6, " #regb "         \n\t"\
  131.     "pand %%mm6, " #regd "         \n\t"\
  132.     "psrlq $1, " #regd "    \n\t"\
  133.     "psrlq $1, " #regb "    \n\t"\
  134.     "psubb " #regb ", " #regr "    \n\t"\
  135.     "psubb " #regd ", " #regp "    \n\t"
  136.  
  137. /***********************************/
  138. /* MMX no rounding */
  139. #define DEF(x, y) x ## _no_rnd_ ## y ##_mmx
  140. #define SET_RND  MOVQ_WONE
  141. #define PAVGBP(a, b, c, d, e, f)    PAVGBP_MMX_NO_RND(a, b, c, d, e, f)
  142. #define PAVGB(a, b, c, e)        PAVGB_MMX_NO_RND(a, b, c, e)
  143.  
  144. #include "dsputil_mmx_rnd.h"
  145.  
  146. #undef DEF
  147. #undef SET_RND
  148. #undef PAVGBP
  149. #undef PAVGB
  150. /***********************************/
  151. /* MMX rounding */
  152.  
  153. #define DEF(x, y) x ## _ ## y ##_mmx
  154. #define SET_RND  MOVQ_WTWO
  155. #define PAVGBP(a, b, c, d, e, f)    PAVGBP_MMX(a, b, c, d, e, f)
  156. #define PAVGB(a, b, c, e)        PAVGB_MMX(a, b, c, e)
  157.  
  158. #include "dsputil_mmx_rnd.h"
  159.  
  160. #undef DEF
  161. #undef SET_RND
  162. #undef PAVGBP
  163. #undef PAVGB
  164.  
  165. /***********************************/
  166. /* 3Dnow specific */
  167.  
  168. #define DEF(x) x ## _3dnow
  169. /* for Athlons PAVGUSB is prefered */
  170. #define PAVGB "pavgusb"
  171.  
  172. #include "dsputil_mmx_avg.h"
  173.  
  174. #undef DEF
  175. #undef PAVGB
  176.  
  177. /***********************************/
  178. /* MMX2 specific */
  179.  
  180. #define DEF(x) x ## _mmx2
  181.  
  182. /* Introduced only in MMX2 set */
  183. #define PAVGB "pavgb"
  184.  
  185. #include "dsputil_mmx_avg.h"
  186.  
  187. #undef DEF
  188. #undef PAVGB
  189.  
  190. /***********************************/
  191. /* standard MMX */
  192.  
  193. static void get_pixels_mmx(DCTELEM *block, const UINT8 *pixels, int line_size)
  194. {
  195.     asm volatile(
  196.         "movl $-128, %%eax    \n\t"
  197.         "pxor %%mm7, %%mm7    \n\t"
  198.         ".balign 16        \n\t"
  199.         "1:            \n\t"
  200.         "movq (%0), %%mm0    \n\t"
  201.         "movq (%0, %2), %%mm2    \n\t"
  202.         "movq %%mm0, %%mm1    \n\t"
  203.         "movq %%mm2, %%mm3    \n\t"
  204.         "punpcklbw %%mm7, %%mm0    \n\t"
  205.         "punpckhbw %%mm7, %%mm1    \n\t"
  206.         "punpcklbw %%mm7, %%mm2    \n\t"
  207.         "punpckhbw %%mm7, %%mm3    \n\t"
  208.         "movq %%mm0, (%1, %%eax)\n\t"
  209.         "movq %%mm1, 8(%1, %%eax)\n\t"
  210.         "movq %%mm2, 16(%1, %%eax)\n\t"
  211.         "movq %%mm3, 24(%1, %%eax)\n\t"
  212.         "addl %3, %0        \n\t"
  213.         "addl $32, %%eax    \n\t"
  214.         "js 1b            \n\t"
  215.         : "+r" (pixels)
  216.         : "r" (block+64), "r" (line_size), "r" (line_size*2)
  217.         : "%eax"
  218.     );
  219. }
  220.  
  221. static void diff_pixels_mmx(DCTELEM *block, const UINT8 *s1, const UINT8 *s2, int stride)
  222. {
  223.     asm volatile(
  224.         "pxor %%mm7, %%mm7    \n\t"
  225.         "movl $-128, %%eax    \n\t"
  226.         ".balign 16        \n\t"
  227.         "1:            \n\t"
  228.         "movq (%0), %%mm0    \n\t"
  229.         "movq (%1), %%mm2    \n\t"
  230.         "movq %%mm0, %%mm1    \n\t"
  231.         "movq %%mm2, %%mm3    \n\t"
  232.         "punpcklbw %%mm7, %%mm0    \n\t"
  233.         "punpckhbw %%mm7, %%mm1    \n\t"
  234.         "punpcklbw %%mm7, %%mm2    \n\t"
  235.         "punpckhbw %%mm7, %%mm3    \n\t"
  236.         "psubw %%mm2, %%mm0    \n\t"
  237.         "psubw %%mm3, %%mm1    \n\t"
  238.         "movq %%mm0, (%2, %%eax)\n\t"
  239.         "movq %%mm1, 8(%2, %%eax)\n\t"
  240.         "addl %3, %0        \n\t"
  241.         "addl %3, %1        \n\t"
  242.         "addl $16, %%eax    \n\t"
  243.         "jnz 1b            \n\t"
  244.         : "+r" (s1), "+r" (s2)
  245.         : "r" (block+64), "r" (stride)
  246.         : "%eax"
  247.     );
  248. }
  249.  
  250. static void put_pixels_clamped_mmx(const DCTELEM *block, UINT8 *pixels, int line_size)
  251. {
  252.     const DCTELEM *p;
  253.     UINT8 *pix;
  254.  
  255.     /* read the pixels */
  256.     p = block;
  257.     pix = pixels;
  258.     /* unrolled loop */
  259.     __asm __volatile(
  260.         "movq    %3, %%mm0\n\t"
  261.         "movq    8%3, %%mm1\n\t"
  262.         "movq    16%3, %%mm2\n\t"
  263.         "movq    24%3, %%mm3\n\t"
  264.         "movq    32%3, %%mm4\n\t"
  265.         "movq    40%3, %%mm5\n\t"
  266.         "movq    48%3, %%mm6\n\t"
  267.         "movq    56%3, %%mm7\n\t"
  268.         "packuswb %%mm1, %%mm0\n\t"
  269.         "packuswb %%mm3, %%mm2\n\t"
  270.         "packuswb %%mm5, %%mm4\n\t"
  271.         "packuswb %%mm7, %%mm6\n\t"
  272.         "movq    %%mm0, (%0)\n\t"
  273.         "movq    %%mm2, (%0, %1)\n\t"
  274.         "movq    %%mm4, (%0, %1, 2)\n\t"
  275.         "movq    %%mm6, (%0, %2)\n\t"
  276.         ::"r" (pix), "r" (line_size), "r" (line_size*3), "m"(*p)
  277.         :"memory");
  278.         pix += line_size*4;
  279.         p += 32;
  280.  
  281.     // if here would be an exact copy of the code above
  282.     // compiler would generate some very strange code
  283.     // thus using "r"
  284.     __asm __volatile(
  285.         "movq    (%3), %%mm0\n\t"
  286.         "movq    8(%3), %%mm1\n\t"
  287.         "movq    16(%3), %%mm2\n\t"
  288.         "movq    24(%3), %%mm3\n\t"
  289.         "movq    32(%3), %%mm4\n\t"
  290.         "movq    40(%3), %%mm5\n\t"
  291.         "movq    48(%3), %%mm6\n\t"
  292.         "movq    56(%3), %%mm7\n\t"
  293.         "packuswb %%mm1, %%mm0\n\t"
  294.         "packuswb %%mm3, %%mm2\n\t"
  295.         "packuswb %%mm5, %%mm4\n\t"
  296.         "packuswb %%mm7, %%mm6\n\t"
  297.         "movq    %%mm0, (%0)\n\t"
  298.         "movq    %%mm2, (%0, %1)\n\t"
  299.         "movq    %%mm4, (%0, %1, 2)\n\t"
  300.         "movq    %%mm6, (%0, %2)\n\t"
  301.         ::"r" (pix), "r" (line_size), "r" (line_size*3), "r"(p)
  302.         :"memory");
  303. }
  304.  
  305. static void add_pixels_clamped_mmx(const DCTELEM *block, UINT8 *pixels, int line_size)
  306. {
  307.     const DCTELEM *p;
  308.     UINT8 *pix;
  309.     int i;
  310.  
  311.     /* read the pixels */
  312.     p = block;
  313.     pix = pixels;
  314.     MOVQ_ZERO(mm7);
  315.     i = 4;
  316.     do {
  317.     __asm __volatile(
  318.         "movq    (%2), %%mm0\n\t"
  319.         "movq    8(%2), %%mm1\n\t"
  320.         "movq    16(%2), %%mm2\n\t"
  321.         "movq    24(%2), %%mm3\n\t"
  322.         "movq    %0, %%mm4\n\t"
  323.         "movq    %1, %%mm6\n\t"
  324.         "movq    %%mm4, %%mm5\n\t"
  325.         "punpcklbw %%mm7, %%mm4\n\t"
  326.         "punpckhbw %%mm7, %%mm5\n\t"
  327.         "paddsw    %%mm4, %%mm0\n\t"
  328.         "paddsw    %%mm5, %%mm1\n\t"
  329.         "movq    %%mm6, %%mm5\n\t"
  330.         "punpcklbw %%mm7, %%mm6\n\t"
  331.         "punpckhbw %%mm7, %%mm5\n\t"
  332.         "paddsw    %%mm6, %%mm2\n\t"
  333.         "paddsw    %%mm5, %%mm3\n\t"
  334.         "packuswb %%mm1, %%mm0\n\t"
  335.         "packuswb %%mm3, %%mm2\n\t"
  336.         "movq    %%mm0, %0\n\t"
  337.         "movq    %%mm2, %1\n\t"
  338.         :"+m"(*pix), "+m"(*(pix+line_size))
  339.         :"r"(p)
  340.         :"memory");
  341.         pix += line_size*2;
  342.         p += 16;
  343.     } while (--i);
  344. }
  345.  
  346. static void put_pixels_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int h)
  347. {
  348.     __asm __volatile(
  349.      "lea (%3, %3), %%eax        \n\t"
  350.      ".balign 8            \n\t"
  351.      "1:                \n\t"
  352.      "movq (%1), %%mm0        \n\t"
  353.      "movq (%1, %3), %%mm1        \n\t"
  354.           "movq %%mm0, (%2)        \n\t"
  355.      "movq %%mm1, (%2, %3)        \n\t"
  356.      "addl %%eax, %1        \n\t"
  357.          "addl %%eax, %2               \n\t"
  358.      "movq (%1), %%mm0        \n\t"
  359.      "movq (%1, %3), %%mm1        \n\t"
  360.      "movq %%mm0, (%2)        \n\t"
  361.      "movq %%mm1, (%2, %3)        \n\t"
  362.      "addl %%eax, %1        \n\t"
  363.      "addl %%eax, %2               \n\t"
  364.      "subl $4, %0            \n\t"
  365.      "jnz 1b            \n\t"
  366.      : "+g"(h), "+r" (pixels),  "+r" (block)
  367.      : "r"(line_size)
  368.      : "%eax", "memory"
  369.     );
  370. }
  371.  
  372. static void clear_blocks_mmx(DCTELEM *blocks)
  373. {
  374.     __asm __volatile(
  375.                 "pxor %%mm7, %%mm7        \n\t"
  376.                 "movl $-128*6, %%eax        \n\t"
  377.                 "1:                \n\t"
  378.                 "movq %%mm7, (%0, %%eax)    \n\t"
  379.                 "movq %%mm7, 8(%0, %%eax)    \n\t"
  380.                 "movq %%mm7, 16(%0, %%eax)    \n\t"
  381.                 "movq %%mm7, 24(%0, %%eax)    \n\t"
  382.                 "addl $32, %%eax        \n\t"
  383.                 " js 1b                \n\t"
  384.                 : : "r" (((int)blocks)+128*6)
  385.                 : "%eax"
  386.         );
  387. }
  388.  
  389. #if 0
  390. static void just_return() { return; }
  391. #endif
  392.  
  393. #ifndef OS2
  394. void dsputil_init_mmx(void)
  395. #else
  396. void optlink dsputil_init_mmx(void)
  397. #endif
  398. {
  399.     mm_flags = mm_support();
  400. #if 0
  401.     printf("libavcodec: CPU flags:");
  402.     if (mm_flags & MM_MMX)
  403.         printf(" mmx");
  404.     if (mm_flags & MM_MMXEXT)
  405.         printf(" mmxext");
  406.     if (mm_flags & MM_3DNOW)
  407.         printf(" 3dnow");
  408.     if (mm_flags & MM_SSE)
  409.         printf(" sse");
  410.     if (mm_flags & MM_SSE2)
  411.         printf(" sse2");
  412.     printf("\n");
  413. #endif
  414.  
  415.     if (mm_flags & MM_MMX) {
  416.         get_pixels = get_pixels_mmx;
  417.         diff_pixels = diff_pixels_mmx;
  418.         put_pixels_clamped = put_pixels_clamped_mmx;
  419.         add_pixels_clamped = add_pixels_clamped_mmx;
  420.         clear_blocks= clear_blocks_mmx;
  421.  
  422.         pix_abs16x16     = pix_abs16x16_mmx;
  423.         pix_abs16x16_x2  = pix_abs16x16_x2_mmx;
  424.         pix_abs16x16_y2  = pix_abs16x16_y2_mmx;
  425.         pix_abs16x16_xy2 = pix_abs16x16_xy2_mmx;
  426.         pix_abs8x8    = pix_abs8x8_mmx;
  427.         pix_abs8x8_x2 = pix_abs8x8_x2_mmx;
  428.         pix_abs8x8_y2 = pix_abs8x8_y2_mmx;
  429.         pix_abs8x8_xy2= pix_abs8x8_xy2_mmx;
  430.         av_fdct = fdct_mmx;
  431.  
  432.         put_pixels_tab[0] = put_pixels_mmx;
  433.         put_pixels_tab[1] = put_pixels_x2_mmx;
  434.         put_pixels_tab[2] = put_pixels_y2_mmx;
  435.         put_pixels_tab[3] = put_pixels_xy2_mmx;
  436.  
  437.         put_no_rnd_pixels_tab[0] = put_pixels_mmx;
  438.         put_no_rnd_pixels_tab[1] = put_no_rnd_pixels_x2_mmx;
  439.         put_no_rnd_pixels_tab[2] = put_no_rnd_pixels_y2_mmx;
  440.         put_no_rnd_pixels_tab[3] = put_no_rnd_pixels_xy2_mmx;
  441.  
  442.         avg_pixels_tab[0] = avg_pixels_mmx;
  443.         avg_pixels_tab[1] = avg_pixels_x2_mmx;
  444.         avg_pixels_tab[2] = avg_pixels_y2_mmx;
  445.         avg_pixels_tab[3] = avg_pixels_xy2_mmx;
  446.  
  447.         avg_no_rnd_pixels_tab[0] = avg_no_rnd_pixels_mmx;
  448.         avg_no_rnd_pixels_tab[1] = avg_no_rnd_pixels_x2_mmx;
  449.         avg_no_rnd_pixels_tab[2] = avg_no_rnd_pixels_y2_mmx;
  450.         avg_no_rnd_pixels_tab[3] = avg_no_rnd_pixels_xy2_mmx;
  451.  
  452.         if (mm_flags & MM_MMXEXT) {
  453.             pix_abs16x16    = pix_abs16x16_mmx2;
  454.             pix_abs16x16_x2 = pix_abs16x16_x2_mmx2;
  455.             pix_abs16x16_y2 = pix_abs16x16_y2_mmx2;
  456.             pix_abs16x16_xy2= pix_abs16x16_xy2_mmx2;
  457.  
  458.             pix_abs8x8    = pix_abs8x8_mmx2;
  459.             pix_abs8x8_x2 = pix_abs8x8_x2_mmx2;
  460.             pix_abs8x8_y2 = pix_abs8x8_y2_mmx2;
  461.             pix_abs8x8_xy2= pix_abs8x8_xy2_mmx2;
  462.  
  463.             put_pixels_tab[1] = put_pixels_x2_mmx2;
  464.             put_pixels_tab[2] = put_pixels_y2_mmx2;
  465.             put_no_rnd_pixels_tab[1] = put_no_rnd_pixels_x2_mmx2;
  466.             put_no_rnd_pixels_tab[2] = put_no_rnd_pixels_y2_mmx2;
  467.  
  468.             avg_pixels_tab[0] = avg_pixels_mmx2;
  469.             avg_pixels_tab[1] = avg_pixels_x2_mmx2;
  470.             avg_pixels_tab[2] = avg_pixels_y2_mmx2;
  471.             avg_pixels_tab[3] = avg_pixels_xy2_mmx2;
  472.         } else if (mm_flags & MM_3DNOW) {
  473.             put_pixels_tab[1] = put_pixels_x2_3dnow;
  474.             put_pixels_tab[2] = put_pixels_y2_3dnow;
  475.             put_no_rnd_pixels_tab[1] = put_no_rnd_pixels_x2_3dnow;
  476.             put_no_rnd_pixels_tab[2] = put_no_rnd_pixels_y2_3dnow;
  477.  
  478.             avg_pixels_tab[0] = avg_pixels_3dnow;
  479.             avg_pixels_tab[1] = avg_pixels_x2_3dnow;
  480.             avg_pixels_tab[2] = avg_pixels_y2_3dnow;
  481.             avg_pixels_tab[3] = avg_pixels_xy2_3dnow;
  482.         }
  483.  
  484.         /* idct */
  485.         if (mm_flags & MM_MMXEXT) {
  486.             ff_idct = ff_mmxext_idct;
  487.         } else {
  488.             ff_idct = ff_mmx_idct;
  489.         }
  490. #ifdef SIMPLE_IDCT
  491. //    ff_idct = simple_idct;
  492.     ff_idct = simple_idct_mmx;
  493. #endif
  494.     }
  495.  
  496. #if 0
  497.     // for speed testing
  498.     get_pixels = just_return;
  499.     put_pixels_clamped = just_return;
  500.     add_pixels_clamped = just_return;
  501.  
  502.     pix_abs16x16 = just_return;
  503.     pix_abs16x16_x2 = just_return;
  504.     pix_abs16x16_y2 = just_return;
  505.     pix_abs16x16_xy2 = just_return;
  506.  
  507.     put_pixels_tab[0] = just_return;
  508.     put_pixels_tab[1] = just_return;
  509.     put_pixels_tab[2] = just_return;
  510.     put_pixels_tab[3] = just_return;
  511.  
  512.     put_no_rnd_pixels_tab[0] = just_return;
  513.     put_no_rnd_pixels_tab[1] = just_return;
  514.     put_no_rnd_pixels_tab[2] = just_return;
  515.     put_no_rnd_pixels_tab[3] = just_return;
  516.  
  517.     avg_pixels_tab[0] = just_return;
  518.     avg_pixels_tab[1] = just_return;
  519.     avg_pixels_tab[2] = just_return;
  520.     avg_pixels_tab[3] = just_return;
  521.  
  522.     avg_no_rnd_pixels_tab[0] = just_return;
  523.     avg_no_rnd_pixels_tab[1] = just_return;
  524.     avg_no_rnd_pixels_tab[2] = just_return;
  525.     avg_no_rnd_pixels_tab[3] = just_return;
  526.  
  527.     //av_fdct = just_return;
  528.     //ff_idct = just_return;
  529. #endif
  530. }
  531.  
  532. /* remove any non bit exact operation (testing purpose). NOTE that
  533.    this function should be kept as small as possible because it is
  534.    always difficult to test automatically non bit exact cases. */
  535. void dsputil_set_bit_exact_mmx(void)
  536. {
  537.     if (mm_flags & MM_MMX) {
  538.         if (mm_flags & MM_MMXEXT) {
  539.             put_no_rnd_pixels_tab[1] = put_no_rnd_pixels_x2_mmx;
  540.             put_no_rnd_pixels_tab[2] = put_no_rnd_pixels_y2_mmx;
  541.             avg_pixels_tab[3] = avg_pixels_xy2_mmx;
  542.         } else if (mm_flags & MM_3DNOW) {
  543.             put_no_rnd_pixels_tab[1] = put_no_rnd_pixels_x2_mmx;
  544.             put_no_rnd_pixels_tab[2] = put_no_rnd_pixels_y2_mmx;
  545.             avg_pixels_tab[3] = avg_pixels_xy2_mmx;
  546.         }
  547.     }
  548. }
  549.