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

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. ;/**************************************************************************
  2. ; *
  3. ; * XVID MPEG-4 VIDEO CODEC
  4. ; * mmx/xmm/3dnow 8x8 block-based halfpel interpolation
  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. ; * 04.02.2002  added xmm and additional 3dnow optimizations (Isibaar)
  35. ; * 27.12.2001 mofified "compensate_halfpel"
  36. ; * 22.12.2001 inital version; (c)2001 peter ross <pross@cs.rmit.edu.au>
  37. ; *
  38. ; *************************************************************************/
  39. bits 32
  40. %macro cglobal 1 
  41. %ifdef PREFIX
  42. global _%1 
  43. %define %1 _%1
  44. %else
  45. global %1
  46. %endif
  47. %endmacro
  48. section .data
  49. align 16
  50. ;===========================================================================
  51. ; (1 - r) rounding table
  52. ;===========================================================================
  53. rounding1_mmx
  54. times 4 dw 1
  55. times 4 dw 0
  56. ;===========================================================================
  57. ; (2 - r) rounding table  
  58. ;===========================================================================
  59. rounding2_mmx
  60. times 4 dw 2
  61. times 4 dw 1
  62. mmx_one
  63. times 8 db 1
  64. section .text
  65. %macro  CALC_AVG 6
  66. punpcklbw %3, %6
  67. punpckhbw %4, %6
  68. paddusw %1, %3 ; mm01 += mm23
  69. paddusw %2, %4
  70. paddusw %1, %5 ; mm01 += rounding
  71. paddusw %2, %5
  72. psrlw %1, 1 ; mm01 >>= 1
  73. psrlw %2, 1
  74. %endmacro
  75. ;===========================================================================
  76. ;
  77. ; void interpolate8x8_halfpel_h_xmm(uint8_t * const dst,
  78. ; const uint8_t * const src,
  79. ; const uint32_t stride,
  80. ; const uint32_t rounding);
  81. ;
  82. ;===========================================================================
  83. align 16
  84. cglobal interpolate8x8_halfpel_h_xmm
  85. interpolate8x8_halfpel_h_xmm
  86. push esi
  87. push edi
  88. mov edi, [esp + 8 + 4] ; dst
  89. mov esi, [esp + 8 + 8] ; src
  90. mov edx, [esp + 8 + 12] ; stride
  91. mov ecx, edx
  92. shl edx, 1
  93. mov eax, [esp + 8 + 16] ; rounding
  94. or al,al
  95. jnz near halfpel_h_xmm_rounding1 ; needs extra hack, still faster than mmx
  96. halfpel_h_xmm_rounding0
  97. ; mov eax, 4
  98. ;.loop
  99. movq mm0, [esi]
  100. movq mm1, [esi + ecx]
  101. pavgb mm0, [esi + 1] ; mm0 = avg([src], [src+1])
  102. pavgb mm1, [esi + ecx + 1] ; mm1 = avg([src+stride], [src+stride+1])
  103. movq [edi], mm0
  104. movq [edi + ecx], mm1
  105. add esi, edx ; src += 2*stride
  106. add edi, edx ; dst += 2*stride
  107. movq mm0, [esi]
  108. movq mm1, [esi + ecx]
  109. pavgb mm0, [esi + 1]
  110. pavgb mm1, [esi + ecx + 1]
  111. movq [edi], mm0
  112. movq [edi + ecx], mm1
  113. add esi, edx
  114. add edi, edx
  115. movq mm0, [esi]
  116. movq mm1, [esi + ecx]
  117. pavgb mm0, [esi + 1]
  118. pavgb mm1, [esi + ecx + 1]
  119. movq [edi], mm0
  120. movq [edi + ecx], mm1
  121. add esi, edx
  122. add edi, edx
  123. movq mm0, [esi]
  124. movq mm1, [esi + ecx]
  125. pavgb mm0, [esi + 1]
  126. pavgb mm1, [esi + ecx + 1]
  127. movq [edi], mm0
  128. movq [edi + ecx], mm1
  129. ; dec eax
  130. ; jnz .loop
  131. pop edi
  132. pop esi
  133. ret
  134. halfpel_h_xmm_rounding1
  135. movq mm7, [mmx_one]
  136. mov eax, 4
  137. .loop
  138. movq mm0, [esi]
  139. movq mm1, [esi + ecx]
  140. movq mm2, [esi + 1]
  141. movq mm3, [esi + ecx + 1]
  142. movq mm4, mm0 ; backup mm01
  143. movq mm5, mm1
  144. pavgb mm0, mm2 ; mm0 = avg([src], [src+1])
  145. pavgb mm1, mm3 ; mm1 = avg([src+stride], [src+stride+1])
  146. paddb mm2, mm4 ; add values, see if lsb is set
  147. paddb mm3, mm5 ; (to patch pavgb's (a+b+1)/2 rounding)
  148. pand mm2, mm7 ; isolate lsb's
  149. pand mm3, mm7
  150. psubusb mm0, mm2 ; mm23 = 0 if lsb wasn't set
  151. psubusb mm1, mm3
  152. movq [edi], mm0
  153. movq [edi + ecx], mm1
  154. add esi, edx ; src += 2*stride
  155. add edi, edx ; dst += 2*stride
  156. dec eax
  157. jnz .loop
  158. pop edi
  159. pop esi
  160. ret
  161. ;===========================================================================
  162. ;
  163. ; void interpolate8x8_halfpel_h_3dn(uint8_t * const dst,
  164. ; const uint8_t * const src,
  165. ; const uint32_t stride,
  166. ; const uint32_t rounding);
  167. ;
  168. ;===========================================================================
  169. align 16
  170. cglobal interpolate8x8_halfpel_h_3dn
  171. interpolate8x8_halfpel_h_3dn
  172. push esi
  173. push edi
  174. mov edi, [esp + 8 + 4] ; dst
  175. mov esi, [esp + 8 + 8] ; src
  176. mov edx, [esp + 8 + 12] ; stride
  177. mov ecx, edx
  178. shl edx, 1
  179. mov eax, [esp + 8 + 16] ; rounding
  180. or al,al ; perform hack for pavgusb rounding issue
  181. jnz near halfpel_h_3dn_rounding1
  182. halfpel_h_3dn_rounding0
  183. ; mov eax, 4
  184. ;.loop
  185. movq mm0, [esi]
  186. movq mm1, [esi + ecx]
  187. pavgusb mm0, [esi + 1] ; mm0 = avg([src], [src+1])
  188. pavgusb mm1, [esi + ecx + 1] ; mm0 = avg([src+stride], [src+stride+1])
  189. movq [edi], mm0
  190. movq [edi + ecx], mm1
  191. add esi, edx ; src += 2*stride
  192. add edi, edx ; dst += 2*stride
  193. movq mm0, [esi]
  194. movq mm1, [esi + ecx]
  195. pavgusb mm0, [esi + 1]
  196. pavgusb mm1, [esi + ecx + 1]
  197. movq [edi], mm0
  198. movq [edi + ecx], mm1
  199. add esi, edx
  200. add edi, edx
  201. movq mm0, [esi]
  202. movq mm1, [esi + ecx]
  203. pavgusb mm0, [esi + 1]
  204. pavgusb mm1, [esi + ecx + 1]
  205. movq [edi], mm0
  206. movq [edi + ecx], mm1
  207. add esi, edx
  208. add edi, edx
  209. movq mm0, [esi]
  210. movq mm1, [esi + ecx]
  211. pavgusb mm0, [esi + 1]
  212. pavgusb mm1, [esi + ecx + 1]
  213. movq [edi], mm0
  214. movq [edi + ecx], mm1
  215. ; dec eax
  216. ; jnz .loop
  217. pop edi
  218. pop esi
  219. ret
  220. halfpel_h_3dn_rounding1
  221. movq mm7, [mmx_one]
  222. mov eax, 4
  223. .loop
  224. movq mm0, [esi]
  225. movq mm1, [esi + ecx]
  226. movq mm2, [esi + 1]
  227. movq mm3, [esi + ecx + 1]
  228. movq mm4, mm0 ; backup mm01
  229. movq mm5, mm1
  230. pavgusb mm0, mm2 ; mm0 = avg([src], [src+1])
  231. pavgusb mm1, mm3 ; mm1 = avg([src+stride], [src+stride+1])
  232. paddb mm2, mm4 ; add values, see if lsb is set
  233. paddb mm3, mm5 ; (to patch pavgb's (a+b+1)/2 rounding)
  234. pand mm2, mm7 ; isolate lsb's
  235. pand mm3, mm7
  236. psubusb mm0, mm2 ; mm23 = 0 if lsb wasn't set
  237. psubusb mm1, mm3
  238. movq [edi], mm0
  239. movq [edi + ecx], mm1
  240. add esi, edx ; src += 2*stride
  241. add edi, edx ; dst += 2*stride
  242. dec eax
  243. jnz .loop
  244. pop edi
  245. pop esi
  246. ret
  247. ;===========================================================================
  248. ;
  249. ; void interpolate8x8_halfpel_h_mmx(uint8_t * const dst,
  250. ; const uint8_t * const src,
  251. ; const uint32_t stride,
  252. ; const uint32_t rounding);
  253. ;
  254. ;===========================================================================
  255. align 16
  256. cglobal interpolate8x8_halfpel_h_mmx
  257. interpolate8x8_halfpel_h_mmx
  258. push esi
  259. push edi
  260. mov eax, [esp + 8 + 16] ; rounding
  261. interpolate8x8_halfpel_h_mmx.start
  262. movq mm7, [rounding1_mmx + eax * 8]
  263. mov edi, [esp + 8 + 4] ; dst
  264. mov esi, [esp + 8 + 8] ; src
  265. mov edx, [esp + 8 + 12] ; stride
  266. mov eax, 8
  267. pxor mm6, mm6 ; zero
  268. .loop
  269. movq mm0, [esi]
  270. movq mm2, [esi + 1]
  271. movq mm1, mm0
  272. movq mm3, mm2
  273. punpcklbw mm0, mm6 ; mm01 = [src]
  274. punpckhbw mm1, mm6 ; mm23 = [src + 1]
  275. CALC_AVG mm0, mm1, mm2, mm3, mm7, mm6
  276. packuswb mm0, mm1
  277. movq [edi], mm0 ; [dst] = mm01
  278. add esi, edx ; src += stride
  279. add edi, edx ; dst += stride
  280. dec eax
  281. jnz .loop
  282. pop edi
  283. pop esi
  284. ret
  285. ;===========================================================================
  286. ;
  287. ; void interpolate8x8_halfpel_v_xmm(uint8_t * const dst,
  288. ; const uint8_t * const src,
  289. ; const uint32_t stride,
  290. ; const uint32_t rounding);
  291. ;
  292. ;===========================================================================
  293. align 16
  294. cglobal interpolate8x8_halfpel_v_xmm
  295. interpolate8x8_halfpel_v_xmm
  296. push esi
  297. push edi
  298. mov edi, [esp + 8 + 4] ; dst
  299. mov esi, [esp + 8 + 8] ; src
  300. mov edx, [esp + 8 + 12] ; stride
  301. mov eax, [esp + 8 + 16] ; rounding
  302. or al,al
  303. jnz near halfpel_v_xmm_rounding1
  304. halfpel_v_xmm_rounding0
  305. ; mov eax, 8
  306. ;.loop
  307. movq mm0, [esi]
  308. pavgb mm0, [esi + edx] ; mm0 = avg([src], [src+stride])
  309. movq [edi], mm0
  310. add edi, edx ; dst += stride
  311. add esi, edx ; src += stride
  312. movq mm0, [esi]
  313. pavgb mm0, [esi + edx]
  314. movq [edi], mm0
  315. add edi, edx
  316. add esi, edx
  317. movq mm0, [esi]
  318. pavgb mm0, [esi + edx]
  319. movq [edi], mm0
  320. add edi, edx
  321. add esi, edx
  322. movq mm0, [esi]
  323. pavgb mm0, [esi + edx]
  324. movq [edi], mm0
  325. add edi, edx
  326. add esi, edx
  327. movq mm0, [esi]
  328. pavgb mm0, [esi + edx]
  329. movq [edi], mm0
  330. add edi, edx
  331. add esi, edx
  332. movq mm0, [esi]
  333. pavgb mm0, [esi + edx]
  334. movq [edi], mm0
  335. add edi, edx
  336. add esi, edx
  337. movq mm0, [esi]
  338. pavgb mm0, [esi + edx]
  339. movq [edi], mm0
  340. add edi, edx
  341. add esi, edx
  342. movq mm0, [esi]
  343. pavgb mm0, [esi + edx]
  344. movq [edi], mm0
  345. ; dec eax
  346. ; jnz .loop
  347. pop edi
  348. pop esi
  349. ret
  350. halfpel_v_xmm_rounding1
  351. movq mm7, [mmx_one]
  352. mov eax, 8
  353. .loop
  354. movq mm0, [esi]
  355. movq mm1, [esi + edx]
  356. movq mm2, mm0 ; backup mm0
  357. pavgb mm0, mm1 ; mm0 = avg([src], [src+stride])
  358. paddb mm1, mm2 ; isolate and subtract lsb's from original values
  359. pand mm1, mm7 ; (compensate for pavgb rounding)
  360. psubusb mm0, mm1
  361. movq [edi], mm0
  362. add edi, edx ; dst += stride
  363. add esi, edx ; src += stride
  364. dec eax
  365. jnz .loop
  366. pop edi
  367. pop esi
  368. ret
  369. ;===========================================================================
  370. ;
  371. ; void interpolate8x8_halfpel_v_3dn(uint8_t * const dst,
  372. ; const uint8_t * const src,
  373. ; const uint32_t stride,
  374. ; const uint32_t rounding);
  375. ;
  376. ;===========================================================================
  377. align 16
  378. cglobal interpolate8x8_halfpel_v_3dn
  379. interpolate8x8_halfpel_v_3dn
  380. push esi
  381. push edi
  382. mov edi, [esp + 8 + 4] ; dst
  383. mov esi, [esp + 8 + 8] ; src
  384. mov edx, [esp + 8 + 12] ; stride
  385. mov eax, [esp + 8 + 16] ; rounding
  386. or al,al ; hack for pavgusb rounding
  387. jnz halfpel_v_3dn_rounding1
  388. halfpel_v_3dn_rounding0
  389. ; mov eax, 8
  390. ;.loop
  391. movq mm0, [esi]
  392. pavgusb mm0, [esi + edx] ; mm0 = avg([src], [src+stride])
  393. movq [edi], mm0
  394. add edi, edx ; dst += stride
  395. add esi, edx ; src += stride
  396. movq mm0, [esi]
  397. pavgusb mm0, [esi + edx]
  398. movq [edi], mm0
  399. add edi, edx
  400. add esi, edx
  401. movq mm0, [esi]
  402. pavgusb mm0, [esi + edx]
  403. movq [edi], mm0
  404. add edi, edx
  405. add esi, edx
  406. movq mm0, [esi]
  407. pavgusb mm0, [esi + edx]
  408. movq [edi], mm0
  409. add edi, edx
  410. add esi, edx
  411. movq mm0, [esi]
  412. pavgusb mm0, [esi + edx]
  413. movq [edi], mm0
  414. add edi, edx
  415. add esi, edx
  416. movq mm0, [esi]
  417. pavgusb mm0, [esi + edx]
  418. movq [edi], mm0
  419. add edi, edx
  420. add esi, edx
  421. movq mm0, [esi]
  422. pavgusb mm0, [esi + edx]
  423. movq [edi], mm0
  424. add edi, edx
  425. add esi, edx
  426. movq mm0, [esi]
  427. pavgusb mm0, [esi + edx]
  428. movq [edi], mm0
  429. ; dec eax
  430. ; jnz .loop
  431. pop edi
  432. pop esi
  433. ret
  434. halfpel_v_3dn_rounding1
  435. movq mm7, [mmx_one]
  436. mov eax, 8
  437. .loop
  438. movq mm0, [esi]
  439. movq mm1, [esi + edx]
  440. movq mm2, mm0 ; backup mm0
  441. pavgusb mm0, mm1 ; mm0 = avg([src], [src+stride])
  442. paddb mm1, mm2 ; isolate and subtract lsb's from original values
  443. pand mm1, mm7 ; (compensate for pavgb rounding)
  444. psubusb mm0, mm1
  445. movq [edi], mm0
  446. add edi, edx ; dst += stride
  447. add esi, edx ; src += stride
  448. dec eax
  449. jnz .loop
  450. pop edi
  451. pop esi
  452. ret
  453. ;===========================================================================
  454. ;
  455. ; void interpolate8x8_halfpel_v_mmx(uint8_t * const dst,
  456. ; const uint8_t * const src,
  457. ; const uint32_t stride,
  458. ; const uint32_t rounding);
  459. ;
  460. ;===========================================================================
  461. align 16
  462. cglobal interpolate8x8_halfpel_v_mmx
  463. interpolate8x8_halfpel_v_mmx
  464. push esi
  465. push edi
  466. mov eax, [esp + 8 + 16] ; rounding
  467. interpolate8x8_halfpel_v_mmx.start
  468. movq mm7, [rounding1_mmx + eax * 8]
  469. mov edi, [esp + 8 + 4] ; dst
  470. mov esi, [esp + 8 + 8] ; src
  471. mov edx, [esp + 8 + 12] ; stride
  472. mov eax, 8
  473. pxor mm6, mm6 ; zero
  474. .loop
  475. movq mm0, [esi]
  476. movq mm2, [esi + edx]
  477. movq mm1, mm0
  478. movq mm3, mm2
  479. punpcklbw mm0, mm6 ; mm01 = [src]
  480. punpckhbw mm1, mm6 ; mm23 = [src + 1]
  481. CALC_AVG mm0, mm1, mm2, mm3, mm7, mm6
  482. packuswb mm0, mm1
  483. movq [edi], mm0 ; [dst] = mm01
  484. add esi, edx ; src += stride
  485. add edi, edx ; dst += stride
  486. dec eax
  487. jnz .loop
  488. pop edi
  489. pop esi
  490. ret
  491. ;===========================================================================
  492. ;
  493. ; void interpolate8x8_halfpel_hv_xmm(uint8_t * const dst,
  494. ; const uint8_t * const src,
  495. ; const uint32_t stride, 
  496. ; const uint32_t rounding);
  497. ;
  498. ;
  499. ;===========================================================================
  500. align 16
  501. cglobal interpolate8x8_halfpel_hv_xmm
  502. interpolate8x8_halfpel_hv_xmm
  503. push esi
  504. push edi
  505. mov eax, [esp + 8 + 16] ; rounding
  506. or al,al
  507. jnz interpolate8x8_halfpel_hv_mmx.start
  508. mov edi, [esp + 8 + 4] ; dst
  509. mov esi, [esp + 8 + 8] ; src
  510. mov edx, [esp + 8 + 12] ; stride
  511. movq mm7, [mmx_one]
  512. mov eax, 8
  513. .loop
  514. ; current row
  515. movq mm0, [esi]
  516. movq mm1, [esi + 1]
  517. movq mm2, mm0
  518. pavgb mm0, mm1
  519. pxor mm1, mm2
  520. ; next row
  521. movq mm2, [esi + edx]
  522. movq mm3, [esi + edx + 1]
  523. movq mm4, mm2
  524. pavgb mm2, mm3
  525. pxor mm3, mm4
  526. ; add current + next row
  527. por mm1, mm3
  528. movq mm3, mm0
  529. pxor mm3, mm2
  530. pand mm1, mm3
  531. pavgb mm0, mm2
  532. pand mm1, mm7
  533. psubusb mm0, mm1
  534. movq [edi], mm0 ; [dst] = mm01
  535. add esi, edx ; src += stride
  536. add edi, edx ; dst += stride
  537. dec eax
  538. jnz .loop
  539. pop edi
  540. pop esi
  541. ret
  542. ;===========================================================================
  543. ;
  544. ; void interpolate8x8_halfpel_hv_mmx(uint8_t * const dst,
  545. ; const uint8_t * const src,
  546. ; const uint32_t stride, 
  547. ; const uint32_t rounding);
  548. ;
  549. ;
  550. ;===========================================================================
  551. align 16
  552. cglobal interpolate8x8_halfpel_hv_mmx
  553. interpolate8x8_halfpel_hv_mmx
  554. push esi
  555. push edi
  556. mov eax, [esp + 8 + 16] ; rounding
  557. interpolate8x8_halfpel_hv_mmx.start
  558. movq mm7, [rounding2_mmx + eax * 8]
  559. mov edi, [esp + 8 + 4] ; dst
  560. mov esi, [esp + 8 + 8] ; src
  561. mov eax, 8
  562. pxor mm6, mm6 ; zero
  563. mov edx, [esp + 8 + 12] ; stride
  564. .loop
  565. ; current row
  566. movq mm0, [esi]
  567. movq mm2, [esi + 1]
  568. movq mm1, mm0
  569. movq mm3, mm2
  570. punpcklbw mm0, mm6 ; mm01 = [src]
  571. punpcklbw mm2, mm6 ; mm23 = [src + 1]
  572. punpckhbw mm1, mm6
  573. punpckhbw mm3, mm6
  574. paddusw mm0, mm2 ; mm01 += mm23
  575. paddusw mm1, mm3
  576. ; next row
  577. movq mm4, [esi + edx]
  578. movq mm2, [esi + edx + 1]
  579. movq mm5, mm4
  580. movq mm3, mm2
  581. punpcklbw mm4, mm6 ; mm45 = [src + stride]
  582. punpcklbw mm2, mm6 ; mm23 = [src + stride + 1]
  583. punpckhbw mm5, mm6
  584. punpckhbw mm3, mm6
  585. paddusw mm4, mm2 ; mm45 += mm23
  586. paddusw mm5, mm3
  587. ; add current + next row
  588. paddusw mm0, mm4 ; mm01 += mm45
  589. paddusw mm1, mm5
  590. paddusw mm0, mm7 ; mm01 += rounding2
  591. paddusw mm1, mm7
  592. psrlw mm0, 2 ; mm01 >>= 2
  593. psrlw mm1, 2
  594. packuswb mm0, mm1
  595. movq [edi], mm0 ; [dst] = mm01
  596. add esi, edx ; src += stride
  597. add edi, edx ; dst += stride
  598. dec eax
  599. jnz .loop
  600. pop edi
  601. pop esi
  602. ret
  603. ;===========================================================================
  604. ;
  605. ; void interpolate8x8_halfpel_hv_3dn(uint8_t * const dst,
  606. ; const uint8_t * const src,
  607. ; const uint32_t stride, 
  608. ; const uint32_t rounding);
  609. ;
  610. ;
  611. ;===========================================================================
  612. align 16
  613. cglobal interpolate8x8_halfpel_hv_3dn
  614. interpolate8x8_halfpel_hv_3dn
  615. push esi
  616. push edi
  617. mov eax, [esp + 8 + 16] ; rounding
  618.                 or      al,al
  619.                 jnz     near interpolate8x8_halfpel_hv_mmx.start
  620. mov edi, [esp + 8 + 4] ; dst
  621. mov esi, [esp + 8 + 8] ; src
  622. mov edx, [esp + 8 + 12] ; stride
  623. movq mm7, [mmx_one]
  624. mov eax, 8
  625. .loop
  626. ; current row
  627. movq mm0, [esi]
  628. movq mm1, [esi + 1]
  629. movq mm2, mm0
  630. pavgusb mm0, mm1
  631. pxor mm1, mm2
  632. ; next row
  633. movq mm2, [esi + edx]
  634. movq mm3, [esi + edx + 1]
  635. movq mm4, mm2
  636. pavgusb mm2, mm3
  637. pxor mm3, mm4
  638. ; add current + next row
  639. por mm1, mm3
  640. movq mm3, mm0
  641. pxor mm3, mm2
  642. pand mm1, mm3
  643. pavgusb mm0, mm2
  644. pand mm1, mm7
  645. psubusb mm0, mm1
  646. movq [edi], mm0 ; [dst] = mm01
  647. add esi, edx ; src += stride
  648. add edi, edx ; dst += stride
  649. dec eax
  650. jnz .loop
  651. pop edi
  652. pop esi
  653. ret