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

Windows CE

开发平台:

C/C++

  1. /*
  2.  * The simplest mpeg encoder (well, it was the simplest!)
  3.  * Copyright (c) 2000,2001 Fabrice Bellard.
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Lesser General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public
  16.  * License along with this library; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  * Optimized for ia32 cpus by Nick Kurshev <nickols_k@mail.ru>
  20.  * h263, mpeg1, mpeg2 dequantizer & draw_edges by Michael Niedermayer <michaelni@gmx.at>
  21.  */
  22. #include "../dsputil.h"
  23. #include "../mpegvideo.h"
  24. #include "../avcodec.h"
  25. #include "mmx.h"
  26. extern uint8_t zigzag_direct_noperm[64];
  27. extern uint16_t inv_zigzag_direct16[64];
  28. static const unsigned long long int mm_wabs __attribute__ ((aligned(8))) = 0xffffffffffffffffULL;
  29. static const unsigned long long int mm_wone __attribute__ ((aligned(8))) = 0x0001000100010001ULL;
  30. static void dct_unquantize_h263_intra_mmx(MpegEncContext *s,
  31.                                   DCTELEM *block, int n, int qscale)
  32. {
  33.     long level, qmul, qadd, nCoeffs;
  34.     qmul = qscale << 1;
  35.     assert(s->block_last_index[n]>=0 || s->h263_aic);
  36.         
  37.     if (!s->h263_aic) {
  38.         if (n < 4)
  39.             level = block[0] * s->y_dc_scale;
  40.         else
  41.             level = block[0] * s->c_dc_scale;
  42.         qadd = (qscale - 1) | 1;
  43.     }else{
  44.         qadd = 0;
  45.         level= block[0];
  46.     }
  47.     if(s->ac_pred)
  48.         nCoeffs=63;
  49.     else
  50.         nCoeffs= s->inter_scantable.raster_end[ s->block_last_index[n] ];
  51. //printf("%d %d  ", qmul, qadd);
  52. asm volatile(
  53. "movd %1, %%mm6 nt" //qmul
  54. "packssdw %%mm6, %%mm6 nt"
  55. "packssdw %%mm6, %%mm6 nt"
  56. "movd %2, %%mm5 nt" //qadd
  57. "pxor %%mm7, %%mm7 nt"
  58. "packssdw %%mm5, %%mm5 nt"
  59. "packssdw %%mm5, %%mm5 nt"
  60. "psubw %%mm5, %%mm7 nt"
  61. "pxor %%mm4, %%mm4 nt"
  62. ".balign 16nt"
  63. "1: nt"
  64. "movq (%0, %3), %%mm0 nt"
  65. "movq 8(%0, %3), %%mm1 nt"
  66. "pmullw %%mm6, %%mm0 nt"
  67. "pmullw %%mm6, %%mm1 nt"
  68. "movq (%0, %3), %%mm2 nt"
  69. "movq 8(%0, %3), %%mm3 nt"
  70. "pcmpgtw %%mm4, %%mm2 nt" // block[i] < 0 ? -1 : 0
  71. "pcmpgtw %%mm4, %%mm3 nt" // block[i] < 0 ? -1 : 0
  72. "pxor %%mm2, %%mm0 nt"
  73. "pxor %%mm3, %%mm1 nt"
  74. "paddw %%mm7, %%mm0 nt"
  75. "paddw %%mm7, %%mm1 nt"
  76. "pxor %%mm0, %%mm2 nt"
  77. "pxor %%mm1, %%mm3 nt"
  78. "pcmpeqw %%mm7, %%mm0 nt" // block[i] == 0 ? -1 : 0
  79. "pcmpeqw %%mm7, %%mm1 nt" // block[i] == 0 ? -1 : 0
  80. "pandn %%mm2, %%mm0 nt"
  81. "pandn %%mm3, %%mm1 nt"
  82. "movq %%mm0, (%0, %3) nt"
  83. "movq %%mm1, 8(%0, %3) nt"
  84. "add $16, %3 nt"
  85. "jng 1b nt"
  86. ::"r" (block+nCoeffs), "g"(qmul), "g" (qadd), "r" (2*(-nCoeffs))
  87. : "memory"
  88. );
  89.         block[0]= level;
  90. }
  91. static void dct_unquantize_h263_inter_mmx(MpegEncContext *s,
  92.                                   DCTELEM *block, int n, int qscale)
  93. {
  94.     long qmul, qadd, nCoeffs;
  95.     qmul = qscale << 1;
  96.     qadd = (qscale - 1) | 1;
  97.     assert(s->block_last_index[n]>=0 || s->h263_aic);
  98.         
  99.     nCoeffs= s->inter_scantable.raster_end[ s->block_last_index[n] ];
  100. //printf("%d %d  ", qmul, qadd);
  101. asm volatile(
  102. "movd %1, %%mm6 nt" //qmul
  103. "packssdw %%mm6, %%mm6 nt"
  104. "packssdw %%mm6, %%mm6 nt"
  105. "movd %2, %%mm5 nt" //qadd
  106. "pxor %%mm7, %%mm7 nt"
  107. "packssdw %%mm5, %%mm5 nt"
  108. "packssdw %%mm5, %%mm5 nt"
  109. "psubw %%mm5, %%mm7 nt"
  110. "pxor %%mm4, %%mm4 nt"
  111. ".balign 16nt"
  112. "1: nt"
  113. "movq (%0, %3), %%mm0 nt"
  114. "movq 8(%0, %3), %%mm1 nt"
  115. "pmullw %%mm6, %%mm0 nt"
  116. "pmullw %%mm6, %%mm1 nt"
  117. "movq (%0, %3), %%mm2 nt"
  118. "movq 8(%0, %3), %%mm3 nt"
  119. "pcmpgtw %%mm4, %%mm2 nt" // block[i] < 0 ? -1 : 0
  120. "pcmpgtw %%mm4, %%mm3 nt" // block[i] < 0 ? -1 : 0
  121. "pxor %%mm2, %%mm0 nt"
  122. "pxor %%mm3, %%mm1 nt"
  123. "paddw %%mm7, %%mm0 nt"
  124. "paddw %%mm7, %%mm1 nt"
  125. "pxor %%mm0, %%mm2 nt"
  126. "pxor %%mm1, %%mm3 nt"
  127. "pcmpeqw %%mm7, %%mm0 nt" // block[i] == 0 ? -1 : 0
  128. "pcmpeqw %%mm7, %%mm1 nt" // block[i] == 0 ? -1 : 0
  129. "pandn %%mm2, %%mm0 nt"
  130. "pandn %%mm3, %%mm1 nt"
  131. "movq %%mm0, (%0, %3) nt"
  132. "movq %%mm1, 8(%0, %3) nt"
  133. "add $16, %3 nt"
  134. "jng 1b nt"
  135. ::"r" (block+nCoeffs), "g"(qmul), "g" (qadd), "r" (2*(-nCoeffs))
  136. : "memory"
  137. );
  138. }
  139. /*
  140.   NK:
  141.   Note: looking at PARANOID:
  142.   "enable all paranoid tests for rounding, overflows, etc..."
  143. #ifdef PARANOID
  144.                 if (level < -2048 || level > 2047)
  145.                     fprintf(stderr, "unquant error %d %dn", i, level);
  146. #endif
  147.   We can suppose that result of two multiplications can't be greate of 0xFFFF
  148.   i.e. is 16-bit, so we use here only PMULLW instruction and can avoid
  149.   a complex multiplication.
  150. =====================================================
  151.  Full formula for multiplication of 2 integer numbers
  152.  which are represent as high:low words:
  153.  input: value1 = high1:low1
  154.         value2 = high2:low2
  155.  output: value3 = value1*value2
  156.  value3=high3:low3 (on overflow: modulus 2^32 wrap-around)
  157.  this mean that for 0x123456 * 0x123456 correct result is 0x766cb0ce4
  158.  but this algorithm will compute only 0x66cb0ce4
  159.  this limited by 16-bit size of operands
  160.  ---------------------------------
  161.  tlow1 = high1*low2
  162.  tlow2 = high2*low1
  163.  tlow1 = tlow1 + tlow2
  164.  high3:low3 = low1*low2
  165.  high3 += tlow1
  166. */
  167. static void dct_unquantize_mpeg1_intra_mmx(MpegEncContext *s,
  168.                                      DCTELEM *block, int n, int qscale)
  169. {
  170.     long nCoeffs;
  171.     const uint16_t *quant_matrix;
  172.     int block0;
  173.     assert(s->block_last_index[n]>=0);
  174.     nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ]+1;
  175.     if (n < 4) 
  176.         block0 = block[0] * s->y_dc_scale;
  177.     else
  178.         block0 = block[0] * s->c_dc_scale;
  179.     /* XXX: only mpeg1 */
  180.     quant_matrix = s->intra_matrix;
  181. asm volatile(
  182. "pcmpeqw %%mm7, %%mm7 nt"
  183. "psrlw $15, %%mm7 nt"
  184. "movd %2, %%mm6 nt"
  185. "packssdw %%mm6, %%mm6 nt"
  186. "packssdw %%mm6, %%mm6 nt"
  187. "mov %3, %%"REG_a" nt"
  188. ".balign 16nt"
  189. "1: nt"
  190. "movq (%0, %%"REG_a"), %%mm0 nt"
  191. "movq 8(%0, %%"REG_a"), %%mm1 nt"
  192. "movq (%1, %%"REG_a"), %%mm4 nt"
  193. "movq 8(%1, %%"REG_a"), %%mm5 nt"
  194. "pmullw %%mm6, %%mm4 nt" // q=qscale*quant_matrix[i]
  195. "pmullw %%mm6, %%mm5 nt" // q=qscale*quant_matrix[i]
  196. "pxor %%mm2, %%mm2 nt"
  197. "pxor %%mm3, %%mm3 nt"
  198. "pcmpgtw %%mm0, %%mm2 nt" // block[i] < 0 ? -1 : 0
  199. "pcmpgtw %%mm1, %%mm3 nt" // block[i] < 0 ? -1 : 0
  200. "pxor %%mm2, %%mm0 nt"
  201. "pxor %%mm3, %%mm1 nt"
  202. "psubw %%mm2, %%mm0 nt" // abs(block[i])
  203. "psubw %%mm3, %%mm1 nt" // abs(block[i])
  204. "pmullw %%mm4, %%mm0 nt" // abs(block[i])*q
  205. "pmullw %%mm5, %%mm1 nt" // abs(block[i])*q
  206. "pxor %%mm4, %%mm4 nt"
  207. "pxor %%mm5, %%mm5 nt" // FIXME slow
  208. "pcmpeqw (%0, %%"REG_a"), %%mm4 nt" // block[i] == 0 ? -1 : 0
  209. "pcmpeqw 8(%0, %%"REG_a"), %%mm5nt" // block[i] == 0 ? -1 : 0
  210. "psraw $3, %%mm0 nt"
  211. "psraw $3, %%mm1 nt"
  212. "psubw %%mm7, %%mm0 nt"
  213. "psubw %%mm7, %%mm1 nt"
  214. "por %%mm7, %%mm0 nt"
  215. "por %%mm7, %%mm1 nt"
  216. "pxor %%mm2, %%mm0 nt"
  217. "pxor %%mm3, %%mm1 nt"
  218. "psubw %%mm2, %%mm0 nt"
  219. "psubw %%mm3, %%mm1 nt"
  220. "pandn %%mm0, %%mm4 nt"
  221. "pandn %%mm1, %%mm5 nt"
  222. "movq %%mm4, (%0, %%"REG_a") nt"
  223. "movq %%mm5, 8(%0, %%"REG_a") nt"
  224. "add $16, %%"REG_a" nt"
  225. "js 1b nt"
  226. ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "g" (qscale), "g" (-2*nCoeffs)
  227. : "%"REG_a, "memory"
  228. );    
  229.     block[0]= block0;
  230. }
  231. static void dct_unquantize_mpeg1_inter_mmx(MpegEncContext *s,
  232.                                      DCTELEM *block, int n, int qscale)
  233. {
  234.     long nCoeffs;
  235.     const uint16_t *quant_matrix;
  236.     assert(s->block_last_index[n]>=0);
  237.     nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ]+1;
  238.         quant_matrix = s->inter_matrix;
  239. asm volatile(
  240. "pcmpeqw %%mm7, %%mm7 nt"
  241. "psrlw $15, %%mm7 nt"
  242. "movd %2, %%mm6 nt"
  243. "packssdw %%mm6, %%mm6 nt"
  244. "packssdw %%mm6, %%mm6 nt"
  245. "mov %3, %%"REG_a" nt"
  246. ".balign 16nt"
  247. "1: nt"
  248. "movq (%0, %%"REG_a"), %%mm0 nt"
  249. "movq 8(%0, %%"REG_a"), %%mm1 nt"
  250. "movq (%1, %%"REG_a"), %%mm4 nt"
  251. "movq 8(%1, %%"REG_a"), %%mm5 nt"
  252. "pmullw %%mm6, %%mm4 nt" // q=qscale*quant_matrix[i]
  253. "pmullw %%mm6, %%mm5 nt" // q=qscale*quant_matrix[i]
  254. "pxor %%mm2, %%mm2 nt"
  255. "pxor %%mm3, %%mm3 nt"
  256. "pcmpgtw %%mm0, %%mm2 nt" // block[i] < 0 ? -1 : 0
  257. "pcmpgtw %%mm1, %%mm3 nt" // block[i] < 0 ? -1 : 0
  258. "pxor %%mm2, %%mm0 nt"
  259. "pxor %%mm3, %%mm1 nt"
  260. "psubw %%mm2, %%mm0 nt" // abs(block[i])
  261. "psubw %%mm3, %%mm1 nt" // abs(block[i])
  262. "paddw %%mm0, %%mm0 nt" // abs(block[i])*2
  263. "paddw %%mm1, %%mm1 nt" // abs(block[i])*2
  264. "paddw %%mm7, %%mm0 nt" // abs(block[i])*2 + 1
  265. "paddw %%mm7, %%mm1 nt" // abs(block[i])*2 + 1
  266. "pmullw %%mm4, %%mm0 nt" // (abs(block[i])*2 + 1)*q
  267. "pmullw %%mm5, %%mm1 nt" // (abs(block[i])*2 + 1)*q
  268. "pxor %%mm4, %%mm4 nt"
  269. "pxor %%mm5, %%mm5 nt" // FIXME slow
  270. "pcmpeqw (%0, %%"REG_a"), %%mm4 nt" // block[i] == 0 ? -1 : 0
  271. "pcmpeqw 8(%0, %%"REG_a"), %%mm5nt" // block[i] == 0 ? -1 : 0
  272. "psraw $4, %%mm0 nt"
  273. "psraw $4, %%mm1 nt"
  274. "psubw %%mm7, %%mm0 nt"
  275. "psubw %%mm7, %%mm1 nt"
  276. "por %%mm7, %%mm0 nt"
  277. "por %%mm7, %%mm1 nt"
  278. "pxor %%mm2, %%mm0 nt"
  279. "pxor %%mm3, %%mm1 nt"
  280. "psubw %%mm2, %%mm0 nt"
  281. "psubw %%mm3, %%mm1 nt"
  282. "pandn %%mm0, %%mm4 nt"
  283. "pandn %%mm1, %%mm5 nt"
  284. "movq %%mm4, (%0, %%"REG_a") nt"
  285. "movq %%mm5, 8(%0, %%"REG_a") nt"
  286. "add $16, %%"REG_a" nt"
  287. "js 1b nt"
  288. ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "g" (qscale), "g" (-2*nCoeffs)
  289. : "%"REG_a, "memory"
  290. );
  291. }
  292. static void dct_unquantize_mpeg2_intra_mmx(MpegEncContext *s,
  293.                                      DCTELEM *block, int n, int qscale)
  294. {
  295.     long nCoeffs;
  296.     const uint16_t *quant_matrix;
  297.     int block0;
  298.     
  299.     assert(s->block_last_index[n]>=0);
  300.     if(s->alternate_scan) nCoeffs= 63; //FIXME
  301.     else nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ];
  302.     if (n < 4) 
  303.         block0 = block[0] * s->y_dc_scale;
  304.     else
  305.         block0 = block[0] * s->c_dc_scale;
  306.     quant_matrix = s->intra_matrix;
  307. asm volatile(
  308. "pcmpeqw %%mm7, %%mm7 nt"
  309. "psrlw $15, %%mm7 nt"
  310. "movd %2, %%mm6 nt"
  311. "packssdw %%mm6, %%mm6 nt"
  312. "packssdw %%mm6, %%mm6 nt"
  313. "mov %3, %%"REG_a" nt"
  314. ".balign 16nt"
  315. "1: nt"
  316. "movq (%0, %%"REG_a"), %%mm0 nt"
  317. "movq 8(%0, %%"REG_a"), %%mm1 nt"
  318. "movq (%1, %%"REG_a"), %%mm4 nt"
  319. "movq 8(%1, %%"REG_a"), %%mm5 nt"
  320. "pmullw %%mm6, %%mm4 nt" // q=qscale*quant_matrix[i]
  321. "pmullw %%mm6, %%mm5 nt" // q=qscale*quant_matrix[i]
  322. "pxor %%mm2, %%mm2 nt"
  323. "pxor %%mm3, %%mm3 nt"
  324. "pcmpgtw %%mm0, %%mm2 nt" // block[i] < 0 ? -1 : 0
  325. "pcmpgtw %%mm1, %%mm3 nt" // block[i] < 0 ? -1 : 0
  326. "pxor %%mm2, %%mm0 nt"
  327. "pxor %%mm3, %%mm1 nt"
  328. "psubw %%mm2, %%mm0 nt" // abs(block[i])
  329. "psubw %%mm3, %%mm1 nt" // abs(block[i])
  330. "pmullw %%mm4, %%mm0 nt" // abs(block[i])*q
  331. "pmullw %%mm5, %%mm1 nt" // abs(block[i])*q
  332. "pxor %%mm4, %%mm4 nt"
  333. "pxor %%mm5, %%mm5 nt" // FIXME slow
  334. "pcmpeqw (%0, %%"REG_a"), %%mm4 nt" // block[i] == 0 ? -1 : 0
  335. "pcmpeqw 8(%0, %%"REG_a"), %%mm5nt" // block[i] == 0 ? -1 : 0
  336. "psraw $3, %%mm0 nt"
  337. "psraw $3, %%mm1 nt"
  338. "pxor %%mm2, %%mm0 nt"
  339. "pxor %%mm3, %%mm1 nt"
  340. "psubw %%mm2, %%mm0 nt"
  341. "psubw %%mm3, %%mm1 nt"
  342. "pandn %%mm0, %%mm4 nt"
  343. "pandn %%mm1, %%mm5 nt"
  344. "movq %%mm4, (%0, %%"REG_a") nt"
  345. "movq %%mm5, 8(%0, %%"REG_a") nt"
  346. "add $16, %%"REG_a" nt"
  347. "jng 1b nt"
  348. ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "g" (qscale), "g" (-2*nCoeffs)
  349. : "%"REG_a, "memory"
  350. );    
  351.     block[0]= block0;
  352.         //Note, we dont do mismatch control for intra as errors cannot accumulate
  353. }
  354. static void dct_unquantize_mpeg2_inter_mmx(MpegEncContext *s,
  355.                                      DCTELEM *block, int n, int qscale)
  356. {
  357.     long nCoeffs;
  358.     const uint16_t *quant_matrix;
  359.     
  360.     assert(s->block_last_index[n]>=0);
  361.     if(s->alternate_scan) nCoeffs= 63; //FIXME
  362.     else nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ];
  363.         quant_matrix = s->inter_matrix;
  364. asm volatile(
  365. "pcmpeqw %%mm7, %%mm7 nt"
  366.                 "psrlq $48, %%mm7 nt"
  367. "movd %2, %%mm6 nt"
  368. "packssdw %%mm6, %%mm6 nt"
  369. "packssdw %%mm6, %%mm6 nt"
  370. "mov %3, %%"REG_a" nt"
  371. ".balign 16nt"
  372. "1: nt"
  373. "movq (%0, %%"REG_a"), %%mm0 nt"
  374. "movq 8(%0, %%"REG_a"), %%mm1 nt"
  375. "movq (%1, %%"REG_a"), %%mm4 nt"
  376. "movq 8(%1, %%"REG_a"), %%mm5 nt"
  377. "pmullw %%mm6, %%mm4 nt" // q=qscale*quant_matrix[i]
  378. "pmullw %%mm6, %%mm5 nt" // q=qscale*quant_matrix[i]
  379. "pxor %%mm2, %%mm2 nt"
  380. "pxor %%mm3, %%mm3 nt"
  381. "pcmpgtw %%mm0, %%mm2 nt" // block[i] < 0 ? -1 : 0
  382. "pcmpgtw %%mm1, %%mm3 nt" // block[i] < 0 ? -1 : 0
  383. "pxor %%mm2, %%mm0 nt"
  384. "pxor %%mm3, %%mm1 nt"
  385. "psubw %%mm2, %%mm0 nt" // abs(block[i])
  386. "psubw %%mm3, %%mm1 nt" // abs(block[i])
  387. "paddw %%mm0, %%mm0 nt" // abs(block[i])*2
  388. "paddw %%mm1, %%mm1 nt" // abs(block[i])*2
  389. "pmullw %%mm4, %%mm0 nt" // abs(block[i])*2*q
  390. "pmullw %%mm5, %%mm1 nt" // abs(block[i])*2*q
  391. "paddw %%mm4, %%mm0 nt" // (abs(block[i])*2 + 1)*q
  392. "paddw %%mm5, %%mm1 nt" // (abs(block[i])*2 + 1)*q
  393. "pxor %%mm4, %%mm4 nt"
  394. "pxor %%mm5, %%mm5 nt" // FIXME slow
  395. "pcmpeqw (%0, %%"REG_a"), %%mm4 nt" // block[i] == 0 ? -1 : 0
  396. "pcmpeqw 8(%0, %%"REG_a"), %%mm5nt" // block[i] == 0 ? -1 : 0
  397. "psrlw $4, %%mm0 nt"
  398. "psrlw $4, %%mm1 nt"
  399. "pxor %%mm2, %%mm0 nt"
  400. "pxor %%mm3, %%mm1 nt"
  401. "psubw %%mm2, %%mm0 nt"
  402. "psubw %%mm3, %%mm1 nt"
  403. "pandn %%mm0, %%mm4 nt"
  404. "pandn %%mm1, %%mm5 nt"
  405.                 "pxor %%mm4, %%mm7 nt"
  406.                 "pxor %%mm5, %%mm7 nt"
  407. "movq %%mm4, (%0, %%"REG_a") nt"
  408. "movq %%mm5, 8(%0, %%"REG_a") nt"
  409. "add $16, %%"REG_a" nt"
  410. "jng 1b nt"
  411.                 "movd 124(%0, %3), %%mm0 nt"
  412.                 "movq %%mm7, %%mm6 nt"
  413.                 "psrlq $32, %%mm7 nt"
  414.                 "pxor %%mm6, %%mm7 nt"
  415.                 "movq %%mm7, %%mm6 nt"
  416.                 "psrlq $16, %%mm7 nt"
  417.                 "pxor %%mm6, %%mm7 nt"
  418.                 "pslld $31, %%mm7 nt"
  419.                 "psrlq $15, %%mm7 nt"
  420.                 "pxor %%mm7, %%mm0 nt"
  421.                 "movd %%mm0, 124(%0, %3) nt"
  422.                 
  423. ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "g" (qscale), "r" (-2*nCoeffs)
  424. : "%"REG_a, "memory"
  425. );
  426. }
  427. /* draw the edges of width 'w' of an image of size width, height 
  428.    this mmx version can only handle w==8 || w==16 */
  429. static void draw_edges_mmx(uint8_t *buf, int wrap, int width, int height, int w)
  430. {
  431.     uint8_t *ptr, *last_line;
  432.     int i;
  433.     last_line = buf + (height - 1) * wrap;
  434.     /* left and right */
  435.     ptr = buf;
  436.     if(w==8)
  437.     {
  438. asm volatile(
  439. "1: nt"
  440. "movd (%0), %%mm0 nt"
  441. "punpcklbw %%mm0, %%mm0 nt" 
  442. "punpcklwd %%mm0, %%mm0 nt"
  443. "punpckldq %%mm0, %%mm0 nt"
  444. "movq %%mm0, -8(%0) nt"
  445. "movq -8(%0, %2), %%mm1 nt"
  446. "punpckhbw %%mm1, %%mm1 nt"
  447. "punpckhwd %%mm1, %%mm1 nt"
  448. "punpckhdq %%mm1, %%mm1 nt"
  449. "movq %%mm1, (%0, %2) nt"
  450. "add %1, %0 nt"
  451. "cmp %3, %0 nt"
  452. " jb 1b nt"
  453. : "+r" (ptr)
  454. : "r" ((long)wrap), "r" ((long)width), "r" (ptr + wrap*height)
  455. );
  456.     }
  457.     else
  458.     {
  459. asm volatile(
  460. "1: nt"
  461. "movd (%0), %%mm0 nt"
  462. "punpcklbw %%mm0, %%mm0 nt" 
  463. "punpcklwd %%mm0, %%mm0 nt"
  464. "punpckldq %%mm0, %%mm0 nt"
  465. "movq %%mm0, -8(%0) nt"
  466. "movq %%mm0, -16(%0) nt"
  467. "movq -8(%0, %2), %%mm1 nt"
  468. "punpckhbw %%mm1, %%mm1 nt"
  469. "punpckhwd %%mm1, %%mm1 nt"
  470. "punpckhdq %%mm1, %%mm1 nt"
  471. "movq %%mm1, (%0, %2) nt"
  472. "movq %%mm1, 8(%0, %2) nt"
  473. "add %1, %0 nt"
  474. "cmp %3, %0 nt"
  475. " jb 1b nt"
  476. : "+r" (ptr)
  477. : "r" ((long)wrap), "r" ((long)width), "r" (ptr + wrap*height)
  478. );
  479.     }
  480.     
  481.     for(i=0;i<w;i+=4) {
  482.         /* top and bottom (and hopefully also the corners) */
  483. ptr= buf - (i + 1) * wrap - w;
  484. asm volatile(
  485. "1: nt"
  486. "movq (%1, %0), %%mm0 nt"
  487. "movq %%mm0, (%0) nt"
  488. "movq %%mm0, (%0, %2) nt"
  489. "movq %%mm0, (%0, %2, 2) nt"
  490. "movq %%mm0, (%0, %3) nt"
  491. "add $8, %0 nt"
  492. "cmp %4, %0 nt"
  493. " jb 1b nt"
  494. : "+r" (ptr)
  495. : "r" ((long)buf - (long)ptr - w), "r" ((long)-wrap), "r" ((long)-wrap*3), "r" (ptr+width+2*w)
  496. );
  497. ptr= last_line + (i + 1) * wrap - w;
  498. asm volatile(
  499. "1: nt"
  500. "movq (%1, %0), %%mm0 nt"
  501. "movq %%mm0, (%0) nt"
  502. "movq %%mm0, (%0, %2) nt"
  503. "movq %%mm0, (%0, %2, 2) nt"
  504. "movq %%mm0, (%0, %3) nt"
  505. "add $8, %0 nt"
  506. "cmp %4, %0 nt"
  507. " jb 1b nt"
  508. : "+r" (ptr)
  509. : "r" ((long)last_line - (long)ptr - w), "r" ((long)wrap), "r" ((long)wrap*3), "r" (ptr+width+2*w)
  510. );
  511.     }
  512. }
  513. static void  denoise_dct_mmx(MpegEncContext *s, DCTELEM *block){
  514.     const int intra= s->mb_intra;
  515.     int *sum= s->dct_error_sum[intra];
  516.     uint16_t *offset= s->dct_offset[intra];
  517.     s->dct_count[intra]++;
  518.     asm volatile(
  519.         "pxor %%mm7, %%mm7 nt"
  520.         "1: nt"
  521.         "pxor %%mm0, %%mm0 nt"
  522.         "pxor %%mm1, %%mm1 nt"
  523.         "movq (%0), %%mm2 nt"
  524.         "movq 8(%0), %%mm3 nt"
  525.         "pcmpgtw %%mm2, %%mm0 nt"
  526.         "pcmpgtw %%mm3, %%mm1 nt"
  527.         "pxor %%mm0, %%mm2 nt"
  528.         "pxor %%mm1, %%mm3 nt"
  529.         "psubw %%mm0, %%mm2 nt"
  530.         "psubw %%mm1, %%mm3 nt"
  531.         "movq %%mm2, %%mm4 nt"
  532.         "movq %%mm3, %%mm5 nt"
  533.         "psubusw (%2), %%mm2 nt"
  534.         "psubusw 8(%2), %%mm3 nt"
  535.         "pxor %%mm0, %%mm2 nt"
  536.         "pxor %%mm1, %%mm3 nt"
  537.         "psubw %%mm0, %%mm2 nt"
  538.         "psubw %%mm1, %%mm3 nt"
  539.         "movq %%mm2, (%0) nt"
  540.         "movq %%mm3, 8(%0) nt"
  541.         "movq %%mm4, %%mm2 nt"
  542.         "movq %%mm5, %%mm3 nt"
  543.         "punpcklwd %%mm7, %%mm4 nt"
  544.         "punpckhwd %%mm7, %%mm2 nt"
  545.         "punpcklwd %%mm7, %%mm5 nt"
  546.         "punpckhwd %%mm7, %%mm3 nt"
  547.         "paddd (%1), %%mm4 nt"
  548.         "paddd 8(%1), %%mm2 nt"
  549.         "paddd 16(%1), %%mm5 nt"
  550.         "paddd 24(%1), %%mm3 nt"
  551.         "movq %%mm4, (%1) nt"
  552.         "movq %%mm2, 8(%1) nt"
  553.         "movq %%mm5, 16(%1) nt"
  554.         "movq %%mm3, 24(%1) nt"
  555.         "add $16, %0 nt"
  556.         "add $32, %1 nt"
  557.         "add $16, %2 nt"
  558.         "cmp %3, %0 nt"
  559.             " jb 1b nt"
  560.         : "+r" (block), "+r" (sum), "+r" (offset)
  561.         : "r"(block+64)
  562.     );
  563. }
  564. static void  denoise_dct_sse2(MpegEncContext *s, DCTELEM *block){
  565.     const int intra= s->mb_intra;
  566.     int *sum= s->dct_error_sum[intra];
  567.     uint16_t *offset= s->dct_offset[intra];
  568.     s->dct_count[intra]++;
  569.     asm volatile(
  570.         "pxor %%xmm7, %%xmm7 nt"
  571.         "1: nt"
  572.         "pxor %%xmm0, %%xmm0 nt"
  573.         "pxor %%xmm1, %%xmm1 nt"
  574.         "movdqa (%0), %%xmm2 nt"
  575.         "movdqa 16(%0), %%xmm3 nt"
  576.         "pcmpgtw %%xmm2, %%xmm0 nt"
  577.         "pcmpgtw %%xmm3, %%xmm1 nt"
  578.         "pxor %%xmm0, %%xmm2 nt"
  579.         "pxor %%xmm1, %%xmm3 nt"
  580.         "psubw %%xmm0, %%xmm2 nt"
  581.         "psubw %%xmm1, %%xmm3 nt"
  582.         "movdqa %%xmm2, %%xmm4 nt"
  583.         "movdqa %%xmm3, %%xmm5 nt"
  584.         "psubusw (%2), %%xmm2 nt"
  585.         "psubusw 16(%2), %%xmm3 nt"
  586.         "pxor %%xmm0, %%xmm2 nt"
  587.         "pxor %%xmm1, %%xmm3 nt"
  588.         "psubw %%xmm0, %%xmm2 nt"
  589.         "psubw %%xmm1, %%xmm3 nt"
  590.         "movdqa %%xmm2, (%0) nt"
  591.         "movdqa %%xmm3, 16(%0) nt"
  592.         "movdqa %%xmm4, %%xmm6 nt"
  593.         "movdqa %%xmm5, %%xmm0 nt"
  594.         "punpcklwd %%xmm7, %%xmm4 nt"
  595.         "punpckhwd %%xmm7, %%xmm6 nt"
  596.         "punpcklwd %%xmm7, %%xmm5 nt"
  597.         "punpckhwd %%xmm7, %%xmm0 nt"
  598.         "paddd (%1), %%xmm4 nt"
  599.         "paddd 16(%1), %%xmm6 nt"
  600.         "paddd 32(%1), %%xmm5 nt"
  601.         "paddd 48(%1), %%xmm0 nt"
  602.         "movdqa %%xmm4, (%1) nt"
  603.         "movdqa %%xmm6, 16(%1) nt"
  604.         "movdqa %%xmm5, 32(%1) nt"
  605.         "movdqa %%xmm0, 48(%1) nt"
  606.         "add $32, %0 nt"
  607.         "add $64, %1 nt"
  608.         "add $32, %2 nt"
  609.         "cmp %3, %0 nt"
  610.             " jb 1b nt"
  611.         : "+r" (block), "+r" (sum), "+r" (offset)
  612.         : "r"(block+64)
  613.     );
  614. }
  615. #undef HAVE_MMX2
  616. #define RENAME(a) a ## _MMX
  617. #define RENAMEl(a) a ## _mmx
  618. #include "mpegvideo_mmx_template.c"
  619. #define HAVE_MMX2
  620. #undef RENAME
  621. #undef RENAMEl
  622. #define RENAME(a) a ## _MMX2
  623. #define RENAMEl(a) a ## _mmx2
  624. #include "mpegvideo_mmx_template.c"
  625. #undef RENAME
  626. #undef RENAMEl
  627. #define RENAME(a) a ## _SSE2
  628. #define RENAMEl(a) a ## _sse2
  629. #include "mpegvideo_mmx_template.c"
  630. void MPV_common_init_mmx(MpegEncContext *s)
  631. {
  632.     if (mm_flags & MM_MMX) {
  633.         const int dct_algo = s->avctx->dct_algo;
  634.         
  635.         s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_mmx;
  636.         s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_mmx;
  637.         s->dct_unquantize_mpeg1_intra = dct_unquantize_mpeg1_intra_mmx;
  638.         s->dct_unquantize_mpeg1_inter = dct_unquantize_mpeg1_inter_mmx;
  639.         s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_mmx;
  640.         s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_mmx;
  641.         draw_edges = draw_edges_mmx;
  642.         
  643.         if (mm_flags & MM_SSE2) {
  644.     s->denoise_dct= denoise_dct_sse2;
  645. } else {
  646.          s->denoise_dct= denoise_dct_mmx;
  647. }
  648.         if(dct_algo==FF_DCT_AUTO || dct_algo==FF_DCT_MMX){
  649.             if(mm_flags & MM_SSE2){
  650.                 s->dct_quantize= dct_quantize_SSE2;
  651.             } else if(mm_flags & MM_MMXEXT){
  652.                 s->dct_quantize= dct_quantize_MMX2;
  653.             } else {
  654.                 s->dct_quantize= dct_quantize_MMX;
  655.             }
  656.         }
  657.     }
  658. }