quantize4_mmx.asm
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:21k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. ;/******************************************************************************
  2. ; *                                                                            *
  3. ; *  This file is part of XviD, a free MPEG-4 video encoder/decoder            *
  4. ; *                                                                            *
  5. ; *  XviD is an implementation of a part of one or more MPEG-4 Video tools     *
  6. ; *  as specified in ISO/IEC 14496-2 standard.  Those intending to use this    *
  7. ; *  software module in hardware or software products are advised that its     *
  8. ; *  use may infringe existing patents or copyrights, and any such use         *
  9. ; *  would be at such party's own risk.  The original developer of this        *
  10. ; *  software module and his/her company, and subsequent editors and their     *
  11. ; *  companies, will have no liability for use of this software or             *
  12. ; *  modifications or derivatives thereof.                                     *
  13. ; *                                                                            *
  14. ; *  XviD is free software; you can redistribute it and/or modify it           *
  15. ; *  under the terms of the GNU General Public License as published by         *
  16. ; *  the Free Software Foundation; either version 2 of the License, or         *
  17. ; *  (at your option) any later version.                                       *
  18. ; *                                                                            *
  19. ; *  XviD is distributed in the hope that it will be useful, but               *
  20. ; *  WITHOUT ANY WARRANTY; without even the implied warranty of                *
  21. ; *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
  22. ; *  GNU General Public License for more details.                              *
  23. ; *                                                                            *
  24. ; *  You should have received a copy of the GNU General Public License         *
  25. ; *  along with this program; if not, write to the Free Software               *
  26. ; *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA  *
  27. ; *                                                                            *
  28. ; ******************************************************************************/
  29. ;
  30. ;/******************************************************************************
  31. ; *                                                                            *
  32. ; *  quantize4.asm, MMX optimized MPEG quantization/dequantization             *
  33. ; *                                                                            *
  34. ; *  Copyright (C) 2002 - Peter Ross <pross@cs.rmit.edu.au>                    *
  35. ; *  Copyright (C) 2002 - Michael Militzer <isibaar@xvid.org>                  *
  36. ; *                                                                            *
  37. ; *  For more information visit the XviD homepage: http://www.xvid.org         *
  38. ; *                                                                            *
  39. ; ******************************************************************************/
  40. ;
  41. ;/******************************************************************************
  42. ; *                                                                            *
  43. ; *  Revision history:                                                         *
  44. ; *                                                                            *
  45. ; *  22.01.2002 initial version                                                *
  46. ; *                                                                            *
  47. ; ******************************************************************************/
  48. ; data/text alignment
  49. %define ALIGN 8
  50. %define SATURATE
  51. bits 32
  52. section .data
  53. %macro cglobal 1 
  54. %ifdef PREFIX
  55. global _%1 
  56. %define %1 _%1
  57. %else
  58. global %1
  59. %endif
  60. %endmacro
  61. %macro cextern 1 
  62. %ifdef PREFIX
  63. extern _%1 
  64. %define %1 _%1
  65. %else
  66. extern %1
  67. %endif
  68. %endmacro
  69. mmx_one times 4 dw  1
  70. ;===========================================================================
  71. ;
  72. ; divide by 2Q table 
  73. ;
  74. ;===========================================================================
  75. %macro MMX_DIV  1
  76. times 4 dw  (1 << 17) / (%1 * 2) + 1
  77. %endmacro
  78. align ALIGN
  79. mmx_div
  80. MMX_DIV 1
  81. MMX_DIV 2
  82. MMX_DIV 3
  83. MMX_DIV 4
  84. MMX_DIV 5
  85. MMX_DIV 6
  86. MMX_DIV 7
  87. MMX_DIV 8
  88. MMX_DIV 9
  89. MMX_DIV 10
  90. MMX_DIV 11
  91. MMX_DIV 12
  92. MMX_DIV 13
  93. MMX_DIV 14
  94. MMX_DIV 15
  95. MMX_DIV 16
  96. MMX_DIV 17
  97. MMX_DIV 18
  98. MMX_DIV 19
  99. MMX_DIV 20
  100. MMX_DIV 21
  101. MMX_DIV 22
  102. MMX_DIV 23
  103. MMX_DIV 24
  104. MMX_DIV 25
  105. MMX_DIV 26
  106. MMX_DIV 27
  107. MMX_DIV 28
  108. MMX_DIV 29
  109. MMX_DIV 30
  110. MMX_DIV 31
  111. ;===========================================================================
  112. ;
  113. ; intra matrix 
  114. ;
  115. ;===========================================================================
  116. cextern intra_matrix
  117. cextern intra_matrix_fix
  118. ;===========================================================================
  119. ;
  120. ; inter matrix
  121. ;
  122. ;===========================================================================
  123. cextern inter_matrix
  124. cextern inter_matrix_fix
  125. %define VM18P 3
  126. %define VM18Q 4
  127. ;===========================================================================
  128. ;
  129. ; quantd table 
  130. ;
  131. ;===========================================================================
  132. %macro MMX_QUANTD  1
  133. times 4 dw ((VM18P*%1) + (VM18Q/2)) / VM18Q
  134. %endmacro
  135. quantd
  136. MMX_QUANTD 1 
  137. MMX_QUANTD 2 
  138. MMX_QUANTD 3 
  139. MMX_QUANTD 4 
  140. MMX_QUANTD 5 
  141. MMX_QUANTD 6 
  142. MMX_QUANTD 7 
  143. MMX_QUANTD 8 
  144. MMX_QUANTD 9 
  145. MMX_QUANTD 10 
  146. MMX_QUANTD 11
  147. MMX_QUANTD 12
  148. MMX_QUANTD 13
  149. MMX_QUANTD 14
  150. MMX_QUANTD 15
  151. MMX_QUANTD 16
  152. MMX_QUANTD 17
  153. MMX_QUANTD 18
  154. MMX_QUANTD 19
  155. MMX_QUANTD 20
  156. MMX_QUANTD 21
  157. MMX_QUANTD 22
  158. MMX_QUANTD 23
  159. MMX_QUANTD 24
  160. MMX_QUANTD 25
  161. MMX_QUANTD 26
  162. MMX_QUANTD 27
  163. MMX_QUANTD 28
  164. MMX_QUANTD 29
  165. MMX_QUANTD 30
  166. MMX_QUANTD 31
  167. ;===========================================================================
  168. ;
  169. ; multiple by 2Q table
  170. ;
  171. ;===========================================================================
  172. %macro MMX_MUL_QUANT  1
  173. times 4   dw  %1
  174. %endmacro
  175. mmx_mul_quant
  176. MMX_MUL_QUANT 1
  177. MMX_MUL_QUANT 2
  178. MMX_MUL_QUANT 3
  179. MMX_MUL_QUANT 4
  180. MMX_MUL_QUANT 5
  181. MMX_MUL_QUANT 6
  182. MMX_MUL_QUANT 7
  183. MMX_MUL_QUANT 8
  184. MMX_MUL_QUANT 9
  185. MMX_MUL_QUANT 10
  186. MMX_MUL_QUANT 11
  187. MMX_MUL_QUANT 12
  188. MMX_MUL_QUANT 13
  189. MMX_MUL_QUANT 14
  190. MMX_MUL_QUANT 15
  191. MMX_MUL_QUANT 16
  192. MMX_MUL_QUANT 17
  193. MMX_MUL_QUANT 18
  194. MMX_MUL_QUANT 19
  195. MMX_MUL_QUANT 20
  196. MMX_MUL_QUANT 21
  197. MMX_MUL_QUANT 22
  198. MMX_MUL_QUANT 23
  199. MMX_MUL_QUANT 24
  200. MMX_MUL_QUANT 25
  201. MMX_MUL_QUANT 26
  202. MMX_MUL_QUANT 27
  203. MMX_MUL_QUANT 28
  204. MMX_MUL_QUANT 29
  205. MMX_MUL_QUANT 30
  206. MMX_MUL_QUANT 31
  207. ;===========================================================================
  208. ;
  209. ; saturation limits 
  210. ;
  211. ;===========================================================================
  212. align 16
  213. mmx_32768_minus_2048                times 4 dw (32768-2048)
  214. mmx_32767_minus_2047                times 4 dw (32767-2047)
  215. section .text
  216. ;===========================================================================
  217. ;
  218. ; void quant_intra4_mmx(int16_t * coeff, 
  219. ; const int16_t const * data,
  220. ; const uint32_t quant,
  221. ; const uint32_t dcscalar);
  222. ;
  223. ;===========================================================================
  224. align ALIGN
  225. cglobal quant4_intra_mmx
  226. quant4_intra_mmx
  227. push ecx
  228. push esi
  229. push edi
  230. mov edi, [esp + 12 + 4] ; coeff
  231. mov esi, [esp + 12 + 8] ; data
  232. mov eax, [esp + 12 + 12] ; quant
  233. movq    mm5, [quantd + eax * 8 - 8] ; quantd -> mm5
  234. xor ecx, ecx
  235. cmp al, 1
  236. jz near .q1loop
  237. cmp al, 2
  238. jz near .q2loop
  239. movq mm7, [mmx_div + eax * 8 - 8] ; multipliers[quant] -> mm7
  240.  
  241. align ALIGN
  242. .loop
  243. movq mm0, [esi + 8*ecx] ; mm0 = [1st]
  244. movq mm3, [esi + 8*ecx + 8] ; 
  245. pxor mm1, mm1 ; mm1 = 0
  246. pxor mm4, mm4
  247. pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
  248. pcmpgtw mm4, mm3
  249. pxor mm0, mm1 ; mm0 = |mm0|
  250. pxor mm3, mm4 ;
  251. psubw mm0, mm1 ; displace
  252. psubw mm3, mm4 ;
  253. psllw   mm0, 4 ; level << 4
  254. psllw   mm3, 4 ;
  255. movq    mm2, [intra_matrix + 8*ecx]
  256. psrlw   mm2, 1 ; intra_matrix[i]>>1
  257. paddw   mm0, mm2
  258. movq    mm2, [intra_matrix_fix + ecx*8]
  259. pmulhw  mm0, mm2 ; (level<<4 + intra_matrix[i]>>1) / intra_matrix[i]
  260. movq    mm2, [intra_matrix + 8*ecx + 8]
  261. psrlw   mm2, 1
  262. paddw   mm3, mm2
  263. movq    mm2, [intra_matrix_fix + ecx*8 + 8]
  264. pmulhw  mm3, mm2
  265.     paddw   mm0, mm5 ; + quantd
  266. paddw   mm3, mm5
  267. pmulhw mm0, mm7 ; mm0 = (mm0 / 2Q) >> 16
  268. pmulhw mm3, mm7 ;
  269. psrlw   mm0, 1 ; additional shift by 1 => 16 + 1 = 17
  270. psrlw   mm3, 1
  271. pxor mm0, mm1 ; mm0 *= sign(mm0)
  272. pxor mm3, mm4 ;
  273. psubw mm0, mm1 ; undisplace
  274. psubw mm3, mm4 ;
  275. movq [edi + 8*ecx], mm0
  276. movq [edi + 8*ecx + 8], mm3
  277. add ecx,2
  278. cmp ecx,16
  279. jnz  near .loop 
  280. .done
  281. ; caclulate  data[0] // (int32_t)dcscalar)
  282. mov  ecx, [esp + 12 + 16] ; dcscalar
  283. mov  edx, ecx
  284. movsx  eax, word [esi] ; data[0]
  285. shr  edx, 1 ; edx = dcscalar /2
  286. cmp eax, 0
  287. jg .gtzero
  288. sub eax, edx
  289. jmp short .mul
  290. .gtzero
  291. add eax, edx
  292. .mul
  293. cdq  ; expand eax -> edx:eax
  294. idiv ecx ; eax = edx:eax / dcscalar
  295. mov [edi], ax ; coeff[0] = ax
  296. pop edi
  297. pop esi
  298. pop ecx
  299. ret
  300. align ALIGN
  301. .q1loop
  302. movq mm0, [esi + 8*ecx] ; mm0 = [1st]
  303. movq mm3, [esi + 8*ecx + 8] ; 
  304. pxor mm1, mm1 ; mm1 = 0
  305. pxor mm4, mm4 ;
  306. pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
  307. pcmpgtw mm4, mm3 ;
  308.  
  309. pxor mm0, mm1 ; mm0 = |mm0|
  310. pxor mm3, mm4 ; 
  311. psubw mm0, mm1 ; displace
  312. psubw mm3, mm4 ; 
  313. psllw   mm0, 4
  314. psllw   mm3, 4
  315. movq    mm2, [intra_matrix + 8*ecx]
  316. psrlw   mm2, 1
  317. paddw   mm0, mm2
  318. movq    mm2, [intra_matrix_fix + ecx*8]
  319. pmulhw  mm0, mm2 ; (level<<4 + intra_matrix[i]>>1) / intra_matrix[i]
  320. movq    mm2, [intra_matrix + 8*ecx + 8]
  321. psrlw   mm2, 1
  322. paddw   mm3, mm2
  323. movq    mm2, [intra_matrix_fix + ecx*8 + 8]
  324. pmulhw  mm3, mm2
  325.         paddw   mm0, mm5
  326. paddw   mm3, mm5
  327. psrlw mm0, 1 ; mm0 >>= 1   (/2)
  328. psrlw mm3, 1 ;
  329. pxor mm0, mm1 ; mm0 *= sign(mm0)
  330. pxor mm3, mm4        ;
  331. psubw mm0, mm1 ; undisplace
  332. psubw mm3, mm4 ;
  333. movq [edi + 8*ecx], mm0
  334. movq [edi + 8*ecx + 8], mm3
  335. add ecx,2
  336. cmp ecx,16
  337. jnz near .q1loop
  338. jmp near .done
  339. align ALIGN
  340. .q2loop
  341. movq mm0, [esi + 8*ecx] ; mm0 = [1st]
  342. movq mm3, [esi + 8*ecx + 8] ; 
  343. pxor mm1, mm1 ; mm1 = 0
  344. pxor mm4, mm4 ;
  345. pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
  346. pcmpgtw mm4, mm3 ;
  347.  
  348. pxor mm0, mm1 ; mm0 = |mm0|
  349. pxor mm3, mm4 ; 
  350. psubw mm0, mm1 ; displace
  351. psubw mm3, mm4 ; 
  352. psllw   mm0, 4
  353. psllw   mm3, 4
  354. movq    mm2, [intra_matrix + 8*ecx]
  355. psrlw   mm2, 1
  356. paddw   mm0, mm2
  357. movq    mm2, [intra_matrix_fix + ecx*8]
  358. pmulhw  mm0, mm2 ; (level<<4 + intra_matrix[i]>>1) / intra_matrix[i]
  359. movq    mm2, [intra_matrix + 8*ecx + 8]
  360. psrlw   mm2, 1
  361. paddw   mm3, mm2
  362. movq    mm2, [intra_matrix_fix + ecx*8 + 8]
  363. pmulhw  mm3, mm2
  364.         paddw   mm0, mm5
  365. paddw   mm3, mm5
  366. psrlw mm0, 2 ; mm0 >>= 1   (/4)
  367. psrlw mm3, 2 ;
  368. pxor mm0, mm1 ; mm0 *= sign(mm0)
  369. pxor mm3, mm4        ;
  370. psubw mm0, mm1 ; undisplace
  371. psubw mm3, mm4 ;
  372. movq [edi + 8*ecx], mm0
  373. movq [edi + 8*ecx + 8], mm3
  374. add ecx,2
  375. cmp ecx,16
  376. jnz near .q2loop
  377. jmp near .done
  378. ;===========================================================================
  379. ;
  380. ; uint32_t quant4_inter_mmx(int16_t * coeff,
  381. ; const int16_t const * data,
  382. ; const uint32_t quant);
  383. ;
  384. ;===========================================================================
  385. align ALIGN
  386. cglobal quant4_inter_mmx
  387. quant4_inter_mmx
  388. push ecx
  389. push esi
  390. push edi
  391. mov edi, [esp + 12 + 4] ; coeff
  392. mov esi, [esp + 12 + 8] ; data
  393. mov eax, [esp + 12 + 12] ; quant
  394. xor ecx, ecx
  395. pxor mm5, mm5 ; sum
  396. cmp al, 1
  397. jz  near .q1loop
  398. cmp al, 2
  399. jz  near .q2loop
  400. movq mm7, [mmx_div + eax * 8 - 8] ; divider
  401. align ALIGN
  402. .loop
  403. movq mm0, [esi + 8*ecx] ; mm0 = [1st]
  404. movq mm3, [esi + 8*ecx + 8] ; 
  405. pxor mm1, mm1 ; mm1 = 0
  406. pxor mm4, mm4 ;
  407. pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
  408. pcmpgtw mm4, mm3 ; 
  409. pxor mm0, mm1 ; mm0 = |mm0|
  410. pxor mm3, mm4 ; 
  411. psubw mm0, mm1 ; displace
  412. psubw mm3, mm4 ;
  413. psllw   mm0, 4
  414. psllw   mm3, 4
  415. movq    mm2, [inter_matrix + 8*ecx]
  416. psrlw   mm2, 1
  417. paddw   mm0, mm2
  418. movq    mm2, [inter_matrix_fix + ecx*8]
  419. pmulhw  mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
  420. movq    mm2, [inter_matrix + 8*ecx + 8]
  421. psrlw   mm2, 1
  422. paddw   mm3, mm2
  423. movq    mm2, [inter_matrix_fix + ecx*8 + 8]
  424. pmulhw  mm3, mm2
  425. pmulhw mm0, mm7 ; mm0 = (mm0 / 2Q) >> 16
  426. pmulhw mm3, mm7 ; 
  427. psrlw   mm0, 1 ; additional shift by 1 => 16 + 1 = 17
  428. psrlw   mm3, 1
  429. paddw mm5, mm0 ; sum += mm0
  430. pxor mm0, mm1 ; mm0 *= sign(mm0)
  431. paddw mm5, mm3 ;
  432. pxor mm3, mm4 ;
  433. psubw mm0, mm1 ; undisplace
  434. psubw mm3, mm4
  435. movq [edi + 8*ecx], mm0
  436. movq [edi + 8*ecx + 8], mm3
  437. add ecx, 2
  438. cmp ecx, 16
  439. jnz near .loop
  440. .done
  441. pmaddwd mm5, [mmx_one]
  442. movq    mm0, mm5
  443. psrlq   mm5, 32
  444. paddd   mm0, mm5
  445. movd eax, mm0 ; return sum
  446. pop edi
  447. pop esi
  448. pop ecx
  449. ret
  450. align ALIGN
  451. .q1loop
  452. movq mm0, [esi + 8*ecx] ; mm0 = [1st]
  453. movq mm3, [esi + 8*ecx+ 8]
  454. pxor mm1, mm1 ; mm1 = 0
  455. pxor mm4, mm4 ;
  456. pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
  457. pcmpgtw mm4, mm3 ;
  458. pxor mm0, mm1 ; mm0 = |mm0|
  459. pxor mm3, mm4 ; 
  460. psubw mm0, mm1 ; displace
  461. psubw mm3, mm4 ;
  462. psllw   mm0, 4
  463. psllw   mm3, 4
  464. movq    mm2, [inter_matrix + 8*ecx]
  465. psrlw   mm2, 1
  466. paddw   mm0, mm2
  467. movq    mm2, [inter_matrix_fix + ecx*8]
  468. pmulhw  mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
  469. movq    mm2, [inter_matrix + 8*ecx + 8]
  470. psrlw   mm2, 1
  471. paddw   mm3, mm2
  472. movq    mm2, [inter_matrix_fix + ecx*8 + 8]
  473. pmulhw  mm3, mm2
  474.  
  475. psrlw mm0, 1 ; mm0 >>= 1   (/2)
  476. psrlw mm3, 1 ;
  477. paddw mm5, mm0 ; sum += mm0
  478. pxor mm0, mm1 ; mm0 *= sign(mm0)
  479. paddw mm5, mm3 ;
  480. pxor mm3, mm4 ;
  481. psubw mm0, mm1 ; undisplace
  482. psubw mm3, mm4
  483. movq [edi + 8*ecx], mm0
  484. movq [edi + 8*ecx + 8], mm3
  485. add ecx,2
  486. cmp ecx,16
  487. jnz near .q1loop
  488. jmp .done
  489. align ALIGN
  490. .q2loop
  491. movq mm0, [esi + 8*ecx] ; mm0 = [1st]
  492. movq mm3, [esi + 8*ecx+ 8]
  493. pxor mm1, mm1 ; mm1 = 0
  494. pxor mm4, mm4 ;
  495. pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
  496. pcmpgtw mm4, mm3 ;
  497. pxor mm0, mm1 ; mm0 = |mm0|
  498. pxor mm3, mm4 ; 
  499. psubw mm0, mm1 ; displace
  500. psubw mm3, mm4 ;
  501. psllw   mm0, 4
  502. psllw   mm3, 4
  503. movq    mm2, [inter_matrix + 8*ecx]
  504. psrlw   mm2, 1
  505. paddw   mm0, mm2
  506. movq    mm2, [inter_matrix_fix + ecx*8]
  507. pmulhw  mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
  508. movq    mm2, [inter_matrix + 8*ecx + 8]
  509. psrlw   mm2, 1
  510. paddw   mm3, mm2
  511. movq    mm2, [inter_matrix_fix + ecx*8 + 8]
  512. pmulhw  mm3, mm2
  513.  
  514. psrlw mm0, 2 ; mm0 >>= 1   (/2)
  515. psrlw mm3, 2 ;
  516. paddw mm5, mm0 ; sum += mm0
  517. pxor mm0, mm1 ; mm0 *= sign(mm0)
  518. paddw mm5, mm3 ;
  519. pxor mm3, mm4 ;
  520. psubw mm0, mm1 ; undisplace
  521. psubw mm3, mm4
  522. movq [edi + 8*ecx], mm0
  523. movq [edi + 8*ecx + 8], mm3
  524. add ecx,2
  525. cmp ecx,16
  526. jnz near .q2loop
  527. jmp .done
  528. ;===========================================================================
  529. ;
  530. ; void dequant4_intra_mmx(int16_t *data,
  531. ;                    const int16_t const *coeff,
  532. ;                    const uint32_t quant,
  533. ;                    const uint32_t dcscalar);
  534. ;
  535. ;===========================================================================
  536. align 16
  537. cglobal dequant4_intra_mmx
  538. dequant4_intra_mmx
  539.         push    esi
  540.         push    edi
  541.         mov    edi, [esp + 8 + 4]        ; data
  542.         mov    esi, [esp + 8 + 8]        ; coeff
  543.         mov    eax, [esp + 8 + 12]        ; quant
  544.         
  545.         movq mm7, [mmx_mul_quant  + eax*8 - 8]
  546.     
  547.         xor eax, eax
  548. align 16        
  549. .loop
  550.         movq    mm0, [esi + 8*eax]        ; mm0 = [coeff]
  551.         
  552.         pxor    mm1, mm1                ; mm1 = 0
  553.         pcmpeqw    mm1, mm0                ; mm1 = (0 == mm0)
  554.         pxor    mm2, mm2                ; mm2 = 0
  555.         pcmpgtw    mm2, mm0                ; mm2 = (0 > mm0)
  556.         pxor    mm0, mm2                ; mm0 = |mm0|
  557.         psubw    mm0, mm2                ; displace
  558.         pmullw    mm0, mm7                ; mm0 *= quant
  559.         
  560.         movq    mm3, [intra_matrix + 8*eax]
  561.         movq  mm4, mm0                    ;
  562.         pmullw    mm0, mm3                ; mm0 = low(mm0 * mm3)
  563.         pmulhw    mm3, mm4                ; mm3 = high(mm0 * mm3)
  564.         movq    mm4, mm0                ; mm0,mm4 = unpack(mm3, mm0)
  565.         punpcklwd mm0, mm3                ;
  566.         punpckhwd mm4, mm3                ;
  567.         psrld mm0, 3                    ; mm0,mm4 /= 8
  568.         psrld mm4, 3                    ;
  569.         packssdw mm0, mm4                ; mm0 = pack(mm4, mm0)
  570.         pxor    mm0, mm2                ; mm0 *= sign(mm0)
  571.         psubw    mm0, mm2                ; undisplace
  572.         pandn    mm1, mm0                ; mm1 = ~(iszero) & mm0
  573. %ifdef SATURATE
  574.         movq mm2, [mmx_32767_minus_2047] 
  575.         movq mm6, [mmx_32768_minus_2048] 
  576.         paddsw    mm1, mm2
  577.         psubsw    mm1, mm2
  578.         psubsw    mm1, mm6
  579.         paddsw    mm1, mm6
  580. %endif
  581.         movq    [edi + 8*eax], mm1        ; [data] = mm0
  582.         add eax, 1
  583.         cmp eax, 16
  584.         jnz    near .loop
  585.         mov    ax, [esi]                    ; ax = data[0]
  586.         imul     ax, [esp + 8 + 16]        ; eax = data[0] * dcscalar
  587.         mov    [edi], ax                    ; data[0] = ax
  588. %ifdef SATURATE
  589.         cmp ax, -2048
  590.         jl .set_n2048
  591.         cmp ax, 2047
  592.         jg .set_2047
  593. %endif
  594.         pop    edi
  595.         pop    esi
  596.         ret
  597. %ifdef SATURATE
  598. .set_n2048
  599.         mov    word [edi], -2048
  600.         pop    edi
  601.         pop    esi
  602.         ret
  603.     
  604. .set_2047
  605.         mov    word [edi], 2047
  606.         pop    edi
  607.         pop    esi
  608. ret
  609. %endif
  610. ;===========================================================================
  611. ;
  612. ; void dequant4_inter_mmx(int16_t * data,
  613. ;                    const int16_t * const coeff,
  614. ;                    const uint32_t quant);
  615. ;
  616. ;===========================================================================
  617. align 16
  618. cglobal dequant4_inter_mmx
  619. dequant4_inter_mmx
  620.         push    esi
  621.         push    edi
  622.         mov    edi, [esp + 8 + 4]        ; data
  623.         mov    esi, [esp + 8 + 8]        ; coeff
  624.         mov    eax, [esp + 8 + 12]        ; quant
  625.         movq mm7, [mmx_mul_quant  + eax*8 - 8]
  626.         movq mm6, [mmx_one]
  627.         xor eax, eax
  628.         pxor mm5, mm5        ; mismatch sum
  629. align 16        
  630. .loop
  631.         movq    mm0, [esi + 8*eax]                        ; mm0 = [coeff]
  632.         pxor    mm1, mm1                ; mm1 = 0
  633.         pcmpeqw    mm1, mm0                ; mm1 = (0 == mm0)
  634.         pxor    mm2, mm2                ; mm2 = 0
  635.         pcmpgtw    mm2, mm0                ; mm2 = (0 > mm0)
  636.         pxor    mm0, mm2                ; mm0 = |mm0|
  637.         psubw    mm0, mm2                ; displace
  638.         psllw    mm0, 1                ;
  639.         paddsw    mm0, mm6            ; mm0 = 2*mm0 + 1
  640.         pmullw    mm0, mm7            ; mm0 *= quant
  641.         movq    mm3, [inter_matrix + 8*eax]
  642.         movq  mm4, mm0
  643.         pmullw    mm0, mm3            ; mm0 = low(mm0 * mm3)
  644.         pmulhw    mm3, mm4            ; mm3 = high(mm0 * mm3)
  645.         movq    mm4, mm0            ; mm0,mm4 = unpack(mm3, mm0)
  646.         punpcklwd mm0, mm3            ;
  647.         punpckhwd mm4, mm3            ;
  648.         psrad mm0, 4                ; mm0,mm4 /= 16
  649.         psrad mm4, 4                ;
  650.         packssdw mm0, mm4            ; mm0 = pack(mm4, mm0)
  651.         pxor    mm0, mm2            ; mm0 *= sign(mm0)
  652.         psubw    mm0, mm2            ; undisplace
  653.         pandn    mm1, mm0            ; mm1 = ~(iszero) & mm0
  654. ;%ifdef SATURATE
  655.         movq mm2, [mmx_32767_minus_2047] 
  656.         movq mm4, [mmx_32768_minus_2048]
  657.         paddsw    mm1, mm2
  658.         psubsw    mm1, mm2
  659.         psubsw    mm1, mm4
  660.         paddsw    mm1, mm4
  661. ;%endif
  662.         pxor mm5, mm1        ; mismatch
  663.     
  664.         movq    [edi + 8*eax], mm1        ; [data] = mm0
  665.         add eax, 1
  666.         cmp eax, 16
  667.         jnz    near .loop
  668.         ; mismatch control
  669.         movq mm0, mm5
  670.         movq mm1, mm5
  671.         movq mm2, mm5
  672.         psrlq mm0, 48
  673.         psrlq mm1, 32
  674.         psrlq mm2, 16
  675.         pxor mm5, mm0
  676.         pxor mm5, mm1
  677.         pxor mm5, mm2
  678.         movd eax, mm5
  679.         test eax, 0x1
  680.         jnz .done
  681.         xor word [edi + 2*63], 1
  682. .done    
  683.         pop    edi
  684.         pop    esi
  685.         ret