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

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. ;/**************************************************************************
  2. ; *
  3. ; * XVID MPEG-4 VIDEO CODEC
  4. ; * mmx quantization/dequantization
  5. ; *
  6. ; * This program is an implementation of a part of one or more MPEG-4
  7. ; * Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
  8. ; * to use this software module in hardware or software products are
  9. ; * advised that its use may infringe existing patents or copyrights, and
  10. ; * any such use would be at such party's own risk.  The original
  11. ; * developer of this software module and his/her company, and subsequent
  12. ; * editors and their companies, will have no liability for use of this
  13. ; * software or modifications or derivatives thereof.
  14. ; *
  15. ; * This program is free software; you can redistribute it and/or modify
  16. ; * it under the terms of the GNU General Public License as published by
  17. ; * the Free Software Foundation; either version 2 of the License, or
  18. ; * (at your option) any later version.
  19. ; *
  20. ; * This program is distributed in the hope that it will be useful,
  21. ; * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. ; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23. ; * GNU General Public License for more details.
  24. ; *
  25. ; * You should have received a copy of the GNU General Public License
  26. ; * along with this program; if not, write to the Free Software
  27. ; * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  28. ; *
  29. ; *************************************************************************/
  30. ;/**************************************************************************
  31. ; *
  32. ; * History:
  33. ; *
  34. ; * 26.12.2001 minor bug fixes, dequant saturate, further optimization
  35. ; * 19.11.2001  quant_inter_mmx now returns sum of abs. coefficient values
  36. ; * 04.11.2001 nasm version; (c)2001 peter ross <pross@cs.rmit.edu.au>
  37. ; *
  38. ; *************************************************************************/
  39. ; enable dequant saturate [-2048,2047], test purposes only.
  40. %define SATURATE
  41. ; data/text alignment
  42. %define ALIGN 8
  43. bits 32
  44. section .data
  45. %macro cglobal 1 
  46. %ifdef PREFIX
  47. global _%1 
  48. %define %1 _%1
  49. %else
  50. global %1
  51. %endif
  52. %endmacro
  53. plus_one times 4 dw  1
  54. ;===========================================================================
  55. ;
  56. ; subtract by Q/2 table
  57. ;
  58. ;===========================================================================
  59. %macro MMX_SUB  1
  60. times 4 dw %1 / 2
  61. %endmacro
  62. align ALIGN
  63. mmx_sub
  64. MMX_SUB 1
  65. MMX_SUB 2
  66. MMX_SUB 3
  67. MMX_SUB 4
  68. MMX_SUB 5
  69. MMX_SUB 6
  70. MMX_SUB 7
  71. MMX_SUB 8
  72. MMX_SUB 9
  73. MMX_SUB 10
  74. MMX_SUB 11
  75. MMX_SUB 12
  76. MMX_SUB 13
  77. MMX_SUB 14
  78. MMX_SUB 15
  79. MMX_SUB 16
  80. MMX_SUB 17
  81. MMX_SUB 18
  82. MMX_SUB 19
  83. MMX_SUB 20
  84. MMX_SUB 21
  85. MMX_SUB 22
  86. MMX_SUB 23
  87. MMX_SUB 24
  88. MMX_SUB 25
  89. MMX_SUB 26
  90. MMX_SUB 27
  91. MMX_SUB 28
  92. MMX_SUB 29
  93. MMX_SUB 30
  94. MMX_SUB 31
  95. ;===========================================================================
  96. ;
  97. ; divide by 2Q table 
  98. ;
  99. ; use a shift of 16 to take full advantage of _pmulhw_
  100. ; for q=1, _pmulhw_ will overflow so it is treated seperately
  101. ; (3dnow2 provides _pmulhuw_ which wont cause overflow)
  102. ;
  103. ;===========================================================================
  104. %macro MMX_DIV  1
  105. times 4 dw  (1 << 16) / (%1 * 2) + 1
  106. %endmacro
  107. align ALIGN
  108. mmx_div
  109. MMX_DIV 1
  110. MMX_DIV 2
  111. MMX_DIV 3
  112. MMX_DIV 4
  113. MMX_DIV 5
  114. MMX_DIV 6
  115. MMX_DIV 7
  116. MMX_DIV 8
  117. MMX_DIV 9
  118. MMX_DIV 10
  119. MMX_DIV 11
  120. MMX_DIV 12
  121. MMX_DIV 13
  122. MMX_DIV 14
  123. MMX_DIV 15
  124. MMX_DIV 16
  125. MMX_DIV 17
  126. MMX_DIV 18
  127. MMX_DIV 19
  128. MMX_DIV 20
  129. MMX_DIV 21
  130. MMX_DIV 22
  131. MMX_DIV 23
  132. MMX_DIV 24
  133. MMX_DIV 25
  134. MMX_DIV 26
  135. MMX_DIV 27
  136. MMX_DIV 28
  137. MMX_DIV 29
  138. MMX_DIV 30
  139. MMX_DIV 31
  140. ;===========================================================================
  141. ;
  142. ; add by (odd(Q) ? Q : Q - 1) table
  143. ;
  144. ;===========================================================================
  145. %macro MMX_ADD  1
  146. %if %1 % 2 != 0
  147. times 4 dw %1
  148. %else
  149. times 4 dw %1 - 1
  150. %endif
  151. %endmacro
  152. align ALIGN
  153. mmx_add
  154. MMX_ADD 1
  155. MMX_ADD 2
  156. MMX_ADD 3
  157. MMX_ADD 4
  158. MMX_ADD 5
  159. MMX_ADD 6
  160. MMX_ADD 7
  161. MMX_ADD 8
  162. MMX_ADD 9
  163. MMX_ADD 10
  164. MMX_ADD 11
  165. MMX_ADD 12
  166. MMX_ADD 13
  167. MMX_ADD 14
  168. MMX_ADD 15
  169. MMX_ADD 16
  170. MMX_ADD 17
  171. MMX_ADD 18
  172. MMX_ADD 19
  173. MMX_ADD 20
  174. MMX_ADD 21
  175. MMX_ADD 22
  176. MMX_ADD 23
  177. MMX_ADD 24
  178. MMX_ADD 25
  179. MMX_ADD 26
  180. MMX_ADD 27
  181. MMX_ADD 28
  182. MMX_ADD 29
  183. MMX_ADD 30
  184. MMX_ADD 31
  185. ;===========================================================================
  186. ;
  187. ; multiple by 2Q table
  188. ;
  189. ;===========================================================================
  190. %macro MMX_MUL  1
  191. times 4 dw %1 * 2
  192. %endmacro
  193. align ALIGN
  194. mmx_mul
  195. MMX_MUL 1
  196. MMX_MUL 2
  197. MMX_MUL 3
  198. MMX_MUL 4
  199. MMX_MUL 5
  200. MMX_MUL 6
  201. MMX_MUL 7
  202. MMX_MUL 8
  203. MMX_MUL 9
  204. MMX_MUL 10
  205. MMX_MUL 11
  206. MMX_MUL 12
  207. MMX_MUL 13
  208. MMX_MUL 14
  209. MMX_MUL 15
  210. MMX_MUL 16
  211. MMX_MUL 17
  212. MMX_MUL 18
  213. MMX_MUL 19
  214. MMX_MUL 20
  215. MMX_MUL 21
  216. MMX_MUL 22
  217. MMX_MUL 23
  218. MMX_MUL 24
  219. MMX_MUL 25
  220. MMX_MUL 26
  221. MMX_MUL 27
  222. MMX_MUL 28
  223. MMX_MUL 29
  224. MMX_MUL 30
  225. MMX_MUL 31
  226. ;===========================================================================
  227. ;
  228. ; saturation limits 
  229. ;
  230. ;===========================================================================
  231. align ALIGN
  232. mmx_32768_minus_2048 times 4 dw (32768-2048)
  233. mmx_32767_minus_2047 times 4 dw (32767-2047)
  234. section .text
  235. ;===========================================================================
  236. ;
  237. ; void quant_intra_mmx(int16_t * coeff, 
  238. ; const int16_t const * data,
  239. ; const uint32_t quant,
  240. ; const uint32_t dcscalar);
  241. ;
  242. ;===========================================================================
  243. align ALIGN
  244. cglobal quant_intra_mmx
  245. quant_intra_mmx
  246. push ecx
  247. push esi
  248. push edi
  249. mov edi, [esp + 12 + 4] ; coeff
  250. mov esi, [esp + 12 + 8] ; data
  251. mov eax, [esp + 12 + 12] ; quant
  252. xor ecx, ecx
  253. cmp al, 1
  254. jz .q1loop
  255. movq mm7, [mmx_div + eax * 8 - 8]
  256. align ALIGN
  257. .loop
  258. movq mm0, [esi + 8*ecx] ; mm0 = [1st]
  259. movq mm3, [esi + 8*ecx + 8] ; 
  260. pxor mm1, mm1 ; mm1 = 0
  261. pxor mm4, mm4 ;
  262. pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
  263. pcmpgtw mm4, mm3 ; 
  264. pxor mm0, mm1 ; mm0 = |mm0|
  265. pxor mm3, mm4 ;
  266. psubw mm0, mm1 ; displace
  267. psubw mm3, mm4 ;
  268. pmulhw mm0, mm7 ; mm0 = (mm0 / 2Q) >> 16
  269. pmulhw mm3, mm7 ;
  270. pxor mm0, mm1 ; mm0 *= sign(mm0)
  271. pxor mm3, mm4 ;
  272. psubw mm0, mm1 ; undisplace
  273. psubw mm3, mm4 ;
  274. movq [edi + 8*ecx], mm0
  275. movq [edi + 8*ecx + 8], mm3
  276. add ecx,2
  277. cmp ecx,16
  278. jnz  .loop 
  279. .done
  280. ; caclulate  data[0] // (int32_t)dcscalar)
  281. mov  ecx, [esp + 12 + 16] ; dcscalar
  282. mov  edx, ecx
  283. movsx  eax, word [esi] ; data[0]
  284. shr  edx, 1 ; edx = dcscalar /2
  285. cmp eax, 0
  286. jg .gtzero
  287. sub eax, edx
  288. jmp short .mul
  289. .gtzero
  290. add eax, edx
  291. .mul
  292. cdq  ; expand eax -> edx:eax
  293. idiv ecx ; eax = edx:eax / dcscalar
  294. mov [edi], ax ; coeff[0] = ax
  295. pop edi
  296. pop esi
  297. pop ecx
  298. ret
  299. align ALIGN
  300. .q1loop
  301. movq mm0, [esi + 8*ecx] ; mm0 = [1st]
  302. movq mm3, [esi + 8*ecx + 8] ; 
  303. pxor mm1, mm1 ; mm1 = 0
  304. pxor mm4, mm4 ;
  305. pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
  306. pcmpgtw mm4, mm3 ; 
  307. pxor mm0, mm1 ; mm0 = |mm0|
  308. pxor mm3, mm4 ; 
  309. psubw mm0, mm1 ; displace
  310. psubw mm3, mm4 ; 
  311. psrlw mm0, 1 ; mm0 >>= 1   (/2)
  312. psrlw mm3, 1 ;
  313. pxor mm0, mm1 ; mm0 *= sign(mm0)
  314. pxor mm3, mm4        ;
  315. psubw mm0, mm1 ; undisplace
  316. psubw mm3, mm4 ;
  317. movq [edi + 8*ecx], mm0
  318. movq [edi + 8*ecx + 8], mm3
  319. add ecx,2
  320. cmp ecx,16
  321. jnz .q1loop
  322. jmp short .done
  323. ;===========================================================================
  324. ;
  325. ; uint32_t quant_inter_mmx(int16_t * coeff,
  326. ; const int16_t const * data,
  327. ; const uint32_t quant);
  328. ;
  329. ;===========================================================================
  330. align ALIGN
  331. cglobal quant_inter_mmx
  332. quant_inter_mmx
  333. push ecx
  334. push esi
  335. push edi
  336. mov edi, [esp + 12 + 4] ; coeff
  337. mov esi, [esp + 12 + 8] ; data
  338. mov eax, [esp + 12 + 12] ; quant
  339. xor ecx, ecx
  340. pxor mm5, mm5 ; sum
  341. movq mm6, [mmx_sub + eax * 8 - 8] ; sub
  342. cmp al, 1
  343. jz  .q1loop
  344. movq mm7, [mmx_div + eax * 8 - 8] ; divider
  345. align ALIGN
  346. .loop
  347. movq mm0, [esi + 8*ecx] ; mm0 = [1st]
  348. movq mm3, [esi + 8*ecx + 8] ; 
  349. pxor mm1, mm1 ; mm1 = 0
  350. pxor mm4, mm4 ;
  351. pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
  352. pcmpgtw mm4, mm3 ; 
  353. pxor mm0, mm1 ; mm0 = |mm0|
  354. pxor mm3, mm4 ; 
  355. psubw mm0, mm1 ; displace
  356. psubw mm3, mm4 ; 
  357. psubusw mm0, mm6 ; mm0 -= sub (unsigned, dont go < 0)
  358. psubusw mm3, mm6 ;
  359. pmulhw mm0, mm7 ; mm0 = (mm0 / 2Q) >> 16
  360. pmulhw mm3, mm7 ; 
  361. paddw mm5, mm0 ; sum += mm0
  362. pxor mm0, mm1 ; mm0 *= sign(mm0)
  363. paddw mm5, mm3 ;
  364. pxor mm3, mm4 ;
  365. psubw mm0, mm1 ; undisplace
  366. psubw mm3, mm4
  367. movq [edi + 8*ecx], mm0
  368. movq [edi + 8*ecx + 8], mm3
  369. add ecx, 2
  370. cmp ecx, 16
  371. jnz .loop
  372. .done
  373. pmaddwd mm5, [plus_one]
  374. movq    mm0, mm5
  375. psrlq   mm5, 32
  376. paddd   mm0, mm5
  377. movd eax, mm0 ; return sum
  378. pop edi
  379. pop esi
  380. pop ecx
  381. ret
  382. align ALIGN
  383. .q1loop
  384. movq mm0, [esi + 8*ecx] ; mm0 = [1st]
  385. movq mm3, [esi + 8*ecx+ 8] ; 
  386. pxor mm1, mm1 ; mm1 = 0
  387. pxor mm4, mm4 ;
  388. pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
  389. pcmpgtw mm4, mm3 ; 
  390. pxor mm0, mm1 ; mm0 = |mm0|
  391. pxor mm3, mm4 ; 
  392. psubw mm0, mm1 ; displace
  393. psubw mm3, mm4 ; 
  394. psubusw mm0, mm6 ; mm0 -= sub (unsigned, dont go < 0)
  395. psubusw mm3, mm6 ;
  396. psrlw mm0, 1 ; mm0 >>= 1   (/2)
  397. psrlw mm3, 1 ;
  398. paddw mm5, mm0 ; sum += mm0
  399. pxor mm0, mm1 ; mm0 *= sign(mm0)
  400. paddw mm5, mm3 ;
  401. pxor mm3, mm4 ;
  402. psubw mm0, mm1 ; undisplace
  403. psubw mm3, mm4
  404. movq [edi + 8*ecx], mm0
  405. movq [edi + 8*ecx + 8], mm3
  406. add ecx,2
  407. cmp ecx,16
  408. jnz .q1loop
  409. jmp .done
  410. ;===========================================================================
  411. ;
  412. ; void dequant_intra_mmx(int16_t *data,
  413. ; const int16_t const *coeff,
  414. ; const uint32_t quant,
  415. ; const uint32_t dcscalar);
  416. ;
  417. ;===========================================================================
  418. align ALIGN
  419. cglobal dequant_intra_mmx
  420. dequant_intra_mmx
  421. push esi
  422. push edi
  423. mov edi, [esp + 8 + 4] ; data
  424. mov esi, [esp + 8 + 8] ; coeff
  425. mov eax, [esp + 8 + 12] ; quant
  426. movq mm6, [mmx_add + eax * 8 - 8]
  427. movq mm7, [mmx_mul + eax * 8 - 8]
  428. xor eax, eax
  429. align ALIGN
  430. .loop
  431. movq mm0, [esi + 8*eax] ; mm0 = [coeff]
  432. movq mm3, [esi + 8*eax + 8] ; 
  433. pxor mm1, mm1 ; mm1 = 0
  434. pxor mm4, mm4 ;
  435. pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
  436. pcmpgtw mm4, mm3 ; 
  437. pxor mm2, mm2 ; mm2 = 0
  438. pxor mm5, mm5 ;
  439. pcmpeqw mm2, mm0 ; mm2 = (0 == mm0)
  440. pcmpeqw mm5, mm3 ; 
  441. pandn   mm2, mm6 ; mm2 = (iszero ? 0 : add)
  442. pandn   mm5, mm6 ;
  443. pxor mm0, mm1 ; mm0 = |mm0|
  444. pxor mm3, mm4 ; 
  445. psubw mm0, mm1 ; displace
  446. psubw mm3, mm4 ; 
  447. pmullw mm0, mm7 ; mm0 *= 2Q
  448. pmullw mm3, mm7 ; 
  449. paddw mm0, mm2 ; mm0 += mm2 (add)
  450. paddw mm3, mm5 ;
  451. pxor mm0, mm1 ; mm0 *= sign(mm0)
  452. pxor mm3, mm4 ;
  453. psubw mm0, mm1 ; undisplace
  454. psubw mm3, mm4
  455. %ifdef SATURATE
  456. movq mm2, [mmx_32767_minus_2047] 
  457. movq mm4, [mmx_32768_minus_2048] 
  458. paddsw mm0, mm2
  459. paddsw mm3, mm2
  460. psubsw mm0, mm2
  461. psubsw mm3, mm2
  462. psubsw mm0, mm4
  463. psubsw mm3, mm4
  464. paddsw mm0, mm4
  465. paddsw mm3, mm4
  466. %endif
  467. movq [edi + 8*eax], mm0 ; [data] = mm0
  468. movq [edi + 8*eax + 8], mm3
  469. add eax, 2
  470. cmp eax, 16
  471. jnz near .loop
  472. mov ax, [esi] ; ax = data[0]
  473. imul ax, [esp + 8 + 16] ; eax = data[0] * dcscalar
  474. %ifdef SATURATE
  475. cmp ax, -2048
  476. jl .set_n2048
  477. cmp ax, 2047
  478. jg .set_2047
  479. %endif
  480. mov [edi], ax
  481. pop edi
  482. pop esi
  483. ret
  484. %ifdef SATURATE
  485. align ALIGN
  486. .set_n2048
  487. mov word [edi], -2048
  488. pop edi
  489. pop esi
  490. ret
  491. align ALIGN
  492. .set_2047
  493. mov word [edi], 2047
  494. pop edi
  495. pop esi
  496. ret
  497. %endif
  498. ;===========================================================================
  499. ;
  500. ; void dequant_inter_mmx(int16_t * data,
  501. ; const int16_t * const coeff,
  502. ; const uint32_t quant);
  503. ;
  504. ;===========================================================================
  505. align ALIGN
  506. cglobal dequant_inter_mmx
  507. dequant_inter_mmx
  508. push  esi
  509. push  edi
  510. mov  edi, [esp + 8 + 4] ; data
  511. mov  esi, [esp + 8 + 8] ; coeff
  512. mov  eax, [esp + 8 + 12] ; quant
  513. movq mm6, [mmx_add + eax * 8 - 8]
  514. movq mm7, [mmx_mul + eax * 8 - 8]
  515. xor eax, eax
  516. align ALIGN
  517. .loop
  518. movq mm0, [esi + 8*eax] ; mm0 = [coeff]
  519. movq mm3, [esi + 8*eax + 8] ; 
  520. pxor mm1, mm1 ; mm1 = 0
  521. pxor mm4, mm4 ;
  522. pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
  523. pcmpgtw mm4, mm3 ; 
  524. pxor mm2, mm2 ; mm2 = 0
  525. pxor mm5, mm5 ;
  526. pcmpeqw mm2, mm0 ; mm2 = (0 == mm0)
  527. pcmpeqw mm5, mm3 ; 
  528. pandn   mm2, mm6 ; mm2 = (iszero ? 0 : add)
  529. pandn   mm5, mm6 ;
  530. pxor mm0, mm1 ; mm0 = |mm0|
  531. pxor mm3, mm4 ; 
  532. psubw mm0, mm1 ; displace
  533. psubw mm3, mm4 ; 
  534. pmullw mm0, mm7 ; mm0 *= 2Q
  535. pmullw mm3, mm7 ; 
  536. paddw mm0, mm2 ; mm0 += mm2 (add)
  537. paddw mm3, mm5 ;
  538. pxor mm0, mm1 ; mm0 *= sign(mm0)
  539. pxor mm3, mm4 ;
  540. psubw mm0, mm1 ; undisplace
  541. psubw mm3, mm4
  542. %ifdef SATURATE
  543. movq mm2, [mmx_32767_minus_2047] 
  544. movq mm4, [mmx_32768_minus_2048] 
  545. paddsw mm0, mm2
  546. paddsw mm3, mm2
  547. psubsw mm0, mm2
  548. psubsw mm3, mm2
  549. psubsw mm0, mm4
  550. psubsw mm3, mm4
  551. paddsw mm0, mm4
  552. paddsw mm3, mm4
  553. %endif
  554. movq [edi + 8*eax], mm0
  555. movq [edi + 8*eax + 8], mm3
  556. add eax, 2
  557. cmp eax, 16
  558. jnz near .loop
  559. pop  edi
  560. pop  esi
  561. ret