Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. ;*****************************************************************************
  2. ;* x86-optimized functions for removegrain filter
  3. ;*
  4. ;* Copyright (C) 2015 James Darnley
  5. ;*
  6. ;* This file is part of FFmpeg.
  7. ;*
  8. ;* FFmpeg is free software; you can redistribute it and/or modify
  9. ;* it under the terms of the GNU General Public License as published by
  10. ;* the Free Software Foundation; either version 2 of the License, or
  11. ;* (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
  16. ;* GNU General Public License for more details.
  17. ;*
  18. ;* You should have received a copy of the GNU General Public License along
  19. ;* with FFmpeg; if not, write to the Free Software Foundation, Inc.,
  20. ;* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. ;*****************************************************************************
  22.  
  23. ; column: -1  0 +1
  24. ; row -1: a1 a2 a3
  25. ; row  0: a4  c a5
  26. ; row +1: a6 a7 a8
  27.  
  28. %include "libavutil/x86/x86util.asm"
  29.  
  30. SECTION_RODATA 32
  31.  
  32. pw_4:    times 16 dw 4
  33. pw_8:    times 16 dw 8
  34. pw_div9: times 16 dw ((1<<16)+4)/9
  35.  
  36. SECTION .text
  37.  
  38. ;*** Preprocessor helpers
  39.  
  40. %define a1 srcq+stride_n-1
  41. %define a2 srcq+stride_n
  42. %define a3 srcq+stride_n+1
  43. %define a4 srcq-1
  44. %define c  srcq
  45. %define a5 srcq+1
  46. %define a6 srcq+stride_p-1
  47. %define a7 srcq+stride_p
  48. %define a8 srcq+stride_p+1
  49.  
  50. ; %1 dest simd register
  51. ; %2 source memory location
  52. ; %3 zero location (simd register/memory)
  53. %macro LOAD 3
  54.     movh %1, %2
  55.     punpcklbw %1, %3
  56. %endmacro
  57.  
  58. %macro LOAD_SQUARE 0
  59.     movu m1, [a1]
  60.     movu m2, [a2]
  61.     movu m3, [a3]
  62.     movu m4, [a4]
  63.     movu m0, [c]
  64.     movu m5, [a5]
  65.     movu m6, [a6]
  66.     movu m7, [a7]
  67.     movu m8, [a8]
  68. %endmacro
  69.  
  70. ; %1 zero location (simd register/memory)
  71. %macro LOAD_SQUARE_16 1
  72.     LOAD m1, [a1], %1
  73.     LOAD m2, [a2], %1
  74.     LOAD m3, [a3], %1
  75.     LOAD m4, [a4], %1
  76.     LOAD m0, [c], %1
  77.     LOAD m5, [a5], %1
  78.     LOAD m6, [a6], %1
  79.     LOAD m7, [a7], %1
  80.     LOAD m8, [a8], %1
  81. %endmacro
  82.  
  83. ; %1 data type
  84. ; %2 simd register to hold maximums
  85. ; %3 simd register to hold minimums
  86. ; %4 temp location (simd register/memory)
  87. %macro SORT_PAIR 4
  88.     mova   %4, %2
  89.     pmin%1 %2, %3
  90.     pmax%1 %3, %4
  91. %endmacro
  92.  
  93. %macro SORT_AXIS 0
  94.     SORT_PAIR ub, m1, m8, m9
  95.     SORT_PAIR ub, m2, m7, m10
  96.     SORT_PAIR ub, m3, m6, m11
  97.     SORT_PAIR ub, m4, m5, m12
  98. %endmacro
  99.  
  100.  
  101. %macro SORT_AXIS_16 0
  102.     SORT_PAIR sw, m1, m8, m9
  103.     SORT_PAIR sw, m2, m7, m10
  104.     SORT_PAIR sw, m3, m6, m11
  105.     SORT_PAIR sw, m4, m5, m12
  106. %endmacro
  107.  
  108. ; The loop doesn't need to do all the iterations.  It could stop when the right
  109. ; pixels are in the right registers.
  110. %macro SORT_SQUARE 0
  111.     %assign k 7
  112.     %rep 7
  113.         %assign i 1
  114.         %assign j 2
  115.         %rep k
  116.             SORT_PAIR ub, m %+ i , m %+ j , m9
  117.             %assign i i+1
  118.             %assign j j+1
  119.         %endrep
  120.         %assign k k-1
  121.     %endrep
  122. %endmacro
  123.  
  124. ; %1 dest simd register
  125. ; %2 source (simd register/memory)
  126. ; %3 temp simd register
  127. %macro ABS_DIFF 3
  128.     mova %3, %2
  129.     psubusb %3, %1
  130.     psubusb %1, %2
  131.     por %1, %3
  132. %endmacro
  133.  
  134. ; %1 dest simd register
  135. ; %2 source (simd register/memory)
  136. ; %3 temp simd register
  137. %macro ABS_DIFF_W 3
  138.     mova %3, %2
  139.     psubusw %3, %1
  140.     psubusw %1, %2
  141.     por %1, %3
  142. %endmacro
  143.  
  144. ; %1 simd register that holds the "false" values and will hold the result
  145. ; %2 simd register that holds the "true" values
  146. ; %3 location (simd register/memory) that hold the mask
  147. %macro BLEND 3
  148. %if cpuflag(avx2)
  149.     vpblendvb %1, %1, %2, %3
  150. %else
  151.     pand      %2, %3
  152.     pandn     %3, %1
  153.     por       %3, %2
  154.     SWAP      %1, %3
  155. %endif
  156. %endmacro
  157.  
  158. ; Functions
  159.  
  160. INIT_XMM sse2
  161. cglobal rg_fl_mode_1, 4, 5, 3, 0, dst, src, stride, pixels
  162.     mov r4q, strideq
  163.     neg r4q
  164.     %define stride_p strideq
  165.     %define stride_n r4q
  166.  
  167.     .loop:
  168.         movu m0, [a1]
  169.         mova m1, m0
  170.  
  171.         movu m2, [a2]
  172.         pmaxub m0, m2
  173.         pminub m1, m2
  174.  
  175.         movu m2, [a3]
  176.         pmaxub m0, m2
  177.         pminub m1, m2
  178.  
  179.         movu m2, [a4]
  180.         pmaxub m0, m2
  181.         pminub m1, m2
  182.  
  183.         movu m2, [a5]
  184.         pmaxub m0, m2
  185.         pminub m1, m2
  186.  
  187.         movu m2, [a6]
  188.         pmaxub m0, m2
  189.         pminub m1, m2
  190.  
  191.         movu m2, [a7]
  192.         pmaxub m0, m2
  193.         pminub m1, m2
  194.  
  195.         movu m2, [a8]
  196.         pmaxub m0, m2
  197.         pminub m1, m2
  198.  
  199.         movu m2, [c]
  200.         pminub m2, m0
  201.         pmaxub m2, m1
  202.  
  203.         movu [dstq], m2
  204.         add srcq, mmsize
  205.         add dstq, mmsize
  206.         sub pixelsd, mmsize
  207.     jg .loop
  208. RET
  209.  
  210. %if ARCH_X86_64
  211. cglobal rg_fl_mode_2, 4, 5, 10, 0, dst, src, stride, pixels
  212.     mov r4q, strideq
  213.     neg r4q
  214.     %define stride_p strideq
  215.     %define stride_n r4q
  216.  
  217.     .loop:
  218.         LOAD_SQUARE
  219.         SORT_SQUARE
  220.  
  221.         CLIPUB m0, m2, m7
  222.  
  223.         movu [dstq], m0
  224.         add srcq, mmsize
  225.         add dstq, mmsize
  226.         sub pixelsd, mmsize
  227.     jg .loop
  228. RET
  229.  
  230. cglobal rg_fl_mode_3, 4, 5, 10, 0, dst, src, stride, pixels
  231.     mov r4q, strideq
  232.     neg r4q
  233.     %define stride_p strideq
  234.     %define stride_n r4q
  235.  
  236.     .loop:
  237.         LOAD_SQUARE
  238.         SORT_SQUARE
  239.  
  240.         CLIPUB m0, m3, m6
  241.  
  242.         movu [dstq], m0
  243.         add srcq, mmsize
  244.         add dstq, mmsize
  245.         sub pixelsd, mmsize
  246.     jg .loop
  247. RET
  248.  
  249. cglobal rg_fl_mode_4, 4, 5, 10, 0, dst, src, stride, pixels
  250.     mov r4q, strideq
  251.     neg r4q
  252.     %define stride_p strideq
  253.     %define stride_n r4q
  254.  
  255.     .loop:
  256.         LOAD_SQUARE
  257.         SORT_SQUARE
  258.  
  259.         CLIPUB m0, m4, m5
  260.  
  261.         movu [dstq], m0
  262.         add srcq, mmsize
  263.         add dstq, mmsize
  264.         sub pixelsd, mmsize
  265.     jg .loop
  266. RET
  267.  
  268. cglobal rg_fl_mode_5, 4, 5, 13, 0, dst, src, stride, pixels
  269.     mov r4q, strideq
  270.     neg r4q
  271.     %define stride_p strideq
  272.     %define stride_n r4q
  273.  
  274.     .loop:
  275.         LOAD_SQUARE
  276.         SORT_AXIS
  277.  
  278.         mova m9, m0
  279.         mova m10, m0
  280.         mova m11, m0
  281.         mova m12, m0
  282.  
  283.         CLIPUB m9, m1, m8
  284.         CLIPUB m10, m2, m7
  285.         CLIPUB m11, m3, m6
  286.         CLIPUB m12, m4, m5
  287.  
  288.         mova m8, m9  ; clip1
  289.         mova m7, m10 ; clip2
  290.         mova m6, m11 ; clip3
  291.         mova m5, m12 ; clip4
  292.  
  293.         ABS_DIFF m9, m0, m1  ; c1
  294.         ABS_DIFF m10, m0, m2 ; c2
  295.         ABS_DIFF m11, m0, m3 ; c3
  296.         ABS_DIFF m12, m0, m4 ; c4
  297.  
  298.         pminub m9, m10
  299.         pminub m9, m11
  300.         pminub m9, m12 ; mindiff
  301.  
  302.         pcmpeqb m10, m9
  303.         pcmpeqb m11, m9
  304.         pcmpeqb m12, m9
  305.  
  306.         ; Notice the order here: c1, c3, c2, c4
  307.         BLEND m8, m6, m11
  308.         BLEND m8, m7, m10
  309.         BLEND m8, m5, m12
  310.  
  311.         movu [dstq], m8
  312.         add srcq, mmsize
  313.         add dstq, mmsize
  314.         sub pixelsd, mmsize
  315.     jg .loop
  316. RET
  317.  
  318. cglobal rg_fl_mode_6, 4, 5, 16, 0, dst, src, stride, pixels
  319.     mov r4q, strideq
  320.     neg r4q
  321.     %define stride_p strideq
  322.     %define stride_n r4q
  323.  
  324.     ; Some register saving suggestions: the zero can be somewhere other than a
  325.     ; register, the center pixels could be on the stack.
  326.  
  327.     pxor m15, m15
  328.     .loop:
  329.         LOAD_SQUARE_16 m15
  330.         SORT_AXIS_16
  331.  
  332.         mova m9, m0
  333.         mova m10, m0
  334.         mova m11, m0
  335.         mova m12, m0
  336.         CLIPW m9, m1, m8  ; clip1
  337.         CLIPW m10, m2, m7 ; clip2
  338.         CLIPW m11, m3, m6 ; clip3
  339.         CLIPW m12, m4, m5 ; clip4
  340.  
  341.         psubw m8, m1 ; d1
  342.         psubw m7, m2 ; d2
  343.         psubw m6, m3 ; d3
  344.         psubw m5, m4 ; d4
  345.  
  346.         mova m1, m9
  347.         mova m2, m10
  348.         mova m3, m11
  349.         mova m4, m12
  350.         ABS_DIFF_W m1, m0, m13
  351.         ABS_DIFF_W m2, m0, m14
  352.         ABS_DIFF_W m3, m0, m13
  353.         ABS_DIFF_W m4, m0, m14
  354.         psllw m1, 1
  355.         psllw m2, 1
  356.         psllw m3, 1
  357.         psllw m4, 1
  358.         paddw m1, m8 ; c1
  359.         paddw m2, m7 ; c2
  360.         paddw m3, m6 ; c3
  361.         paddw m4, m5 ; c4
  362.         ; As the differences (d1..d4) can only be positive, there is no need to
  363.         ; clip to zero.  Also, the maximum positive value is less than 768.
  364.  
  365.         pminsw m1, m2
  366.         pminsw m1, m3
  367.         pminsw m1, m4
  368.  
  369.         pcmpeqw m2, m1
  370.         pcmpeqw m3, m1
  371.         pcmpeqw m4, m1
  372.  
  373.         BLEND m9, m11, m3
  374.         BLEND m9, m10, m2
  375.         BLEND m9, m12, m4
  376.         packuswb m9, m9
  377.  
  378.         movh [dstq], m9
  379.         add srcq, mmsize/2
  380.         add dstq, mmsize/2
  381.         sub pixelsd, mmsize/2
  382.     jg .loop
  383. RET
  384.  
  385. ; This is just copy-pasted straight from mode 6 with the left shifts removed.
  386. cglobal rg_fl_mode_7, 4, 5, 16, 0, dst, src, stride, pixels
  387.     mov r4q, strideq
  388.     neg r4q
  389.     %define stride_p strideq
  390.     %define stride_n r4q
  391.  
  392.     ; Can this be done without unpacking?
  393.  
  394.     pxor m15, m15
  395.     .loop:
  396.         LOAD_SQUARE_16 m15
  397.         SORT_AXIS_16
  398.  
  399.         mova m9, m0
  400.         mova m10, m0
  401.         mova m11, m0
  402.         mova m12, m0
  403.         CLIPW m9, m1, m8  ; clip1
  404.         CLIPW m10, m2, m7 ; clip2
  405.         CLIPW m11, m3, m6 ; clip3
  406.         CLIPW m12, m4, m5 ; clip4
  407.  
  408.         psubw m8, m1 ; d1
  409.         psubw m7, m2 ; d2
  410.         psubw m6, m3 ; d3
  411.         psubw m5, m4 ; d4
  412.  
  413.         mova m1, m9
  414.         mova m2, m10
  415.         mova m3, m11
  416.         mova m4, m12
  417.         ABS_DIFF_W m1, m0, m13
  418.         ABS_DIFF_W m2, m0, m14
  419.         ABS_DIFF_W m3, m0, m13
  420.         ABS_DIFF_W m4, m0, m14
  421.         paddw m1, m8 ; c1
  422.         paddw m2, m7 ; c2
  423.         paddw m3, m6 ; c3
  424.         paddw m4, m5 ; c4
  425.  
  426.         pminsw m1, m2
  427.         pminsw m1, m3
  428.         pminsw m1, m4
  429.  
  430.         pcmpeqw m2, m1
  431.         pcmpeqw m3, m1
  432.         pcmpeqw m4, m1
  433.  
  434.         BLEND m9, m11, m3
  435.         BLEND m9, m10, m2
  436.         BLEND m9, m12, m4
  437.         packuswb m9, m9
  438.  
  439.         movh [dstq], m9
  440.         add srcq, mmsize/2
  441.         add dstq, mmsize/2
  442.         sub pixelsd, mmsize/2
  443.     jg .loop
  444. RET
  445.  
  446. ; This is just copy-pasted straight from mode 6 with a few changes.
  447. cglobal rg_fl_mode_8, 4, 5, 16, 0, dst, src, stride, pixels
  448.     mov r4q, strideq
  449.     neg r4q
  450.     %define stride_p strideq
  451.     %define stride_n r4q
  452.  
  453.     pxor m15, m15
  454.     .loop:
  455.         LOAD_SQUARE_16 m15
  456.         SORT_AXIS_16
  457.  
  458.         mova m9, m0
  459.         mova m10, m0
  460.         mova m11, m0
  461.         mova m12, m0
  462.         CLIPW m9, m1, m8  ; clip1
  463.         CLIPW m10, m2, m7 ; clip2
  464.         CLIPW m11, m3, m6 ; clip3
  465.         CLIPW m12, m4, m5 ; clip4
  466.  
  467.         psubw m8, m1 ; d1
  468.         psubw m7, m2 ; d2
  469.         psubw m6, m3 ; d3
  470.         psubw m5, m4 ; d4
  471.         psllw m8, 1
  472.         psllw m7, 1
  473.         psllw m6, 1
  474.         psllw m5, 1
  475.  
  476.         mova m1, m9
  477.         mova m2, m10
  478.         mova m3, m11
  479.         mova m4, m12
  480.         ABS_DIFF_W m1, m0, m13
  481.         ABS_DIFF_W m2, m0, m14
  482.         ABS_DIFF_W m3, m0, m13
  483.         ABS_DIFF_W m4, m0, m14
  484.         paddw m1, m8 ; c1
  485.         paddw m2, m7 ; c1
  486.         paddw m3, m6 ; c1
  487.         paddw m4, m5 ; c1
  488.         ; As the differences (d1..d4) can only be positive, there is no need to
  489.         ; clip to zero.  Also, the maximum positive value is less than 768.
  490.  
  491.         pminsw m1, m2
  492.         pminsw m1, m3
  493.         pminsw m1, m4
  494.  
  495.         pcmpeqw m2, m1
  496.         pcmpeqw m3, m1
  497.         pcmpeqw m4, m1
  498.  
  499.         BLEND m9, m11, m3
  500.         BLEND m9, m10, m2
  501.         BLEND m9, m12, m4
  502.         packuswb m9, m9
  503.  
  504.         movh [dstq], m9
  505.         add srcq, mmsize/2
  506.         add dstq, mmsize/2
  507.         sub pixelsd, mmsize/2
  508.     jg .loop
  509. RET
  510.  
  511. cglobal rg_fl_mode_9, 4, 5, 13, 0, dst, src, stride, pixels
  512.     mov r4q, strideq
  513.     neg r4q
  514.     %define stride_p strideq
  515.     %define stride_n r4q
  516.  
  517.     .loop:
  518.         LOAD_SQUARE
  519.         SORT_AXIS
  520.  
  521.         mova m9, m0
  522.         mova m10, m0
  523.         mova m11, m0
  524.         mova m12, m0
  525.         CLIPUB m9, m1, m8  ; clip1
  526.         CLIPUB m10, m2, m7 ; clip2
  527.         CLIPUB m11, m3, m6 ; clip3
  528.         CLIPUB m12, m4, m5 ; clip4
  529.  
  530.         psubb m8, m1 ; d1
  531.         psubb m7, m2 ; d2
  532.         psubb m6, m3 ; d3
  533.         psubb m5, m4 ; d4
  534.  
  535.         pminub m8, m7
  536.         pminub m8, m6
  537.         pminub m8, m5
  538.  
  539.         pcmpeqb m7, m8
  540.         pcmpeqb m6, m8
  541.         pcmpeqb m5, m8
  542.  
  543.         BLEND m9, m11, m6
  544.         BLEND m9, m10, m7
  545.         BLEND m9, m12, m5
  546.  
  547.         movu [dstq], m9
  548.         add srcq, mmsize
  549.         add dstq, mmsize
  550.         sub pixelsd, mmsize
  551.     jg .loop
  552. RET
  553. %endif
  554.  
  555. cglobal rg_fl_mode_10, 4, 5, 8, 0, dst, src, stride, pixels
  556.     mov r4q, strideq
  557.     neg r4q
  558.     %define stride_p strideq
  559.     %define stride_n r4q
  560.  
  561.     .loop:
  562.         movu m0, [c]
  563.  
  564.         movu m1, [a4]
  565.         mova m2, m1
  566.         ABS_DIFF m1, m0, m7
  567.  
  568.         movu m3, [a5]       ; load pixel
  569.         mova m4, m3
  570.         ABS_DIFF m4, m0, m7 ; absolute difference from center
  571.         pminub m1, m4       ; mindiff
  572.         pcmpeqb m4, m1      ; if (difference == mindiff)
  573.         BLEND m2, m3, m4    ;     return pixel
  574.  
  575.         movu m5, [a1]
  576.         mova m6, m5
  577.         ABS_DIFF m6, m0, m7
  578.         pminub m1, m6
  579.         pcmpeqb m6, m1
  580.         BLEND m2, m5, m6
  581.  
  582.         movu m3, [a3]
  583.         mova m4, m3
  584.         ABS_DIFF m4, m0, m7
  585.         pminub m1, m4
  586.         pcmpeqb m4, m1
  587.         BLEND m2, m3, m4
  588.  
  589.         movu m5, [a2]
  590.         mova m6, m5
  591.         ABS_DIFF m6, m0, m7
  592.         pminub m1, m6
  593.         pcmpeqb m6, m1
  594.         BLEND m2, m5, m6
  595.  
  596.         movu m3, [a6]
  597.         mova m4, m3
  598.         ABS_DIFF m4, m0, m7
  599.         pminub m1, m4
  600.         pcmpeqb m4, m1
  601.         BLEND m2, m3, m4
  602.  
  603.         movu m5, [a8]
  604.         mova m6, m5
  605.         ABS_DIFF m6, m0, m7
  606.         pminub m1, m6
  607.         pcmpeqb m6, m1
  608.         BLEND m2, m5, m6
  609.  
  610.         movu m3, [a7]
  611.         mova m4, m3
  612.         ABS_DIFF m4, m0, m7
  613.         pminub m1, m4
  614.         pcmpeqb m4, m1
  615.         BLEND m2, m3, m4
  616.  
  617.         movu [dstq], m2
  618.         add srcq, mmsize
  619.         add dstq, mmsize
  620.         sub pixelsd, mmsize
  621.     jg .loop
  622. RET
  623.  
  624. cglobal rg_fl_mode_11_12, 4, 5, 7, 0, dst, src, stride, pixels
  625.     mov r4q, strideq
  626.     neg r4q
  627.     %define stride_p strideq
  628.     %define stride_n r4q
  629.  
  630.     pxor m0, m0
  631.     .loop:
  632.         LOAD m1, [c], m0
  633.         LOAD m2, [a2], m0
  634.         LOAD m3, [a4], m0
  635.         LOAD m4, [a5], m0
  636.         LOAD m5, [a7], m0
  637.  
  638.         psllw m1, 2
  639.         paddw m2, m3
  640.         paddw m4, m5
  641.         paddw m2, m4
  642.         psllw m2, 1
  643.  
  644.         LOAD m3, [a1], m0
  645.         LOAD m4, [a3], m0
  646.         LOAD m5, [a6], m0
  647.         LOAD m6, [a8], m0
  648.         paddw m1, m2
  649.         paddw m3, m4
  650.         paddw m5, m6
  651.         paddw m1, m3
  652.         paddw m1, m5
  653.  
  654.         paddw m1, [pw_8]
  655.         psraw m1, 4
  656.  
  657.         packuswb m1, m1
  658.  
  659.         movh [dstq], m1
  660.         add srcq, mmsize/2
  661.         add dstq, mmsize/2
  662.         sub pixelsd, mmsize/2
  663.     jg .loop
  664. RET
  665.  
  666. cglobal rg_fl_mode_13_14, 4, 5, 8, 0, dst, src, stride, pixels
  667.     mov r4q, strideq
  668.     neg r4q
  669.     %define stride_p strideq
  670.     %define stride_n r4q
  671.  
  672.     .loop:
  673.         movu m1, [a1]
  674.         movu m2, [a8]
  675.         mova m0, m1
  676.         pavgb m1, m2
  677.         ABS_DIFF m0, m2, m6
  678.  
  679.         movu m3, [a3]
  680.         movu m4, [a6]
  681.         mova m5, m3
  682.         pavgb m3, m4
  683.         ABS_DIFF m5, m4, m7
  684.         pminub m0, m5
  685.         pcmpeqb m5, m0
  686.         BLEND m1, m3, m5
  687.  
  688.         movu m2, [a2]
  689.         movu m3, [a7]
  690.         mova m4, m2
  691.         pavgb m2, m3
  692.         ABS_DIFF m4, m3, m6
  693.         pminub m0, m4
  694.         pcmpeqb m4, m0
  695.         BLEND m1, m2, m4
  696.  
  697.         movu [dstq], m1
  698.         add srcq, mmsize
  699.         add dstq, mmsize
  700.         sub pixelsd, mmsize
  701.     jg .loop
  702. RET
  703.  
  704. %if ARCH_X86_64
  705. cglobal rg_fl_mode_15_16, 4, 5, 16, 0, dst, src, stride, pixels
  706.     mov r4q, strideq
  707.     neg r4q
  708.     %define stride_p strideq
  709.     %define stride_n r4q
  710.  
  711.     pxor m15, m15
  712.     .loop:
  713.         LOAD_SQUARE_16 m15
  714.  
  715.         mova m9, m1
  716.         mova m10, m2
  717.         mova m11, m3
  718.         ABS_DIFF_W m9, m8, m12
  719.         ABS_DIFF_W m10, m7, m13
  720.         ABS_DIFF_W m11, m6, m14
  721.         pminsw m9, m10
  722.         pminsw m9, m11
  723.         pcmpeqw m10, m9
  724.         pcmpeqw m11, m9
  725.  
  726.         mova m12, m2
  727.         mova m13, m1
  728.         mova m14, m6
  729.         paddw m12, m7
  730.         psllw m12, 1
  731.         paddw m13, m3
  732.         paddw m14, m8
  733.         paddw m12, [pw_4]
  734.         paddw m13, m14
  735.         paddw m12, m13
  736.         psrlw m12, 3
  737.  
  738.         SORT_PAIR ub, m1, m8, m0
  739.         SORT_PAIR ub, m2, m7, m9
  740.         SORT_PAIR ub, m3, m6, m14
  741.         mova m4, m12
  742.         mova m5, m12
  743.         CLIPW m4, m1, m8
  744.         CLIPW m5, m2, m7
  745.         CLIPW m12, m3, m6
  746.  
  747.         BLEND m4, m12, m11
  748.         BLEND m4,  m5, m10
  749.         packuswb m4, m4
  750.  
  751.         movh [dstq], m4
  752.         add srcq, mmsize/2
  753.         add dstq, mmsize/2
  754.         sub pixelsd, mmsize/2
  755.     jg .loop
  756. RET
  757.  
  758. cglobal rg_fl_mode_17, 4, 5, 9, 0, dst, src, stride, pixels
  759.     mov r4q, strideq
  760.     neg r4q
  761.     %define stride_p strideq
  762.     %define stride_n r4q
  763.  
  764.     .loop:
  765.         LOAD_SQUARE
  766.         SORT_AXIS
  767.  
  768.         pmaxub m1, m2
  769.         pmaxub m3, m4
  770.  
  771.         pminub m8, m7
  772.         pminub m5, m6
  773.  
  774.         pmaxub m1, m3
  775.         pminub m8, m5
  776.  
  777.         mova m2, m1
  778.         pminub m1, m8
  779.         pmaxub m8, m2
  780.  
  781.         CLIPUB m0, m1, m8
  782.  
  783.         movu [dstq], m0
  784.         add srcq, mmsize
  785.         add dstq, mmsize
  786.         sub pixelsd, mmsize
  787.     jg .loop
  788. RET
  789.  
  790. cglobal rg_fl_mode_18, 4, 5, 16, 0, dst, src, stride, pixels
  791.     mov r4q, strideq
  792.     neg r4q
  793.     %define stride_p strideq
  794.     %define stride_n r4q
  795.  
  796.     .loop:
  797.         LOAD_SQUARE
  798.  
  799.         mova m9, m1
  800.         mova m10, m8
  801.         ABS_DIFF m9, m0, m11
  802.         ABS_DIFF m10, m0, m12
  803.         pmaxub m9, m10 ; m9 = d1
  804.  
  805.         mova m10, m2
  806.         mova m11, m7
  807.         ABS_DIFF m10, m0, m12
  808.         ABS_DIFF m11, m0, m13
  809.         pmaxub m10, m11 ; m10 = d2
  810.  
  811.         mova m11, m3
  812.         mova m12, m6
  813.         ABS_DIFF m11, m0, m13
  814.         ABS_DIFF m12, m0, m14
  815.         pmaxub m11, m12 ; m11 = d3
  816.  
  817.         mova m12, m4
  818.         mova m13, m5
  819.         ABS_DIFF m12, m0, m14
  820.         ABS_DIFF m13, m0, m15
  821.         pmaxub m12, m13 ; m12 = d4
  822.  
  823.         mova m13, m9
  824.         pminub m13, m10
  825.         pminub m13, m11
  826.         pminub m13, m12 ; m13 = mindiff
  827.  
  828.         pcmpeqb m10, m13
  829.         pcmpeqb m11, m13
  830.         pcmpeqb m12, m13
  831.  
  832.         mova m14, m1
  833.         pminub m1, m8
  834.         pmaxub m8, m14
  835.  
  836.         mova m13, m0
  837.         mova m14, m1
  838.         pminub m1, m8
  839.         pmaxub m8, m14
  840.         CLIPUB m13, m1, m8 ; m13 = ret...d1
  841.  
  842.         mova m14, m0
  843.         mova m15, m3
  844.         pminub m3, m6
  845.         pmaxub m6, m15
  846.         CLIPUB m14, m3, m6
  847.         pand m14, m11
  848.         pandn m11, m13
  849.         por m14, m11 ; m14 = ret...d3
  850.  
  851.         mova m15, m0
  852.         mova m1, m2
  853.         pminub m2, m7
  854.         pmaxub m7, m1
  855.         CLIPUB m15, m2, m7
  856.         pand m15, m10
  857.         pandn m10, m14
  858.         por m15, m10 ; m15 = ret...d2
  859.  
  860.         mova m1, m0
  861.         mova m2, m4
  862.         pminub m4, m5
  863.         pmaxub m5, m2
  864.         CLIPUB m1, m4, m5
  865.         pand m1, m12
  866.         pandn m12, m15
  867.         por m1, m12 ; m15 = ret...d4
  868.  
  869.         movu [dstq], m1
  870.         add srcq, mmsize
  871.         add dstq, mmsize
  872.         sub pixelsd, mmsize
  873.     jg .loop
  874. RET
  875. %endif
  876.  
  877. cglobal rg_fl_mode_19, 4, 5, 7, 0, dst, src, stride, pixels
  878.     mov r4q, strideq
  879.     neg r4q
  880.     %define stride_p strideq
  881.     %define stride_n r4q
  882.  
  883.     pxor m0, m0
  884.     .loop:
  885.         LOAD m1, [a1], m0
  886.         LOAD m2, [a2], m0
  887.         paddw m1, m2
  888.  
  889.         LOAD m3, [a3], m0
  890.         LOAD m4, [a4], m0
  891.         paddw m3, m4
  892.  
  893.         LOAD m5, [a5], m0
  894.         LOAD m6, [a6], m0
  895.         paddw m5, m6
  896.  
  897.         LOAD m2, [a7], m0
  898.         LOAD m4, [a8], m0
  899.         paddw m2, m4
  900.  
  901.         paddw m1, m3
  902.         paddw m2, m5
  903.         paddw m1, m2
  904.  
  905.         paddw m1, [pw_4]
  906.         psraw m1, 3
  907.  
  908.         packuswb m1, m1
  909.  
  910.         movh [dstq], m1
  911.         add srcq, mmsize/2
  912.         add dstq, mmsize/2
  913.         sub pixelsd, mmsize/2
  914.     jg .loop
  915. RET
  916.  
  917. cglobal rg_fl_mode_20, 4, 5, 7, 0, dst, src, stride, pixels
  918.     mov r4q, strideq
  919.     neg r4q
  920.     %define stride_p strideq
  921.     %define stride_n r4q
  922.  
  923.     pxor m0, m0
  924.     .loop:
  925.         LOAD m1, [a1], m0
  926.         LOAD m2, [a2], m0
  927.         paddw m1, m2
  928.  
  929.         LOAD m3, [a3], m0
  930.         LOAD m4, [a4], m0
  931.         paddw m3, m4
  932.  
  933.         LOAD m5, [a5], m0
  934.         LOAD m6, [a6], m0
  935.         paddw m5, m6
  936.  
  937.         LOAD m2, [a7], m0
  938.         LOAD m4, [a8], m0
  939.         paddw m2, m4
  940.  
  941.         LOAD m6, [c], m0
  942.         paddw m1, m3
  943.         paddw m2, m5
  944.         paddw m6, [pw_4]
  945.  
  946.         paddw m1, m2
  947.         paddw m1, m6
  948.  
  949.         pmulhuw m1, [pw_div9]
  950.  
  951.         packuswb m1, m1
  952.  
  953.         movh [dstq], m1
  954.         add srcq, mmsize/2
  955.         add dstq, mmsize/2
  956.         sub pixelsd, mmsize/2
  957.     jg .loop
  958. RET
  959.  
  960. cglobal rg_fl_mode_21, 4, 5, 8, 0, dst, src, stride, pixels
  961.     mov r4q, strideq
  962.     neg r4q
  963.     %define stride_p strideq
  964.     %define stride_n r4q
  965.  
  966.     pxor m0, m0
  967.     .loop:
  968.         movu m1, [a1]
  969.         movu m2, [a8]
  970.         pavgb m7, m1, m2
  971.         punpckhbw m3, m1, m0
  972.         punpcklbw m1, m0
  973.         punpckhbw m4, m2, m0
  974.         punpcklbw m2, m0
  975.         paddw m3, m4
  976.         paddw m1, m2
  977.         psrlw m3, 1
  978.         psrlw m1, 1
  979.         packuswb m1, m3
  980.  
  981.         movu m2, [a2]
  982.         movu m3, [a7]
  983.         pavgb m6, m2, m3
  984.         punpckhbw m4, m2, m0
  985.         punpcklbw m2, m0
  986.         punpckhbw m5, m3, m0
  987.         punpcklbw m3, m0
  988.         paddw m4, m5
  989.         paddw m2, m3
  990.         psrlw m4, 1
  991.         psrlw m2, 1
  992.         packuswb m2, m4
  993.  
  994.         pminub m1, m2
  995.         pmaxub m7, m6
  996.  
  997.         movu m2, [a3]
  998.         movu m3, [a6]
  999.         pavgb m6, m2, m3
  1000.         punpckhbw m4, m2, m0
  1001.         punpcklbw m2, m0
  1002.         punpckhbw m5, m3, m0
  1003.         punpcklbw m3, m0
  1004.         paddw m4, m5
  1005.         paddw m2, m3
  1006.         psrlw m4, 1
  1007.         psrlw m2, 1
  1008.         packuswb m2, m4
  1009.  
  1010.         pminub m1, m2
  1011.         pmaxub m7, m6
  1012.  
  1013.         movu m2, [a4]
  1014.         movu m3, [a5]
  1015.         pavgb m6, m2, m3
  1016.         punpckhbw m4, m2, m0
  1017.         punpcklbw m2, m0
  1018.         punpckhbw m5, m3, m0
  1019.         punpcklbw m3, m0
  1020.         paddw m4, m5
  1021.         paddw m2, m3
  1022.         psrlw m4, 1
  1023.         psrlw m2, 1
  1024.         packuswb m2, m4
  1025.  
  1026.         pminub m1, m2
  1027.         pmaxub m7, m6
  1028.  
  1029.         movu m3, [c]
  1030.         CLIPUB m3, m1, m7
  1031.  
  1032.         movu [dstq], m3
  1033.         add srcq, mmsize
  1034.         add dstq, mmsize
  1035.         sub pixelsd, mmsize
  1036.     jg .loop
  1037. RET
  1038.  
  1039. cglobal rg_fl_mode_22, 4, 5, 8, 0, dst, src, stride, pixels
  1040.     mov r4q, strideq
  1041.     neg r4q
  1042.     %define stride_p strideq
  1043.     %define stride_n r4q
  1044.  
  1045.     .loop:
  1046.         movu m0, [a1]
  1047.         movu m1, [a8]
  1048.         pavgb m0, m1
  1049.         movu m2, [a2]
  1050.         movu m3, [a7]
  1051.         pavgb m2, m3
  1052.         movu m4, [a3]
  1053.         movu m5, [a6]
  1054.         pavgb m4, m5
  1055.         movu m6, [a4]
  1056.         movu m7, [a5]
  1057.         pavgb m6, m7
  1058.  
  1059.         mova m1, m0
  1060.         mova m3, m2
  1061.         mova m5, m4
  1062.         mova m7, m6
  1063.         pminub m0, m2
  1064.         pminub m4, m6
  1065.         pmaxub m1, m3
  1066.         pmaxub m5, m7
  1067.         pminub m0, m4
  1068.         pmaxub m1, m5
  1069.  
  1070.         movu m2, [c]
  1071.         CLIPUB m2, m0, m1
  1072.  
  1073.         movu [dstq], m2
  1074.         add srcq, mmsize
  1075.         add dstq, mmsize
  1076.         sub pixelsd, mmsize
  1077.     jg .loop
  1078. RET
  1079.  
  1080. %if ARCH_X86_64
  1081. cglobal rg_fl_mode_23, 4, 5, 16, 0, dst, src, stride, pixels
  1082.     mov r4q, strideq
  1083.     neg r4q
  1084.     %define stride_p strideq
  1085.     %define stride_n r4q
  1086.  
  1087.     pxor m15, m15
  1088.     .loop:
  1089.         LOAD_SQUARE_16 m15
  1090.         SORT_AXIS_16
  1091.  
  1092.         mova m9, m8
  1093.         mova m10, m7
  1094.         mova m11, m6
  1095.         mova m12, m5
  1096.         psubw m9, m1  ; linediff1
  1097.         psubw m10, m2 ; linediff2
  1098.         psubw m11, m3 ; linediff3
  1099.         psubw m12, m4 ; linediff4
  1100.  
  1101.         psubw m1, m0
  1102.         psubw m2, m0
  1103.         psubw m3, m0
  1104.         psubw m4, m0
  1105.         pminsw m1, m9  ; d1
  1106.         pminsw m2, m10 ; d2
  1107.         pminsw m3, m11 ; d3
  1108.         pminsw m4, m12 ; d4
  1109.         pmaxsw m1, m2
  1110.         pmaxsw m3, m4
  1111.         pmaxsw m1, m3
  1112.         pmaxsw m1, m15 ; d
  1113.  
  1114.         mova m13, m0
  1115.         mova m14, m0
  1116.         mova m2, m0
  1117.         mova m4, m0
  1118.         psubw m13, m8
  1119.         psubw m14, m7
  1120.         psubw m2, m6
  1121.         psubw m4, m5
  1122.         pminsw m9, m13  ; u1
  1123.         pminsw m10, m14 ; u2
  1124.         pminsw m11, m2  ; u3
  1125.         pminsw m12, m4  ; u4
  1126.         pmaxsw m9, m10
  1127.         pmaxsw m11, m12
  1128.         pmaxsw m9, m11
  1129.         pmaxsw m9, m15  ; u
  1130.  
  1131.         paddw m0, m1
  1132.         psubw m0, m9
  1133.         packuswb m0, m0
  1134.  
  1135.         movh [dstq], m0
  1136.         add srcq, mmsize/2
  1137.         add dstq, mmsize/2
  1138.         sub pixelsd, mmsize/2
  1139.     jg .loop
  1140. RET
  1141.  
  1142. cglobal rg_fl_mode_24, 4, 5, 16, mmsize, dst, src, stride, pixels
  1143.     mov r4q, strideq
  1144.     neg r4q
  1145.     %define stride_p strideq
  1146.     %define stride_n r4q
  1147.  
  1148.     pxor m15, m15
  1149.     .loop:
  1150.         LOAD_SQUARE_16 m15
  1151.         mova [rsp], m0
  1152.         SORT_AXIS_16
  1153.  
  1154.         mova m9, m8
  1155.         mova m10, m7
  1156.         mova m11, m6
  1157.         mova m12, m5
  1158.         psubw m9, m1  ; linediff1
  1159.         psubw m10, m2 ; linediff2
  1160.         psubw m11, m3 ; linediff3
  1161.         psubw m12, m4 ; linediff4
  1162.  
  1163.         psubw m1, [rsp] ; td1
  1164.         psubw m2, [rsp] ; td2
  1165.         psubw m3, [rsp] ; td3
  1166.         psubw m4, [rsp] ; td4
  1167.         mova m0, m9
  1168.         mova m13, m10
  1169.         mova m14, m11
  1170.         mova m15, m12
  1171.         psubw m0, m1
  1172.         psubw m13, m2
  1173.         psubw m14, m3
  1174.         psubw m15, m4
  1175.         pminsw m1, m0  ; d1
  1176.         pminsw m2, m13 ; d2
  1177.         pminsw m3, m14 ; d3
  1178.         pminsw m4, m15 ; d4
  1179.         pmaxsw m1, m2
  1180.         pmaxsw m3, m4
  1181.  
  1182.         mova m0, [rsp]
  1183.         mova m13, [rsp]
  1184.         mova m14, [rsp]
  1185.         mova m15, [rsp]
  1186.         psubw m0, m8  ; tu1
  1187.         psubw m13, m7 ; tu2
  1188.         psubw m14, m6 ; tu3
  1189.         psubw m15, m5 ; tu4
  1190.         psubw m9, m0
  1191.         psubw m10, m13
  1192.         psubw m11, m14
  1193.         psubw m12, m15
  1194.         pminsw m9, m0   ; u1
  1195.         pminsw m10, m13 ; u2
  1196.         pminsw m11, m14 ; u3
  1197.         pminsw m12, m15 ; u4
  1198.         pmaxsw m9, m10
  1199.         pmaxsw m11, m12
  1200.  
  1201.         pmaxsw m1, m3  ; d without max(d,0)
  1202.         pmaxsw m9, m11  ; u without max(u,0)
  1203.         pxor m15, m15
  1204.         pmaxsw m1, m15
  1205.         pmaxsw m9, m15
  1206.  
  1207.         mova m0, [rsp]
  1208.         paddw m0, m1
  1209.         psubw m0, m9
  1210.         packuswb m0, m0
  1211.  
  1212.         movh [dstq], m0
  1213.         add srcq, mmsize/2
  1214.         add dstq, mmsize/2
  1215.         sub pixelsd, mmsize/2
  1216.     jg .loop
  1217. RET
  1218. %endif
  1219.