Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. ;******************************************************************************
  2. ;* VP8 MMXEXT optimizations
  3. ;* Copyright (c) 2010 Ronald S. Bultje <rsbultje@gmail.com>
  4. ;* Copyright (c) 2010 Fiona Glaser <fiona@x264.com>
  5. ;*
  6. ;* This file is part of FFmpeg.
  7. ;*
  8. ;* FFmpeg is free software; you can redistribute it and/or
  9. ;* modify it under the terms of the GNU Lesser General Public
  10. ;* License as published by the Free Software Foundation; either
  11. ;* version 2.1 of the License, or (at your option) any later version.
  12. ;*
  13. ;* FFmpeg is distributed in the hope that it will be useful,
  14. ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. ;* Lesser General Public License for more details.
  17. ;*
  18. ;* You should have received a copy of the GNU Lesser General Public
  19. ;* License along with FFmpeg; if not, write to the Free Software
  20. ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. ;******************************************************************************
  22.  
  23. %include "libavutil/x86/x86util.asm"
  24.  
  25. SECTION_RODATA
  26.  
  27. pw_27:    times 8 dw 27
  28. pw_63:    times 8 dw 63
  29.  
  30. pb_4:     times 16 db 4
  31. pb_F8:    times 16 db 0xF8
  32. pb_FE:    times 16 db 0xFE
  33. pb_27_63: times 8 db 27, 63
  34. pb_18_63: times 8 db 18, 63
  35. pb_9_63:  times 8 db  9, 63
  36.  
  37. cextern pb_1
  38. cextern pb_3
  39. cextern pw_9
  40. cextern pw_18
  41. cextern pb_80
  42.  
  43. SECTION .text
  44.  
  45. ;-----------------------------------------------------------------------------
  46. ; void ff_vp8_h/v_loop_filter_simple_<opt>(uint8_t *dst, int stride, int flim);
  47. ;-----------------------------------------------------------------------------
  48.  
  49. ; macro called with 7 mm register indexes as argument, and 4 regular registers
  50. ;
  51. ; first 4 mm registers will carry the transposed pixel data
  52. ; the other three are scratchspace (one would be sufficient, but this allows
  53. ; for more spreading/pipelining and thus faster execution on OOE CPUs)
  54. ;
  55. ; first two regular registers are buf+4*stride and buf+5*stride
  56. ; third is -stride, fourth is +stride
  57. %macro READ_8x4_INTERLEAVED 11
  58.     ; interleave 8 (A-H) rows of 4 pixels each
  59.     movd          m%1, [%8+%10*4]   ; A0-3
  60.     movd          m%5, [%9+%10*4]   ; B0-3
  61.     movd          m%2, [%8+%10*2]   ; C0-3
  62.     movd          m%6, [%8+%10]     ; D0-3
  63.     movd          m%3, [%8]         ; E0-3
  64.     movd          m%7, [%9]         ; F0-3
  65.     movd          m%4, [%9+%11]     ; G0-3
  66.     punpcklbw     m%1, m%5          ; A/B interleaved
  67.     movd          m%5, [%9+%11*2]   ; H0-3
  68.     punpcklbw     m%2, m%6          ; C/D interleaved
  69.     punpcklbw     m%3, m%7          ; E/F interleaved
  70.     punpcklbw     m%4, m%5          ; G/H interleaved
  71. %endmacro
  72.  
  73. ; macro called with 7 mm register indexes as argument, and 5 regular registers
  74. ; first 11 mean the same as READ_8x4_TRANSPOSED above
  75. ; fifth regular register is scratchspace to reach the bottom 8 rows, it
  76. ; will be set to second regular register + 8*stride at the end
  77. %macro READ_16x4_INTERLEAVED 12
  78.     ; transpose 16 (A-P) rows of 4 pixels each
  79.     lea           %12, [r0+8*r2]
  80.  
  81.     ; read (and interleave) those addressable by %8 (=r0), A/C/D/E/I/K/L/M
  82.     movd          m%1, [%8+%10*4]   ; A0-3
  83.     movd          m%3, [%12+%10*4]  ; I0-3
  84.     movd          m%2, [%8+%10*2]   ; C0-3
  85.     movd          m%4, [%12+%10*2]  ; K0-3
  86.     movd          m%6, [%8+%10]     ; D0-3
  87.     movd          m%5, [%12+%10]    ; L0-3
  88.     movd          m%7, [%12]        ; M0-3
  89.     add           %12, %11
  90.     punpcklbw     m%1, m%3          ; A/I
  91.     movd          m%3, [%8]         ; E0-3
  92.     punpcklbw     m%2, m%4          ; C/K
  93.     punpcklbw     m%6, m%5          ; D/L
  94.     punpcklbw     m%3, m%7          ; E/M
  95.     punpcklbw     m%2, m%6          ; C/D/K/L interleaved
  96.  
  97.     ; read (and interleave) those addressable by %9 (=r4), B/F/G/H/J/N/O/P
  98.     movd         m%5, [%9+%10*4]   ; B0-3
  99.     movd         m%4, [%12+%10*4]  ; J0-3
  100.     movd         m%7, [%9]         ; F0-3
  101.     movd         m%6, [%12]        ; N0-3
  102.     punpcklbw    m%5, m%4          ; B/J
  103.     punpcklbw    m%7, m%6          ; F/N
  104.     punpcklbw    m%1, m%5          ; A/B/I/J interleaved
  105.     punpcklbw    m%3, m%7          ; E/F/M/N interleaved
  106.     movd         m%4, [%9+%11]     ; G0-3
  107.     movd         m%6, [%12+%11]    ; O0-3
  108.     movd         m%5, [%9+%11*2]   ; H0-3
  109.     movd         m%7, [%12+%11*2]  ; P0-3
  110.     punpcklbw    m%4, m%6          ; G/O
  111.     punpcklbw    m%5, m%7          ; H/P
  112.     punpcklbw    m%4, m%5          ; G/H/O/P interleaved
  113. %endmacro
  114.  
  115. ; write 4 mm registers of 2 dwords each
  116. ; first four arguments are mm register indexes containing source data
  117. ; last four are registers containing buf+4*stride, buf+5*stride,
  118. ; -stride and +stride
  119. %macro WRITE_4x2D 8
  120.     ; write out (2 dwords per register)
  121.     movd    [%5+%7*4], m%1
  122.     movd    [%5+%7*2], m%2
  123.     movd         [%5], m%3
  124.     movd      [%6+%8], m%4
  125.     punpckhdq     m%1, m%1
  126.     punpckhdq     m%2, m%2
  127.     punpckhdq     m%3, m%3
  128.     punpckhdq     m%4, m%4
  129.     movd    [%6+%7*4], m%1
  130.     movd      [%5+%7], m%2
  131.     movd         [%6], m%3
  132.     movd    [%6+%8*2], m%4
  133. %endmacro
  134.  
  135. ; write 4 xmm registers of 4 dwords each
  136. ; arguments same as WRITE_2x4D, but with an extra register, so that the 5 regular
  137. ; registers contain buf+4*stride, buf+5*stride, buf+12*stride, -stride and +stride
  138. ; we add 1*stride to the third regular registry in the process
  139. ; the 10th argument is 16 if it's a Y filter (i.e. all regular registers cover the
  140. ; same memory region), or 8 if they cover two separate buffers (third one points to
  141. ; a different memory region than the first two), allowing for more optimal code for
  142. ; the 16-width case
  143. %macro WRITE_4x4D 10
  144.     ; write out (4 dwords per register), start with dwords zero
  145.     movd    [%5+%8*4], m%1
  146.     movd         [%5], m%2
  147.     movd    [%7+%8*4], m%3
  148.     movd         [%7], m%4
  149.  
  150.     ; store dwords 1
  151.     psrldq        m%1, 4
  152.     psrldq        m%2, 4
  153.     psrldq        m%3, 4
  154.     psrldq        m%4, 4
  155.     movd    [%6+%8*4], m%1
  156.     movd         [%6], m%2
  157. %if %10 == 16
  158.     movd    [%6+%9*4], m%3
  159. %endif
  160.     movd      [%7+%9], m%4
  161.  
  162.     ; write dwords 2
  163.     psrldq        m%1, 4
  164.     psrldq        m%2, 4
  165. %if %10 == 8
  166.     movd    [%5+%8*2], m%1
  167.     movd          %5d, m%3
  168. %endif
  169.     psrldq        m%3, 4
  170.     psrldq        m%4, 4
  171. %if %10 == 16
  172.     movd    [%5+%8*2], m%1
  173. %endif
  174.     movd      [%6+%9], m%2
  175.     movd    [%7+%8*2], m%3
  176.     movd    [%7+%9*2], m%4
  177.     add            %7, %9
  178.  
  179.     ; store dwords 3
  180.     psrldq        m%1, 4
  181.     psrldq        m%2, 4
  182.     psrldq        m%3, 4
  183.     psrldq        m%4, 4
  184. %if %10 == 8
  185.     mov     [%7+%8*4], %5d
  186.     movd    [%6+%8*2], m%1
  187. %else
  188.     movd      [%5+%8], m%1
  189. %endif
  190.     movd    [%6+%9*2], m%2
  191.     movd    [%7+%8*2], m%3
  192.     movd    [%7+%9*2], m%4
  193. %endmacro
  194.  
  195. ; write 4 or 8 words in the mmx/xmm registers as 8 lines
  196. ; 1 and 2 are the registers to write, this can be the same (for SSE2)
  197. ; for pre-SSE4:
  198. ; 3 is a general-purpose register that we will clobber
  199. ; for SSE4:
  200. ; 3 is a pointer to the destination's 5th line
  201. ; 4 is a pointer to the destination's 4th line
  202. ; 5/6 is -stride and +stride
  203. %macro WRITE_2x4W 6
  204.     movd            %3d, %1
  205.     punpckhdq        %1, %1
  206.     mov       [%4+%5*4], %3w
  207.     shr              %3, 16
  208.     add              %4, %6
  209.     mov       [%4+%5*4], %3w
  210.  
  211.     movd            %3d, %1
  212.     add              %4, %5
  213.     mov       [%4+%5*2], %3w
  214.     shr              %3, 16
  215.     mov       [%4+%5  ], %3w
  216.  
  217.     movd            %3d, %2
  218.     punpckhdq        %2, %2
  219.     mov       [%4     ], %3w
  220.     shr              %3, 16
  221.     mov       [%4+%6  ], %3w
  222.  
  223.     movd            %3d, %2
  224.     add              %4, %6
  225.     mov       [%4+%6  ], %3w
  226.     shr              %3, 16
  227.     mov       [%4+%6*2], %3w
  228.     add              %4, %5
  229. %endmacro
  230.  
  231. %macro WRITE_8W 5
  232. %if cpuflag(sse4)
  233.     pextrw    [%3+%4*4], %1, 0
  234.     pextrw    [%2+%4*4], %1, 1
  235.     pextrw    [%3+%4*2], %1, 2
  236.     pextrw    [%3+%4  ], %1, 3
  237.     pextrw    [%3     ], %1, 4
  238.     pextrw    [%2     ], %1, 5
  239.     pextrw    [%2+%5  ], %1, 6
  240.     pextrw    [%2+%5*2], %1, 7
  241. %else
  242.     movd            %2d, %1
  243.     psrldq           %1, 4
  244.     mov       [%3+%4*4], %2w
  245.     shr              %2, 16
  246.     add              %3, %5
  247.     mov       [%3+%4*4], %2w
  248.  
  249.     movd            %2d, %1
  250.     psrldq           %1, 4
  251.     add              %3, %4
  252.     mov       [%3+%4*2], %2w
  253.     shr              %2, 16
  254.     mov       [%3+%4  ], %2w
  255.  
  256.     movd            %2d, %1
  257.     psrldq           %1, 4
  258.     mov       [%3     ], %2w
  259.     shr              %2, 16
  260.     mov       [%3+%5  ], %2w
  261.  
  262.     movd            %2d, %1
  263.     add              %3, %5
  264.     mov       [%3+%5  ], %2w
  265.     shr              %2, 16
  266.     mov       [%3+%5*2], %2w
  267. %endif
  268. %endmacro
  269.  
  270. %macro SIMPLE_LOOPFILTER 2
  271. cglobal vp8_%1_loop_filter_simple, 3, %2, 8, dst, stride, flim, cntr
  272. %if mmsize == 8 ; mmx/mmxext
  273.     mov         cntrq, 2
  274. %endif
  275. %if cpuflag(ssse3)
  276.     pxor           m0, m0
  277. %endif
  278.     SPLATB_REG     m7, flim, m0     ; splat "flim" into register
  279.  
  280.     ; set up indexes to address 4 rows
  281. %if mmsize == 8
  282.     DEFINE_ARGS dst1, mstride, stride, cntr, dst2
  283. %else
  284.     DEFINE_ARGS dst1, mstride, stride, dst3, dst2
  285. %endif
  286.     mov       strideq, mstrideq
  287.     neg      mstrideq
  288. %ifidn %1, h
  289.     lea         dst1q, [dst1q+4*strideq-2]
  290. %endif
  291.  
  292. %if mmsize == 8 ; mmx / mmxext
  293. .next8px:
  294. %endif
  295. %ifidn %1, v
  296.     ; read 4 half/full rows of pixels
  297.     mova           m0, [dst1q+mstrideq*2]    ; p1
  298.     mova           m1, [dst1q+mstrideq]      ; p0
  299.     mova           m2, [dst1q]               ; q0
  300.     mova           m3, [dst1q+ strideq]      ; q1
  301. %else ; h
  302.     lea         dst2q, [dst1q+ strideq]
  303.  
  304. %if mmsize == 8 ; mmx/mmxext
  305.     READ_8x4_INTERLEAVED  0, 1, 2, 3, 4, 5, 6, dst1q, dst2q, mstrideq, strideq
  306. %else ; sse2
  307.     READ_16x4_INTERLEAVED 0, 1, 2, 3, 4, 5, 6, dst1q, dst2q, mstrideq, strideq, dst3q
  308. %endif
  309.     TRANSPOSE4x4W         0, 1, 2, 3, 4
  310. %endif
  311.  
  312.     ; simple_limit
  313.     mova           m5, m2           ; m5=backup of q0
  314.     mova           m6, m1           ; m6=backup of p0
  315.     psubusb        m1, m2           ; p0-q0
  316.     psubusb        m2, m6           ; q0-p0
  317.     por            m1, m2           ; FFABS(p0-q0)
  318.     paddusb        m1, m1           ; m1=FFABS(p0-q0)*2
  319.  
  320.     mova           m4, m3
  321.     mova           m2, m0
  322.     psubusb        m3, m0           ; q1-p1
  323.     psubusb        m0, m4           ; p1-q1
  324.     por            m3, m0           ; FFABS(p1-q1)
  325.     mova           m0, [pb_80]
  326.     pxor           m2, m0
  327.     pxor           m4, m0
  328.     psubsb         m2, m4           ; m2=p1-q1 (signed) backup for below
  329.     pand           m3, [pb_FE]
  330.     psrlq          m3, 1            ; m3=FFABS(p1-q1)/2, this can be used signed
  331.     paddusb        m3, m1
  332.     psubusb        m3, m7
  333.     pxor           m1, m1
  334.     pcmpeqb        m3, m1           ; abs(p0-q0)*2+abs(p1-q1)/2<=flim mask(0xff/0x0)
  335.  
  336.     ; filter_common (use m2/p1-q1, m4=q0, m6=p0, m5/q0-p0 and m3/mask)
  337.     mova           m4, m5
  338.     pxor           m5, m0
  339.     pxor           m0, m6
  340.     psubsb         m5, m0           ; q0-p0 (signed)
  341.     paddsb         m2, m5
  342.     paddsb         m2, m5
  343.     paddsb         m2, m5           ; a=(p1-q1) + 3*(q0-p0)
  344.     pand           m2, m3           ; apply filter mask (m3)
  345.  
  346.     mova           m3, [pb_F8]
  347.     mova           m1, m2
  348.     paddsb         m2, [pb_4]       ; f1<<3=a+4
  349.     paddsb         m1, [pb_3]       ; f2<<3=a+3
  350.     pand           m2, m3
  351.     pand           m1, m3           ; cache f2<<3
  352.  
  353.     pxor           m0, m0
  354.     pxor           m3, m3
  355.     pcmpgtb        m0, m2           ; which values are <0?
  356.     psubb          m3, m2           ; -f1<<3
  357.     psrlq          m2, 3            ; +f1
  358.     psrlq          m3, 3            ; -f1
  359.     pand           m3, m0
  360.     pandn          m0, m2
  361.     psubusb        m4, m0
  362.     paddusb        m4, m3           ; q0-f1
  363.  
  364.     pxor           m0, m0
  365.     pxor           m3, m3
  366.     pcmpgtb        m0, m1           ; which values are <0?
  367.     psubb          m3, m1           ; -f2<<3
  368.     psrlq          m1, 3            ; +f2
  369.     psrlq          m3, 3            ; -f2
  370.     pand           m3, m0
  371.     pandn          m0, m1
  372.     paddusb        m6, m0
  373.     psubusb        m6, m3           ; p0+f2
  374.  
  375.     ; store
  376. %ifidn %1, v
  377.     mova      [dst1q], m4
  378.     mova [dst1q+mstrideq], m6
  379. %else ; h
  380.     inc        dst1q
  381.     SBUTTERFLY    bw, 6, 4, 0
  382.  
  383. %if mmsize == 16 ; sse2
  384. %if cpuflag(sse4)
  385.     inc         dst2q
  386. %endif
  387.     WRITE_8W       m6, dst2q, dst1q, mstrideq, strideq
  388.     lea         dst2q, [dst3q+mstrideq+1]
  389. %if cpuflag(sse4)
  390.     inc         dst3q
  391. %endif
  392.     WRITE_8W       m4, dst3q, dst2q, mstrideq, strideq
  393. %else ; mmx/mmxext
  394.     WRITE_2x4W     m6, m4, dst2q, dst1q, mstrideq, strideq
  395. %endif
  396. %endif
  397.  
  398. %if mmsize == 8 ; mmx/mmxext
  399.     ; next 8 pixels
  400. %ifidn %1, v
  401.     add         dst1q, 8            ; advance 8 cols = pixels
  402. %else ; h
  403.     lea         dst1q, [dst1q+strideq*8-1]  ; advance 8 rows = lines
  404. %endif
  405.     dec         cntrq
  406.     jg .next8px
  407.     REP_RET
  408. %else ; sse2
  409.     RET
  410. %endif
  411. %endmacro
  412.  
  413. %if ARCH_X86_32
  414. INIT_MMX mmx
  415. SIMPLE_LOOPFILTER v, 4
  416. SIMPLE_LOOPFILTER h, 5
  417. INIT_MMX mmxext
  418. SIMPLE_LOOPFILTER v, 4
  419. SIMPLE_LOOPFILTER h, 5
  420. %endif
  421.  
  422. INIT_XMM sse2
  423. SIMPLE_LOOPFILTER v, 3
  424. SIMPLE_LOOPFILTER h, 5
  425. INIT_XMM ssse3
  426. SIMPLE_LOOPFILTER v, 3
  427. SIMPLE_LOOPFILTER h, 5
  428. INIT_XMM sse4
  429. SIMPLE_LOOPFILTER h, 5
  430.  
  431. ;-----------------------------------------------------------------------------
  432. ; void ff_vp8_h/v_loop_filter<size>_inner_<opt>(uint8_t *dst, [uint8_t *v,] int stride,
  433. ;                                               int flimE, int flimI, int hev_thr);
  434. ;-----------------------------------------------------------------------------
  435.  
  436. %macro INNER_LOOPFILTER 2
  437. %define stack_size 0
  438. %ifndef m8   ; stack layout: [0]=E, [1]=I, [2]=hev_thr
  439. %ifidn %1, v ;               [3]=hev() result
  440. %define stack_size mmsize * -4
  441. %else ; h    ; extra storage space for transposes
  442. %define stack_size mmsize * -5
  443. %endif
  444. %endif
  445.  
  446. %if %2 == 8 ; chroma
  447. cglobal vp8_%1_loop_filter8uv_inner, 6, 6, 13, stack_size, dst, dst8, stride, flimE, flimI, hevthr
  448. %else ; luma
  449. cglobal vp8_%1_loop_filter16y_inner, 5, 5, 13, stack_size, dst, stride, flimE, flimI, hevthr
  450. %endif
  451.  
  452. %if cpuflag(ssse3)
  453.     pxor             m7, m7
  454. %endif
  455.  
  456. %ifndef m8
  457.     ; splat function arguments
  458.     SPLATB_REG       m0, flimEq, m7   ; E
  459.     SPLATB_REG       m1, flimIq, m7   ; I
  460.     SPLATB_REG       m2, hevthrq, m7  ; hev_thresh
  461.  
  462. %define m_flimE    [rsp]
  463. %define m_flimI    [rsp+mmsize]
  464. %define m_hevthr   [rsp+mmsize*2]
  465. %define m_maskres  [rsp+mmsize*3]
  466. %define m_p0backup [rsp+mmsize*3]
  467. %define m_q0backup [rsp+mmsize*4]
  468.  
  469.     mova        m_flimE, m0
  470.     mova        m_flimI, m1
  471.     mova       m_hevthr, m2
  472. %else
  473. %define m_flimE    m9
  474. %define m_flimI    m10
  475. %define m_hevthr   m11
  476. %define m_maskres  m12
  477. %define m_p0backup m12
  478. %define m_q0backup m8
  479.  
  480.     ; splat function arguments
  481.     SPLATB_REG  m_flimE, flimEq, m7   ; E
  482.     SPLATB_REG  m_flimI, flimIq, m7   ; I
  483.     SPLATB_REG m_hevthr, hevthrq, m7  ; hev_thresh
  484. %endif
  485.  
  486. %if %2 == 8 ; chroma
  487.     DEFINE_ARGS dst1, dst8, mstride, stride, dst2
  488. %elif mmsize == 8
  489.     DEFINE_ARGS dst1, mstride, stride, dst2, cntr
  490.     mov           cntrq, 2
  491. %else
  492.     DEFINE_ARGS dst1, mstride, stride, dst2, dst8
  493. %endif
  494.     mov         strideq, mstrideq
  495.     neg        mstrideq
  496. %ifidn %1, h
  497.     lea           dst1q, [dst1q+strideq*4-4]
  498. %if %2 == 8 ; chroma
  499.     lea           dst8q, [dst8q+strideq*4-4]
  500. %endif
  501. %endif
  502.  
  503. %if mmsize == 8
  504. .next8px:
  505. %endif
  506.     ; read
  507.     lea           dst2q, [dst1q+strideq]
  508. %ifidn %1, v
  509. %if %2 == 8 && mmsize == 16
  510. %define movrow movh
  511. %else
  512. %define movrow mova
  513. %endif
  514.     movrow           m0, [dst1q+mstrideq*4] ; p3
  515.     movrow           m1, [dst2q+mstrideq*4] ; p2
  516.     movrow           m2, [dst1q+mstrideq*2] ; p1
  517.     movrow           m5, [dst2q]            ; q1
  518.     movrow           m6, [dst2q+ strideq*1] ; q2
  519.     movrow           m7, [dst2q+ strideq*2] ; q3
  520. %if mmsize == 16 && %2 == 8
  521.     movhps           m0, [dst8q+mstrideq*4]
  522.     movhps           m2, [dst8q+mstrideq*2]
  523.     add           dst8q, strideq
  524.     movhps           m1, [dst8q+mstrideq*4]
  525.     movhps           m5, [dst8q]
  526.     movhps           m6, [dst8q+ strideq  ]
  527.     movhps           m7, [dst8q+ strideq*2]
  528.     add           dst8q, mstrideq
  529. %endif
  530. %elif mmsize == 8 ; mmx/mmxext (h)
  531.     ; read 8 rows of 8px each
  532.     movu             m0, [dst1q+mstrideq*4]
  533.     movu             m1, [dst2q+mstrideq*4]
  534.     movu             m2, [dst1q+mstrideq*2]
  535.     movu             m3, [dst1q+mstrideq  ]
  536.     movu             m4, [dst1q]
  537.     movu             m5, [dst2q]
  538.     movu             m6, [dst2q+ strideq  ]
  539.  
  540.     ; 8x8 transpose
  541.     TRANSPOSE4x4B     0, 1, 2, 3, 7
  542.     mova     m_q0backup, m1
  543.     movu             m7, [dst2q+ strideq*2]
  544.     TRANSPOSE4x4B     4, 5, 6, 7, 1
  545.     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
  546.     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
  547.     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
  548.     mova             m1, m_q0backup
  549.     mova     m_q0backup, m2          ; store q0
  550.     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
  551.     mova     m_p0backup, m5          ; store p0
  552.     SWAP              1, 4
  553.     SWAP              2, 4
  554.     SWAP              6, 3
  555.     SWAP              5, 3
  556. %else ; sse2 (h)
  557. %if %2 == 16
  558.     lea           dst8q, [dst1q+ strideq*8]
  559. %endif
  560.  
  561.     ; read 16 rows of 8px each, interleave
  562.     movh             m0, [dst1q+mstrideq*4]
  563.     movh             m1, [dst8q+mstrideq*4]
  564.     movh             m2, [dst1q+mstrideq*2]
  565.     movh             m5, [dst8q+mstrideq*2]
  566.     movh             m3, [dst1q+mstrideq  ]
  567.     movh             m6, [dst8q+mstrideq  ]
  568.     movh             m4, [dst1q]
  569.     movh             m7, [dst8q]
  570.     punpcklbw        m0, m1          ; A/I
  571.     punpcklbw        m2, m5          ; C/K
  572.     punpcklbw        m3, m6          ; D/L
  573.     punpcklbw        m4, m7          ; E/M
  574.  
  575.     add           dst8q, strideq
  576.     movh             m1, [dst2q+mstrideq*4]
  577.     movh             m6, [dst8q+mstrideq*4]
  578.     movh             m5, [dst2q]
  579.     movh             m7, [dst8q]
  580.     punpcklbw        m1, m6          ; B/J
  581.     punpcklbw        m5, m7          ; F/N
  582.     movh             m6, [dst2q+ strideq  ]
  583.     movh             m7, [dst8q+ strideq  ]
  584.     punpcklbw        m6, m7          ; G/O
  585.  
  586.     ; 8x16 transpose
  587.     TRANSPOSE4x4B     0, 1, 2, 3, 7
  588. %ifdef m8
  589.     SWAP              1, 8
  590. %else
  591.     mova     m_q0backup, m1
  592. %endif
  593.     movh             m7, [dst2q+ strideq*2]
  594.     movh             m1, [dst8q+ strideq*2]
  595.     punpcklbw        m7, m1          ; H/P
  596.     TRANSPOSE4x4B     4, 5, 6, 7, 1
  597.     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
  598.     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
  599.     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
  600. %ifdef m8
  601.     SWAP              1, 8
  602.     SWAP              2, 8
  603. %else
  604.     mova             m1, m_q0backup
  605.     mova     m_q0backup, m2          ; store q0
  606. %endif
  607.     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
  608. %ifdef m12
  609.     SWAP              5, 12
  610. %else
  611.     mova     m_p0backup, m5          ; store p0
  612. %endif
  613.     SWAP              1, 4
  614.     SWAP              2, 4
  615.     SWAP              6, 3
  616.     SWAP              5, 3
  617. %endif
  618.  
  619.     ; normal_limit for p3-p2, p2-p1, q3-q2 and q2-q1
  620.     mova             m4, m1
  621.     SWAP              4, 1
  622.     psubusb          m4, m0          ; p2-p3
  623.     psubusb          m0, m1          ; p3-p2
  624.     por              m0, m4          ; abs(p3-p2)
  625.  
  626.     mova             m4, m2
  627.     SWAP              4, 2
  628.     psubusb          m4, m1          ; p1-p2
  629.     psubusb          m1, m2          ; p2-p1
  630.     por              m1, m4          ; abs(p2-p1)
  631.  
  632.     mova             m4, m6
  633.     SWAP              4, 6
  634.     psubusb          m4, m7          ; q2-q3
  635.     psubusb          m7, m6          ; q3-q2
  636.     por              m7, m4          ; abs(q3-q2)
  637.  
  638.     mova             m4, m5
  639.     SWAP              4, 5
  640.     psubusb          m4, m6          ; q1-q2
  641.     psubusb          m6, m5          ; q2-q1
  642.     por              m6, m4          ; abs(q2-q1)
  643.  
  644. %if notcpuflag(mmxext)
  645.     mova             m4, m_flimI
  646.     pxor             m3, m3
  647.     psubusb          m0, m4
  648.     psubusb          m1, m4
  649.     psubusb          m7, m4
  650.     psubusb          m6, m4
  651.     pcmpeqb          m0, m3          ; abs(p3-p2) <= I
  652.     pcmpeqb          m1, m3          ; abs(p2-p1) <= I
  653.     pcmpeqb          m7, m3          ; abs(q3-q2) <= I
  654.     pcmpeqb          m6, m3          ; abs(q2-q1) <= I
  655.     pand             m0, m1
  656.     pand             m7, m6
  657.     pand             m0, m7
  658. %else ; mmxext/sse2
  659.     pmaxub           m0, m1
  660.     pmaxub           m6, m7
  661.     pmaxub           m0, m6
  662. %endif
  663.  
  664.     ; normal_limit and high_edge_variance for p1-p0, q1-q0
  665.     SWAP              7, 3           ; now m7 is zero
  666. %ifidn %1, v
  667.     movrow           m3, [dst1q+mstrideq  ] ; p0
  668. %if mmsize == 16 && %2 == 8
  669.     movhps           m3, [dst8q+mstrideq  ]
  670. %endif
  671. %elifdef m12
  672.     SWAP              3, 12
  673. %else
  674.     mova             m3, m_p0backup
  675. %endif
  676.  
  677.     mova             m1, m2
  678.     SWAP              1, 2
  679.     mova             m6, m3
  680.     SWAP              3, 6
  681.     psubusb          m1, m3          ; p1-p0
  682.     psubusb          m6, m2          ; p0-p1
  683.     por              m1, m6          ; abs(p1-p0)
  684. %if notcpuflag(mmxext)
  685.     mova             m6, m1
  686.     psubusb          m1, m4
  687.     psubusb          m6, m_hevthr
  688.     pcmpeqb          m1, m7          ; abs(p1-p0) <= I
  689.     pcmpeqb          m6, m7          ; abs(p1-p0) <= hev_thresh
  690.     pand             m0, m1
  691.     mova      m_maskres, m6
  692. %else ; mmxext/sse2
  693.     pmaxub           m0, m1          ; max_I
  694.     SWAP              1, 4           ; max_hev_thresh
  695. %endif
  696.  
  697.     SWAP              6, 4           ; now m6 is I
  698. %ifidn %1, v
  699.     movrow           m4, [dst1q]     ; q0
  700. %if mmsize == 16 && %2 == 8
  701.     movhps           m4, [dst8q]
  702. %endif
  703. %elifdef m8
  704.     SWAP              4, 8
  705. %else
  706.     mova             m4, m_q0backup
  707. %endif
  708.     mova             m1, m4
  709.     SWAP              1, 4
  710.     mova             m7, m5
  711.     SWAP              7, 5
  712.     psubusb          m1, m5          ; q0-q1
  713.     psubusb          m7, m4          ; q1-q0
  714.     por              m1, m7          ; abs(q1-q0)
  715. %if notcpuflag(mmxext)
  716.     mova             m7, m1
  717.     psubusb          m1, m6
  718.     psubusb          m7, m_hevthr
  719.     pxor             m6, m6
  720.     pcmpeqb          m1, m6          ; abs(q1-q0) <= I
  721.     pcmpeqb          m7, m6          ; abs(q1-q0) <= hev_thresh
  722.     mova             m6, m_maskres
  723.     pand             m0, m1          ; abs([pq][321]-[pq][210]) <= I
  724.     pand             m6, m7
  725. %else ; mmxext/sse2
  726.     pxor             m7, m7
  727.     pmaxub           m0, m1
  728.     pmaxub           m6, m1
  729.     psubusb          m0, m_flimI
  730.     psubusb          m6, m_hevthr
  731.     pcmpeqb          m0, m7          ; max(abs(..)) <= I
  732.     pcmpeqb          m6, m7          ; !(max(abs..) > thresh)
  733. %endif
  734. %ifdef m12
  735.     SWAP              6, 12
  736. %else
  737.     mova      m_maskres, m6          ; !(abs(p1-p0) > hev_t || abs(q1-q0) > hev_t)
  738. %endif
  739.  
  740.     ; simple_limit
  741.     mova             m1, m3
  742.     SWAP              1, 3
  743.     mova             m6, m4          ; keep copies of p0/q0 around for later use
  744.     SWAP              6, 4
  745.     psubusb          m1, m4          ; p0-q0
  746.     psubusb          m6, m3          ; q0-p0
  747.     por              m1, m6          ; abs(q0-p0)
  748.     paddusb          m1, m1          ; m1=2*abs(q0-p0)
  749.  
  750.     mova             m7, m2
  751.     SWAP              7, 2
  752.     mova             m6, m5
  753.     SWAP              6, 5
  754.     psubusb          m7, m5          ; p1-q1
  755.     psubusb          m6, m2          ; q1-p1
  756.     por              m7, m6          ; abs(q1-p1)
  757.     pxor             m6, m6
  758.     pand             m7, [pb_FE]
  759.     psrlq            m7, 1           ; abs(q1-p1)/2
  760.     paddusb          m7, m1          ; abs(q0-p0)*2+abs(q1-p1)/2
  761.     psubusb          m7, m_flimE
  762.     pcmpeqb          m7, m6          ; abs(q0-p0)*2+abs(q1-p1)/2 <= E
  763.     pand             m0, m7          ; normal_limit result
  764.  
  765.     ; filter_common; at this point, m2-m5=p1-q1 and m0 is filter_mask
  766. %ifdef m8 ; x86-64 && sse2
  767.     mova             m8, [pb_80]
  768. %define m_pb_80 m8
  769. %else ; x86-32 or mmx/mmxext
  770. %define m_pb_80 [pb_80]
  771. %endif
  772.     mova             m1, m4
  773.     mova             m7, m3
  774.     pxor             m1, m_pb_80
  775.     pxor             m7, m_pb_80
  776.     psubsb           m1, m7          ; (signed) q0-p0
  777.     mova             m6, m2
  778.     mova             m7, m5
  779.     pxor             m6, m_pb_80
  780.     pxor             m7, m_pb_80
  781.     psubsb           m6, m7          ; (signed) p1-q1
  782.     mova             m7, m_maskres
  783.     pandn            m7, m6
  784.     paddsb           m7, m1
  785.     paddsb           m7, m1
  786.     paddsb           m7, m1          ; 3*(q0-p0)+is4tap?(p1-q1)
  787.  
  788.     pand             m7, m0
  789.     mova             m1, [pb_F8]
  790.     mova             m6, m7
  791.     paddsb           m7, [pb_3]
  792.     paddsb           m6, [pb_4]
  793.     pand             m7, m1
  794.     pand             m6, m1
  795.  
  796.     pxor             m1, m1
  797.     pxor             m0, m0
  798.     pcmpgtb          m1, m7
  799.     psubb            m0, m7
  800.     psrlq            m7, 3           ; +f2
  801.     psrlq            m0, 3           ; -f2
  802.     pand             m0, m1
  803.     pandn            m1, m7
  804.     psubusb          m3, m0
  805.     paddusb          m3, m1          ; p0+f2
  806.  
  807.     pxor             m1, m1
  808.     pxor             m0, m0
  809.     pcmpgtb          m0, m6
  810.     psubb            m1, m6
  811.     psrlq            m6, 3           ; +f1
  812.     psrlq            m1, 3           ; -f1
  813.     pand             m1, m0
  814.     pandn            m0, m6
  815.     psubusb          m4, m0
  816.     paddusb          m4, m1          ; q0-f1
  817.  
  818. %ifdef m12
  819.     SWAP              6, 12
  820. %else
  821.     mova             m6, m_maskres
  822. %endif
  823. %if notcpuflag(mmxext)
  824.     mova             m7, [pb_1]
  825. %else ; mmxext/sse2
  826.     pxor             m7, m7
  827. %endif
  828.     pand             m0, m6
  829.     pand             m1, m6
  830. %if notcpuflag(mmxext)
  831.     paddusb          m0, m7
  832.     pand             m1, [pb_FE]
  833.     pandn            m7, m0
  834.     psrlq            m1, 1
  835.     psrlq            m7, 1
  836.     SWAP              0, 7
  837. %else ; mmxext/sse2
  838.     psubusb          m1, [pb_1]
  839.     pavgb            m0, m7          ; a
  840.     pavgb            m1, m7          ; -a
  841. %endif
  842.     psubusb          m5, m0
  843.     psubusb          m2, m1
  844.     paddusb          m5, m1          ; q1-a
  845.     paddusb          m2, m0          ; p1+a
  846.  
  847.     ; store
  848. %ifidn %1, v
  849.     movrow [dst1q+mstrideq*2], m2
  850.     movrow [dst1q+mstrideq  ], m3
  851.     movrow      [dst1q], m4
  852.     movrow [dst1q+ strideq  ], m5
  853. %if mmsize == 16 && %2 == 8
  854.     movhps [dst8q+mstrideq*2], m2
  855.     movhps [dst8q+mstrideq  ], m3
  856.     movhps      [dst8q], m4
  857.     movhps [dst8q+ strideq  ], m5
  858. %endif
  859. %else ; h
  860.     add           dst1q, 2
  861.     add           dst2q, 2
  862.  
  863.     ; 4x8/16 transpose
  864.     TRANSPOSE4x4B     2, 3, 4, 5, 6
  865.  
  866. %if mmsize == 8 ; mmx/mmxext (h)
  867.     WRITE_4x2D        2, 3, 4, 5, dst1q, dst2q, mstrideq, strideq
  868. %else ; sse2 (h)
  869.     lea           dst8q, [dst8q+mstrideq  +2]
  870.     WRITE_4x4D        2, 3, 4, 5, dst1q, dst2q, dst8q, mstrideq, strideq, %2
  871. %endif
  872. %endif
  873.  
  874. %if mmsize == 8
  875. %if %2 == 8 ; chroma
  876. %ifidn %1, h
  877.     sub           dst1q, 2
  878. %endif
  879.     cmp           dst1q, dst8q
  880.     mov           dst1q, dst8q
  881.     jnz .next8px
  882. %else
  883. %ifidn %1, h
  884.     lea           dst1q, [dst1q+ strideq*8-2]
  885. %else ; v
  886.     add           dst1q, 8
  887. %endif
  888.     dec           cntrq
  889.     jg .next8px
  890. %endif
  891.     REP_RET
  892. %else ; mmsize == 16
  893.     RET
  894. %endif
  895. %endmacro
  896.  
  897. %if ARCH_X86_32
  898. INIT_MMX mmx
  899. INNER_LOOPFILTER v, 16
  900. INNER_LOOPFILTER h, 16
  901. INNER_LOOPFILTER v,  8
  902. INNER_LOOPFILTER h,  8
  903.  
  904. INIT_MMX mmxext
  905. INNER_LOOPFILTER v, 16
  906. INNER_LOOPFILTER h, 16
  907. INNER_LOOPFILTER v,  8
  908. INNER_LOOPFILTER h,  8
  909. %endif
  910.  
  911. INIT_XMM sse2
  912. INNER_LOOPFILTER v, 16
  913. INNER_LOOPFILTER h, 16
  914. INNER_LOOPFILTER v,  8
  915. INNER_LOOPFILTER h,  8
  916.  
  917. INIT_XMM ssse3
  918. INNER_LOOPFILTER v, 16
  919. INNER_LOOPFILTER h, 16
  920. INNER_LOOPFILTER v,  8
  921. INNER_LOOPFILTER h,  8
  922.  
  923. ;-----------------------------------------------------------------------------
  924. ; void ff_vp8_h/v_loop_filter<size>_mbedge_<opt>(uint8_t *dst, [uint8_t *v,] int stride,
  925. ;                                                int flimE, int flimI, int hev_thr);
  926. ;-----------------------------------------------------------------------------
  927.  
  928. %macro MBEDGE_LOOPFILTER 2
  929. %define stack_size 0
  930. %ifndef m8       ; stack layout: [0]=E, [1]=I, [2]=hev_thr
  931. %if mmsize == 16 ;               [3]=hev() result
  932.                  ;               [4]=filter tmp result
  933.                  ;               [5]/[6] = p2/q2 backup
  934.                  ;               [7]=lim_res sign result
  935. %define stack_size mmsize * -7
  936. %else ; 8        ; extra storage space for transposes
  937. %define stack_size mmsize * -8
  938. %endif
  939. %endif
  940.  
  941. %if %2 == 8 ; chroma
  942. cglobal vp8_%1_loop_filter8uv_mbedge, 6, 6, 15, stack_size, dst1, dst8, stride, flimE, flimI, hevthr
  943. %else ; luma
  944. cglobal vp8_%1_loop_filter16y_mbedge, 5, 5, 15, stack_size, dst1, stride, flimE, flimI, hevthr
  945. %endif
  946.  
  947. %if cpuflag(ssse3)
  948.     pxor             m7, m7
  949. %endif
  950.  
  951. %ifndef m8
  952.     ; splat function arguments
  953.     SPLATB_REG       m0, flimEq, m7   ; E
  954.     SPLATB_REG       m1, flimIq, m7   ; I
  955.     SPLATB_REG       m2, hevthrq, m7  ; hev_thresh
  956.  
  957. %define m_flimE    [rsp]
  958. %define m_flimI    [rsp+mmsize]
  959. %define m_hevthr   [rsp+mmsize*2]
  960. %define m_maskres  [rsp+mmsize*3]
  961. %define m_limres   [rsp+mmsize*4]
  962. %define m_p0backup [rsp+mmsize*3]
  963. %define m_q0backup [rsp+mmsize*4]
  964. %define m_p2backup [rsp+mmsize*5]
  965. %define m_q2backup [rsp+mmsize*6]
  966. %if mmsize == 16
  967. %define m_limsign  [rsp]
  968. %else
  969. %define m_limsign  [rsp+mmsize*7]
  970. %endif
  971.  
  972.     mova        m_flimE, m0
  973.     mova        m_flimI, m1
  974.     mova       m_hevthr, m2
  975. %else ; sse2 on x86-64
  976. %define m_flimE    m9
  977. %define m_flimI    m10
  978. %define m_hevthr   m11
  979. %define m_maskres  m12
  980. %define m_limres   m8
  981. %define m_p0backup m12
  982. %define m_q0backup m8
  983. %define m_p2backup m13
  984. %define m_q2backup m14
  985. %define m_limsign  m9
  986.  
  987.     ; splat function arguments
  988.     SPLATB_REG  m_flimE, flimEq, m7   ; E
  989.     SPLATB_REG  m_flimI, flimIq, m7   ; I
  990.     SPLATB_REG m_hevthr, hevthrq, m7  ; hev_thresh
  991. %endif
  992.  
  993. %if %2 == 8 ; chroma
  994.     DEFINE_ARGS dst1, dst8, mstride, stride, dst2
  995. %elif mmsize == 8
  996.     DEFINE_ARGS dst1, mstride, stride, dst2, cntr
  997.     mov           cntrq, 2
  998. %else
  999.     DEFINE_ARGS dst1, mstride, stride, dst2, dst8
  1000. %endif
  1001.     mov         strideq, mstrideq
  1002.     neg        mstrideq
  1003. %ifidn %1, h
  1004.     lea           dst1q, [dst1q+strideq*4-4]
  1005. %if %2 == 8 ; chroma
  1006.     lea           dst8q, [dst8q+strideq*4-4]
  1007. %endif
  1008. %endif
  1009.  
  1010. %if mmsize == 8
  1011. .next8px:
  1012. %endif
  1013.     ; read
  1014.     lea           dst2q, [dst1q+ strideq  ]
  1015. %ifidn %1, v
  1016. %if %2 == 8 && mmsize == 16
  1017. %define movrow movh
  1018. %else
  1019. %define movrow mova
  1020. %endif
  1021.     movrow           m0, [dst1q+mstrideq*4] ; p3
  1022.     movrow           m1, [dst2q+mstrideq*4] ; p2
  1023.     movrow           m2, [dst1q+mstrideq*2] ; p1
  1024.     movrow           m5, [dst2q]            ; q1
  1025.     movrow           m6, [dst2q+ strideq  ] ; q2
  1026.     movrow           m7, [dst2q+ strideq*2] ; q3
  1027. %if mmsize == 16 && %2 == 8
  1028.     movhps           m0, [dst8q+mstrideq*4]
  1029.     movhps           m2, [dst8q+mstrideq*2]
  1030.     add           dst8q, strideq
  1031.     movhps           m1, [dst8q+mstrideq*4]
  1032.     movhps           m5, [dst8q]
  1033.     movhps           m6, [dst8q+ strideq  ]
  1034.     movhps           m7, [dst8q+ strideq*2]
  1035.     add           dst8q, mstrideq
  1036. %endif
  1037. %elif mmsize == 8 ; mmx/mmxext (h)
  1038.     ; read 8 rows of 8px each
  1039.     movu             m0, [dst1q+mstrideq*4]
  1040.     movu             m1, [dst2q+mstrideq*4]
  1041.     movu             m2, [dst1q+mstrideq*2]
  1042.     movu             m3, [dst1q+mstrideq  ]
  1043.     movu             m4, [dst1q]
  1044.     movu             m5, [dst2q]
  1045.     movu             m6, [dst2q+ strideq  ]
  1046.  
  1047.     ; 8x8 transpose
  1048.     TRANSPOSE4x4B     0, 1, 2, 3, 7
  1049.     mova     m_q0backup, m1
  1050.     movu             m7, [dst2q+ strideq*2]
  1051.     TRANSPOSE4x4B     4, 5, 6, 7, 1
  1052.     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
  1053.     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
  1054.     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
  1055.     mova             m1, m_q0backup
  1056.     mova     m_q0backup, m2          ; store q0
  1057.     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
  1058.     mova     m_p0backup, m5          ; store p0
  1059.     SWAP              1, 4
  1060.     SWAP              2, 4
  1061.     SWAP              6, 3
  1062.     SWAP              5, 3
  1063. %else ; sse2 (h)
  1064. %if %2 == 16
  1065.     lea           dst8q, [dst1q+ strideq*8  ]
  1066. %endif
  1067.  
  1068.     ; read 16 rows of 8px each, interleave
  1069.     movh             m0, [dst1q+mstrideq*4]
  1070.     movh             m1, [dst8q+mstrideq*4]
  1071.     movh             m2, [dst1q+mstrideq*2]
  1072.     movh             m5, [dst8q+mstrideq*2]
  1073.     movh             m3, [dst1q+mstrideq  ]
  1074.     movh             m6, [dst8q+mstrideq  ]
  1075.     movh             m4, [dst1q]
  1076.     movh             m7, [dst8q]
  1077.     punpcklbw        m0, m1          ; A/I
  1078.     punpcklbw        m2, m5          ; C/K
  1079.     punpcklbw        m3, m6          ; D/L
  1080.     punpcklbw        m4, m7          ; E/M
  1081.  
  1082.     add           dst8q, strideq
  1083.     movh             m1, [dst2q+mstrideq*4]
  1084.     movh             m6, [dst8q+mstrideq*4]
  1085.     movh             m5, [dst2q]
  1086.     movh             m7, [dst8q]
  1087.     punpcklbw        m1, m6          ; B/J
  1088.     punpcklbw        m5, m7          ; F/N
  1089.     movh             m6, [dst2q+ strideq  ]
  1090.     movh             m7, [dst8q+ strideq  ]
  1091.     punpcklbw        m6, m7          ; G/O
  1092.  
  1093.     ; 8x16 transpose
  1094.     TRANSPOSE4x4B     0, 1, 2, 3, 7
  1095. %ifdef m8
  1096.     SWAP              1, 8
  1097. %else
  1098.     mova     m_q0backup, m1
  1099. %endif
  1100.     movh             m7, [dst2q+ strideq*2]
  1101.     movh             m1, [dst8q+ strideq*2]
  1102.     punpcklbw        m7, m1          ; H/P
  1103.     TRANSPOSE4x4B     4, 5, 6, 7, 1
  1104.     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
  1105.     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
  1106.     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
  1107. %ifdef m8
  1108.     SWAP              1, 8
  1109.     SWAP              2, 8
  1110. %else
  1111.     mova             m1, m_q0backup
  1112.     mova     m_q0backup, m2          ; store q0
  1113. %endif
  1114.     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
  1115. %ifdef m12
  1116.     SWAP              5, 12
  1117. %else
  1118.     mova     m_p0backup, m5          ; store p0
  1119. %endif
  1120.     SWAP              1, 4
  1121.     SWAP              2, 4
  1122.     SWAP              6, 3
  1123.     SWAP              5, 3
  1124. %endif
  1125.  
  1126.     ; normal_limit for p3-p2, p2-p1, q3-q2 and q2-q1
  1127.     mova             m4, m1
  1128.     SWAP              4, 1
  1129.     psubusb          m4, m0          ; p2-p3
  1130.     psubusb          m0, m1          ; p3-p2
  1131.     por              m0, m4          ; abs(p3-p2)
  1132.  
  1133.     mova             m4, m2
  1134.     SWAP              4, 2
  1135.     psubusb          m4, m1          ; p1-p2
  1136.     mova     m_p2backup, m1
  1137.     psubusb          m1, m2          ; p2-p1
  1138.     por              m1, m4          ; abs(p2-p1)
  1139.  
  1140.     mova             m4, m6
  1141.     SWAP              4, 6
  1142.     psubusb          m4, m7          ; q2-q3
  1143.     psubusb          m7, m6          ; q3-q2
  1144.     por              m7, m4          ; abs(q3-q2)
  1145.  
  1146.     mova             m4, m5
  1147.     SWAP              4, 5
  1148.     psubusb          m4, m6          ; q1-q2
  1149.     mova     m_q2backup, m6
  1150.     psubusb          m6, m5          ; q2-q1
  1151.     por              m6, m4          ; abs(q2-q1)
  1152.  
  1153. %if notcpuflag(mmxext)
  1154.     mova             m4, m_flimI
  1155.     pxor             m3, m3
  1156.     psubusb          m0, m4
  1157.     psubusb          m1, m4
  1158.     psubusb          m7, m4
  1159.     psubusb          m6, m4
  1160.     pcmpeqb          m0, m3          ; abs(p3-p2) <= I
  1161.     pcmpeqb          m1, m3          ; abs(p2-p1) <= I
  1162.     pcmpeqb          m7, m3          ; abs(q3-q2) <= I
  1163.     pcmpeqb          m6, m3          ; abs(q2-q1) <= I
  1164.     pand             m0, m1
  1165.     pand             m7, m6
  1166.     pand             m0, m7
  1167. %else ; mmxext/sse2
  1168.     pmaxub           m0, m1
  1169.     pmaxub           m6, m7
  1170.     pmaxub           m0, m6
  1171. %endif
  1172.  
  1173.     ; normal_limit and high_edge_variance for p1-p0, q1-q0
  1174.     SWAP              7, 3           ; now m7 is zero
  1175. %ifidn %1, v
  1176.     movrow           m3, [dst1q+mstrideq  ] ; p0
  1177. %if mmsize == 16 && %2 == 8
  1178.     movhps           m3, [dst8q+mstrideq  ]
  1179. %endif
  1180. %elifdef m12
  1181.     SWAP              3, 12
  1182. %else
  1183.     mova             m3, m_p0backup
  1184. %endif
  1185.  
  1186.     mova             m1, m2
  1187.     SWAP              1, 2
  1188.     mova             m6, m3
  1189.     SWAP              3, 6
  1190.     psubusb          m1, m3          ; p1-p0
  1191.     psubusb          m6, m2          ; p0-p1
  1192.     por              m1, m6          ; abs(p1-p0)
  1193. %if notcpuflag(mmxext)
  1194.     mova             m6, m1
  1195.     psubusb          m1, m4
  1196.     psubusb          m6, m_hevthr
  1197.     pcmpeqb          m1, m7          ; abs(p1-p0) <= I
  1198.     pcmpeqb          m6, m7          ; abs(p1-p0) <= hev_thresh
  1199.     pand             m0, m1
  1200.     mova      m_maskres, m6
  1201. %else ; mmxext/sse2
  1202.     pmaxub           m0, m1          ; max_I
  1203.     SWAP              1, 4           ; max_hev_thresh
  1204. %endif
  1205.  
  1206.     SWAP              6, 4           ; now m6 is I
  1207. %ifidn %1, v
  1208.     movrow           m4, [dst1q]     ; q0
  1209. %if mmsize == 16 && %2 == 8
  1210.     movhps           m4, [dst8q]
  1211. %endif
  1212. %elifdef m8
  1213.     SWAP              4, 8
  1214. %else
  1215.     mova             m4, m_q0backup
  1216. %endif
  1217.     mova             m1, m4
  1218.     SWAP              1, 4
  1219.     mova             m7, m5
  1220.     SWAP              7, 5
  1221.     psubusb          m1, m5          ; q0-q1
  1222.     psubusb          m7, m4          ; q1-q0
  1223.     por              m1, m7          ; abs(q1-q0)
  1224. %if notcpuflag(mmxext)
  1225.     mova             m7, m1
  1226.     psubusb          m1, m6
  1227.     psubusb          m7, m_hevthr
  1228.     pxor             m6, m6
  1229.     pcmpeqb          m1, m6          ; abs(q1-q0) <= I
  1230.     pcmpeqb          m7, m6          ; abs(q1-q0) <= hev_thresh
  1231.     mova             m6, m_maskres
  1232.     pand             m0, m1          ; abs([pq][321]-[pq][210]) <= I
  1233.     pand             m6, m7
  1234. %else ; mmxext/sse2
  1235.     pxor             m7, m7
  1236.     pmaxub           m0, m1
  1237.     pmaxub           m6, m1
  1238.     psubusb          m0, m_flimI
  1239.     psubusb          m6, m_hevthr
  1240.     pcmpeqb          m0, m7          ; max(abs(..)) <= I
  1241.     pcmpeqb          m6, m7          ; !(max(abs..) > thresh)
  1242. %endif
  1243. %ifdef m12
  1244.     SWAP              6, 12
  1245. %else
  1246.     mova      m_maskres, m6          ; !(abs(p1-p0) > hev_t || abs(q1-q0) > hev_t)
  1247. %endif
  1248.  
  1249.     ; simple_limit
  1250.     mova             m1, m3
  1251.     SWAP              1, 3
  1252.     mova             m6, m4          ; keep copies of p0/q0 around for later use
  1253.     SWAP              6, 4
  1254.     psubusb          m1, m4          ; p0-q0
  1255.     psubusb          m6, m3          ; q0-p0
  1256.     por              m1, m6          ; abs(q0-p0)
  1257.     paddusb          m1, m1          ; m1=2*abs(q0-p0)
  1258.  
  1259.     mova             m7, m2
  1260.     SWAP              7, 2
  1261.     mova             m6, m5
  1262.     SWAP              6, 5
  1263.     psubusb          m7, m5          ; p1-q1
  1264.     psubusb          m6, m2          ; q1-p1
  1265.     por              m7, m6          ; abs(q1-p1)
  1266.     pxor             m6, m6
  1267.     pand             m7, [pb_FE]
  1268.     psrlq            m7, 1           ; abs(q1-p1)/2
  1269.     paddusb          m7, m1          ; abs(q0-p0)*2+abs(q1-p1)/2
  1270.     psubusb          m7, m_flimE
  1271.     pcmpeqb          m7, m6          ; abs(q0-p0)*2+abs(q1-p1)/2 <= E
  1272.     pand             m0, m7          ; normal_limit result
  1273.  
  1274.     ; filter_common; at this point, m2-m5=p1-q1 and m0 is filter_mask
  1275. %ifdef m8 ; x86-64 && sse2
  1276.     mova             m8, [pb_80]
  1277. %define m_pb_80 m8
  1278. %else ; x86-32 or mmx/mmxext
  1279. %define m_pb_80 [pb_80]
  1280. %endif
  1281.     mova             m1, m4
  1282.     mova             m7, m3
  1283.     pxor             m1, m_pb_80
  1284.     pxor             m7, m_pb_80
  1285.     psubsb           m1, m7          ; (signed) q0-p0
  1286.     mova             m6, m2
  1287.     mova             m7, m5
  1288.     pxor             m6, m_pb_80
  1289.     pxor             m7, m_pb_80
  1290.     psubsb           m6, m7          ; (signed) p1-q1
  1291.     mova             m7, m_maskres
  1292.     paddsb           m6, m1
  1293.     paddsb           m6, m1
  1294.     paddsb           m6, m1
  1295.     pand             m6, m0
  1296. %ifdef m8
  1297.     mova       m_limres, m6          ; 3*(qp-p0)+(p1-q1) masked for filter_mbedge
  1298.     pand       m_limres, m7
  1299. %else
  1300.     mova             m0, m6
  1301.     pand             m0, m7
  1302.     mova       m_limres, m0
  1303. %endif
  1304.     pandn            m7, m6          ; 3*(q0-p0)+(p1-q1) masked for filter_common
  1305.  
  1306.     mova             m1, [pb_F8]
  1307.     mova             m6, m7
  1308.     paddsb           m7, [pb_3]
  1309.     paddsb           m6, [pb_4]
  1310.     pand             m7, m1
  1311.     pand             m6, m1
  1312.  
  1313.     pxor             m1, m1
  1314.     pxor             m0, m0
  1315.     pcmpgtb          m1, m7
  1316.     psubb            m0, m7
  1317.     psrlq            m7, 3           ; +f2
  1318.     psrlq            m0, 3           ; -f2
  1319.     pand             m0, m1
  1320.     pandn            m1, m7
  1321.     psubusb          m3, m0
  1322.     paddusb          m3, m1          ; p0+f2
  1323.  
  1324.     pxor             m1, m1
  1325.     pxor             m0, m0
  1326.     pcmpgtb          m0, m6
  1327.     psubb            m1, m6
  1328.     psrlq            m6, 3           ; +f1
  1329.     psrlq            m1, 3           ; -f1
  1330.     pand             m1, m0
  1331.     pandn            m0, m6
  1332.     psubusb          m4, m0
  1333.     paddusb          m4, m1          ; q0-f1
  1334.  
  1335.     ; filter_mbedge (m2-m5 = p1-q1; lim_res carries w)
  1336. %if cpuflag(ssse3)
  1337.     mova             m7, [pb_1]
  1338. %else
  1339.     mova             m7, [pw_63]
  1340. %endif
  1341. %ifdef m8
  1342.     SWAP              1, 8
  1343. %else
  1344.     mova             m1, m_limres
  1345. %endif
  1346.     pxor             m0, m0
  1347.     mova             m6, m1
  1348.     pcmpgtb          m0, m1         ; which are negative
  1349. %if cpuflag(ssse3)
  1350.     punpcklbw        m6, m7         ; interleave with "1" for rounding
  1351.     punpckhbw        m1, m7
  1352. %else
  1353.     punpcklbw        m6, m0         ; signed byte->word
  1354.     punpckhbw        m1, m0
  1355. %endif
  1356.     mova      m_limsign, m0
  1357. %if cpuflag(ssse3)
  1358.     mova             m7, [pb_27_63]
  1359. %ifndef m8
  1360.     mova       m_limres, m1
  1361. %endif
  1362. %ifdef m10
  1363.     SWAP              0, 10         ; don't lose lim_sign copy
  1364. %endif
  1365.     mova             m0, m7
  1366.     pmaddubsw        m7, m6
  1367.     SWAP              6, 7
  1368.     pmaddubsw        m0, m1
  1369.     SWAP              1, 0
  1370. %ifdef m10
  1371.     SWAP              0, 10
  1372. %else
  1373.     mova             m0, m_limsign
  1374. %endif
  1375. %else
  1376.     mova      m_maskres, m6         ; backup for later in filter
  1377.     mova       m_limres, m1
  1378.     pmullw          m6, [pw_27]
  1379.     pmullw          m1, [pw_27]
  1380.     paddw           m6, m7
  1381.     paddw           m1, m7
  1382. %endif
  1383.     psraw           m6, 7
  1384.     psraw           m1, 7
  1385.     packsswb        m6, m1          ; a0
  1386.     pxor            m1, m1
  1387.     psubb           m1, m6
  1388.     pand            m1, m0          ; -a0
  1389.     pandn           m0, m6          ; +a0
  1390. %if cpuflag(ssse3)
  1391.     mova            m6, [pb_18_63]  ; pipelining
  1392. %endif
  1393.     psubusb         m3, m1
  1394.     paddusb         m4, m1
  1395.     paddusb         m3, m0          ; p0+a0
  1396.     psubusb         m4, m0          ; q0-a0
  1397.  
  1398. %if cpuflag(ssse3)
  1399.     SWAP             6, 7
  1400. %ifdef m10
  1401.     SWAP             1, 10
  1402. %else
  1403.     mova            m1, m_limres
  1404. %endif
  1405.     mova            m0, m7
  1406.     pmaddubsw       m7, m6
  1407.     SWAP             6, 7
  1408.     pmaddubsw       m0, m1
  1409.     SWAP             1, 0
  1410. %ifdef m10
  1411.     SWAP             0, 10
  1412. %endif
  1413.     mova            m0, m_limsign
  1414. %else
  1415.     mova            m6, m_maskres
  1416.     mova            m1, m_limres
  1417.     pmullw          m6, [pw_18]
  1418.     pmullw          m1, [pw_18]
  1419.     paddw           m6, m7
  1420.     paddw           m1, m7
  1421. %endif
  1422.     mova            m0, m_limsign
  1423.     psraw           m6, 7
  1424.     psraw           m1, 7
  1425.     packsswb        m6, m1          ; a1
  1426.     pxor            m1, m1
  1427.     psubb           m1, m6
  1428.     pand            m1, m0          ; -a1
  1429.     pandn           m0, m6          ; +a1
  1430. %if cpuflag(ssse3)
  1431.     mova            m6, [pb_9_63]
  1432. %endif
  1433.     psubusb         m2, m1
  1434.     paddusb         m5, m1
  1435.     paddusb         m2, m0          ; p1+a1
  1436.     psubusb         m5, m0          ; q1-a1
  1437.  
  1438. %if cpuflag(ssse3)
  1439.     SWAP             6, 7
  1440. %ifdef m10
  1441.     SWAP             1, 10
  1442. %else
  1443.     mova            m1, m_limres
  1444. %endif
  1445.     mova            m0, m7
  1446.     pmaddubsw       m7, m6
  1447.     SWAP             6, 7
  1448.     pmaddubsw       m0, m1
  1449.     SWAP             1, 0
  1450. %else
  1451. %ifdef m8
  1452.     SWAP             6, 12
  1453.     SWAP             1, 8
  1454. %else
  1455.     mova            m6, m_maskres
  1456.     mova            m1, m_limres
  1457. %endif
  1458.     pmullw          m6, [pw_9]
  1459.     pmullw          m1, [pw_9]
  1460.     paddw           m6, m7
  1461.     paddw           m1, m7
  1462. %endif
  1463. %ifdef m9
  1464.     SWAP             7, 9
  1465. %else
  1466.     mova            m7, m_limsign
  1467. %endif
  1468.     psraw           m6, 7
  1469.     psraw           m1, 7
  1470.     packsswb        m6, m1          ; a1
  1471.     pxor            m0, m0
  1472.     psubb           m0, m6
  1473.     pand            m0, m7          ; -a1
  1474.     pandn           m7, m6          ; +a1
  1475. %ifdef m8
  1476.     SWAP             1, 13
  1477.     SWAP             6, 14
  1478. %else
  1479.     mova            m1, m_p2backup
  1480.     mova            m6, m_q2backup
  1481. %endif
  1482.     psubusb         m1, m0
  1483.     paddusb         m6, m0
  1484.     paddusb         m1, m7          ; p1+a1
  1485.     psubusb         m6, m7          ; q1-a1
  1486.  
  1487.     ; store
  1488. %ifidn %1, v
  1489.     movrow [dst2q+mstrideq*4], m1
  1490.     movrow [dst1q+mstrideq*2], m2
  1491.     movrow [dst1q+mstrideq  ], m3
  1492.     movrow     [dst1q], m4
  1493.     movrow     [dst2q], m5
  1494.     movrow [dst2q+ strideq  ], m6
  1495. %if mmsize == 16 && %2 == 8
  1496.     add           dst8q, mstrideq
  1497.     movhps [dst8q+mstrideq*2], m1
  1498.     movhps [dst8q+mstrideq  ], m2
  1499.     movhps     [dst8q], m3
  1500.     add          dst8q, strideq
  1501.     movhps     [dst8q], m4
  1502.     movhps [dst8q+ strideq  ], m5
  1503.     movhps [dst8q+ strideq*2], m6
  1504. %endif
  1505. %else ; h
  1506.     inc          dst1q
  1507.     inc          dst2q
  1508.  
  1509.     ; 4x8/16 transpose
  1510.     TRANSPOSE4x4B    1, 2, 3, 4, 0
  1511.     SBUTTERFLY      bw, 5, 6, 0
  1512.  
  1513. %if mmsize == 8 ; mmx/mmxext (h)
  1514.     WRITE_4x2D       1, 2, 3, 4, dst1q, dst2q, mstrideq, strideq
  1515.     add          dst1q, 4
  1516.     WRITE_2x4W      m5, m6, dst2q, dst1q, mstrideq, strideq
  1517. %else ; sse2 (h)
  1518.     lea          dst8q, [dst8q+mstrideq+1]
  1519.     WRITE_4x4D       1, 2, 3, 4, dst1q, dst2q, dst8q, mstrideq, strideq, %2
  1520.     lea          dst1q, [dst2q+mstrideq+4]
  1521.     lea          dst8q, [dst8q+mstrideq+4]
  1522. %if cpuflag(sse4)
  1523.     add          dst2q, 4
  1524. %endif
  1525.     WRITE_8W        m5, dst2q, dst1q,  mstrideq, strideq
  1526. %if cpuflag(sse4)
  1527.     lea          dst2q, [dst8q+ strideq  ]
  1528. %endif
  1529.     WRITE_8W        m6, dst2q, dst8q, mstrideq, strideq
  1530. %endif
  1531. %endif
  1532.  
  1533. %if mmsize == 8
  1534. %if %2 == 8 ; chroma
  1535. %ifidn %1, h
  1536.     sub          dst1q, 5
  1537. %endif
  1538.     cmp          dst1q, dst8q
  1539.     mov          dst1q, dst8q
  1540.     jnz .next8px
  1541. %else
  1542. %ifidn %1, h
  1543.     lea          dst1q, [dst1q+ strideq*8-5]
  1544. %else ; v
  1545.     add          dst1q, 8
  1546. %endif
  1547.     dec          cntrq
  1548.     jg .next8px
  1549. %endif
  1550.     REP_RET
  1551. %else ; mmsize == 16
  1552.     RET
  1553. %endif
  1554. %endmacro
  1555.  
  1556. %if ARCH_X86_32
  1557. INIT_MMX mmx
  1558. MBEDGE_LOOPFILTER v, 16
  1559. MBEDGE_LOOPFILTER h, 16
  1560. MBEDGE_LOOPFILTER v,  8
  1561. MBEDGE_LOOPFILTER h,  8
  1562.  
  1563. INIT_MMX mmxext
  1564. MBEDGE_LOOPFILTER v, 16
  1565. MBEDGE_LOOPFILTER h, 16
  1566. MBEDGE_LOOPFILTER v,  8
  1567. MBEDGE_LOOPFILTER h,  8
  1568. %endif
  1569.  
  1570. INIT_XMM sse2
  1571. MBEDGE_LOOPFILTER v, 16
  1572. MBEDGE_LOOPFILTER h, 16
  1573. MBEDGE_LOOPFILTER v,  8
  1574. MBEDGE_LOOPFILTER h,  8
  1575.  
  1576. INIT_XMM ssse3
  1577. MBEDGE_LOOPFILTER v, 16
  1578. MBEDGE_LOOPFILTER h, 16
  1579. MBEDGE_LOOPFILTER v,  8
  1580. MBEDGE_LOOPFILTER h,  8
  1581.  
  1582. INIT_XMM sse4
  1583. MBEDGE_LOOPFILTER h, 16
  1584. MBEDGE_LOOPFILTER h,  8
  1585.