dsputil_mmx.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:102k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*
  2.  * MMX optimized DSP utils
  3.  * Copyright (c) 2000, 2001 Fabrice Bellard.
  4.  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Lesser General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with this library; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  *
  20.  * MMX optimization by Nick Kurshev <nickols_k@mail.ru>
  21.  */
  22. #include "../dsputil.h"
  23. #include "../simple_idct.h"
  24. #include "../mpegvideo.h"
  25. #include "mmx.h"
  26. //#undef NDEBUG
  27. //#include <assert.h>
  28. extern const uint8_t ff_h263_loop_filter_strength[32];
  29. extern void ff_idct_xvid_mmx(short *block);
  30. extern void ff_idct_xvid_mmx2(short *block);
  31. int mm_flags; /* multimedia extension flags */
  32. /* pixel operations */
  33. static const uint64_t mm_bone attribute_used __attribute__ ((aligned(8))) = 0x0101010101010101ULL;
  34. static const uint64_t mm_wone attribute_used __attribute__ ((aligned(8))) = 0x0001000100010001ULL;
  35. static const uint64_t mm_wtwo attribute_used __attribute__ ((aligned(8))) = 0x0002000200020002ULL;
  36. static const uint64_t ff_pw_20 attribute_used __attribute__ ((aligned(8))) = 0x0014001400140014ULL;
  37. static const uint64_t ff_pw_3  attribute_used __attribute__ ((aligned(8))) = 0x0003000300030003ULL;
  38. static const uint64_t ff_pw_4  attribute_used __attribute__ ((aligned(8))) = 0x0004000400040004ULL;
  39. static const uint64_t ff_pw_5  attribute_used __attribute__ ((aligned(8))) = 0x0005000500050005ULL;
  40. static const uint64_t ff_pw_16 attribute_used __attribute__ ((aligned(8))) = 0x0010001000100010ULL;
  41. static const uint64_t ff_pw_32 attribute_used __attribute__ ((aligned(8))) = 0x0020002000200020ULL;
  42. static const uint64_t ff_pw_64 attribute_used __attribute__ ((aligned(8))) = 0x0040004000400040ULL;
  43. static const uint64_t ff_pw_15 attribute_used __attribute__ ((aligned(8))) = 0x000F000F000F000FULL;
  44. static const uint64_t ff_pb_3F attribute_used __attribute__ ((aligned(8))) = 0x3F3F3F3F3F3F3F3FULL;
  45. static const uint64_t ff_pb_FC attribute_used __attribute__ ((aligned(8))) = 0xFCFCFCFCFCFCFCFCULL;
  46. #define JUMPALIGN() __asm __volatile (".balign 8"::)
  47. #define MOVQ_ZERO(regd)  __asm __volatile ("pxor %%" #regd ", %%" #regd ::)
  48. #define MOVQ_WONE(regd) 
  49.     __asm __volatile ( 
  50.     "pcmpeqd %%" #regd ", %%" #regd " nt" 
  51.     "psrlw $15, %%" #regd ::)
  52. #define MOVQ_BFE(regd) 
  53.     __asm __volatile ( 
  54.     "pcmpeqd %%" #regd ", %%" #regd " nt"
  55.     "paddb %%" #regd ", %%" #regd " nt" ::)
  56. #ifndef PIC
  57. #define MOVQ_BONE(regd)  __asm __volatile ("movq %0, %%" #regd " nt" ::"m"(mm_bone))
  58. #define MOVQ_WTWO(regd)  __asm __volatile ("movq %0, %%" #regd " nt" ::"m"(mm_wtwo))
  59. #else
  60. // for shared library it's better to use this way for accessing constants
  61. // pcmpeqd -> -1
  62. #define MOVQ_BONE(regd) 
  63.     __asm __volatile ( 
  64.     "pcmpeqd %%" #regd ", %%" #regd " nt" 
  65.     "psrlw $15, %%" #regd " nt" 
  66.     "packuswb %%" #regd ", %%" #regd " nt" ::)
  67. #define MOVQ_WTWO(regd) 
  68.     __asm __volatile ( 
  69.     "pcmpeqd %%" #regd ", %%" #regd " nt" 
  70.     "psrlw $15, %%" #regd " nt" 
  71.     "psllw $1, %%" #regd " nt"::)
  72. #endif
  73. // using regr as temporary and for the output result
  74. // first argument is unmodifed and second is trashed
  75. // regfe is supposed to contain 0xfefefefefefefefe
  76. #define PAVGB_MMX_NO_RND(rega, regb, regr, regfe) 
  77.     "movq " #rega ", " #regr " nt"
  78.     "pand " #regb ", " #regr " nt"
  79.     "pxor " #rega ", " #regb " nt"
  80.     "pand " #regfe "," #regb " nt"
  81.     "psrlq $1, " #regb "  nt"
  82.     "paddb " #regb ", " #regr " nt"
  83. #define PAVGB_MMX(rega, regb, regr, regfe) 
  84.     "movq " #rega ", " #regr " nt"
  85.     "por  " #regb ", " #regr " nt"
  86.     "pxor " #rega ", " #regb " nt"
  87.     "pand " #regfe "," #regb " nt"
  88.     "psrlq $1, " #regb " nt"
  89.     "psubb " #regb ", " #regr " nt"
  90. // mm6 is supposed to contain 0xfefefefefefefefe
  91. #define PAVGBP_MMX_NO_RND(rega, regb, regr,  regc, regd, regp) 
  92.     "movq " #rega ", " #regr " nt"
  93.     "movq " #regc ", " #regp " nt"
  94.     "pand " #regb ", " #regr " nt"
  95.     "pand " #regd ", " #regp " nt"
  96.     "pxor " #rega ", " #regb " nt"
  97.     "pxor " #regc ", " #regd " nt"
  98.     "pand %%mm6, " #regb " nt"
  99.     "pand %%mm6, " #regd " nt"
  100.     "psrlq $1, " #regb "  nt"
  101.     "psrlq $1, " #regd "  nt"
  102.     "paddb " #regb ", " #regr " nt"
  103.     "paddb " #regd ", " #regp " nt"
  104. #define PAVGBP_MMX(rega, regb, regr, regc, regd, regp) 
  105.     "movq " #rega ", " #regr " nt"
  106.     "movq " #regc ", " #regp " nt"
  107.     "por  " #regb ", " #regr " nt"
  108.     "por  " #regd ", " #regp " nt"
  109.     "pxor " #rega ", " #regb " nt"
  110.     "pxor " #regc ", " #regd " nt"
  111.     "pand %%mm6, " #regb "      nt"
  112.     "pand %%mm6, " #regd "      nt"
  113.     "psrlq $1, " #regd " nt"
  114.     "psrlq $1, " #regb " nt"
  115.     "psubb " #regb ", " #regr " nt"
  116.     "psubb " #regd ", " #regp " nt"
  117. /***********************************/
  118. /* MMX no rounding */
  119. #define DEF(x, y) x ## _no_rnd_ ## y ##_mmx
  120. #define SET_RND  MOVQ_WONE
  121. #define PAVGBP(a, b, c, d, e, f) PAVGBP_MMX_NO_RND(a, b, c, d, e, f)
  122. #define PAVGB(a, b, c, e) PAVGB_MMX_NO_RND(a, b, c, e)
  123. #include "dsputil_mmx_rnd.h"
  124. #undef DEF
  125. #undef SET_RND
  126. #undef PAVGBP
  127. #undef PAVGB
  128. /***********************************/
  129. /* MMX rounding */
  130. #define DEF(x, y) x ## _ ## y ##_mmx
  131. #define SET_RND  MOVQ_WTWO
  132. #define PAVGBP(a, b, c, d, e, f) PAVGBP_MMX(a, b, c, d, e, f)
  133. #define PAVGB(a, b, c, e) PAVGB_MMX(a, b, c, e)
  134. #include "dsputil_mmx_rnd.h"
  135. #undef DEF
  136. #undef SET_RND
  137. #undef PAVGBP
  138. #undef PAVGB
  139. /***********************************/
  140. /* 3Dnow specific */
  141. #define DEF(x) x ## _3dnow
  142. /* for Athlons PAVGUSB is prefered */
  143. #define PAVGB "pavgusb"
  144. #include "dsputil_mmx_avg.h"
  145. #undef DEF
  146. #undef PAVGB
  147. /***********************************/
  148. /* MMX2 specific */
  149. #define DEF(x) x ## _mmx2
  150. /* Introduced only in MMX2 set */
  151. #define PAVGB "pavgb"
  152. #include "dsputil_mmx_avg.h"
  153. #undef DEF
  154. #undef PAVGB
  155. /***********************************/
  156. /* standard MMX */
  157. #ifdef CONFIG_ENCODERS
  158. static void get_pixels_mmx(DCTELEM *block, const uint8_t *pixels, int line_size)
  159. {
  160.     asm volatile(
  161.         "mov $-128, %%"REG_a" nt"
  162.         "pxor %%mm7, %%mm7 nt"
  163.         ".balign 16 nt"
  164.         "1: nt"
  165.         "movq (%0), %%mm0 nt"
  166.         "movq (%0, %2), %%mm2 nt"
  167.         "movq %%mm0, %%mm1 nt"
  168.         "movq %%mm2, %%mm3 nt"
  169.         "punpcklbw %%mm7, %%mm0 nt"
  170.         "punpckhbw %%mm7, %%mm1 nt"
  171.         "punpcklbw %%mm7, %%mm2 nt"
  172.         "punpckhbw %%mm7, %%mm3 nt"
  173.         "movq %%mm0, (%1, %%"REG_a")nt"
  174.         "movq %%mm1, 8(%1, %%"REG_a")nt"
  175.         "movq %%mm2, 16(%1, %%"REG_a")nt"
  176.         "movq %%mm3, 24(%1, %%"REG_a")nt"
  177.         "add %3, %0 nt"
  178.         "add $32, %%"REG_a" nt"
  179.         "js 1b nt"
  180.         : "+r" (pixels)
  181.         : "r" (block+64), "r" ((long)line_size), "r" ((long)line_size*2)
  182.         : "%"REG_a
  183.     );
  184. }
  185. static inline void diff_pixels_mmx(DCTELEM *block, const uint8_t *s1, const uint8_t *s2, int stride)
  186. {
  187.     asm volatile(
  188.         "pxor %%mm7, %%mm7 nt"
  189.         "mov $-128, %%"REG_a" nt"
  190.         ".balign 16 nt"
  191.         "1: nt"
  192.         "movq (%0), %%mm0 nt"
  193.         "movq (%1), %%mm2 nt"
  194.         "movq %%mm0, %%mm1 nt"
  195.         "movq %%mm2, %%mm3 nt"
  196.         "punpcklbw %%mm7, %%mm0 nt"
  197.         "punpckhbw %%mm7, %%mm1 nt"
  198.         "punpcklbw %%mm7, %%mm2 nt"
  199.         "punpckhbw %%mm7, %%mm3 nt"
  200.         "psubw %%mm2, %%mm0 nt"
  201.         "psubw %%mm3, %%mm1 nt"
  202.         "movq %%mm0, (%2, %%"REG_a")nt"
  203.         "movq %%mm1, 8(%2, %%"REG_a")nt"
  204.         "add %3, %0 nt"
  205.         "add %3, %1 nt"
  206.         "add $16, %%"REG_a" nt"
  207.         "jnz 1b nt"
  208.         : "+r" (s1), "+r" (s2)
  209.         : "r" (block+64), "r" ((long)stride)
  210.         : "%"REG_a
  211.     );
  212. }
  213. #endif //CONFIG_ENCODERS
  214. void put_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size)
  215. {
  216.     const DCTELEM *p;
  217.     uint8_t *pix;
  218.     /* read the pixels */
  219.     p = block;
  220.     pix = pixels;
  221.     /* unrolled loop */
  222. __asm __volatile(
  223. "movq %3, %%mm0nt"
  224. "movq 8%3, %%mm1nt"
  225. "movq 16%3, %%mm2nt"
  226. "movq 24%3, %%mm3nt"
  227. "movq 32%3, %%mm4nt"
  228. "movq 40%3, %%mm5nt"
  229. "movq 48%3, %%mm6nt"
  230. "movq 56%3, %%mm7nt"
  231. "packuswb %%mm1, %%mm0nt"
  232. "packuswb %%mm3, %%mm2nt"
  233. "packuswb %%mm5, %%mm4nt"
  234. "packuswb %%mm7, %%mm6nt"
  235. "movq %%mm0, (%0)nt"
  236. "movq %%mm2, (%0, %1)nt"
  237. "movq %%mm4, (%0, %1, 2)nt"
  238. "movq %%mm6, (%0, %2)nt"
  239. ::"r" (pix), "r" ((long)line_size), "r" ((long)line_size*3), "m"(*p)
  240. :"memory");
  241.         pix += line_size*4;
  242.         p += 32;
  243.     // if here would be an exact copy of the code above
  244.     // compiler would generate some very strange code
  245.     // thus using "r"
  246.     __asm __volatile(
  247.     "movq (%3), %%mm0nt"
  248.     "movq 8(%3), %%mm1nt"
  249.     "movq 16(%3), %%mm2nt"
  250.     "movq 24(%3), %%mm3nt"
  251.     "movq 32(%3), %%mm4nt"
  252.     "movq 40(%3), %%mm5nt"
  253.     "movq 48(%3), %%mm6nt"
  254.     "movq 56(%3), %%mm7nt"
  255.     "packuswb %%mm1, %%mm0nt"
  256.     "packuswb %%mm3, %%mm2nt"
  257.     "packuswb %%mm5, %%mm4nt"
  258.     "packuswb %%mm7, %%mm6nt"
  259.     "movq %%mm0, (%0)nt"
  260.     "movq %%mm2, (%0, %1)nt"
  261.     "movq %%mm4, (%0, %1, 2)nt"
  262.     "movq %%mm6, (%0, %2)nt"
  263.     ::"r" (pix), "r" ((long)line_size), "r" ((long)line_size*3), "r"(p)
  264.     :"memory");
  265. }
  266. static const unsigned char __align8 vector128[8] =
  267.   { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
  268. void put_signed_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size)
  269. {
  270.     int i;
  271.     movq_m2r(*vector128, mm1);
  272.     for (i = 0; i < 8; i++) {
  273.         movq_m2r(*(block), mm0);
  274.         packsswb_m2r(*(block + 4), mm0);
  275.         block += 8;
  276.         paddb_r2r(mm1, mm0);
  277.         movq_r2m(mm0, *pixels);
  278.         pixels += line_size;
  279.     }
  280. }
  281. void add_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size)
  282. {
  283.     const DCTELEM *p;
  284.     uint8_t *pix;
  285.     int i;
  286.     /* read the pixels */
  287.     p = block;
  288.     pix = pixels;
  289.     MOVQ_ZERO(mm7);
  290.     i = 4;
  291.     do {
  292. __asm __volatile(
  293. "movq (%2), %%mm0nt"
  294. "movq 8(%2), %%mm1nt"
  295. "movq 16(%2), %%mm2nt"
  296. "movq 24(%2), %%mm3nt"
  297. "movq %0, %%mm4nt"
  298. "movq %1, %%mm6nt"
  299. "movq %%mm4, %%mm5nt"
  300. "punpcklbw %%mm7, %%mm4nt"
  301. "punpckhbw %%mm7, %%mm5nt"
  302. "paddsw %%mm4, %%mm0nt"
  303. "paddsw %%mm5, %%mm1nt"
  304. "movq %%mm6, %%mm5nt"
  305. "punpcklbw %%mm7, %%mm6nt"
  306. "punpckhbw %%mm7, %%mm5nt"
  307. "paddsw %%mm6, %%mm2nt"
  308. "paddsw %%mm5, %%mm3nt"
  309. "packuswb %%mm1, %%mm0nt"
  310. "packuswb %%mm3, %%mm2nt"
  311. "movq %%mm0, %0nt"
  312. "movq %%mm2, %1nt"
  313. :"+m"(*pix), "+m"(*(pix+line_size))
  314. :"r"(p)
  315. :"memory");
  316.         pix += line_size*2;
  317.         p += 16;
  318.     } while (--i);
  319. }
  320. static void put_pixels4_mmx(uint8_t *block, const uint8_t *pixels, int line_size, int h)
  321. {
  322.     __asm __volatile(
  323.  "lea (%3, %3), %%"REG_a" nt"
  324.  ".balign 8 nt"
  325.  "1: nt"
  326.  "movd (%1), %%mm0 nt"
  327.  "movd (%1, %3), %%mm1 nt"
  328.  "movd %%mm0, (%2) nt"
  329.  "movd %%mm1, (%2, %3) nt"
  330.  "add %%"REG_a", %1 nt"
  331.  "add %%"REG_a", %2 nt"
  332.  "movd (%1), %%mm0 nt"
  333.  "movd (%1, %3), %%mm1 nt"
  334.  "movd %%mm0, (%2) nt"
  335.  "movd %%mm1, (%2, %3) nt"
  336.  "add %%"REG_a", %1 nt"
  337.  "add %%"REG_a", %2 nt"
  338.  "subl $4, %0 nt"
  339.  "jnz 1b nt"
  340.  : "+g"(h), "+r" (pixels),  "+r" (block)
  341.  : "r"((long)line_size)
  342.  : "%"REG_a, "memory"
  343. );
  344. }
  345. static void put_pixels8_mmx(uint8_t *block, const uint8_t *pixels, int line_size, int h)
  346. {
  347.     __asm __volatile(
  348.  "lea (%3, %3), %%"REG_a" nt"
  349.  ".balign 8 nt"
  350.  "1: nt"
  351.  "movq (%1), %%mm0 nt"
  352.  "movq (%1, %3), %%mm1 nt"
  353.        "movq %%mm0, (%2) nt"
  354.  "movq %%mm1, (%2, %3) nt"
  355.  "add %%"REG_a", %1 nt"
  356.  "add %%"REG_a", %2 nt"
  357.  "movq (%1), %%mm0 nt"
  358.  "movq (%1, %3), %%mm1 nt"
  359.  "movq %%mm0, (%2) nt"
  360.  "movq %%mm1, (%2, %3) nt"
  361.  "add %%"REG_a", %1 nt"
  362.  "add %%"REG_a", %2 nt"
  363.  "subl $4, %0 nt"
  364.  "jnz 1b nt"
  365.  : "+g"(h), "+r" (pixels),  "+r" (block)
  366.  : "r"((long)line_size)
  367.  : "%"REG_a, "memory"
  368. );
  369. }
  370. static void put_pixels16_mmx(uint8_t *block, const uint8_t *pixels, int line_size, int h)
  371. {
  372.     __asm __volatile(
  373.  "lea (%3, %3), %%"REG_a" nt"
  374.  ".balign 8 nt"
  375.  "1: nt"
  376.  "movq (%1), %%mm0 nt"
  377.  "movq 8(%1), %%mm4 nt"
  378.  "movq (%1, %3), %%mm1 nt"
  379.  "movq 8(%1, %3), %%mm5 nt"
  380.        "movq %%mm0, (%2) nt"
  381.        "movq %%mm4, 8(%2) nt"
  382.  "movq %%mm1, (%2, %3) nt"
  383.  "movq %%mm5, 8(%2, %3) nt"
  384.  "add %%"REG_a", %1 nt"
  385.  "add %%"REG_a", %2        nt"
  386.  "movq (%1), %%mm0 nt"
  387.  "movq 8(%1), %%mm4 nt"
  388.  "movq (%1, %3), %%mm1 nt"
  389.  "movq 8(%1, %3), %%mm5 nt"
  390.  "movq %%mm0, (%2) nt"
  391.  "movq %%mm4, 8(%2) nt"
  392.  "movq %%mm1, (%2, %3) nt"
  393.  "movq %%mm5, 8(%2, %3) nt"
  394.  "add %%"REG_a", %1 nt"
  395.  "add %%"REG_a", %2        nt"
  396.  "subl $4, %0 nt"
  397.  "jnz 1b nt"
  398.  : "+g"(h), "+r" (pixels),  "+r" (block)
  399.  : "r"((long)line_size)
  400.  : "%"REG_a, "memory"
  401. );
  402. }
  403. static void clear_blocks_mmx(DCTELEM *blocks)
  404. {
  405.     __asm __volatile(
  406.                 "pxor %%mm7, %%mm7 nt"
  407.                 "mov $-128*6, %%"REG_a" nt"
  408.                 "1: nt"
  409.                 "movq %%mm7, (%0, %%"REG_a") nt"
  410.                 "movq %%mm7, 8(%0, %%"REG_a") nt"
  411.                 "movq %%mm7, 16(%0, %%"REG_a") nt"
  412.                 "movq %%mm7, 24(%0, %%"REG_a") nt"
  413.                 "add $32, %%"REG_a" nt"
  414.                 " js 1b nt"
  415.                 : : "r" (((uint8_t *)blocks)+128*6)
  416.                 : "%"REG_a
  417.         );
  418. }
  419. #ifdef CONFIG_ENCODERS
  420. static int pix_sum16_mmx(uint8_t * pix, int line_size){
  421.     const int h=16;
  422.     int sum;
  423.     long index= -line_size*h;
  424.     __asm __volatile(
  425.                 "pxor %%mm7, %%mm7 nt"
  426.                 "pxor %%mm6, %%mm6 nt"
  427.                 "1: nt"
  428.                 "movq (%2, %1), %%mm0 nt"
  429.                 "movq (%2, %1), %%mm1 nt"
  430.                 "movq 8(%2, %1), %%mm2 nt"
  431.                 "movq 8(%2, %1), %%mm3 nt"
  432.                 "punpcklbw %%mm7, %%mm0 nt"
  433.                 "punpckhbw %%mm7, %%mm1 nt"
  434.                 "punpcklbw %%mm7, %%mm2 nt"
  435.                 "punpckhbw %%mm7, %%mm3 nt"
  436.                 "paddw %%mm0, %%mm1 nt"
  437.                 "paddw %%mm2, %%mm3 nt"
  438.                 "paddw %%mm1, %%mm3 nt"
  439.                 "paddw %%mm3, %%mm6 nt"
  440.                 "add %3, %1 nt"
  441.                 " js 1b nt"
  442.                 "movq %%mm6, %%mm5 nt"
  443.                 "psrlq $32, %%mm6 nt"
  444.                 "paddw %%mm5, %%mm6 nt"
  445.                 "movq %%mm6, %%mm5 nt"
  446.                 "psrlq $16, %%mm6 nt"
  447.                 "paddw %%mm5, %%mm6 nt"
  448.                 "movd %%mm6, %0 nt"
  449.                 "andl $0xFFFF, %0 nt"
  450.                 : "=&r" (sum), "+r" (index)
  451.                 : "r" (pix - index), "r" ((long)line_size)
  452.         );
  453.         return sum;
  454. }
  455. #endif //CONFIG_ENCODERS
  456. static void add_bytes_mmx(uint8_t *dst, uint8_t *src, int w){
  457.     long i=0;
  458.     asm volatile(
  459.         "1: nt"
  460.         "movq  (%1, %0), %%mm0 nt"
  461.         "movq  (%2, %0), %%mm1 nt"
  462.         "paddb %%mm0, %%mm1 nt"
  463.         "movq %%mm1, (%2, %0) nt"
  464.         "movq 8(%1, %0), %%mm0 nt"
  465.         "movq 8(%2, %0), %%mm1 nt"
  466.         "paddb %%mm0, %%mm1 nt"
  467.         "movq %%mm1, 8(%2, %0) nt"
  468.         "add $16, %0 nt"
  469.         "cmp %3, %0 nt"
  470.         " jb 1b nt"
  471.         : "+r" (i)
  472.         : "r"(src), "r"(dst), "r"((long)w-15)
  473.     );
  474.     for(; i<w; i++)
  475.         dst[i+0] += src[i+0];
  476. }
  477. #define H263_LOOP_FILTER 
  478.         "pxor %%mm7, %%mm7 nt"
  479.         "movq  %0, %%mm0 nt"
  480.         "movq  %0, %%mm1 nt"
  481.         "movq  %3, %%mm2 nt"
  482.         "movq  %3, %%mm3 nt"
  483.         "punpcklbw %%mm7, %%mm0 nt"
  484.         "punpckhbw %%mm7, %%mm1 nt"
  485.         "punpcklbw %%mm7, %%mm2 nt"
  486.         "punpckhbw %%mm7, %%mm3 nt"
  487.         "psubw %%mm2, %%mm0 nt"
  488.         "psubw %%mm3, %%mm1 nt"
  489.         "movq  %1, %%mm2 nt"
  490.         "movq  %1, %%mm3 nt"
  491.         "movq  %2, %%mm4 nt"
  492.         "movq  %2, %%mm5 nt"
  493.         "punpcklbw %%mm7, %%mm2 nt"
  494.         "punpckhbw %%mm7, %%mm3 nt"
  495.         "punpcklbw %%mm7, %%mm4 nt"
  496.         "punpckhbw %%mm7, %%mm5 nt"
  497.         "psubw %%mm2, %%mm4 nt"
  498.         "psubw %%mm3, %%mm5 nt"
  499.         "psllw $2, %%mm4 nt"
  500.         "psllw $2, %%mm5 nt"
  501.         "paddw %%mm0, %%mm4 nt"
  502.         "paddw %%mm1, %%mm5 nt"
  503.         "pxor %%mm6, %%mm6 nt"
  504.         "pcmpgtw %%mm4, %%mm6 nt"
  505.         "pcmpgtw %%mm5, %%mm7 nt"
  506.         "pxor %%mm6, %%mm4 nt"
  507.         "pxor %%mm7, %%mm5 nt"
  508.         "psubw %%mm6, %%mm4 nt"
  509.         "psubw %%mm7, %%mm5 nt"
  510.         "psrlw $3, %%mm4 nt"
  511.         "psrlw $3, %%mm5 nt"
  512.         "packuswb %%mm5, %%mm4 nt"
  513.         "packsswb %%mm7, %%mm6 nt"
  514.         "pxor %%mm7, %%mm7 nt"
  515.         "movd %4, %%mm2 nt"
  516.         "punpcklbw %%mm2, %%mm2 nt"
  517.         "punpcklbw %%mm2, %%mm2 nt"
  518.         "punpcklbw %%mm2, %%mm2 nt"
  519.         "psubusb %%mm4, %%mm2 nt"
  520.         "movq %%mm2, %%mm3 nt"
  521.         "psubusb %%mm4, %%mm3 nt"
  522.         "psubb %%mm3, %%mm2 nt"
  523.         "movq %1, %%mm3 nt"
  524.         "movq %2, %%mm4 nt"
  525.         "pxor %%mm6, %%mm3 nt"
  526.         "pxor %%mm6, %%mm4 nt"
  527.         "paddusb %%mm2, %%mm3 nt"
  528.         "psubusb %%mm2, %%mm4 nt"
  529.         "pxor %%mm6, %%mm3 nt"
  530.         "pxor %%mm6, %%mm4 nt"
  531.         "paddusb %%mm2, %%mm2 nt"
  532.         "packsswb %%mm1, %%mm0 nt"
  533.         "pcmpgtb %%mm0, %%mm7 nt"
  534.         "pxor %%mm7, %%mm0 nt"
  535.         "psubb %%mm7, %%mm0 nt"
  536.         "movq %%mm0, %%mm1 nt"
  537.         "psubusb %%mm2, %%mm0 nt"
  538.         "psubb %%mm0, %%mm1 nt"
  539.         "pand %5, %%mm1 nt"
  540.         "psrlw $2, %%mm1 nt"
  541.         "pxor %%mm7, %%mm1 nt"
  542.         "psubb %%mm7, %%mm1 nt"
  543.         "movq %0, %%mm5 nt"
  544.         "movq %3, %%mm6 nt"
  545.         "psubb %%mm1, %%mm5 nt"
  546.         "paddb %%mm1, %%mm6 nt"
  547. static void h263_v_loop_filter_mmx(uint8_t *src, int stride, int qscale){
  548.     const int strength= ff_h263_loop_filter_strength[qscale];
  549.     asm volatile(
  550.     
  551.         H263_LOOP_FILTER
  552.         
  553.         "movq %%mm3, %1 nt"
  554.         "movq %%mm4, %2 nt"
  555.         "movq %%mm5, %0 nt"
  556.         "movq %%mm6, %3 nt"
  557.         : "+m" (*(uint64_t*)(src - 2*stride)),
  558.           "+m" (*(uint64_t*)(src - 1*stride)),
  559.           "+m" (*(uint64_t*)(src + 0*stride)),
  560.           "+m" (*(uint64_t*)(src + 1*stride))
  561.         : "g" (2*strength), "m"(ff_pb_FC)
  562.     );
  563. }
  564. static inline void transpose4x4(uint8_t *dst, uint8_t *src, int dst_stride, int src_stride){
  565.     asm volatile( //FIXME could save 1 instruction if done as 8x4 ...
  566.         "movd  %4, %%mm0 nt"
  567.         "movd  %5, %%mm1 nt"
  568.         "movd  %6, %%mm2 nt"
  569.         "movd  %7, %%mm3 nt"
  570.         "punpcklbw %%mm1, %%mm0 nt"
  571.         "punpcklbw %%mm3, %%mm2 nt"
  572.         "movq %%mm0, %%mm1 nt"
  573.         "punpcklwd %%mm2, %%mm0 nt"
  574.         "punpckhwd %%mm2, %%mm1 nt"
  575.         "movd  %%mm0, %0 nt"
  576.         "punpckhdq %%mm0, %%mm0 nt"
  577.         "movd  %%mm0, %1 nt"
  578.         "movd  %%mm1, %2 nt"
  579.         "punpckhdq %%mm1, %%mm1 nt"
  580.         "movd  %%mm1, %3 nt"
  581.         
  582.         : "=m" (*(uint32_t*)(dst + 0*dst_stride)),
  583.           "=m" (*(uint32_t*)(dst + 1*dst_stride)),
  584.           "=m" (*(uint32_t*)(dst + 2*dst_stride)),
  585.           "=m" (*(uint32_t*)(dst + 3*dst_stride))
  586.         :  "m" (*(uint32_t*)(src + 0*src_stride)),
  587.            "m" (*(uint32_t*)(src + 1*src_stride)),
  588.            "m" (*(uint32_t*)(src + 2*src_stride)),
  589.            "m" (*(uint32_t*)(src + 3*src_stride))
  590.     );
  591. }
  592. static void h263_h_loop_filter_mmx(uint8_t *src, int stride, int qscale){
  593.     const int strength= ff_h263_loop_filter_strength[qscale];
  594.     uint64_t temp[4] __attribute__ ((aligned(8)));
  595.     uint8_t *btemp= (uint8_t*)temp;
  596.     
  597.     src -= 2;
  598.     transpose4x4(btemp  , src           , 8, stride);
  599.     transpose4x4(btemp+4, src + 4*stride, 8, stride);
  600.     asm volatile(
  601.         H263_LOOP_FILTER // 5 3 4 6
  602.         
  603.         : "+m" (temp[0]),
  604.           "+m" (temp[1]),
  605.           "+m" (temp[2]),
  606.           "+m" (temp[3])
  607.         : "g" (2*strength), "m"(ff_pb_FC)
  608.     );
  609.     asm volatile(
  610.         "movq %%mm5, %%mm1 nt"
  611.         "movq %%mm4, %%mm0 nt"
  612.         "punpcklbw %%mm3, %%mm5 nt"
  613.         "punpcklbw %%mm6, %%mm4 nt"
  614.         "punpckhbw %%mm3, %%mm1 nt"
  615.         "punpckhbw %%mm6, %%mm0 nt"
  616.         "movq %%mm5, %%mm3 nt"
  617.         "movq %%mm1, %%mm6 nt"
  618.         "punpcklwd %%mm4, %%mm5 nt"
  619.         "punpcklwd %%mm0, %%mm1 nt"
  620.         "punpckhwd %%mm4, %%mm3 nt"
  621.         "punpckhwd %%mm0, %%mm6 nt"
  622.         "movd %%mm5, (%0) nt"
  623.         "punpckhdq %%mm5, %%mm5 nt"
  624.         "movd %%mm5, (%0,%2) nt"
  625.         "movd %%mm3, (%0,%2,2) nt"
  626.         "punpckhdq %%mm3, %%mm3 nt"
  627.         "movd %%mm3, (%0,%3) nt"
  628.         "movd %%mm1, (%1) nt"
  629.         "punpckhdq %%mm1, %%mm1 nt"
  630.         "movd %%mm1, (%1,%2) nt"
  631.         "movd %%mm6, (%1,%2,2) nt"
  632.         "punpckhdq %%mm6, %%mm6 nt"
  633.         "movd %%mm6, (%1,%3) nt"
  634.         :: "r" (src),
  635.            "r" (src + 4*stride),
  636.            "r" ((long)   stride ),
  637.            "r" ((long)(3*stride))
  638.     );
  639. }
  640. #ifdef CONFIG_ENCODERS
  641. static int pix_norm1_mmx(uint8_t *pix, int line_size) {
  642.     int tmp;
  643.   asm volatile (
  644.       "movl $16,%%ecxn"
  645.       "pxor %%mm0,%%mm0n"
  646.       "pxor %%mm7,%%mm7n"
  647.       "1:n"
  648.       "movq (%0),%%mm2n" /* mm2 = pix[0-7] */
  649.       "movq 8(%0),%%mm3n" /* mm3 = pix[8-15] */
  650.       "movq %%mm2,%%mm1n" /* mm1 = mm2 = pix[0-7] */
  651.       "punpckhbw %%mm0,%%mm1n" /* mm1 = [pix4-7] */
  652.       "punpcklbw %%mm0,%%mm2n" /* mm2 = [pix0-3] */
  653.       "movq %%mm3,%%mm4n" /* mm4 = mm3 = pix[8-15] */
  654.       "punpckhbw %%mm0,%%mm3n" /* mm3 = [pix12-15] */
  655.       "punpcklbw %%mm0,%%mm4n" /* mm4 = [pix8-11] */
  656.       "pmaddwd %%mm1,%%mm1n" /* mm1 = (pix0^2+pix1^2,pix2^2+pix3^2) */
  657.       "pmaddwd %%mm2,%%mm2n" /* mm2 = (pix4^2+pix5^2,pix6^2+pix7^2) */
  658.       "pmaddwd %%mm3,%%mm3n"
  659.       "pmaddwd %%mm4,%%mm4n"
  660.       "paddd %%mm1,%%mm2n" /* mm2 = (pix0^2+pix1^2+pix4^2+pix5^2,
  661.   pix2^2+pix3^2+pix6^2+pix7^2) */
  662.       "paddd %%mm3,%%mm4n"
  663.       "paddd %%mm2,%%mm7n"
  664.       "add %2, %0n"
  665.       "paddd %%mm4,%%mm7n"
  666.       "dec %%ecxn"
  667.       "jnz 1bn"
  668.       "movq %%mm7,%%mm1n"
  669.       "psrlq $32, %%mm7n" /* shift hi dword to lo */
  670.       "paddd %%mm7,%%mm1n"
  671.       "movd %%mm1,%1n"
  672.       : "+r" (pix), "=r"(tmp) : "r" ((long)line_size) : "%ecx" );
  673.     return tmp;
  674. }
  675. static int sse8_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
  676.     int tmp;
  677.   asm volatile (
  678.       "movl %4,%%ecxn"
  679.       "pxor %%mm0,%%mm0n" /* mm0 = 0 */
  680.       "pxor %%mm7,%%mm7n" /* mm7 holds the sum */
  681.       "1:n"
  682.       "movq (%0),%%mm1n" /* mm1 = pix1[0-7] */
  683.       "movq (%1),%%mm2n" /* mm2 = pix2[0-7] */
  684.       "movq %%mm1,%%mm5n"
  685.       "psubusb %%mm2,%%mm1n"
  686.       "psubusb %%mm5,%%mm2n"
  687.       "por %%mm1,%%mm2n"
  688.       "movq %%mm2,%%mm1n"
  689.       "punpckhbw %%mm0,%%mm2n"
  690.       "punpcklbw %%mm0,%%mm1n" /* mm1 now spread over (mm1,mm2) */
  691.       "pmaddwd %%mm2,%%mm2n"
  692.       "pmaddwd %%mm1,%%mm1n"
  693.       "add %3,%0n"
  694.       "add %3,%1n"
  695.       "paddd %%mm2,%%mm1n"
  696.       "paddd %%mm1,%%mm7n"
  697.       "decl %%ecxn"
  698.       "jnz 1bn"
  699.       "movq %%mm7,%%mm1n"
  700.       "psrlq $32, %%mm7n" /* shift hi dword to lo */
  701.       "paddd %%mm7,%%mm1n"
  702.       "movd %%mm1,%2n"
  703.       : "+r" (pix1), "+r" (pix2), "=r"(tmp) 
  704.       : "r" ((long)line_size) , "m" (h)
  705.       : "%ecx");
  706.     return tmp;
  707. }
  708. static int sse16_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
  709.     int tmp;
  710.   asm volatile (
  711.       "movl %4,%%ecxn"
  712.       "pxor %%mm0,%%mm0n" /* mm0 = 0 */
  713.       "pxor %%mm7,%%mm7n" /* mm7 holds the sum */
  714.       "1:n"
  715.       "movq (%0),%%mm1n" /* mm1 = pix1[0-7] */
  716.       "movq (%1),%%mm2n" /* mm2 = pix2[0-7] */
  717.       "movq 8(%0),%%mm3n" /* mm3 = pix1[8-15] */
  718.       "movq 8(%1),%%mm4n" /* mm4 = pix2[8-15] */
  719.       /* todo: mm1-mm2, mm3-mm4 */
  720.       /* algo: substract mm1 from mm2 with saturation and vice versa */
  721.       /*       OR the results to get absolute difference */
  722.       "movq %%mm1,%%mm5n"
  723.       "movq %%mm3,%%mm6n"
  724.       "psubusb %%mm2,%%mm1n"
  725.       "psubusb %%mm4,%%mm3n"
  726.       "psubusb %%mm5,%%mm2n"
  727.       "psubusb %%mm6,%%mm4n"
  728.       "por %%mm1,%%mm2n"
  729.       "por %%mm3,%%mm4n"
  730.       /* now convert to 16-bit vectors so we can square them */
  731.       "movq %%mm2,%%mm1n"
  732.       "movq %%mm4,%%mm3n"
  733.       "punpckhbw %%mm0,%%mm2n"
  734.       "punpckhbw %%mm0,%%mm4n"
  735.       "punpcklbw %%mm0,%%mm1n" /* mm1 now spread over (mm1,mm2) */
  736.       "punpcklbw %%mm0,%%mm3n" /* mm4 now spread over (mm3,mm4) */
  737.       "pmaddwd %%mm2,%%mm2n"
  738.       "pmaddwd %%mm4,%%mm4n"
  739.       "pmaddwd %%mm1,%%mm1n"
  740.       "pmaddwd %%mm3,%%mm3n"
  741.       "add %3,%0n"
  742.       "add %3,%1n"
  743.       "paddd %%mm2,%%mm1n"
  744.       "paddd %%mm4,%%mm3n"
  745.       "paddd %%mm1,%%mm7n"
  746.       "paddd %%mm3,%%mm7n"
  747.       "decl %%ecxn"
  748.       "jnz 1bn"
  749.       "movq %%mm7,%%mm1n"
  750.       "psrlq $32, %%mm7n" /* shift hi dword to lo */
  751.       "paddd %%mm7,%%mm1n"
  752.       "movd %%mm1,%2n"
  753.       : "+r" (pix1), "+r" (pix2), "=r"(tmp) 
  754.       : "r" ((long)line_size) , "m" (h)
  755.       : "%ecx");
  756.     return tmp;
  757. }
  758. static int hf_noise8_mmx(uint8_t * pix1, int line_size, int h) {
  759.     int tmp;
  760.   asm volatile (
  761.       "movl %3,%%ecxn"
  762.       "pxor %%mm7,%%mm7n"
  763.       "pxor %%mm6,%%mm6n"
  764.       
  765.       "movq (%0),%%mm0n"
  766.       "movq %%mm0, %%mm1n"
  767.       "psllq $8, %%mm0n"
  768.       "psrlq $8, %%mm1n"
  769.       "psrlq $8, %%mm0n"
  770.       "movq %%mm0, %%mm2n"
  771.       "movq %%mm1, %%mm3n"
  772.       "punpcklbw %%mm7,%%mm0n"
  773.       "punpcklbw %%mm7,%%mm1n"
  774.       "punpckhbw %%mm7,%%mm2n"
  775.       "punpckhbw %%mm7,%%mm3n"
  776.       "psubw %%mm1, %%mm0n"
  777.       "psubw %%mm3, %%mm2n"
  778.       
  779.       "add %2,%0n"
  780.       
  781.       "movq (%0),%%mm4n"
  782.       "movq %%mm4, %%mm1n"
  783.       "psllq $8, %%mm4n"
  784.       "psrlq $8, %%mm1n"
  785.       "psrlq $8, %%mm4n"
  786.       "movq %%mm4, %%mm5n"
  787.       "movq %%mm1, %%mm3n"
  788.       "punpcklbw %%mm7,%%mm4n"
  789.       "punpcklbw %%mm7,%%mm1n"
  790.       "punpckhbw %%mm7,%%mm5n"
  791.       "punpckhbw %%mm7,%%mm3n"
  792.       "psubw %%mm1, %%mm4n"
  793.       "psubw %%mm3, %%mm5n"
  794.       "psubw %%mm4, %%mm0n"
  795.       "psubw %%mm5, %%mm2n"
  796.       "pxor %%mm3, %%mm3n"
  797.       "pxor %%mm1, %%mm1n"
  798.       "pcmpgtw %%mm0, %%mm3nt"
  799.       "pcmpgtw %%mm2, %%mm1nt"
  800.       "pxor %%mm3, %%mm0n"
  801.       "pxor %%mm1, %%mm2n"
  802.       "psubw %%mm3, %%mm0n" 
  803.       "psubw %%mm1, %%mm2n"
  804.       "paddw %%mm0, %%mm2n"
  805.       "paddw %%mm2, %%mm6n"
  806.       "add %2,%0n"
  807.       "1:n"
  808.   
  809.       "movq (%0),%%mm0n"
  810.       "movq %%mm0, %%mm1n"
  811.       "psllq $8, %%mm0n"
  812.       "psrlq $8, %%mm1n"
  813.       "psrlq $8, %%mm0n"
  814.       "movq %%mm0, %%mm2n"
  815.       "movq %%mm1, %%mm3n"
  816.       "punpcklbw %%mm7,%%mm0n"
  817.       "punpcklbw %%mm7,%%mm1n"
  818.       "punpckhbw %%mm7,%%mm2n"
  819.       "punpckhbw %%mm7,%%mm3n"
  820.       "psubw %%mm1, %%mm0n"
  821.       "psubw %%mm3, %%mm2n"
  822.       "psubw %%mm0, %%mm4n"
  823.       "psubw %%mm2, %%mm5n"
  824.       "pxor %%mm3, %%mm3n"
  825.       "pxor %%mm1, %%mm1n"
  826.       "pcmpgtw %%mm4, %%mm3nt"
  827.       "pcmpgtw %%mm5, %%mm1nt"
  828.       "pxor %%mm3, %%mm4n"
  829.       "pxor %%mm1, %%mm5n"
  830.       "psubw %%mm3, %%mm4n" 
  831.       "psubw %%mm1, %%mm5n"
  832.       "paddw %%mm4, %%mm5n"
  833.       "paddw %%mm5, %%mm6n"
  834.       
  835.       "add %2,%0n"
  836.       
  837.       "movq (%0),%%mm4n"
  838.       "movq %%mm4, %%mm1n"
  839.       "psllq $8, %%mm4n"
  840.       "psrlq $8, %%mm1n"
  841.       "psrlq $8, %%mm4n"
  842.       "movq %%mm4, %%mm5n"
  843.       "movq %%mm1, %%mm3n"
  844.       "punpcklbw %%mm7,%%mm4n"
  845.       "punpcklbw %%mm7,%%mm1n"
  846.       "punpckhbw %%mm7,%%mm5n"
  847.       "punpckhbw %%mm7,%%mm3n"
  848.       "psubw %%mm1, %%mm4n"
  849.       "psubw %%mm3, %%mm5n"
  850.       "psubw %%mm4, %%mm0n"
  851.       "psubw %%mm5, %%mm2n"
  852.       "pxor %%mm3, %%mm3n"
  853.       "pxor %%mm1, %%mm1n"
  854.       "pcmpgtw %%mm0, %%mm3nt"
  855.       "pcmpgtw %%mm2, %%mm1nt"
  856.       "pxor %%mm3, %%mm0n"
  857.       "pxor %%mm1, %%mm2n"
  858.       "psubw %%mm3, %%mm0n" 
  859.       "psubw %%mm1, %%mm2n"
  860.       "paddw %%mm0, %%mm2n"
  861.       "paddw %%mm2, %%mm6n"
  862.       "add %2,%0n"
  863.       "subl $2, %%ecxn"
  864.       " jnz 1bn"
  865.       "movq %%mm6, %%mm0n"
  866.       "punpcklwd %%mm7,%%mm0n"
  867.       "punpckhwd %%mm7,%%mm6n"
  868.       "paddd %%mm0, %%mm6n"
  869.       
  870.       "movq %%mm6,%%mm0n"
  871.       "psrlq $32, %%mm6n"
  872.       "paddd %%mm6,%%mm0n"
  873.       "movd %%mm0,%1n"
  874.       : "+r" (pix1), "=r"(tmp) 
  875.       : "r" ((long)line_size) , "g" (h-2)
  876.       : "%ecx");
  877.       return tmp;
  878. }
  879. static int hf_noise16_mmx(uint8_t * pix1, int line_size, int h) {
  880.     int tmp;
  881.     uint8_t * pix= pix1;
  882.   asm volatile (
  883.       "movl %3,%%ecxn"
  884.       "pxor %%mm7,%%mm7n"
  885.       "pxor %%mm6,%%mm6n"
  886.       
  887.       "movq (%0),%%mm0n"
  888.       "movq 1(%0),%%mm1n"
  889.       "movq %%mm0, %%mm2n"
  890.       "movq %%mm1, %%mm3n"
  891.       "punpcklbw %%mm7,%%mm0n"
  892.       "punpcklbw %%mm7,%%mm1n"
  893.       "punpckhbw %%mm7,%%mm2n"
  894.       "punpckhbw %%mm7,%%mm3n"
  895.       "psubw %%mm1, %%mm0n"
  896.       "psubw %%mm3, %%mm2n"
  897.       
  898.       "add %2,%0n"
  899.       
  900.       "movq (%0),%%mm4n"
  901.       "movq 1(%0),%%mm1n"
  902.       "movq %%mm4, %%mm5n"
  903.       "movq %%mm1, %%mm3n"
  904.       "punpcklbw %%mm7,%%mm4n"
  905.       "punpcklbw %%mm7,%%mm1n"
  906.       "punpckhbw %%mm7,%%mm5n"
  907.       "punpckhbw %%mm7,%%mm3n"
  908.       "psubw %%mm1, %%mm4n"
  909.       "psubw %%mm3, %%mm5n"
  910.       "psubw %%mm4, %%mm0n"
  911.       "psubw %%mm5, %%mm2n"
  912.       "pxor %%mm3, %%mm3n"
  913.       "pxor %%mm1, %%mm1n"
  914.       "pcmpgtw %%mm0, %%mm3nt"
  915.       "pcmpgtw %%mm2, %%mm1nt"
  916.       "pxor %%mm3, %%mm0n"
  917.       "pxor %%mm1, %%mm2n"
  918.       "psubw %%mm3, %%mm0n" 
  919.       "psubw %%mm1, %%mm2n"
  920.       "paddw %%mm0, %%mm2n"
  921.       "paddw %%mm2, %%mm6n"
  922.       "add %2,%0n"
  923.       "1:n"
  924.   
  925.       "movq (%0),%%mm0n"
  926.       "movq 1(%0),%%mm1n"
  927.       "movq %%mm0, %%mm2n"
  928.       "movq %%mm1, %%mm3n"
  929.       "punpcklbw %%mm7,%%mm0n"
  930.       "punpcklbw %%mm7,%%mm1n"
  931.       "punpckhbw %%mm7,%%mm2n"
  932.       "punpckhbw %%mm7,%%mm3n"
  933.       "psubw %%mm1, %%mm0n"
  934.       "psubw %%mm3, %%mm2n"
  935.       "psubw %%mm0, %%mm4n"
  936.       "psubw %%mm2, %%mm5n"
  937.       "pxor %%mm3, %%mm3n"
  938.       "pxor %%mm1, %%mm1n"
  939.       "pcmpgtw %%mm4, %%mm3nt"
  940.       "pcmpgtw %%mm5, %%mm1nt"
  941.       "pxor %%mm3, %%mm4n"
  942.       "pxor %%mm1, %%mm5n"
  943.       "psubw %%mm3, %%mm4n"
  944.       "psubw %%mm1, %%mm5n"
  945.       "paddw %%mm4, %%mm5n"
  946.       "paddw %%mm5, %%mm6n"
  947.       
  948.       "add %2,%0n"
  949.       
  950.       "movq (%0),%%mm4n"
  951.       "movq 1(%0),%%mm1n"
  952.       "movq %%mm4, %%mm5n"
  953.       "movq %%mm1, %%mm3n"
  954.       "punpcklbw %%mm7,%%mm4n"
  955.       "punpcklbw %%mm7,%%mm1n"
  956.       "punpckhbw %%mm7,%%mm5n"
  957.       "punpckhbw %%mm7,%%mm3n"
  958.       "psubw %%mm1, %%mm4n"
  959.       "psubw %%mm3, %%mm5n"
  960.       "psubw %%mm4, %%mm0n"
  961.       "psubw %%mm5, %%mm2n"
  962.       "pxor %%mm3, %%mm3n"
  963.       "pxor %%mm1, %%mm1n"
  964.       "pcmpgtw %%mm0, %%mm3nt"
  965.       "pcmpgtw %%mm2, %%mm1nt"
  966.       "pxor %%mm3, %%mm0n"
  967.       "pxor %%mm1, %%mm2n"
  968.       "psubw %%mm3, %%mm0n" 
  969.       "psubw %%mm1, %%mm2n"
  970.       "paddw %%mm0, %%mm2n"
  971.       "paddw %%mm2, %%mm6n"
  972.       "add %2,%0n"
  973.       "subl $2, %%ecxn"
  974.       " jnz 1bn"
  975.       "movq %%mm6, %%mm0n"
  976.       "punpcklwd %%mm7,%%mm0n"
  977.       "punpckhwd %%mm7,%%mm6n"
  978.       "paddd %%mm0, %%mm6n"
  979.       
  980.       "movq %%mm6,%%mm0n"
  981.       "psrlq $32, %%mm6n"
  982.       "paddd %%mm6,%%mm0n"
  983.       "movd %%mm0,%1n"
  984.       : "+r" (pix1), "=r"(tmp) 
  985.       : "r" ((long)line_size) , "g" (h-2)
  986.       : "%ecx");
  987.       return tmp + hf_noise8_mmx(pix+8, line_size, h);
  988. }
  989. static int nsse16_mmx(void *p, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
  990.     MpegEncContext *c = p;
  991.     int score1= sse16_mmx(c, pix1, pix2, line_size, h);
  992.     int score2= hf_noise16_mmx(pix1, line_size, h) - hf_noise16_mmx(pix2, line_size, h);
  993.     if(c) return score1 + ABS(score2)*c->avctx->nsse_weight;
  994.     else  return score1 + ABS(score2)*8;
  995. }
  996. static int nsse8_mmx(void *p, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
  997.     MpegEncContext *c = p;
  998.     int score1= sse8_mmx(c, pix1, pix2, line_size, h);
  999.     int score2= hf_noise8_mmx(pix1, line_size, h) - hf_noise8_mmx(pix2, line_size, h);
  1000.     if(c) return score1 + ABS(score2)*c->avctx->nsse_weight;
  1001.     else  return score1 + ABS(score2)*8;
  1002. }
  1003. static int vsad_intra16_mmx(void *v, uint8_t * pix, uint8_t * dummy, int line_size, int h) {
  1004.     int tmp;
  1005.     
  1006.     assert( (((int)pix) & 7) == 0);
  1007.     assert((line_size &7) ==0);
  1008.     
  1009. #define SUM(in0, in1, out0, out1) 
  1010.       "movq (%0), %%mm2n"
  1011.       "movq 8(%0), %%mm3n"
  1012.       "add %2,%0n"
  1013.       "movq %%mm2, " #out0 "n"
  1014.       "movq %%mm3, " #out1 "n"
  1015.       "psubusb " #in0 ", %%mm2n"
  1016.       "psubusb " #in1 ", %%mm3n"
  1017.       "psubusb " #out0 ", " #in0 "n"
  1018.       "psubusb " #out1 ", " #in1 "n"
  1019.       "por %%mm2, " #in0 "n"
  1020.       "por %%mm3, " #in1 "n"
  1021.       "movq " #in0 ", %%mm2n"
  1022.       "movq " #in1 ", %%mm3n"
  1023.       "punpcklbw %%mm7, " #in0 "n"
  1024.       "punpcklbw %%mm7, " #in1 "n"
  1025.       "punpckhbw %%mm7, %%mm2n"
  1026.       "punpckhbw %%mm7, %%mm3n"
  1027.       "paddw " #in1 ", " #in0 "n"
  1028.       "paddw %%mm3, %%mm2n"
  1029.       "paddw %%mm2, " #in0 "n"
  1030.       "paddw " #in0 ", %%mm6n"
  1031.     
  1032.   asm volatile (
  1033.       "movl %3,%%ecxn"
  1034.       "pxor %%mm6,%%mm6n"
  1035.       "pxor %%mm7,%%mm7n"
  1036.       "movq (%0),%%mm0n"
  1037.       "movq 8(%0),%%mm1n"
  1038.       "add %2,%0n"
  1039.       "subl $2, %%ecxn"
  1040.       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
  1041.       "1:n"
  1042.       
  1043.       SUM(%%mm4, %%mm5, %%mm0, %%mm1)
  1044.       
  1045.       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
  1046.       
  1047.       "subl $2, %%ecxn"
  1048.       "jnz 1bn"
  1049.       "movq %%mm6,%%mm0n"
  1050.       "psrlq $32, %%mm6n"
  1051.       "paddw %%mm6,%%mm0n"
  1052.       "movq %%mm0,%%mm6n"
  1053.       "psrlq $16, %%mm0n"
  1054.       "paddw %%mm6,%%mm0n"
  1055.       "movd %%mm0,%1n"
  1056.       : "+r" (pix), "=r"(tmp) 
  1057.       : "r" ((long)line_size) , "m" (h)
  1058.       : "%ecx");
  1059.     return tmp & 0xFFFF;
  1060. }
  1061. #undef SUM
  1062. static int vsad_intra16_mmx2(void *v, uint8_t * pix, uint8_t * dummy, int line_size, int h) {
  1063.     int tmp;
  1064.     
  1065.     assert( (((int)pix) & 7) == 0);
  1066.     assert((line_size &7) ==0);
  1067.     
  1068. #define SUM(in0, in1, out0, out1) 
  1069.       "movq (%0), " #out0 "n"
  1070.       "movq 8(%0), " #out1 "n"
  1071.       "add %2,%0n"
  1072.       "psadbw " #out0 ", " #in0 "n"
  1073.       "psadbw " #out1 ", " #in1 "n"
  1074.       "paddw " #in1 ", " #in0 "n"
  1075.       "paddw " #in0 ", %%mm6n"
  1076.   asm volatile (
  1077.       "movl %3,%%ecxn"
  1078.       "pxor %%mm6,%%mm6n"
  1079.       "pxor %%mm7,%%mm7n"
  1080.       "movq (%0),%%mm0n"
  1081.       "movq 8(%0),%%mm1n"
  1082.       "add %2,%0n"
  1083.       "subl $2, %%ecxn"
  1084.       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
  1085.       "1:n"
  1086.       
  1087.       SUM(%%mm4, %%mm5, %%mm0, %%mm1)
  1088.       
  1089.       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
  1090.       
  1091.       "subl $2, %%ecxn"
  1092.       "jnz 1bn"
  1093.       "movd %%mm6,%1n"
  1094.       : "+r" (pix), "=r"(tmp) 
  1095.       : "r" ((long)line_size) , "m" (h)
  1096.       : "%ecx");
  1097.     return tmp;
  1098. }
  1099. #undef SUM
  1100. static int vsad16_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
  1101.     int tmp;
  1102.     
  1103.     assert( (((int)pix1) & 7) == 0);
  1104.     assert( (((int)pix2) & 7) == 0);
  1105.     assert((line_size &7) ==0);
  1106.     
  1107. #define SUM(in0, in1, out0, out1) 
  1108.       "movq (%0),%%mm2n"
  1109.       "movq (%1)," #out0 "n"
  1110.       "movq 8(%0),%%mm3n"
  1111.       "movq 8(%1)," #out1 "n"
  1112.       "add %3,%0n"
  1113.       "add %3,%1n"
  1114.       "psubb " #out0 ", %%mm2n"
  1115.       "psubb " #out1 ", %%mm3n"
  1116.       "pxor %%mm7, %%mm2n"
  1117.       "pxor %%mm7, %%mm3n"
  1118.       "movq %%mm2, " #out0 "n"
  1119.       "movq %%mm3, " #out1 "n"
  1120.       "psubusb " #in0 ", %%mm2n"
  1121.       "psubusb " #in1 ", %%mm3n"
  1122.       "psubusb " #out0 ", " #in0 "n"
  1123.       "psubusb " #out1 ", " #in1 "n"
  1124.       "por %%mm2, " #in0 "n"
  1125.       "por %%mm3, " #in1 "n"
  1126.       "movq " #in0 ", %%mm2n"
  1127.       "movq " #in1 ", %%mm3n"
  1128.       "punpcklbw %%mm7, " #in0 "n"
  1129.       "punpcklbw %%mm7, " #in1 "n"
  1130.       "punpckhbw %%mm7, %%mm2n"
  1131.       "punpckhbw %%mm7, %%mm3n"
  1132.       "paddw " #in1 ", " #in0 "n"
  1133.       "paddw %%mm3, %%mm2n"
  1134.       "paddw %%mm2, " #in0 "n"
  1135.       "paddw " #in0 ", %%mm6n"
  1136.     
  1137.   asm volatile (
  1138.       "movl %4,%%ecxn"
  1139.       "pxor %%mm6,%%mm6n"
  1140.       "pcmpeqw %%mm7,%%mm7n"
  1141.       "psllw $15, %%mm7n"
  1142.       "packsswb %%mm7, %%mm7n"
  1143.       "movq (%0),%%mm0n"
  1144.       "movq (%1),%%mm2n"
  1145.       "movq 8(%0),%%mm1n"
  1146.       "movq 8(%1),%%mm3n"
  1147.       "add %3,%0n"
  1148.       "add %3,%1n"
  1149.       "subl $2, %%ecxn"
  1150.       "psubb %%mm2, %%mm0n"
  1151.       "psubb %%mm3, %%mm1n"
  1152.       "pxor %%mm7, %%mm0n"
  1153.       "pxor %%mm7, %%mm1n"
  1154.       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
  1155.       "1:n"
  1156.       
  1157.       SUM(%%mm4, %%mm5, %%mm0, %%mm1)
  1158.       
  1159.       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
  1160.       
  1161.       "subl $2, %%ecxn"
  1162.       "jnz 1bn"
  1163.       "movq %%mm6,%%mm0n"
  1164.       "psrlq $32, %%mm6n"
  1165.       "paddw %%mm6,%%mm0n"
  1166.       "movq %%mm0,%%mm6n"
  1167.       "psrlq $16, %%mm0n"
  1168.       "paddw %%mm6,%%mm0n"
  1169.       "movd %%mm0,%2n"
  1170.       : "+r" (pix1), "+r" (pix2), "=r"(tmp) 
  1171.       : "r" ((long)line_size) , "m" (h)
  1172.       : "%ecx");
  1173.     return tmp & 0x7FFF;
  1174. }
  1175. #undef SUM
  1176. static int vsad16_mmx2(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
  1177.     int tmp;
  1178.     
  1179.     assert( (((int)pix1) & 7) == 0);
  1180.     assert( (((int)pix2) & 7) == 0);
  1181.     assert((line_size &7) ==0);
  1182.     
  1183. #define SUM(in0, in1, out0, out1) 
  1184.       "movq (%0)," #out0 "n"
  1185.       "movq (%1),%%mm2n"
  1186.       "movq 8(%0)," #out1 "n"
  1187.       "movq 8(%1),%%mm3n"
  1188.       "add %3,%0n"
  1189.       "add %3,%1n"
  1190.       "psubb %%mm2, " #out0 "n"
  1191.       "psubb %%mm3, " #out1 "n"
  1192.       "pxor %%mm7, " #out0 "n"
  1193.       "pxor %%mm7, " #out1 "n"
  1194.       "psadbw " #out0 ", " #in0 "n"
  1195.       "psadbw " #out1 ", " #in1 "n"
  1196.       "paddw " #in1 ", " #in0 "n"
  1197.       "paddw " #in0 ", %%mm6n"
  1198.   asm volatile (
  1199.       "movl %4,%%ecxn"
  1200.       "pxor %%mm6,%%mm6n"
  1201.       "pcmpeqw %%mm7,%%mm7n"
  1202.       "psllw $15, %%mm7n"
  1203.       "packsswb %%mm7, %%mm7n"
  1204.       "movq (%0),%%mm0n"
  1205.       "movq (%1),%%mm2n"
  1206.       "movq 8(%0),%%mm1n"
  1207.       "movq 8(%1),%%mm3n"
  1208.       "add %3,%0n"
  1209.       "add %3,%1n"
  1210.       "subl $2, %%ecxn"
  1211.       "psubb %%mm2, %%mm0n"
  1212.       "psubb %%mm3, %%mm1n"
  1213.       "pxor %%mm7, %%mm0n"
  1214.       "pxor %%mm7, %%mm1n"
  1215.       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
  1216.       "1:n"
  1217.       
  1218.       SUM(%%mm4, %%mm5, %%mm0, %%mm1)
  1219.       
  1220.       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
  1221.       
  1222.       "subl $2, %%ecxn"
  1223.       "jnz 1bn"
  1224.       "movd %%mm6,%2n"
  1225.       : "+r" (pix1), "+r" (pix2), "=r"(tmp) 
  1226.       : "r" ((long)line_size) , "m" (h)
  1227.       : "%ecx");
  1228.     return tmp;
  1229. }
  1230. #undef SUM
  1231. static void diff_bytes_mmx(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w){
  1232.     long i=0;
  1233.     asm volatile(
  1234.         "1: nt"
  1235.         "movq  (%2, %0), %%mm0 nt"
  1236.         "movq  (%1, %0), %%mm1 nt"
  1237.         "psubb %%mm0, %%mm1 nt"
  1238.         "movq %%mm1, (%3, %0) nt"
  1239.         "movq 8(%2, %0), %%mm0 nt"
  1240.         "movq 8(%1, %0), %%mm1 nt"
  1241.         "psubb %%mm0, %%mm1 nt"
  1242.         "movq %%mm1, 8(%3, %0) nt"
  1243.         "add $16, %0 nt"
  1244.         "cmp %4, %0 nt"
  1245.         " jb 1b nt"
  1246.         : "+r" (i)
  1247.         : "r"(src1), "r"(src2), "r"(dst), "r"((long)w-15)
  1248.     );
  1249.     for(; i<w; i++)
  1250.         dst[i+0] = src1[i+0]-src2[i+0];
  1251. }
  1252. static void sub_hfyu_median_prediction_mmx2(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w, int *left, int *left_top){
  1253.     long i=0;
  1254.     uint8_t l, lt;
  1255.     
  1256.     asm volatile(
  1257.         "1: nt"
  1258.         "movq  -1(%1, %0), %%mm0 nt" // LT
  1259.         "movq  (%1, %0), %%mm1 nt" // T
  1260.         "movq  -1(%2, %0), %%mm2 nt" // L
  1261.         "movq  (%2, %0), %%mm3 nt" // X
  1262.         "movq %%mm2, %%mm4 nt" // L
  1263.         "psubb %%mm0, %%mm2 nt"
  1264.         "paddb %%mm1, %%mm2 nt" // L + T - LT
  1265.         "movq %%mm4, %%mm5 nt" // L
  1266.         "pmaxub %%mm1, %%mm4 nt" // max(T, L)
  1267.         "pminub %%mm5, %%mm1 nt" // min(T, L)
  1268.         "pminub %%mm2, %%mm4 nt" 
  1269.         "pmaxub %%mm1, %%mm4 nt"
  1270.         "psubb %%mm4, %%mm3 nt" // dst - pred
  1271.         "movq %%mm3, (%3, %0) nt"
  1272.         "add $8, %0 nt"
  1273.         "cmp %4, %0 nt"
  1274.         " jb 1b nt"
  1275.         : "+r" (i)
  1276.         : "r"(src1), "r"(src2), "r"(dst), "r"((long)w)
  1277.     );
  1278.     l= *left;
  1279.     lt= *left_top;
  1280.     
  1281.     dst[0]= src2[0] - mid_pred(l, src1[0], (l + src1[0] - lt)&0xFF);
  1282.     
  1283.     *left_top= src1[w-1];
  1284.     *left    = src2[w-1];
  1285. }
  1286. #define LBUTTERFLY2(a1,b1,a2,b2)
  1287.     "paddw " #b1 ", " #a1 " nt"
  1288.     "paddw " #b2 ", " #a2 " nt"
  1289.     "paddw " #b1 ", " #b1 " nt"
  1290.     "paddw " #b2 ", " #b2 " nt"
  1291.     "psubw " #a1 ", " #b1 " nt"
  1292.     "psubw " #a2 ", " #b2 " nt"
  1293. #define HADAMARD48
  1294.         LBUTTERFLY2(%%mm0, %%mm1, %%mm2, %%mm3)
  1295.         LBUTTERFLY2(%%mm4, %%mm5, %%mm6, %%mm7)
  1296.         LBUTTERFLY2(%%mm0, %%mm2, %%mm1, %%mm3)
  1297.         LBUTTERFLY2(%%mm4, %%mm6, %%mm5, %%mm7)
  1298.         LBUTTERFLY2(%%mm0, %%mm4, %%mm1, %%mm5)
  1299.         LBUTTERFLY2(%%mm2, %%mm6, %%mm3, %%mm7)
  1300. #define MMABS(a,z)
  1301.     "pxor " #z ", " #z " nt"
  1302.     "pcmpgtw " #a ", " #z " nt"
  1303.     "pxor " #z ", " #a " nt"
  1304.     "psubw " #z ", " #a " nt"
  1305. #define MMABS_SUM(a,z, sum)
  1306.     "pxor " #z ", " #z " nt"
  1307.     "pcmpgtw " #a ", " #z " nt"
  1308.     "pxor " #z ", " #a " nt"
  1309.     "psubw " #z ", " #a " nt"
  1310.     "paddusw " #a ", " #sum " nt"
  1311. #define MMABS_MMX2(a,z)
  1312.     "pxor " #z ", " #z " nt"
  1313.     "psubw " #a ", " #z " nt"
  1314.     "pmaxsw " #z ", " #a " nt"
  1315. #define MMABS_SUM_MMX2(a,z, sum)
  1316.     "pxor " #z ", " #z " nt"
  1317.     "psubw " #a ", " #z " nt"
  1318.     "pmaxsw " #z ", " #a " nt"
  1319.     "paddusw " #a ", " #sum " nt"
  1320.         
  1321. #define SBUTTERFLY(a,b,t,n)
  1322.     "movq " #a ", " #t " nt" /* abcd */
  1323.     "punpckl" #n " " #b ", " #a " nt" /* aebf */
  1324.     "punpckh" #n " " #b ", " #t " nt" /* cgdh */
  1325. #define TRANSPOSE4(a,b,c,d,t)
  1326.     SBUTTERFLY(a,b,t,wd) /* a=aebf t=cgdh */
  1327.     SBUTTERFLY(c,d,b,wd) /* c=imjn b=kolp */
  1328.     SBUTTERFLY(a,c,d,dq) /* a=aeim d=bfjn */
  1329.     SBUTTERFLY(t,b,c,dq) /* t=cgko c=dhlp */
  1330. #define LOAD4(o, a, b, c, d)
  1331.         "movq "#o"(%1), " #a " nt"
  1332.         "movq "#o"+16(%1), " #b " nt"
  1333.         "movq "#o"+32(%1), " #c " nt"
  1334.         "movq "#o"+48(%1), " #d " nt"
  1335. #define STORE4(o, a, b, c, d)
  1336.         "movq "#a", "#o"(%1) nt"
  1337.         "movq "#b", "#o"+16(%1) nt"
  1338.         "movq "#c", "#o"+32(%1) nt"
  1339.         "movq "#d", "#o"+48(%1) nt"
  1340. static int hadamard8_diff_mmx(void *s, uint8_t *src1, uint8_t *src2, int stride, int h){
  1341.     uint64_t temp[16] __align8;
  1342.     int sum=0;
  1343.     
  1344.     assert(h==8);
  1345.     diff_pixels_mmx((DCTELEM*)temp, src1, src2, stride);
  1346.     asm volatile(
  1347.         LOAD4(0 , %%mm0, %%mm1, %%mm2, %%mm3)
  1348.         LOAD4(64, %%mm4, %%mm5, %%mm6, %%mm7)
  1349.         
  1350.         HADAMARD48
  1351.         
  1352.         "movq %%mm7, 112(%1) nt"
  1353.         
  1354.         TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)
  1355.         STORE4(0 , %%mm0, %%mm3, %%mm7, %%mm2)
  1356.         
  1357.         "movq 112(%1), %%mm7  nt"
  1358.         TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)
  1359.         STORE4(64, %%mm4, %%mm7, %%mm0, %%mm6)
  1360.         LOAD4(8 , %%mm0, %%mm1, %%mm2, %%mm3)
  1361.         LOAD4(72, %%mm4, %%mm5, %%mm6, %%mm7)
  1362.         
  1363.         HADAMARD48
  1364.         
  1365.         "movq %%mm7, 120(%1) nt"
  1366.         
  1367.         TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)
  1368.         STORE4(8 , %%mm0, %%mm3, %%mm7, %%mm2)
  1369.         
  1370.         "movq 120(%1), %%mm7  nt"
  1371.         TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)
  1372.         "movq %%mm7, %%mm5 nt"//FIXME remove
  1373.         "movq %%mm6, %%mm7 nt"
  1374.         "movq %%mm0, %%mm6 nt"
  1375. //        STORE4(72, %%mm4, %%mm7, %%mm0, %%mm6) //FIXME remove
  1376.         
  1377.         LOAD4(64, %%mm0, %%mm1, %%mm2, %%mm3)
  1378. //        LOAD4(72, %%mm4, %%mm5, %%mm6, %%mm7)
  1379.         
  1380.         HADAMARD48
  1381.         "movq %%mm7, 64(%1) nt"
  1382.         MMABS(%%mm0, %%mm7)
  1383.         MMABS_SUM(%%mm1, %%mm7, %%mm0)
  1384.         MMABS_SUM(%%mm2, %%mm7, %%mm0)
  1385.         MMABS_SUM(%%mm3, %%mm7, %%mm0)
  1386.         MMABS_SUM(%%mm4, %%mm7, %%mm0)
  1387.         MMABS_SUM(%%mm5, %%mm7, %%mm0)
  1388.         MMABS_SUM(%%mm6, %%mm7, %%mm0)
  1389.         "movq 64(%1), %%mm1 nt"
  1390.         MMABS_SUM(%%mm1, %%mm7, %%mm0)
  1391.         "movq %%mm0, 64(%1) nt"
  1392.         
  1393.         LOAD4(0 , %%mm0, %%mm1, %%mm2, %%mm3)
  1394.         LOAD4(8 , %%mm4, %%mm5, %%mm6, %%mm7)
  1395.         
  1396.         HADAMARD48
  1397.         "movq %%mm7, (%1) nt"
  1398.         MMABS(%%mm0, %%mm7)
  1399.         MMABS_SUM(%%mm1, %%mm7, %%mm0)
  1400.         MMABS_SUM(%%mm2, %%mm7, %%mm0)
  1401.         MMABS_SUM(%%mm3, %%mm7, %%mm0)
  1402.         MMABS_SUM(%%mm4, %%mm7, %%mm0)
  1403.         MMABS_SUM(%%mm5, %%mm7, %%mm0)
  1404.         MMABS_SUM(%%mm6, %%mm7, %%mm0)
  1405.         "movq (%1), %%mm1 nt"
  1406.         MMABS_SUM(%%mm1, %%mm7, %%mm0)
  1407.         "movq 64(%1), %%mm1 nt"
  1408.         MMABS_SUM(%%mm1, %%mm7, %%mm0)
  1409.         
  1410.         "movq %%mm0, %%mm1 nt"
  1411.         "psrlq $32, %%mm0 nt"
  1412.         "paddusw %%mm1, %%mm0 nt"
  1413.         "movq %%mm0, %%mm1 nt"
  1414.         "psrlq $16, %%mm0 nt"
  1415.         "paddusw %%mm1, %%mm0 nt"
  1416.         "movd %%mm0, %0 nt"
  1417.                 
  1418.         : "=r" (sum)
  1419.         : "r"(temp)
  1420.     );
  1421.     return sum&0xFFFF;
  1422. }
  1423. static int hadamard8_diff_mmx2(void *s, uint8_t *src1, uint8_t *src2, int stride, int h){
  1424.     uint64_t temp[16] __align8;
  1425.     int sum=0;
  1426.     
  1427.     assert(h==8);
  1428.     diff_pixels_mmx((DCTELEM*)temp, src1, src2, stride);
  1429.     asm volatile(
  1430.         LOAD4(0 , %%mm0, %%mm1, %%mm2, %%mm3)
  1431.         LOAD4(64, %%mm4, %%mm5, %%mm6, %%mm7)
  1432.         
  1433.         HADAMARD48
  1434.         
  1435.         "movq %%mm7, 112(%1) nt"
  1436.         
  1437.         TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)
  1438.         STORE4(0 , %%mm0, %%mm3, %%mm7, %%mm2)
  1439.         
  1440.         "movq 112(%1), %%mm7  nt"
  1441.         TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)
  1442.         STORE4(64, %%mm4, %%mm7, %%mm0, %%mm6)
  1443.         LOAD4(8 , %%mm0, %%mm1, %%mm2, %%mm3)
  1444.         LOAD4(72, %%mm4, %%mm5, %%mm6, %%mm7)
  1445.         
  1446.         HADAMARD48
  1447.         
  1448.         "movq %%mm7, 120(%1) nt"
  1449.         
  1450.         TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)
  1451.         STORE4(8 , %%mm0, %%mm3, %%mm7, %%mm2)
  1452.         
  1453.         "movq 120(%1), %%mm7  nt"
  1454.         TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)
  1455.         "movq %%mm7, %%mm5 nt"//FIXME remove
  1456.         "movq %%mm6, %%mm7 nt"
  1457.         "movq %%mm0, %%mm6 nt"
  1458. //        STORE4(72, %%mm4, %%mm7, %%mm0, %%mm6) //FIXME remove
  1459.         
  1460.         LOAD4(64, %%mm0, %%mm1, %%mm2, %%mm3)
  1461. //        LOAD4(72, %%mm4, %%mm5, %%mm6, %%mm7)
  1462.         
  1463.         HADAMARD48
  1464.         "movq %%mm7, 64(%1) nt"
  1465.         MMABS_MMX2(%%mm0, %%mm7)
  1466.         MMABS_SUM_MMX2(%%mm1, %%mm7, %%mm0)
  1467.         MMABS_SUM_MMX2(%%mm2, %%mm7, %%mm0)
  1468.         MMABS_SUM_MMX2(%%mm3, %%mm7, %%mm0)
  1469.         MMABS_SUM_MMX2(%%mm4, %%mm7, %%mm0)
  1470.         MMABS_SUM_MMX2(%%mm5, %%mm7, %%mm0)
  1471.         MMABS_SUM_MMX2(%%mm6, %%mm7, %%mm0)
  1472.         "movq 64(%1), %%mm1 nt"
  1473.         MMABS_SUM_MMX2(%%mm1, %%mm7, %%mm0)
  1474.         "movq %%mm0, 64(%1) nt"
  1475.         
  1476.         LOAD4(0 , %%mm0, %%mm1, %%mm2, %%mm3)
  1477.         LOAD4(8 , %%mm4, %%mm5, %%mm6, %%mm7)
  1478.         
  1479.         HADAMARD48
  1480.         "movq %%mm7, (%1) nt"
  1481.         MMABS_MMX2(%%mm0, %%mm7)
  1482.         MMABS_SUM_MMX2(%%mm1, %%mm7, %%mm0)
  1483.         MMABS_SUM_MMX2(%%mm2, %%mm7, %%mm0)
  1484.         MMABS_SUM_MMX2(%%mm3, %%mm7, %%mm0)
  1485.         MMABS_SUM_MMX2(%%mm4, %%mm7, %%mm0)
  1486.         MMABS_SUM_MMX2(%%mm5, %%mm7, %%mm0)
  1487.         MMABS_SUM_MMX2(%%mm6, %%mm7, %%mm0)
  1488.         "movq (%1), %%mm1 nt"
  1489.         MMABS_SUM_MMX2(%%mm1, %%mm7, %%mm0)
  1490.         "movq 64(%1), %%mm1 nt"
  1491.         MMABS_SUM_MMX2(%%mm1, %%mm7, %%mm0)
  1492.         
  1493.         "movq %%mm0, %%mm1 nt"
  1494.         "psrlq $32, %%mm0 nt"
  1495.         "paddusw %%mm1, %%mm0 nt"
  1496.         "movq %%mm0, %%mm1 nt"
  1497.         "psrlq $16, %%mm0 nt"
  1498.         "paddusw %%mm1, %%mm0 nt"
  1499.         "movd %%mm0, %0 nt"
  1500.                 
  1501.         : "=r" (sum)
  1502.         : "r"(temp)
  1503.     );
  1504.     return sum&0xFFFF;
  1505. }
  1506. WARPER8_16_SQ(hadamard8_diff_mmx, hadamard8_diff16_mmx)
  1507. WARPER8_16_SQ(hadamard8_diff_mmx2, hadamard8_diff16_mmx2)
  1508. #endif //CONFIG_ENCODERS
  1509. #define put_no_rnd_pixels8_mmx(a,b,c,d) put_pixels8_mmx(a,b,c,d)
  1510. #define put_no_rnd_pixels16_mmx(a,b,c,d) put_pixels16_mmx(a,b,c,d)
  1511. #define QPEL_V_LOW(m3,m4,m5,m6, pw_20, pw_3, rnd, in0, in1, in2, in7, out, OP)
  1512.         "paddw " #m4 ", " #m3 " nt" /* x1 */
  1513.         "movq "MANGLE(ff_pw_20)", %%mm4 nt" /* 20 */
  1514.         "pmullw " #m3 ", %%mm4 nt" /* 20x1 */
  1515.         "movq "#in7", " #m3 " nt" /* d */
  1516.         "movq "#in0", %%mm5 nt" /* D */
  1517.         "paddw " #m3 ", %%mm5 nt" /* x4 */
  1518.         "psubw %%mm5, %%mm4 nt" /* 20x1 - x4 */
  1519.         "movq "#in1", %%mm5 nt" /* C */
  1520.         "movq "#in2", %%mm6 nt" /* B */
  1521.         "paddw " #m6 ", %%mm5 nt" /* x3 */
  1522.         "paddw " #m5 ", %%mm6 nt" /* x2 */
  1523.         "paddw %%mm6, %%mm6 nt" /* 2x2 */
  1524.         "psubw %%mm6, %%mm5 nt" /* -2x2 + x3 */
  1525.         "pmullw "MANGLE(ff_pw_3)", %%mm5 nt" /* -6x2 + 3x3 */
  1526.         "paddw " #rnd ", %%mm4 nt" /* x2 */
  1527.         "paddw %%mm4, %%mm5 nt" /* 20x1 - 6x2 + 3x3 - x4 */
  1528.         "psraw $5, %%mm5 nt"
  1529.         "packuswb %%mm5, %%mm5 nt"
  1530.         OP(%%mm5, out, %%mm7, d)
  1531. #define QPEL_BASE(OPNAME, ROUNDER, RND, OP_MMX2, OP_3DNOW)
  1532. static void OPNAME ## mpeg4_qpel16_h_lowpass_mmx2(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){
  1533.     uint64_t temp;
  1534.     asm volatile(
  1535.         "pxor %%mm7, %%mm7 nt"
  1536.         "1: nt"
  1537.         "movq  (%0), %%mm0 nt" /* ABCDEFGH */
  1538.         "movq %%mm0, %%mm1 nt" /* ABCDEFGH */
  1539.         "movq %%mm0, %%mm2 nt" /* ABCDEFGH */
  1540.         "punpcklbw %%mm7, %%mm0 nt" /* 0A0B0C0D */
  1541.         "punpckhbw %%mm7, %%mm1 nt" /* 0E0F0G0H */
  1542.         "pshufw $0x90, %%mm0, %%mm5 nt" /* 0A0A0B0C */
  1543.         "pshufw $0x41, %%mm0, %%mm6 nt" /* 0B0A0A0B */
  1544.         "movq %%mm2, %%mm3 nt" /* ABCDEFGH */
  1545.         "movq %%mm2, %%mm4 nt" /* ABCDEFGH */
  1546.         "psllq $8, %%mm2 nt" /* 0ABCDEFG */
  1547.         "psllq $16, %%mm3 nt" /* 00ABCDEF */
  1548.         "psllq $24, %%mm4 nt" /* 000ABCDE */
  1549.         "punpckhbw %%mm7, %%mm2 nt" /* 0D0E0F0G */
  1550.         "punpckhbw %%mm7, %%mm3 nt" /* 0C0D0E0F */
  1551.         "punpckhbw %%mm7, %%mm4 nt" /* 0B0C0D0E */
  1552.         "paddw %%mm3, %%mm5 nt" /* b */
  1553.         "paddw %%mm2, %%mm6 nt" /* c */
  1554.         "paddw %%mm5, %%mm5 nt" /* 2b */
  1555.         "psubw %%mm5, %%mm6 nt" /* c - 2b */
  1556.         "pshufw $0x06, %%mm0, %%mm5 nt" /* 0C0B0A0A */
  1557.         "pmullw "MANGLE(ff_pw_3)", %%mm6 nt" /* 3c - 6b */
  1558.         "paddw %%mm4, %%mm0 nt" /* a */
  1559.         "paddw %%mm1, %%mm5 nt" /* d */
  1560.         "pmullw "MANGLE(ff_pw_20)", %%mm0 nt" /* 20a */
  1561.         "psubw %%mm5, %%mm0 nt" /* 20a - d */
  1562.         "paddw %6, %%mm6 nt"
  1563.         "paddw %%mm6, %%mm0 nt" /* 20a - 6b + 3c - d */
  1564.         "psraw $5, %%mm0 nt"
  1565.         "movq %%mm0, %5 nt"
  1566.         /* mm1=EFGH, mm2=DEFG, mm3=CDEF, mm4=BCDE, mm7=0 */
  1567.         
  1568.         "movq 5(%0), %%mm0 nt" /* FGHIJKLM */
  1569.         "movq %%mm0, %%mm5 nt" /* FGHIJKLM */
  1570.         "movq %%mm0, %%mm6 nt" /* FGHIJKLM */
  1571.         "psrlq $8, %%mm0 nt" /* GHIJKLM0 */
  1572.         "psrlq $16, %%mm5 nt" /* HIJKLM00 */
  1573.         "punpcklbw %%mm7, %%mm0 nt" /* 0G0H0I0J */
  1574.         "punpcklbw %%mm7, %%mm5 nt" /* 0H0I0J0K */
  1575.         "paddw %%mm0, %%mm2 nt" /* b */
  1576.         "paddw %%mm5, %%mm3 nt" /* c */
  1577.         "paddw %%mm2, %%mm2 nt" /* 2b */
  1578.         "psubw %%mm2, %%mm3 nt" /* c - 2b */
  1579.         "movq %%mm6, %%mm2 nt" /* FGHIJKLM */
  1580.         "psrlq $24, %%mm6 nt" /* IJKLM000 */
  1581.         "punpcklbw %%mm7, %%mm2 nt" /* 0F0G0H0I */
  1582.         "punpcklbw %%mm7, %%mm6 nt" /* 0I0J0K0L */
  1583.         "pmullw "MANGLE(ff_pw_3)", %%mm3 nt" /* 3c - 6b */
  1584.         "paddw %%mm2, %%mm1 nt" /* a */
  1585.         "paddw %%mm6, %%mm4 nt" /* d */
  1586.         "pmullw "MANGLE(ff_pw_20)", %%mm1 nt" /* 20a */
  1587.         "psubw %%mm4, %%mm3 nt" /* - 6b +3c - d */
  1588.         "paddw %6, %%mm1 nt"
  1589.         "paddw %%mm1, %%mm3 nt" /* 20a - 6b +3c - d */
  1590.         "psraw $5, %%mm3 nt"
  1591.         "movq %5, %%mm1 nt"
  1592.         "packuswb %%mm3, %%mm1 nt"
  1593.         OP_MMX2(%%mm1, (%1),%%mm4, q)
  1594.         /* mm0= GHIJ, mm2=FGHI, mm5=HIJK, mm6=IJKL, mm7=0 */
  1595.         
  1596.         "movq 9(%0), %%mm1 nt" /* JKLMNOPQ */
  1597.         "movq %%mm1, %%mm4 nt" /* JKLMNOPQ */
  1598.         "movq %%mm1, %%mm3 nt" /* JKLMNOPQ */
  1599.         "psrlq $8, %%mm1 nt" /* KLMNOPQ0 */
  1600.         "psrlq $16, %%mm4 nt" /* LMNOPQ00 */
  1601.         "punpcklbw %%mm7, %%mm1 nt" /* 0K0L0M0N */
  1602.         "punpcklbw %%mm7, %%mm4 nt" /* 0L0M0N0O */
  1603.         "paddw %%mm1, %%mm5 nt" /* b */
  1604.         "paddw %%mm4, %%mm0 nt" /* c */
  1605.         "paddw %%mm5, %%mm5 nt" /* 2b */
  1606.         "psubw %%mm5, %%mm0 nt" /* c - 2b */
  1607.         "movq %%mm3, %%mm5 nt" /* JKLMNOPQ */
  1608.         "psrlq $24, %%mm3 nt" /* MNOPQ000 */
  1609.         "pmullw "MANGLE(ff_pw_3)", %%mm0 nt" /* 3c - 6b */
  1610.         "punpcklbw %%mm7, %%mm3 nt" /* 0M0N0O0P */
  1611.         "paddw %%mm3, %%mm2 nt" /* d */
  1612.         "psubw %%mm2, %%mm0 nt" /* -6b + 3c - d */
  1613.         "movq %%mm5, %%mm2 nt" /* JKLMNOPQ */
  1614.         "punpcklbw %%mm7, %%mm2 nt" /* 0J0K0L0M */
  1615.         "punpckhbw %%mm7, %%mm5 nt" /* 0N0O0P0Q */
  1616.         "paddw %%mm2, %%mm6 nt" /* a */
  1617.         "pmullw "MANGLE(ff_pw_20)", %%mm6 nt" /* 20a */
  1618.         "paddw %6, %%mm0 nt"
  1619.         "paddw %%mm6, %%mm0 nt" /* 20a - 6b + 3c - d */
  1620.         "psraw $5, %%mm0 nt"
  1621.         /* mm1=KLMN, mm2=JKLM, mm3=MNOP, mm4=LMNO, mm5=NOPQ mm7=0 */
  1622.         
  1623.         "paddw %%mm5, %%mm3 nt" /* a */
  1624.         "pshufw $0xF9, %%mm5, %%mm6 nt" /* 0O0P0Q0Q */
  1625.         "paddw %%mm4, %%mm6 nt" /* b */
  1626.         "pshufw $0xBE, %%mm5, %%mm4 nt" /* 0P0Q0Q0P */
  1627.         "pshufw $0x6F, %%mm5, %%mm5 nt" /* 0Q0Q0P0O */
  1628.         "paddw %%mm1, %%mm4 nt" /* c */
  1629.         "paddw %%mm2, %%mm5 nt" /* d */
  1630.         "paddw %%mm6, %%mm6 nt" /* 2b */
  1631.         "psubw %%mm6, %%mm4 nt" /* c - 2b */
  1632.         "pmullw "MANGLE(ff_pw_20)", %%mm3 nt" /* 20a */
  1633.         "pmullw "MANGLE(ff_pw_3)", %%mm4 nt" /* 3c - 6b */
  1634.         "psubw %%mm5, %%mm3 nt" /* -6b + 3c - d */
  1635.         "paddw %6, %%mm4 nt"
  1636.         "paddw %%mm3, %%mm4 nt" /* 20a - 6b + 3c - d */
  1637.         "psraw $5, %%mm4 nt"
  1638.         "packuswb %%mm4, %%mm0 nt"
  1639.         OP_MMX2(%%mm0, 8(%1), %%mm4, q)
  1640.         
  1641.         "add %3, %0 nt"
  1642.         "add %4, %1 nt"
  1643.         "decl %2 nt"
  1644.         " jnz 1b nt"
  1645.         : "+a"(src), "+c"(dst), "+m"(h)
  1646.         : "d"((long)srcStride), "S"((long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(temp), "m"(ROUNDER)
  1647.         : "memory"
  1648.     );
  1649. }
  1650. static void OPNAME ## mpeg4_qpel16_h_lowpass_3dnow(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){
  1651.     int i;
  1652.     int16_t temp[16];
  1653.     /* quick HACK, XXX FIXME MUST be optimized */
  1654.     for(i=0; i<h; i++)
  1655.     {
  1656.         temp[ 0]= (src[ 0]+src[ 1])*20 - (src[ 0]+src[ 2])*6 + (src[ 1]+src[ 3])*3 - (src[ 2]+src[ 4]);
  1657.         temp[ 1]= (src[ 1]+src[ 2])*20 - (src[ 0]+src[ 3])*6 + (src[ 0]+src[ 4])*3 - (src[ 1]+src[ 5]);
  1658.         temp[ 2]= (src[ 2]+src[ 3])*20 - (src[ 1]+src[ 4])*6 + (src[ 0]+src[ 5])*3 - (src[ 0]+src[ 6]);
  1659.         temp[ 3]= (src[ 3]+src[ 4])*20 - (src[ 2]+src[ 5])*6 + (src[ 1]+src[ 6])*3 - (src[ 0]+src[ 7]);
  1660.         temp[ 4]= (src[ 4]+src[ 5])*20 - (src[ 3]+src[ 6])*6 + (src[ 2]+src[ 7])*3 - (src[ 1]+src[ 8]);
  1661.         temp[ 5]= (src[ 5]+src[ 6])*20 - (src[ 4]+src[ 7])*6 + (src[ 3]+src[ 8])*3 - (src[ 2]+src[ 9]);
  1662.         temp[ 6]= (src[ 6]+src[ 7])*20 - (src[ 5]+src[ 8])*6 + (src[ 4]+src[ 9])*3 - (src[ 3]+src[10]);
  1663.         temp[ 7]= (src[ 7]+src[ 8])*20 - (src[ 6]+src[ 9])*6 + (src[ 5]+src[10])*3 - (src[ 4]+src[11]);
  1664.         temp[ 8]= (src[ 8]+src[ 9])*20 - (src[ 7]+src[10])*6 + (src[ 6]+src[11])*3 - (src[ 5]+src[12]);
  1665.         temp[ 9]= (src[ 9]+src[10])*20 - (src[ 8]+src[11])*6 + (src[ 7]+src[12])*3 - (src[ 6]+src[13]);
  1666.         temp[10]= (src[10]+src[11])*20 - (src[ 9]+src[12])*6 + (src[ 8]+src[13])*3 - (src[ 7]+src[14]);
  1667.         temp[11]= (src[11]+src[12])*20 - (src[10]+src[13])*6 + (src[ 9]+src[14])*3 - (src[ 8]+src[15]);
  1668.         temp[12]= (src[12]+src[13])*20 - (src[11]+src[14])*6 + (src[10]+src[15])*3 - (src[ 9]+src[16]);
  1669.         temp[13]= (src[13]+src[14])*20 - (src[12]+src[15])*6 + (src[11]+src[16])*3 - (src[10]+src[16]);
  1670.         temp[14]= (src[14]+src[15])*20 - (src[13]+src[16])*6 + (src[12]+src[16])*3 - (src[11]+src[15]);
  1671.         temp[15]= (src[15]+src[16])*20 - (src[14]+src[16])*6 + (src[13]+src[15])*3 - (src[12]+src[14]);
  1672.         asm volatile(
  1673.             "movq (%0), %%mm0 nt"
  1674.             "movq 8(%0), %%mm1 nt"
  1675.             "paddw %2, %%mm0 nt"
  1676.             "paddw %2, %%mm1 nt"
  1677.             "psraw $5, %%mm0 nt"
  1678.             "psraw $5, %%mm1 nt"
  1679.             "packuswb %%mm1, %%mm0 nt"
  1680.             OP_3DNOW(%%mm0, (%1), %%mm1, q)
  1681.             "movq 16(%0), %%mm0 nt"
  1682.             "movq 24(%0), %%mm1 nt"
  1683.             "paddw %2, %%mm0 nt"
  1684.             "paddw %2, %%mm1 nt"
  1685.             "psraw $5, %%mm0 nt"
  1686.             "psraw $5, %%mm1 nt"
  1687.             "packuswb %%mm1, %%mm0 nt"
  1688.             OP_3DNOW(%%mm0, 8(%1), %%mm1, q)
  1689.             :: "r"(temp), "r"(dst), "m"(ROUNDER)
  1690.             : "memory"
  1691.         );
  1692.         dst+=dstStride;
  1693.         src+=srcStride;
  1694.     }
  1695. }
  1696. static void OPNAME ## mpeg4_qpel8_h_lowpass_mmx2(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){
  1697.     uint64_t temp;
  1698.     asm volatile(
  1699.         "pxor %%mm7, %%mm7 nt"
  1700.         "1: nt"
  1701.         "movq  (%0), %%mm0 nt" /* ABCDEFGH */
  1702.         "movq %%mm0, %%mm1 nt" /* ABCDEFGH */
  1703.         "movq %%mm0, %%mm2 nt" /* ABCDEFGH */
  1704.         "punpcklbw %%mm7, %%mm0 nt" /* 0A0B0C0D */
  1705.         "punpckhbw %%mm7, %%mm1 nt" /* 0E0F0G0H */
  1706.         "pshufw $0x90, %%mm0, %%mm5 nt" /* 0A0A0B0C */
  1707.         "pshufw $0x41, %%mm0, %%mm6 nt" /* 0B0A0A0B */
  1708.         "movq %%mm2, %%mm3 nt" /* ABCDEFGH */
  1709.         "movq %%mm2, %%mm4 nt" /* ABCDEFGH */
  1710.         "psllq $8, %%mm2 nt" /* 0ABCDEFG */
  1711.         "psllq $16, %%mm3 nt" /* 00ABCDEF */
  1712.         "psllq $24, %%mm4 nt" /* 000ABCDE */
  1713.         "punpckhbw %%mm7, %%mm2 nt" /* 0D0E0F0G */
  1714.         "punpckhbw %%mm7, %%mm3 nt" /* 0C0D0E0F */
  1715.         "punpckhbw %%mm7, %%mm4 nt" /* 0B0C0D0E */
  1716.         "paddw %%mm3, %%mm5 nt" /* b */
  1717.         "paddw %%mm2, %%mm6 nt" /* c */
  1718.         "paddw %%mm5, %%mm5 nt" /* 2b */
  1719.         "psubw %%mm5, %%mm6 nt" /* c - 2b */
  1720.         "pshufw $0x06, %%mm0, %%mm5 nt" /* 0C0B0A0A */
  1721.         "pmullw "MANGLE(ff_pw_3)", %%mm6 nt" /* 3c - 6b */
  1722.         "paddw %%mm4, %%mm0 nt" /* a */
  1723.         "paddw %%mm1, %%mm5 nt" /* d */
  1724.         "pmullw "MANGLE(ff_pw_20)", %%mm0 nt" /* 20a */
  1725.         "psubw %%mm5, %%mm0 nt" /* 20a - d */
  1726.         "paddw %6, %%mm6 nt"
  1727.         "paddw %%mm6, %%mm0 nt" /* 20a - 6b + 3c - d */
  1728.         "psraw $5, %%mm0 nt"
  1729.         /* mm1=EFGH, mm2=DEFG, mm3=CDEF, mm4=BCDE, mm7=0 */
  1730.         
  1731.         "movd 5(%0), %%mm5 nt" /* FGHI */
  1732.         "punpcklbw %%mm7, %%mm5 nt" /* 0F0G0H0I */
  1733.         "pshufw $0xF9, %%mm5, %%mm6 nt" /* 0G0H0I0I */
  1734.         "paddw %%mm5, %%mm1 nt" /* a */
  1735.         "paddw %%mm6, %%mm2 nt" /* b */
  1736.         "pshufw $0xBE, %%mm5, %%mm6 nt" /* 0H0I0I0H */
  1737.         "pshufw $0x6F, %%mm5, %%mm5 nt" /* 0I0I0H0G */
  1738.         "paddw %%mm6, %%mm3 nt" /* c */
  1739.         "paddw %%mm5, %%mm4 nt" /* d */
  1740.         "paddw %%mm2, %%mm2 nt" /* 2b */
  1741.         "psubw %%mm2, %%mm3 nt" /* c - 2b */
  1742.         "pmullw "MANGLE(ff_pw_20)", %%mm1 nt" /* 20a */
  1743.         "pmullw "MANGLE(ff_pw_3)", %%mm3 nt" /* 3c - 6b */
  1744.         "psubw %%mm4, %%mm3 nt" /* -6b + 3c - d */
  1745.         "paddw %6, %%mm1 nt"
  1746.         "paddw %%mm1, %%mm3 nt" /* 20a - 6b + 3c - d */
  1747.         "psraw $5, %%mm3 nt"
  1748.         "packuswb %%mm3, %%mm0 nt"
  1749.         OP_MMX2(%%mm0, (%1), %%mm4, q)
  1750.         
  1751.         "add %3, %0 nt"
  1752.         "add %4, %1 nt"
  1753.         "decl %2 nt"
  1754.         " jnz 1b nt"
  1755.         : "+a"(src), "+c"(dst), "+m"(h)
  1756.         : "S"((long)srcStride), "D"((long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(temp), "m"(ROUNDER)
  1757.         : "memory"
  1758.     );
  1759. }
  1760. static void OPNAME ## mpeg4_qpel8_h_lowpass_3dnow(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){
  1761.     int i;
  1762.     int16_t temp[8];
  1763.     /* quick HACK, XXX FIXME MUST be optimized */
  1764.     for(i=0; i<h; i++)
  1765.     {
  1766.         temp[ 0]= (src[ 0]+src[ 1])*20 - (src[ 0]+src[ 2])*6 + (src[ 1]+src[ 3])*3 - (src[ 2]+src[ 4]);
  1767.         temp[ 1]= (src[ 1]+src[ 2])*20 - (src[ 0]+src[ 3])*6 + (src[ 0]+src[ 4])*3 - (src[ 1]+src[ 5]);
  1768.         temp[ 2]= (src[ 2]+src[ 3])*20 - (src[ 1]+src[ 4])*6 + (src[ 0]+src[ 5])*3 - (src[ 0]+src[ 6]);
  1769.         temp[ 3]= (src[ 3]+src[ 4])*20 - (src[ 2]+src[ 5])*6 + (src[ 1]+src[ 6])*3 - (src[ 0]+src[ 7]);
  1770.         temp[ 4]= (src[ 4]+src[ 5])*20 - (src[ 3]+src[ 6])*6 + (src[ 2]+src[ 7])*3 - (src[ 1]+src[ 8]);
  1771.         temp[ 5]= (src[ 5]+src[ 6])*20 - (src[ 4]+src[ 7])*6 + (src[ 3]+src[ 8])*3 - (src[ 2]+src[ 8]);
  1772.         temp[ 6]= (src[ 6]+src[ 7])*20 - (src[ 5]+src[ 8])*6 + (src[ 4]+src[ 8])*3 - (src[ 3]+src[ 7]);
  1773.         temp[ 7]= (src[ 7]+src[ 8])*20 - (src[ 6]+src[ 8])*6 + (src[ 5]+src[ 7])*3 - (src[ 4]+src[ 6]);
  1774.         asm volatile(
  1775.             "movq (%0), %%mm0 nt"
  1776.             "movq 8(%0), %%mm1 nt"
  1777.             "paddw %2, %%mm0 nt"
  1778.             "paddw %2, %%mm1 nt"
  1779.             "psraw $5, %%mm0 nt"
  1780.             "psraw $5, %%mm1 nt"
  1781.             "packuswb %%mm1, %%mm0 nt"
  1782.             OP_3DNOW(%%mm0, (%1), %%mm1, q)
  1783.             :: "r"(temp), "r"(dst), "m"(ROUNDER)
  1784.             :"memory"
  1785.         );
  1786.         dst+=dstStride;
  1787.         src+=srcStride;
  1788.     }
  1789. }
  1790. #define QPEL_OP(OPNAME, ROUNDER, RND, OP, MMX)
  1791. static void OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){
  1792.     uint64_t temp[17*4];
  1793.     uint64_t *temp_ptr= temp;
  1794.     int count= 17;
  1795.     /*FIXME unroll */
  1796.     asm volatile(
  1797.         "pxor %%mm7, %%mm7 nt"
  1798.         "1: nt"
  1799.         "movq (%0), %%mm0 nt"
  1800.         "movq (%0), %%mm1 nt"
  1801.         "movq 8(%0), %%mm2 nt"
  1802.         "movq 8(%0), %%mm3 nt"
  1803.         "punpcklbw %%mm7, %%mm0 nt"
  1804.         "punpckhbw %%mm7, %%mm1 nt"
  1805.         "punpcklbw %%mm7, %%mm2 nt"
  1806.         "punpckhbw %%mm7, %%mm3 nt"
  1807.         "movq %%mm0, (%1) nt"
  1808.         "movq %%mm1, 17*8(%1) nt"
  1809.         "movq %%mm2, 2*17*8(%1) nt"
  1810.         "movq %%mm3, 3*17*8(%1) nt"
  1811.         "add $8, %1 nt"
  1812.         "add %3, %0 nt"
  1813.         "decl %2 nt"
  1814.         " jnz 1b nt"
  1815.         : "+r" (src), "+r" (temp_ptr), "+r"(count)
  1816.         : "r" ((long)srcStride)
  1817.         : "memory"
  1818.     );
  1819.     
  1820.     temp_ptr= temp;
  1821.     count=4;
  1822.     
  1823. /*FIXME reorder for speed */
  1824.     asm volatile(
  1825.         /*"pxor %%mm7, %%mm7 nt"*/
  1826.         "1: nt"
  1827.         "movq (%0), %%mm0 nt"
  1828.         "movq 8(%0), %%mm1 nt"
  1829.         "movq 16(%0), %%mm2 nt"
  1830.         "movq 24(%0), %%mm3 nt"
  1831.         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 16(%0),  8(%0),   (%0), 32(%0), (%1), OP)
  1832.         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5,  8(%0),   (%0),   (%0), 40(%0), (%1, %3), OP)
  1833.         "add %4, %1 nt"
  1834.         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5,   (%0),   (%0),  8(%0), 48(%0), (%1), OP)
  1835.         
  1836.         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5,   (%0),  8(%0), 16(%0), 56(%0), (%1, %3), OP)
  1837.         "add %4, %1 nt"
  1838.         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5,  8(%0), 16(%0), 24(%0), 64(%0), (%1), OP)
  1839.         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 16(%0), 24(%0), 32(%0), 72(%0), (%1, %3), OP)
  1840.         "add %4, %1 nt"
  1841.         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 24(%0), 32(%0), 40(%0), 80(%0), (%1), OP)
  1842.         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 32(%0), 40(%0), 48(%0), 88(%0), (%1, %3), OP)
  1843.         "add %4, %1 nt"
  1844.         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 40(%0), 48(%0), 56(%0), 96(%0), (%1), OP)
  1845.         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 48(%0), 56(%0), 64(%0),104(%0), (%1, %3), OP)
  1846.         "add %4, %1 nt"
  1847.         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 56(%0), 64(%0), 72(%0),112(%0), (%1), OP)
  1848.         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 64(%0), 72(%0), 80(%0),120(%0), (%1, %3), OP)
  1849.         "add %4, %1 nt"
  1850.         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 72(%0), 80(%0), 88(%0),128(%0), (%1), OP)
  1851.         
  1852.         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 80(%0), 88(%0), 96(%0),128(%0), (%1, %3), OP)
  1853.         "add %4, %1 nt"  
  1854.         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 88(%0), 96(%0),104(%0),120(%0), (%1), OP)
  1855.         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 96(%0),104(%0),112(%0),112(%0), (%1, %3), OP)
  1856.         
  1857.         "add $136, %0 nt"
  1858.         "add %6, %1 nt"
  1859.         "decl %2 nt"
  1860.         " jnz 1b nt"
  1861.         
  1862.         : "+r"(temp_ptr), "+r"(dst), "+g"(count)
  1863.         : "r"((long)dstStride), "r"(2*(long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(ROUNDER), "g"(4-14*(long)dstStride)
  1864.         :"memory"
  1865.     );
  1866. }
  1867. static void OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){
  1868.     uint64_t temp[9*2];
  1869.     uint64_t *temp_ptr= temp;
  1870.     int count= 9;
  1871.     /*FIXME unroll */
  1872.     asm volatile(
  1873.         "pxor %%mm7, %%mm7 nt"
  1874.         "1: nt"
  1875.         "movq (%0), %%mm0 nt"
  1876.         "movq (%0), %%mm1 nt"
  1877.         "punpcklbw %%mm7, %%mm0 nt"
  1878.         "punpckhbw %%mm7, %%mm1 nt"
  1879.         "movq %%mm0, (%1) nt"
  1880.         "movq %%mm1, 9*8(%1) nt"
  1881.         "add $8, %1 nt"
  1882.         "add %3, %0 nt"
  1883.         "decl %2 nt"
  1884.         " jnz 1b nt"
  1885.         : "+r" (src), "+r" (temp_ptr), "+r"(count)
  1886.         : "r" ((long)srcStride)
  1887.         : "memory"
  1888.     );
  1889.     
  1890.     temp_ptr= temp;
  1891.     count=2;
  1892.     
  1893. /*FIXME reorder for speed */
  1894.     asm volatile(
  1895.         /*"pxor %%mm7, %%mm7 nt"*/
  1896.         "1: nt"
  1897.         "movq (%0), %%mm0 nt"
  1898.         "movq 8(%0), %%mm1 nt"
  1899.         "movq 16(%0), %%mm2 nt"
  1900.         "movq 24(%0), %%mm3 nt"
  1901.         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 16(%0),  8(%0),   (%0), 32(%0), (%1), OP)
  1902.         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5,  8(%0),   (%0),   (%0), 40(%0), (%1, %3), OP)
  1903.         "add %4, %1 nt"
  1904.         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5,   (%0),   (%0),  8(%0), 48(%0), (%1), OP)
  1905.         
  1906.         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5,   (%0),  8(%0), 16(%0), 56(%0), (%1, %3), OP)
  1907.         "add %4, %1 nt"
  1908.         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5,  8(%0), 16(%0), 24(%0), 64(%0), (%1), OP)
  1909.         
  1910.         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 16(%0), 24(%0), 32(%0), 64(%0), (%1, %3), OP)
  1911.         "add %4, %1 nt"
  1912.         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 24(%0), 32(%0), 40(%0), 56(%0), (%1), OP)
  1913.         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 32(%0), 40(%0), 48(%0), 48(%0), (%1, %3), OP)
  1914.                 
  1915.         "add $72, %0 nt"
  1916.         "add %6, %1 nt"
  1917.         "decl %2 nt"
  1918.         " jnz 1b nt"
  1919.          
  1920.         : "+r"(temp_ptr), "+r"(dst), "+g"(count)
  1921.         : "r"((long)dstStride), "r"(2*(long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(ROUNDER), "g"(4-6*(long)dstStride)
  1922.         : "memory"
  1923.    );
  1924. }
  1925. static void OPNAME ## qpel8_mc00_ ## MMX (uint8_t *dst, uint8_t *src, int stride){
  1926.     OPNAME ## pixels8_mmx(dst, src, stride, 8);
  1927. }
  1928. static void OPNAME ## qpel8_mc10_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  1929.     uint64_t temp[8];
  1930.     uint8_t * const half= (uint8_t*)temp;
  1931.     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, stride, 8);
  1932.     OPNAME ## pixels8_l2_ ## MMX(dst, src, half, stride, stride, 8);
  1933. }
  1934. static void OPNAME ## qpel8_mc20_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  1935.     OPNAME ## mpeg4_qpel8_h_lowpass_ ## MMX(dst, src, stride, stride, 8);
  1936. }
  1937. static void OPNAME ## qpel8_mc30_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  1938.     uint64_t temp[8];
  1939.     uint8_t * const half= (uint8_t*)temp;
  1940.     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, stride, 8);
  1941.     OPNAME ## pixels8_l2_ ## MMX(dst, src+1, half, stride, stride, 8);
  1942. }
  1943. static void OPNAME ## qpel8_mc01_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  1944.     uint64_t temp[8];
  1945.     uint8_t * const half= (uint8_t*)temp;
  1946.     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, 8, stride);
  1947.     OPNAME ## pixels8_l2_ ## MMX(dst, src, half, stride, stride, 8);
  1948. }
  1949. static void OPNAME ## qpel8_mc02_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  1950.     OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, src, stride, stride);
  1951. }
  1952. static void OPNAME ## qpel8_mc03_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  1953.     uint64_t temp[8];
  1954.     uint8_t * const half= (uint8_t*)temp;
  1955.     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, 8, stride);
  1956.     OPNAME ## pixels8_l2_ ## MMX(dst, src+stride, half, stride, stride, 8);
  1957. }
  1958. static void OPNAME ## qpel8_mc11_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  1959.     uint64_t half[8 + 9];
  1960.     uint8_t * const halfH= ((uint8_t*)half) + 64;
  1961.     uint8_t * const halfHV= ((uint8_t*)half);
  1962.     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);
  1963.     put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, stride, 9);
  1964.     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);
  1965.     OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, stride, 8, 8);
  1966. }
  1967. static void OPNAME ## qpel8_mc31_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  1968.     uint64_t half[8 + 9];
  1969.     uint8_t * const halfH= ((uint8_t*)half) + 64;
  1970.     uint8_t * const halfHV= ((uint8_t*)half);
  1971.     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);
  1972.     put ## RND ## pixels8_l2_ ## MMX(halfH, src+1, halfH, 8, stride, 9);
  1973.     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);
  1974.     OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, stride, 8, 8);
  1975. }
  1976. static void OPNAME ## qpel8_mc13_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  1977.     uint64_t half[8 + 9];
  1978.     uint8_t * const halfH= ((uint8_t*)half) + 64;
  1979.     uint8_t * const halfHV= ((uint8_t*)half);
  1980.     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);
  1981.     put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, stride, 9);
  1982.     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);
  1983.     OPNAME ## pixels8_l2_ ## MMX(dst, halfH+8, halfHV, stride, 8, 8);
  1984. }
  1985. static void OPNAME ## qpel8_mc33_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  1986.     uint64_t half[8 + 9];
  1987.     uint8_t * const halfH= ((uint8_t*)half) + 64;
  1988.     uint8_t * const halfHV= ((uint8_t*)half);
  1989.     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);
  1990.     put ## RND ## pixels8_l2_ ## MMX(halfH, src+1, halfH, 8, stride, 9);
  1991.     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);
  1992.     OPNAME ## pixels8_l2_ ## MMX(dst, halfH+8, halfHV, stride, 8, 8);
  1993. }
  1994. static void OPNAME ## qpel8_mc21_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  1995.     uint64_t half[8 + 9];
  1996.     uint8_t * const halfH= ((uint8_t*)half) + 64;
  1997.     uint8_t * const halfHV= ((uint8_t*)half);
  1998.     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);
  1999.     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);
  2000.     OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, stride, 8, 8);
  2001. }
  2002. static void OPNAME ## qpel8_mc23_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2003.     uint64_t half[8 + 9];
  2004.     uint8_t * const halfH= ((uint8_t*)half) + 64;
  2005.     uint8_t * const halfHV= ((uint8_t*)half);
  2006.     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);
  2007.     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);
  2008.     OPNAME ## pixels8_l2_ ## MMX(dst, halfH+8, halfHV, stride, 8, 8);
  2009. }
  2010. static void OPNAME ## qpel8_mc12_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2011.     uint64_t half[8 + 9];
  2012.     uint8_t * const halfH= ((uint8_t*)half);
  2013.     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);
  2014.     put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, stride, 9);
  2015.     OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);
  2016. }
  2017. static void OPNAME ## qpel8_mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2018.     uint64_t half[8 + 9];
  2019.     uint8_t * const halfH= ((uint8_t*)half);
  2020.     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);
  2021.     put ## RND ## pixels8_l2_ ## MMX(halfH, src+1, halfH, 8, stride, 9);
  2022.     OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);
  2023. }
  2024. static void OPNAME ## qpel8_mc22_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2025.     uint64_t half[9];
  2026.     uint8_t * const halfH= ((uint8_t*)half);
  2027.     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);
  2028.     OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);
  2029. }
  2030. static void OPNAME ## qpel16_mc00_ ## MMX (uint8_t *dst, uint8_t *src, int stride){
  2031.     OPNAME ## pixels16_mmx(dst, src, stride, 16);
  2032. }
  2033. static void OPNAME ## qpel16_mc10_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2034.     uint64_t temp[32];
  2035.     uint8_t * const half= (uint8_t*)temp;
  2036.     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, stride, 16);
  2037.     OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, stride, 16);
  2038. }
  2039. static void OPNAME ## qpel16_mc20_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2040.     OPNAME ## mpeg4_qpel16_h_lowpass_ ## MMX(dst, src, stride, stride, 16);
  2041. }
  2042. static void OPNAME ## qpel16_mc30_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2043.     uint64_t temp[32];
  2044.     uint8_t * const half= (uint8_t*)temp;
  2045.     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, stride, 16);
  2046.     OPNAME ## pixels16_l2_ ## MMX(dst, src+1, half, stride, stride, 16);
  2047. }
  2048. static void OPNAME ## qpel16_mc01_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2049.     uint64_t temp[32];
  2050.     uint8_t * const half= (uint8_t*)temp;
  2051.     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, stride);
  2052.     OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, stride, 16);
  2053. }
  2054. static void OPNAME ## qpel16_mc02_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2055.     OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, src, stride, stride);
  2056. }
  2057. static void OPNAME ## qpel16_mc03_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2058.     uint64_t temp[32];
  2059.     uint8_t * const half= (uint8_t*)temp;
  2060.     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, stride);
  2061.     OPNAME ## pixels16_l2_ ## MMX(dst, src+stride, half, stride, stride, 16);
  2062. }
  2063. static void OPNAME ## qpel16_mc11_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2064.     uint64_t half[16*2 + 17*2];
  2065.     uint8_t * const halfH= ((uint8_t*)half) + 256;
  2066.     uint8_t * const halfHV= ((uint8_t*)half);
  2067.     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);
  2068.     put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, stride, 17);
  2069.     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);
  2070.     OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, stride, 16, 16);
  2071. }
  2072. static void OPNAME ## qpel16_mc31_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2073.     uint64_t half[16*2 + 17*2];
  2074.     uint8_t * const halfH= ((uint8_t*)half) + 256;
  2075.     uint8_t * const halfHV= ((uint8_t*)half);
  2076.     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);
  2077.     put ## RND ## pixels16_l2_ ## MMX(halfH, src+1, halfH, 16, stride, 17);
  2078.     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);
  2079.     OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, stride, 16, 16);
  2080. }
  2081. static void OPNAME ## qpel16_mc13_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2082.     uint64_t half[16*2 + 17*2];
  2083.     uint8_t * const halfH= ((uint8_t*)half) + 256;
  2084.     uint8_t * const halfHV= ((uint8_t*)half);
  2085.     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);
  2086.     put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, stride, 17);
  2087.     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);
  2088.     OPNAME ## pixels16_l2_ ## MMX(dst, halfH+16, halfHV, stride, 16, 16);
  2089. }
  2090. static void OPNAME ## qpel16_mc33_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2091.     uint64_t half[16*2 + 17*2];
  2092.     uint8_t * const halfH= ((uint8_t*)half) + 256;
  2093.     uint8_t * const halfHV= ((uint8_t*)half);
  2094.     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);
  2095.     put ## RND ## pixels16_l2_ ## MMX(halfH, src+1, halfH, 16, stride, 17);
  2096.     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);
  2097.     OPNAME ## pixels16_l2_ ## MMX(dst, halfH+16, halfHV, stride, 16, 16);
  2098. }
  2099. static void OPNAME ## qpel16_mc21_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2100.     uint64_t half[16*2 + 17*2];
  2101.     uint8_t * const halfH= ((uint8_t*)half) + 256;
  2102.     uint8_t * const halfHV= ((uint8_t*)half);
  2103.     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);
  2104.     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);
  2105.     OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, stride, 16, 16);
  2106. }
  2107. static void OPNAME ## qpel16_mc23_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2108.     uint64_t half[16*2 + 17*2];
  2109.     uint8_t * const halfH= ((uint8_t*)half) + 256;
  2110.     uint8_t * const halfHV= ((uint8_t*)half);
  2111.     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);
  2112.     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);
  2113.     OPNAME ## pixels16_l2_ ## MMX(dst, halfH+16, halfHV, stride, 16, 16);
  2114. }
  2115. static void OPNAME ## qpel16_mc12_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2116.     uint64_t half[17*2];
  2117.     uint8_t * const halfH= ((uint8_t*)half);
  2118.     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);
  2119.     put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, stride, 17);
  2120.     OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);
  2121. }
  2122. static void OPNAME ## qpel16_mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2123.     uint64_t half[17*2];
  2124.     uint8_t * const halfH= ((uint8_t*)half);
  2125.     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);
  2126.     put ## RND ## pixels16_l2_ ## MMX(halfH, src+1, halfH, 16, stride, 17);
  2127.     OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);
  2128. }
  2129. static void OPNAME ## qpel16_mc22_ ## MMX(uint8_t *dst, uint8_t *src, int stride){
  2130.     uint64_t half[17*2];
  2131.     uint8_t * const halfH= ((uint8_t*)half);
  2132.     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);
  2133.     OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);
  2134. }
  2135. #define PUT_OP(a,b,temp, size) "mov" #size " " #a ", " #b " nt"
  2136. #define AVG_3DNOW_OP(a,b,temp, size) 
  2137. "mov" #size " " #b ", " #temp " nt"
  2138. "pavgusb " #temp ", " #a " nt"
  2139. "mov" #size " " #a ", " #b " nt"
  2140. #define AVG_MMX2_OP(a,b,temp, size) 
  2141. "mov" #size " " #b ", " #temp " nt"
  2142. "pavgb " #temp ", " #a " nt"
  2143. "mov" #size " " #a ", " #b " nt"
  2144. QPEL_BASE(put_       , ff_pw_16, _       , PUT_OP, PUT_OP)
  2145. QPEL_BASE(avg_       , ff_pw_16, _       , AVG_MMX2_OP, AVG_3DNOW_OP)
  2146. QPEL_BASE(put_no_rnd_, ff_pw_15, _no_rnd_, PUT_OP, PUT_OP)
  2147. QPEL_OP(put_       , ff_pw_16, _       , PUT_OP, 3dnow)
  2148. QPEL_OP(avg_       , ff_pw_16, _       , AVG_3DNOW_OP, 3dnow)
  2149. QPEL_OP(put_no_rnd_, ff_pw_15, _no_rnd_, PUT_OP, 3dnow)
  2150. QPEL_OP(put_       , ff_pw_16, _       , PUT_OP, mmx2)
  2151. QPEL_OP(avg_       , ff_pw_16, _       , AVG_MMX2_OP, mmx2)
  2152. QPEL_OP(put_no_rnd_, ff_pw_15, _no_rnd_, PUT_OP, mmx2)
  2153. #if 0
  2154. static void just_return() { return; }
  2155. #endif
  2156. #define SET_QPEL_FUNC(postfix1, postfix2) 
  2157.     c->put_ ## postfix1 = put_ ## postfix2;
  2158.     c->put_no_rnd_ ## postfix1 = put_no_rnd_ ## postfix2;
  2159.     c->avg_ ## postfix1 = avg_ ## postfix2;
  2160. static int try_8x8basis_mmx(int16_t rem[64], int16_t weight[64], int16_t basis[64], int scale){
  2161.     long i=0;
  2162.     
  2163.     assert(ABS(scale) < 256);
  2164.     scale<<= 16 + 1 - BASIS_SHIFT + RECON_SHIFT;
  2165.     asm volatile(
  2166.         "pcmpeqw %%mm6, %%mm6 nt" // -1w
  2167.         "psrlw $15, %%mm6 nt" //  1w
  2168.         "pxor %%mm7, %%mm7 nt"
  2169.         "movd  %4, %%mm5 nt" 
  2170.         "punpcklwd %%mm5, %%mm5 nt" 
  2171.         "punpcklwd %%mm5, %%mm5 nt" 
  2172.         "1: nt"
  2173.         "movq  (%1, %0), %%mm0 nt" 
  2174.         "movq  8(%1, %0), %%mm1 nt"
  2175.         "pmulhw %%mm5, %%mm0 nt"
  2176.         "pmulhw %%mm5, %%mm1 nt"
  2177.         "paddw %%mm6, %%mm0 nt"
  2178.         "paddw %%mm6, %%mm1 nt"
  2179.         "psraw $1, %%mm0 nt"
  2180.         "psraw $1, %%mm1 nt"
  2181.         "paddw (%2, %0), %%mm0 nt"
  2182.         "paddw 8(%2, %0), %%mm1 nt"
  2183.         "psraw $6, %%mm0 nt"
  2184.         "psraw $6, %%mm1 nt"
  2185.         "pmullw (%3, %0), %%mm0 nt"
  2186.         "pmullw 8(%3, %0), %%mm1 nt"
  2187.         "pmaddwd %%mm0, %%mm0 nt"
  2188.         "pmaddwd %%mm1, %%mm1 nt"
  2189.         "paddd %%mm1, %%mm0 nt"
  2190.         "psrld $4, %%mm0 nt"
  2191.         "paddd %%mm0, %%mm7 nt"
  2192.         "add $16, %0 nt"
  2193.         "cmp $128, %0 nt" //FIXME optimize & bench
  2194.         " jb 1b nt"
  2195.         "movq %%mm7, %%mm6 nt"
  2196.         "psrlq $32, %%mm7 nt"
  2197.         "paddd %%mm6, %%mm7 nt"
  2198.         "psrld $2, %%mm7 nt"
  2199.         "movd %%mm7, %0 nt"
  2200.         
  2201.         : "+r" (i)
  2202.         : "r"(basis), "r"(rem), "r"(weight), "g"(scale)
  2203.     );
  2204.     return i;
  2205. }
  2206. static void add_8x8basis_mmx(int16_t rem[64], int16_t basis[64], int scale){
  2207.     long i=0;
  2208.     
  2209.     if(ABS(scale) < 256){
  2210.         scale<<= 16 + 1 - BASIS_SHIFT + RECON_SHIFT;
  2211.         asm volatile(
  2212.                 "pcmpeqw %%mm6, %%mm6 nt" // -1w
  2213.                 "psrlw $15, %%mm6 nt" //  1w
  2214.                 "movd  %3, %%mm5 nt" 
  2215.                 "punpcklwd %%mm5, %%mm5 nt" 
  2216.                 "punpcklwd %%mm5, %%mm5 nt" 
  2217.                 "1: nt"
  2218.                 "movq  (%1, %0), %%mm0 nt" 
  2219.                 "movq  8(%1, %0), %%mm1 nt"
  2220.                 "pmulhw %%mm5, %%mm0 nt"
  2221.                 "pmulhw %%mm5, %%mm1 nt"
  2222.                 "paddw %%mm6, %%mm0 nt" 
  2223.                 "paddw %%mm6, %%mm1 nt"
  2224.                 "psraw $1, %%mm0 nt"
  2225.                 "psraw $1, %%mm1 nt"
  2226.                 "paddw (%2, %0), %%mm0 nt"
  2227.                 "paddw 8(%2, %0), %%mm1 nt"
  2228.                 "movq %%mm0, (%2, %0) nt"
  2229.                 "movq %%mm1, 8(%2, %0) nt"
  2230.                 "add $16, %0 nt"
  2231.                 "cmp $128, %0 nt" //FIXME optimize & bench
  2232.                 " jb 1b nt"
  2233.                 
  2234.                 : "+r" (i)
  2235.                 : "r"(basis), "r"(rem), "g"(scale)
  2236.         );
  2237.     }else{
  2238.         for(i=0; i<8*8; i++){
  2239.             rem[i] += (basis[i]*scale + (1<<(BASIS_SHIFT - RECON_SHIFT-1)))>>(BASIS_SHIFT - RECON_SHIFT);
  2240.         }    
  2241.     }
  2242. }
  2243. #include "h264dsp_mmx.c"
  2244.     
  2245. /* external functions, from idct_mmx.c */
  2246. void ff_mmx_idct(DCTELEM *block);
  2247. void ff_mmxext_idct(DCTELEM *block);
  2248. void ff_vp3_idct_sse2(int16_t *input_data);
  2249. void ff_vp3_idct_mmx(int16_t *data);
  2250. void ff_vp3_dsp_init_mmx(void);
  2251. /* XXX: those functions should be suppressed ASAP when all IDCTs are
  2252.    converted */
  2253. static void ff_libmpeg2mmx_idct_put(uint8_t *dest, int line_size, DCTELEM *block)
  2254. {
  2255.     ff_mmx_idct (block);
  2256.     put_pixels_clamped_mmx(block, dest, line_size);
  2257. }
  2258. static void ff_libmpeg2mmx_idct_add(uint8_t *dest, int line_size, DCTELEM *block)
  2259. {
  2260.     ff_mmx_idct (block);
  2261.     add_pixels_clamped_mmx(block, dest, line_size);
  2262. }
  2263. static void ff_libmpeg2mmx2_idct_put(uint8_t *dest, int line_size, DCTELEM *block)
  2264. {
  2265.     ff_mmxext_idct (block);
  2266.     put_pixels_clamped_mmx(block, dest, line_size);
  2267. }
  2268. static void ff_libmpeg2mmx2_idct_add(uint8_t *dest, int line_size, DCTELEM *block)
  2269. {
  2270.     ff_mmxext_idct (block);
  2271.     add_pixels_clamped_mmx(block, dest, line_size);
  2272. }
  2273. static void ff_vp3_idct_put_sse2(uint8_t *dest, int line_size, DCTELEM *block)
  2274. {
  2275.     ff_vp3_idct_sse2(block);
  2276.     put_signed_pixels_clamped_mmx(block, dest, line_size);
  2277. }
  2278. static void ff_vp3_idct_add_sse2(uint8_t *dest, int line_size, DCTELEM *block)
  2279. {
  2280.     ff_vp3_idct_sse2(block);
  2281.     add_pixels_clamped_mmx(block, dest, line_size);
  2282. }
  2283. static void ff_vp3_idct_put_mmx(uint8_t *dest, int line_size, DCTELEM *block)
  2284. {
  2285.     ff_vp3_idct_mmx(block);
  2286.     put_signed_pixels_clamped_mmx(block, dest, line_size);
  2287. }
  2288. static void ff_vp3_idct_add_mmx(uint8_t *dest, int line_size, DCTELEM *block)
  2289. {
  2290.     ff_vp3_idct_mmx(block);
  2291.     add_pixels_clamped_mmx(block, dest, line_size);
  2292. }
  2293. #ifdef CONFIG_GPL
  2294. static void ff_idct_xvid_mmx_put(uint8_t *dest, int line_size, DCTELEM *block)
  2295. {
  2296.     ff_idct_xvid_mmx (block);
  2297.     put_pixels_clamped_mmx(block, dest, line_size);
  2298. }
  2299. static void ff_idct_xvid_mmx_add(uint8_t *dest, int line_size, DCTELEM *block)
  2300. {
  2301.     ff_idct_xvid_mmx (block);
  2302.     add_pixels_clamped_mmx(block, dest, line_size);
  2303. }
  2304. static void ff_idct_xvid_mmx2_put(uint8_t *dest, int line_size, DCTELEM *block)
  2305. {
  2306.     ff_idct_xvid_mmx2 (block);
  2307.     put_pixels_clamped_mmx(block, dest, line_size);
  2308. }
  2309. static void ff_idct_xvid_mmx2_add(uint8_t *dest, int line_size, DCTELEM *block)
  2310. {
  2311.     ff_idct_xvid_mmx2 (block);
  2312.     add_pixels_clamped_mmx(block, dest, line_size);
  2313. }
  2314. #endif
  2315.     
  2316. void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx)
  2317. {
  2318.     mm_flags = mm_support();
  2319.     if (avctx->dsp_mask) {
  2320. if (avctx->dsp_mask & FF_MM_FORCE)
  2321.     mm_flags |= (avctx->dsp_mask & 0xffff);
  2322. else
  2323.     mm_flags &= ~(avctx->dsp_mask & 0xffff);
  2324.     }
  2325. #if 0
  2326.     av_log(avctx, AV_LOG_INFO, "libavcodec: CPU flags:");
  2327.     if (mm_flags & MM_MMX)
  2328.         av_log(avctx, AV_LOG_INFO, " mmx");
  2329.     if (mm_flags & MM_MMXEXT)
  2330.         av_log(avctx, AV_LOG_INFO, " mmxext");
  2331.     if (mm_flags & MM_3DNOW)
  2332.         av_log(avctx, AV_LOG_INFO, " 3dnow");
  2333.     if (mm_flags & MM_SSE)
  2334.         av_log(avctx, AV_LOG_INFO, " sse");
  2335.     if (mm_flags & MM_SSE2)
  2336.         av_log(avctx, AV_LOG_INFO, " sse2");
  2337.     av_log(avctx, AV_LOG_INFO, "n");
  2338. #endif
  2339.     if (mm_flags & MM_MMX) {
  2340.         const int idct_algo= avctx->idct_algo;
  2341. #ifdef CONFIG_ENCODERS
  2342.         const int dct_algo = avctx->dct_algo;
  2343.         if(dct_algo==FF_DCT_AUTO || dct_algo==FF_DCT_MMX){
  2344.             if(mm_flags & MM_SSE2){
  2345.                 c->fdct = ff_fdct_sse2;
  2346.     }else if(mm_flags & MM_MMXEXT){
  2347.                 c->fdct = ff_fdct_mmx2;
  2348.             }else{
  2349.                 c->fdct = ff_fdct_mmx;
  2350.             }
  2351.         }
  2352. #endif //CONFIG_ENCODERS
  2353.         if(avctx->lowres==0){
  2354.             if(idct_algo==FF_IDCT_AUTO || idct_algo==FF_IDCT_SIMPLEMMX){
  2355.                 c->idct_put= ff_simple_idct_put_mmx;
  2356.                 c->idct_add= ff_simple_idct_add_mmx;
  2357.                 c->idct    = ff_simple_idct_mmx;
  2358.                 c->idct_permutation_type= FF_SIMPLE_IDCT_PERM;
  2359.             }else if(idct_algo==FF_IDCT_LIBMPEG2MMX){
  2360.                 if(mm_flags & MM_MMXEXT){
  2361.                     c->idct_put= ff_libmpeg2mmx2_idct_put;
  2362.                     c->idct_add= ff_libmpeg2mmx2_idct_add;
  2363.                     c->idct    = ff_mmxext_idct;
  2364.                 }else{
  2365.                     c->idct_put= ff_libmpeg2mmx_idct_put;
  2366.                     c->idct_add= ff_libmpeg2mmx_idct_add;
  2367.                     c->idct    = ff_mmx_idct;
  2368.                 }
  2369.                 c->idct_permutation_type= FF_LIBMPEG2_IDCT_PERM;
  2370.             }else if(idct_algo==FF_IDCT_VP3){
  2371.                 if(mm_flags & MM_SSE2){
  2372.                     c->idct_put= ff_vp3_idct_put_sse2;
  2373.                     c->idct_add= ff_vp3_idct_add_sse2;
  2374.                     c->idct    = ff_vp3_idct_sse2;
  2375.                     c->idct_permutation_type= FF_TRANSPOSE_IDCT_PERM;
  2376.                 }else{
  2377.                     ff_vp3_dsp_init_mmx();
  2378.                     c->idct_put= ff_vp3_idct_put_mmx;
  2379.                     c->idct_add= ff_vp3_idct_add_mmx;
  2380.                     c->idct    = ff_vp3_idct_mmx;
  2381.                     c->idct_permutation_type= FF_PARTTRANS_IDCT_PERM;
  2382.                 }
  2383. #ifdef CONFIG_GPL
  2384.             }else if(idct_algo==FF_IDCT_XVIDMMX){
  2385.                 if(mm_flags & MM_MMXEXT){
  2386.                     c->idct_put= ff_idct_xvid_mmx2_put;
  2387.                     c->idct_add= ff_idct_xvid_mmx2_add;
  2388.                     c->idct    = ff_idct_xvid_mmx2;
  2389.                 }else{
  2390.                     c->idct_put= ff_idct_xvid_mmx_put;
  2391.                     c->idct_add= ff_idct_xvid_mmx_add;
  2392.                     c->idct    = ff_idct_xvid_mmx;
  2393.                 }
  2394. #endif
  2395.             }
  2396.         }
  2397. #ifdef CONFIG_ENCODERS
  2398.         c->get_pixels = get_pixels_mmx;
  2399.         c->diff_pixels = diff_pixels_mmx;
  2400. #endif //CONFIG_ENCODERS
  2401.         c->put_pixels_clamped = put_pixels_clamped_mmx;
  2402.         c->put_signed_pixels_clamped = put_signed_pixels_clamped_mmx;
  2403.         c->add_pixels_clamped = add_pixels_clamped_mmx;
  2404.         c->clear_blocks = clear_blocks_mmx;
  2405. #ifdef CONFIG_ENCODERS
  2406.         c->pix_sum = pix_sum16_mmx;
  2407. #endif //CONFIG_ENCODERS
  2408.         c->put_pixels_tab[0][0] = put_pixels16_mmx;
  2409.         c->put_pixels_tab[0][1] = put_pixels16_x2_mmx;
  2410.         c->put_pixels_tab[0][2] = put_pixels16_y2_mmx;
  2411.         c->put_pixels_tab[0][3] = put_pixels16_xy2_mmx;
  2412.         c->put_no_rnd_pixels_tab[0][0] = put_pixels16_mmx;
  2413.         c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_mmx;
  2414.         c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_mmx;
  2415.         c->put_no_rnd_pixels_tab[0][3] = put_no_rnd_pixels16_xy2_mmx;
  2416.         c->avg_pixels_tab[0][0] = avg_pixels16_mmx;
  2417.         c->avg_pixels_tab[0][1] = avg_pixels16_x2_mmx;
  2418.         c->avg_pixels_tab[0][2] = avg_pixels16_y2_mmx;
  2419.         c->avg_pixels_tab[0][3] = avg_pixels16_xy2_mmx;
  2420.         c->avg_no_rnd_pixels_tab[0][0] = avg_no_rnd_pixels16_mmx;
  2421.         c->avg_no_rnd_pixels_tab[0][1] = avg_no_rnd_pixels16_x2_mmx;
  2422.         c->avg_no_rnd_pixels_tab[0][2] = avg_no_rnd_pixels16_y2_mmx;
  2423.         c->avg_no_rnd_pixels_tab[0][3] = avg_no_rnd_pixels16_xy2_mmx;
  2424.         c->put_pixels_tab[1][0] = put_pixels8_mmx;
  2425.         c->put_pixels_tab[1][1] = put_pixels8_x2_mmx;
  2426.         c->put_pixels_tab[1][2] = put_pixels8_y2_mmx;
  2427.         c->put_pixels_tab[1][3] = put_pixels8_xy2_mmx;
  2428.         c->put_no_rnd_pixels_tab[1][0] = put_pixels8_mmx;
  2429.         c->put_no_rnd_pixels_tab[1][1] = put_no_rnd_pixels8_x2_mmx;
  2430.         c->put_no_rnd_pixels_tab[1][2] = put_no_rnd_pixels8_y2_mmx;
  2431.         c->put_no_rnd_pixels_tab[1][3] = put_no_rnd_pixels8_xy2_mmx;
  2432.         c->avg_pixels_tab[1][0] = avg_pixels8_mmx;
  2433.         c->avg_pixels_tab[1][1] = avg_pixels8_x2_mmx;
  2434.         c->avg_pixels_tab[1][2] = avg_pixels8_y2_mmx;
  2435.         c->avg_pixels_tab[1][3] = avg_pixels8_xy2_mmx;
  2436.         c->avg_no_rnd_pixels_tab[1][0] = avg_no_rnd_pixels8_mmx;
  2437.         c->avg_no_rnd_pixels_tab[1][1] = avg_no_rnd_pixels8_x2_mmx;
  2438.         c->avg_no_rnd_pixels_tab[1][2] = avg_no_rnd_pixels8_y2_mmx;
  2439.         c->avg_no_rnd_pixels_tab[1][3] = avg_no_rnd_pixels8_xy2_mmx;
  2440.                 
  2441.         c->add_bytes= add_bytes_mmx;
  2442. #ifdef CONFIG_ENCODERS
  2443.         c->diff_bytes= diff_bytes_mmx;
  2444.         
  2445.         c->hadamard8_diff[0]= hadamard8_diff16_mmx;
  2446.         c->hadamard8_diff[1]= hadamard8_diff_mmx;
  2447.         
  2448. c->pix_norm1 = pix_norm1_mmx;
  2449. c->sse[0] = sse16_mmx;
  2450.    c->sse[1] = sse8_mmx;
  2451.         c->vsad[4]= vsad_intra16_mmx;
  2452. c->nsse[0] = nsse16_mmx;
  2453. c->nsse[1] = nsse8_mmx;
  2454.         if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
  2455.             c->vsad[0] = vsad16_mmx;
  2456.         }
  2457.         
  2458.         if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
  2459.             c->try_8x8basis= try_8x8basis_mmx;
  2460.         }
  2461.         c->add_8x8basis= add_8x8basis_mmx;
  2462.         
  2463. #endif //CONFIG_ENCODERS
  2464.         c->h263_v_loop_filter= h263_v_loop_filter_mmx;
  2465.         c->h263_h_loop_filter= h263_h_loop_filter_mmx;        
  2466. c->put_h264_chroma_pixels_tab[0]= put_h264_chroma_mc8_mmx;
  2467.         
  2468.         if (mm_flags & MM_MMXEXT) {
  2469.             c->put_pixels_tab[0][1] = put_pixels16_x2_mmx2;
  2470.             c->put_pixels_tab[0][2] = put_pixels16_y2_mmx2;
  2471.             c->avg_pixels_tab[0][0] = avg_pixels16_mmx2;
  2472.             c->avg_pixels_tab[0][1] = avg_pixels16_x2_mmx2;
  2473.             c->avg_pixels_tab[0][2] = avg_pixels16_y2_mmx2;
  2474.             c->put_pixels_tab[1][1] = put_pixels8_x2_mmx2;
  2475.             c->put_pixels_tab[1][2] = put_pixels8_y2_mmx2;
  2476.             c->avg_pixels_tab[1][0] = avg_pixels8_mmx2;
  2477.             c->avg_pixels_tab[1][1] = avg_pixels8_x2_mmx2;
  2478.             c->avg_pixels_tab[1][2] = avg_pixels8_y2_mmx2;
  2479. #ifdef CONFIG_ENCODERS
  2480.             c->hadamard8_diff[0]= hadamard8_diff16_mmx2;
  2481.             c->hadamard8_diff[1]= hadamard8_diff_mmx2;
  2482.             c->vsad[4]= vsad_intra16_mmx2;
  2483. #endif //CONFIG_ENCODERS
  2484.             c->h264_idct_add= ff_h264_idct_add_mmx2;
  2485.             if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
  2486.                 c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_mmx2;
  2487.                 c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_mmx2;
  2488.                 c->put_no_rnd_pixels_tab[1][1] = put_no_rnd_pixels8_x2_mmx2;
  2489.                 c->put_no_rnd_pixels_tab[1][2] = put_no_rnd_pixels8_y2_mmx2;
  2490.                 c->avg_pixels_tab[0][3] = avg_pixels16_xy2_mmx2;
  2491.                 c->avg_pixels_tab[1][3] = avg_pixels8_xy2_mmx2;
  2492. #ifdef CONFIG_ENCODERS
  2493.                 c->vsad[0] = vsad16_mmx2;
  2494. #endif //CONFIG_ENCODERS
  2495.             }
  2496. #if 1
  2497.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 0], qpel16_mc00_mmx2)
  2498.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 1], qpel16_mc10_mmx2)
  2499.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 2], qpel16_mc20_mmx2)
  2500.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 3], qpel16_mc30_mmx2)
  2501.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 4], qpel16_mc01_mmx2)
  2502.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 5], qpel16_mc11_mmx2)
  2503.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 6], qpel16_mc21_mmx2)
  2504.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 7], qpel16_mc31_mmx2)
  2505.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 8], qpel16_mc02_mmx2)
  2506.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 9], qpel16_mc12_mmx2)
  2507.             SET_QPEL_FUNC(qpel_pixels_tab[0][10], qpel16_mc22_mmx2)
  2508.             SET_QPEL_FUNC(qpel_pixels_tab[0][11], qpel16_mc32_mmx2)
  2509.             SET_QPEL_FUNC(qpel_pixels_tab[0][12], qpel16_mc03_mmx2)
  2510.             SET_QPEL_FUNC(qpel_pixels_tab[0][13], qpel16_mc13_mmx2)
  2511.             SET_QPEL_FUNC(qpel_pixels_tab[0][14], qpel16_mc23_mmx2)
  2512.             SET_QPEL_FUNC(qpel_pixels_tab[0][15], qpel16_mc33_mmx2)
  2513.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 0], qpel8_mc00_mmx2)
  2514.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 1], qpel8_mc10_mmx2)
  2515.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 2], qpel8_mc20_mmx2)
  2516.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 3], qpel8_mc30_mmx2)
  2517.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 4], qpel8_mc01_mmx2)
  2518.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 5], qpel8_mc11_mmx2)
  2519.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 6], qpel8_mc21_mmx2)
  2520.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 7], qpel8_mc31_mmx2)
  2521.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 8], qpel8_mc02_mmx2)
  2522.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 9], qpel8_mc12_mmx2)
  2523.             SET_QPEL_FUNC(qpel_pixels_tab[1][10], qpel8_mc22_mmx2)
  2524.             SET_QPEL_FUNC(qpel_pixels_tab[1][11], qpel8_mc32_mmx2)
  2525.             SET_QPEL_FUNC(qpel_pixels_tab[1][12], qpel8_mc03_mmx2)
  2526.             SET_QPEL_FUNC(qpel_pixels_tab[1][13], qpel8_mc13_mmx2)
  2527.             SET_QPEL_FUNC(qpel_pixels_tab[1][14], qpel8_mc23_mmx2)
  2528.             SET_QPEL_FUNC(qpel_pixels_tab[1][15], qpel8_mc33_mmx2)
  2529. #endif
  2530. //FIXME 3dnow too
  2531. #define dspfunc(PFX, IDX, NUM) 
  2532.     c->PFX ## _pixels_tab[IDX][ 0] = PFX ## NUM ## _mc00_mmx2; 
  2533.     c->PFX ## _pixels_tab[IDX][ 1] = PFX ## NUM ## _mc10_mmx2; 
  2534.     c->PFX ## _pixels_tab[IDX][ 2] = PFX ## NUM ## _mc20_mmx2; 
  2535.     c->PFX ## _pixels_tab[IDX][ 3] = PFX ## NUM ## _mc30_mmx2; 
  2536.     c->PFX ## _pixels_tab[IDX][ 4] = PFX ## NUM ## _mc01_mmx2; 
  2537.     c->PFX ## _pixels_tab[IDX][ 5] = PFX ## NUM ## _mc11_mmx2; 
  2538.     c->PFX ## _pixels_tab[IDX][ 6] = PFX ## NUM ## _mc21_mmx2; 
  2539.     c->PFX ## _pixels_tab[IDX][ 7] = PFX ## NUM ## _mc31_mmx2; 
  2540.     c->PFX ## _pixels_tab[IDX][ 8] = PFX ## NUM ## _mc02_mmx2; 
  2541.     c->PFX ## _pixels_tab[IDX][ 9] = PFX ## NUM ## _mc12_mmx2; 
  2542.     c->PFX ## _pixels_tab[IDX][10] = PFX ## NUM ## _mc22_mmx2; 
  2543.     c->PFX ## _pixels_tab[IDX][11] = PFX ## NUM ## _mc32_mmx2; 
  2544.     c->PFX ## _pixels_tab[IDX][12] = PFX ## NUM ## _mc03_mmx2; 
  2545.     c->PFX ## _pixels_tab[IDX][13] = PFX ## NUM ## _mc13_mmx2; 
  2546.     c->PFX ## _pixels_tab[IDX][14] = PFX ## NUM ## _mc23_mmx2; 
  2547.     c->PFX ## _pixels_tab[IDX][15] = PFX ## NUM ## _mc33_mmx2
  2548.             dspfunc(put_h264_qpel, 0, 16);
  2549.             dspfunc(put_h264_qpel, 1, 8);
  2550.             dspfunc(put_h264_qpel, 2, 4);
  2551.             dspfunc(avg_h264_qpel, 0, 16);
  2552.             dspfunc(avg_h264_qpel, 1, 8);
  2553.             dspfunc(avg_h264_qpel, 2, 4);
  2554. #undef dspfunc
  2555.     c->avg_h264_chroma_pixels_tab[0]= avg_h264_chroma_mc8_mmx2;
  2556.             c->h264_v_loop_filter_luma= h264_v_loop_filter_luma_mmx2;
  2557.             c->h264_h_loop_filter_luma= h264_h_loop_filter_luma_mmx2;
  2558.             c->h264_v_loop_filter_chroma= h264_v_loop_filter_chroma_mmx2;
  2559.             c->h264_h_loop_filter_chroma= h264_h_loop_filter_chroma_mmx2;
  2560.             c->h264_v_loop_filter_chroma_intra= h264_v_loop_filter_chroma_intra_mmx2;
  2561.             c->h264_h_loop_filter_chroma_intra= h264_h_loop_filter_chroma_intra_mmx2;
  2562. #ifdef CONFIG_ENCODERS
  2563.             c->sub_hfyu_median_prediction= sub_hfyu_median_prediction_mmx2;
  2564. #endif //CONFIG_ENCODERS
  2565.         } else if (mm_flags & MM_3DNOW) {
  2566.             c->put_pixels_tab[0][1] = put_pixels16_x2_3dnow;
  2567.             c->put_pixels_tab[0][2] = put_pixels16_y2_3dnow;
  2568.             c->avg_pixels_tab[0][0] = avg_pixels16_3dnow;
  2569.             c->avg_pixels_tab[0][1] = avg_pixels16_x2_3dnow;
  2570.             c->avg_pixels_tab[0][2] = avg_pixels16_y2_3dnow;
  2571.             c->put_pixels_tab[1][1] = put_pixels8_x2_3dnow;
  2572.             c->put_pixels_tab[1][2] = put_pixels8_y2_3dnow;
  2573.             c->avg_pixels_tab[1][0] = avg_pixels8_3dnow;
  2574.             c->avg_pixels_tab[1][1] = avg_pixels8_x2_3dnow;
  2575.             c->avg_pixels_tab[1][2] = avg_pixels8_y2_3dnow;
  2576.             if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
  2577.                 c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_3dnow;
  2578.                 c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_3dnow;
  2579.                 c->put_no_rnd_pixels_tab[1][1] = put_no_rnd_pixels8_x2_3dnow;
  2580.                 c->put_no_rnd_pixels_tab[1][2] = put_no_rnd_pixels8_y2_3dnow;
  2581.                 c->avg_pixels_tab[0][3] = avg_pixels16_xy2_3dnow;
  2582.                 c->avg_pixels_tab[1][3] = avg_pixels8_xy2_3dnow;
  2583.             }
  2584.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 0], qpel16_mc00_3dnow)
  2585.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 1], qpel16_mc10_3dnow)
  2586.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 2], qpel16_mc20_3dnow)
  2587.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 3], qpel16_mc30_3dnow)
  2588.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 4], qpel16_mc01_3dnow)
  2589.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 5], qpel16_mc11_3dnow)
  2590.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 6], qpel16_mc21_3dnow)
  2591.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 7], qpel16_mc31_3dnow)
  2592.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 8], qpel16_mc02_3dnow)
  2593.             SET_QPEL_FUNC(qpel_pixels_tab[0][ 9], qpel16_mc12_3dnow)
  2594.             SET_QPEL_FUNC(qpel_pixels_tab[0][10], qpel16_mc22_3dnow)
  2595.             SET_QPEL_FUNC(qpel_pixels_tab[0][11], qpel16_mc32_3dnow)
  2596.             SET_QPEL_FUNC(qpel_pixels_tab[0][12], qpel16_mc03_3dnow)
  2597.             SET_QPEL_FUNC(qpel_pixels_tab[0][13], qpel16_mc13_3dnow)
  2598.             SET_QPEL_FUNC(qpel_pixels_tab[0][14], qpel16_mc23_3dnow)
  2599.             SET_QPEL_FUNC(qpel_pixels_tab[0][15], qpel16_mc33_3dnow)
  2600.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 0], qpel8_mc00_3dnow)
  2601.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 1], qpel8_mc10_3dnow)
  2602.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 2], qpel8_mc20_3dnow)
  2603.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 3], qpel8_mc30_3dnow)
  2604.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 4], qpel8_mc01_3dnow)
  2605.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 5], qpel8_mc11_3dnow)
  2606.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 6], qpel8_mc21_3dnow)
  2607.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 7], qpel8_mc31_3dnow)
  2608.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 8], qpel8_mc02_3dnow)
  2609.             SET_QPEL_FUNC(qpel_pixels_tab[1][ 9], qpel8_mc12_3dnow)
  2610.             SET_QPEL_FUNC(qpel_pixels_tab[1][10], qpel8_mc22_3dnow)
  2611.             SET_QPEL_FUNC(qpel_pixels_tab[1][11], qpel8_mc32_3dnow)
  2612.             SET_QPEL_FUNC(qpel_pixels_tab[1][12], qpel8_mc03_3dnow)
  2613.             SET_QPEL_FUNC(qpel_pixels_tab[1][13], qpel8_mc13_3dnow)
  2614.             SET_QPEL_FUNC(qpel_pixels_tab[1][14], qpel8_mc23_3dnow)
  2615.             SET_QPEL_FUNC(qpel_pixels_tab[1][15], qpel8_mc33_3dnow)
  2616. #define dspfunc(PFX, IDX, NUM) 
  2617.     c->PFX ## _pixels_tab[IDX][ 0] = PFX ## NUM ## _mc00_3dnow; 
  2618.     c->PFX ## _pixels_tab[IDX][ 1] = PFX ## NUM ## _mc10_3dnow; 
  2619.     c->PFX ## _pixels_tab[IDX][ 2] = PFX ## NUM ## _mc20_3dnow; 
  2620.     c->PFX ## _pixels_tab[IDX][ 3] = PFX ## NUM ## _mc30_3dnow; 
  2621.     c->PFX ## _pixels_tab[IDX][ 4] = PFX ## NUM ## _mc01_3dnow; 
  2622.     c->PFX ## _pixels_tab[IDX][ 5] = PFX ## NUM ## _mc11_3dnow; 
  2623.     c->PFX ## _pixels_tab[IDX][ 6] = PFX ## NUM ## _mc21_3dnow; 
  2624.     c->PFX ## _pixels_tab[IDX][ 7] = PFX ## NUM ## _mc31_3dnow; 
  2625.     c->PFX ## _pixels_tab[IDX][ 8] = PFX ## NUM ## _mc02_3dnow; 
  2626.     c->PFX ## _pixels_tab[IDX][ 9] = PFX ## NUM ## _mc12_3dnow; 
  2627.     c->PFX ## _pixels_tab[IDX][10] = PFX ## NUM ## _mc22_3dnow; 
  2628.     c->PFX ## _pixels_tab[IDX][11] = PFX ## NUM ## _mc32_3dnow; 
  2629.     c->PFX ## _pixels_tab[IDX][12] = PFX ## NUM ## _mc03_3dnow; 
  2630.     c->PFX ## _pixels_tab[IDX][13] = PFX ## NUM ## _mc13_3dnow; 
  2631.     c->PFX ## _pixels_tab[IDX][14] = PFX ## NUM ## _mc23_3dnow; 
  2632.     c->PFX ## _pixels_tab[IDX][15] = PFX ## NUM ## _mc33_3dnow
  2633.             dspfunc(put_h264_qpel, 0, 16);
  2634.             dspfunc(put_h264_qpel, 1, 8);
  2635.             dspfunc(put_h264_qpel, 2, 4);
  2636.             dspfunc(avg_h264_qpel, 0, 16);
  2637.             dspfunc(avg_h264_qpel, 1, 8);
  2638.             dspfunc(avg_h264_qpel, 2, 4);
  2639.     c->avg_h264_chroma_pixels_tab[0]= avg_h264_chroma_mc8_3dnow;
  2640.         }
  2641.     }
  2642.         
  2643. #ifdef CONFIG_ENCODERS
  2644.     dsputil_init_pix_mmx(c, avctx);
  2645. #endif //CONFIG_ENCODERS
  2646. #if 0
  2647.     // for speed testing
  2648.     get_pixels = just_return;
  2649.     put_pixels_clamped = just_return;
  2650.     add_pixels_clamped = just_return;
  2651.     pix_abs16x16 = just_return;
  2652.     pix_abs16x16_x2 = just_return;
  2653.     pix_abs16x16_y2 = just_return;
  2654.     pix_abs16x16_xy2 = just_return;
  2655.     put_pixels_tab[0] = just_return;
  2656.     put_pixels_tab[1] = just_return;
  2657.     put_pixels_tab[2] = just_return;
  2658.     put_pixels_tab[3] = just_return;
  2659.     put_no_rnd_pixels_tab[0] = just_return;
  2660.     put_no_rnd_pixels_tab[1] = just_return;
  2661.     put_no_rnd_pixels_tab[2] = just_return;
  2662.     put_no_rnd_pixels_tab[3] = just_return;
  2663.     avg_pixels_tab[0] = just_return;
  2664.     avg_pixels_tab[1] = just_return;
  2665.     avg_pixels_tab[2] = just_return;
  2666.     avg_pixels_tab[3] = just_return;
  2667.     avg_no_rnd_pixels_tab[0] = just_return;
  2668.     avg_no_rnd_pixels_tab[1] = just_return;
  2669.     avg_no_rnd_pixels_tab[2] = just_return;
  2670.     avg_no_rnd_pixels_tab[3] = just_return;
  2671.     //av_fdct = just_return;
  2672.     //ff_idct = just_return;
  2673. #endif
  2674. }