]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/dsputilenc.asm
x86: include x86inc.asm in x86util.asm
[ffmpeg] / libavcodec / x86 / dsputilenc.asm
1 ;*****************************************************************************
2 ;* MMX optimized DSP utils
3 ;*****************************************************************************
4 ;* Copyright (c) 2000, 2001 Fabrice Bellard
5 ;* Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
6 ;*
7 ;* This file is part of Libav.
8 ;*
9 ;* Libav is free software; you can redistribute it and/or
10 ;* modify it under the terms of the GNU Lesser General Public
11 ;* License as published by the Free Software Foundation; either
12 ;* version 2.1 of the License, or (at your option) any later version.
13 ;*
14 ;* Libav is distributed in the hope that it will be useful,
15 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 ;* Lesser General Public License for more details.
18 ;*
19 ;* You should have received a copy of the GNU Lesser General Public
20 ;* License along with Libav; if not, write to the Free Software
21 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 ;*****************************************************************************
23
24 %include "x86util.asm"
25
26 SECTION .text
27
28 %macro DIFF_PIXELS_1 4
29     movh            %1, %3
30     movh            %2, %4
31     punpcklbw       %2, %1
32     punpcklbw       %1, %1
33     psubw           %1, %2
34 %endmacro
35
36 ; %1=uint8_t *pix1, %2=uint8_t *pix2, %3=static offset, %4=stride, %5=stride*3
37 ; %6=temporary storage location
38 ; this macro requires $mmsize stack space (aligned) on %6 (except on SSE+x86-64)
39 %macro DIFF_PIXELS_8 6
40     DIFF_PIXELS_1   m0, m7, [%1     +%3], [%2     +%3]
41     DIFF_PIXELS_1   m1, m7, [%1+%4  +%3], [%2+%4  +%3]
42     DIFF_PIXELS_1   m2, m7, [%1+%4*2+%3], [%2+%4*2+%3]
43     add             %1, %5
44     add             %2, %5
45     DIFF_PIXELS_1   m3, m7, [%1     +%3], [%2     +%3]
46     DIFF_PIXELS_1   m4, m7, [%1+%4  +%3], [%2+%4  +%3]
47     DIFF_PIXELS_1   m5, m7, [%1+%4*2+%3], [%2+%4*2+%3]
48     DIFF_PIXELS_1   m6, m7, [%1+%5  +%3], [%2+%5  +%3]
49 %ifdef m8
50     DIFF_PIXELS_1   m7, m8, [%1+%4*4+%3], [%2+%4*4+%3]
51 %else
52     mova          [%6], m0
53     DIFF_PIXELS_1   m7, m0, [%1+%4*4+%3], [%2+%4*4+%3]
54     mova            m0, [%6]
55 %endif
56     sub             %1, %5
57     sub             %2, %5
58 %endmacro
59
60 %macro HADAMARD8 0
61     SUMSUB_BADC       w, 0, 1, 2, 3
62     SUMSUB_BADC       w, 4, 5, 6, 7
63     SUMSUB_BADC       w, 0, 2, 1, 3
64     SUMSUB_BADC       w, 4, 6, 5, 7
65     SUMSUB_BADC       w, 0, 4, 1, 5
66     SUMSUB_BADC       w, 2, 6, 3, 7
67 %endmacro
68
69 %macro ABS1_SUM 3
70     ABS1            %1, %2
71     paddusw         %3, %1
72 %endmacro
73
74 %macro ABS2_SUM 6
75     ABS2            %1, %2, %3, %4
76     paddusw         %5, %1
77     paddusw         %6, %2
78 %endmacro
79
80 %macro ABS_SUM_8x8_64 1
81     ABS2            m0, m1, m8, m9
82     ABS2_SUM        m2, m3, m8, m9, m0, m1
83     ABS2_SUM        m4, m5, m8, m9, m0, m1
84     ABS2_SUM        m6, m7, m8, m9, m0, m1
85     paddusw         m0, m1
86 %endmacro
87
88 %macro ABS_SUM_8x8_32 1
89     mova          [%1], m7
90     ABS1            m0, m7
91     ABS1            m1, m7
92     ABS1_SUM        m2, m7, m0
93     ABS1_SUM        m3, m7, m1
94     ABS1_SUM        m4, m7, m0
95     ABS1_SUM        m5, m7, m1
96     ABS1_SUM        m6, m7, m0
97     mova            m2, [%1]
98     ABS1_SUM        m2, m7, m1
99     paddusw         m0, m1
100 %endmacro
101
102 ; FIXME: HSUM_* saturates at 64k, while an 8x8 hadamard or dct block can get up to
103 ; about 100k on extreme inputs. But that's very unlikely to occur in natural video,
104 ; and it's even more unlikely to not have any alternative mvs/modes with lower cost.
105 %macro HSUM_MMX 3
106     mova            %2, %1
107     psrlq           %1, 32
108     paddusw         %1, %2
109     mova            %2, %1
110     psrlq           %1, 16
111     paddusw         %1, %2
112     movd            %3, %1
113 %endmacro
114
115 %macro HSUM_MMX2 3
116     pshufw          %2, %1, 0xE
117     paddusw         %1, %2
118     pshufw          %2, %1, 0x1
119     paddusw         %1, %2
120     movd            %3, %1
121 %endmacro
122
123 %macro HSUM_SSE2 3
124     movhlps         %2, %1
125     paddusw         %1, %2
126     pshuflw         %2, %1, 0xE
127     paddusw         %1, %2
128     pshuflw         %2, %1, 0x1
129     paddusw         %1, %2
130     movd            %3, %1
131 %endmacro
132
133 %macro STORE4 5
134     mova [%1+mmsize*0], %2
135     mova [%1+mmsize*1], %3
136     mova [%1+mmsize*2], %4
137     mova [%1+mmsize*3], %5
138 %endmacro
139
140 %macro LOAD4 5
141     mova            %2, [%1+mmsize*0]
142     mova            %3, [%1+mmsize*1]
143     mova            %4, [%1+mmsize*2]
144     mova            %5, [%1+mmsize*3]
145 %endmacro
146
147 %macro hadamard8_16_wrapper 3
148 cglobal hadamard8_diff_%1, 4, 4, %2
149 %ifndef m8
150     %assign pad %3*mmsize-(4+stack_offset&(mmsize-1))
151     SUB            rsp, pad
152 %endif
153     call hadamard8x8_diff_%1
154 %ifndef m8
155     ADD            rsp, pad
156 %endif
157     RET
158
159 cglobal hadamard8_diff16_%1, 5, 6, %2
160 %ifndef m8
161     %assign pad %3*mmsize-(4+stack_offset&(mmsize-1))
162     SUB            rsp, pad
163 %endif
164
165     call hadamard8x8_diff_%1
166     mov            r5d, eax
167
168     add             r1, 8
169     add             r2, 8
170     call hadamard8x8_diff_%1
171     add            r5d, eax
172
173     cmp            r4d, 16
174     jne .done
175
176     lea             r1, [r1+r3*8-8]
177     lea             r2, [r2+r3*8-8]
178     call hadamard8x8_diff_%1
179     add            r5d, eax
180
181     add             r1, 8
182     add             r2, 8
183     call hadamard8x8_diff_%1
184     add            r5d, eax
185
186 .done:
187     mov            eax, r5d
188 %ifndef m8
189     ADD            rsp, pad
190 %endif
191     RET
192 %endmacro
193
194 %macro HADAMARD8_DIFF_MMX 1
195 ALIGN 16
196 ; int hadamard8_diff_##cpu(void *s, uint8_t *src1, uint8_t *src2,
197 ;                          int stride, int h)
198 ; r0 = void *s = unused, int h = unused (always 8)
199 ; note how r1, r2 and r3 are not clobbered in this function, so 16x16
200 ; can simply call this 2x2x (and that's why we access rsp+gprsize
201 ; everywhere, which is rsp of calling func
202 hadamard8x8_diff_%1:
203     lea                          r0, [r3*3]
204
205     ; first 4x8 pixels
206     DIFF_PIXELS_8                r1, r2,  0, r3, r0, rsp+gprsize+0x60
207     HADAMARD8
208     mova         [rsp+gprsize+0x60], m7
209     TRANSPOSE4x4W                 0,  1,  2,  3,  7
210     STORE4              rsp+gprsize, m0, m1, m2, m3
211     mova                         m7, [rsp+gprsize+0x60]
212     TRANSPOSE4x4W                 4,  5,  6,  7,  0
213     STORE4         rsp+gprsize+0x40, m4, m5, m6, m7
214
215     ; second 4x8 pixels
216     DIFF_PIXELS_8                r1, r2,  4, r3, r0, rsp+gprsize+0x60
217     HADAMARD8
218     mova         [rsp+gprsize+0x60], m7
219     TRANSPOSE4x4W                 0,  1,  2,  3,  7
220     STORE4         rsp+gprsize+0x20, m0, m1, m2, m3
221     mova                         m7, [rsp+gprsize+0x60]
222     TRANSPOSE4x4W                 4,  5,  6,  7,  0
223
224     LOAD4          rsp+gprsize+0x40, m0, m1, m2, m3
225     HADAMARD8
226     ABS_SUM_8x8_32 rsp+gprsize+0x60
227     mova         [rsp+gprsize+0x60], m0
228
229     LOAD4          rsp+gprsize     , m0, m1, m2, m3
230     LOAD4          rsp+gprsize+0x20, m4, m5, m6, m7
231     HADAMARD8
232     ABS_SUM_8x8_32 rsp+gprsize
233     paddusw                      m0, [rsp+gprsize+0x60]
234
235     HSUM                         m0, m1, eax
236     and                         rax, 0xFFFF
237     ret
238
239 hadamard8_16_wrapper %1, 0, 14
240 %endmacro
241
242 %macro HADAMARD8_DIFF_SSE2 2
243 hadamard8x8_diff_%1:
244     lea                          r0, [r3*3]
245     DIFF_PIXELS_8                r1, r2,  0, r3, r0, rsp+gprsize
246     HADAMARD8
247 %if ARCH_X86_64
248     TRANSPOSE8x8W                 0,  1,  2,  3,  4,  5,  6,  7,  8
249 %else
250     TRANSPOSE8x8W                 0,  1,  2,  3,  4,  5,  6,  7, [rsp+gprsize], [rsp+mmsize+gprsize]
251 %endif
252     HADAMARD8
253     ABS_SUM_8x8         rsp+gprsize
254     HSUM_SSE2                    m0, m1, eax
255     and                         eax, 0xFFFF
256     ret
257
258 hadamard8_16_wrapper %1, %2, 3
259 %endmacro
260
261 INIT_MMX
262 %define ABS1 ABS1_MMX
263 %define HSUM HSUM_MMX
264 HADAMARD8_DIFF_MMX mmx
265
266 %define ABS1 ABS1_MMX2
267 %define HSUM HSUM_MMX2
268 HADAMARD8_DIFF_MMX mmx2
269
270 INIT_XMM
271 %define ABS2 ABS2_MMX2
272 %if ARCH_X86_64
273 %define ABS_SUM_8x8 ABS_SUM_8x8_64
274 %else
275 %define ABS_SUM_8x8 ABS_SUM_8x8_32
276 %endif
277 HADAMARD8_DIFF_SSE2 sse2, 10
278
279 %define ABS2        ABS2_SSSE3
280 %define ABS_SUM_8x8 ABS_SUM_8x8_64
281 HADAMARD8_DIFF_SSE2 ssse3, 9
282
283 INIT_XMM
284 ; sse16_sse2(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h)
285 cglobal sse16_sse2, 5, 5, 8
286     shr      r4d, 1
287     pxor      m0, m0         ; mm0 = 0
288     pxor      m7, m7         ; mm7 holds the sum
289
290 .next2lines: ; FIXME why are these unaligned movs? pix1[] is aligned
291     movu      m1, [r1   ]    ; mm1 = pix1[0][0-15]
292     movu      m2, [r2   ]    ; mm2 = pix2[0][0-15]
293     movu      m3, [r1+r3]    ; mm3 = pix1[1][0-15]
294     movu      m4, [r2+r3]    ; mm4 = pix2[1][0-15]
295
296     ; todo: mm1-mm2, mm3-mm4
297     ; algo: subtract mm1 from mm2 with saturation and vice versa
298     ;       OR the result to get the absolute difference
299     mova      m5, m1
300     mova      m6, m3
301     psubusb   m1, m2
302     psubusb   m3, m4
303     psubusb   m2, m5
304     psubusb   m4, m6
305
306     por       m2, m1
307     por       m4, m3
308
309     ; now convert to 16-bit vectors so we can square them
310     mova      m1, m2
311     mova      m3, m4
312
313     punpckhbw m2, m0
314     punpckhbw m4, m0
315     punpcklbw m1, m0         ; mm1 not spread over (mm1,mm2)
316     punpcklbw m3, m0         ; mm4 not spread over (mm3,mm4)
317
318     pmaddwd   m2, m2
319     pmaddwd   m4, m4
320     pmaddwd   m1, m1
321     pmaddwd   m3, m3
322
323     lea       r1, [r1+r3*2]  ; pix1 += 2*line_size
324     lea       r2, [r2+r3*2]  ; pix2 += 2*line_size
325
326     paddd     m1, m2
327     paddd     m3, m4
328     paddd     m7, m1
329     paddd     m7, m3
330
331     dec       r4
332     jnz .next2lines
333
334     mova      m1, m7
335     psrldq    m7, 8          ; shift hi qword to lo
336     paddd     m7, m1
337     mova      m1, m7
338     psrldq    m7, 4          ; shift hi dword to lo
339     paddd     m7, m1
340     movd     eax, m7         ; return value
341     RET