]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/proresdsp.asm
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavcodec / x86 / proresdsp.asm
1 ;******************************************************************************
2 ;* x86-SIMD-optimized IDCT for prores
3 ;* this is identical to "simple" IDCT written by Michael Niedermayer
4 ;* except for the clip range
5 ;*
6 ;* Copyright (c) 2011 Ronald S. Bultje <rsbultje@gmail.com>
7 ;*
8 ;* This file is part of FFmpeg.
9 ;*
10 ;* FFmpeg is free software; you can redistribute it and/or
11 ;* modify it under the terms of the GNU Lesser General Public
12 ;* License as published by the Free Software Foundation; either
13 ;* version 2.1 of the License, or (at your option) any later version.
14 ;*
15 ;* FFmpeg is distributed in the hope that it will be useful,
16 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 ;* Lesser General Public License for more details.
19 ;*
20 ;* You should have received a copy of the GNU Lesser General Public
21 ;* License along with FFmpeg; if not, write to the Free Software
22 ;* 51, Inc., Foundation Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 ;******************************************************************************
24
25 %include "x86inc.asm"
26 %include "x86util.asm"
27
28 %define W1sh2 22725 ; W1 = 90901 = 22725<<2 + 1
29 %define W2sh2 21407 ; W2 = 85627 = 21407<<2 - 1
30 %define W3sh2 19265 ; W3 = 77062 = 19265<<2 + 2
31 %define W4sh2 16384 ; W4 = 65535 = 16384<<2 - 1
32 %define W5sh2 12873 ; W5 = 51491 = 12873<<2 - 1
33 %define W6sh2  8867 ; W6 = 35468 =  8867<<2
34 %define W7sh2  4520 ; W7 = 18081 =  4520<<2 + 1
35
36 %if ARCH_X86_64
37
38 SECTION_RODATA
39
40 w4_plus_w2: times 4 dw W4sh2, +W2sh2
41 w4_min_w2:  times 4 dw W4sh2, -W2sh2
42 w4_plus_w6: times 4 dw W4sh2, +W6sh2
43 w4_min_w6:  times 4 dw W4sh2, -W6sh2
44 w1_plus_w3: times 4 dw W1sh2, +W3sh2
45 w3_min_w1:  times 4 dw W3sh2, -W1sh2
46 w7_plus_w3: times 4 dw W7sh2, +W3sh2
47 w3_min_w7:  times 4 dw W3sh2, -W7sh2
48 w1_plus_w5: times 4 dw W1sh2, +W5sh2
49 w5_min_w1:  times 4 dw W5sh2, -W1sh2
50 w5_plus_w7: times 4 dw W5sh2, +W7sh2
51 w7_min_w5:  times 4 dw W7sh2, -W5sh2
52 pw_88:      times 8 dw 0x2008
53
54 cextern pw_1
55 cextern pw_4
56 cextern pw_512
57 cextern pw_1019
58
59 section .text align=16
60
61 ; interleave data while maintaining source
62 ; %1=type, %2=dstlo, %3=dsthi, %4=src, %5=interleave
63 %macro SBUTTERFLY3 5
64     punpckl%1   m%2, m%4, m%5
65     punpckh%1   m%3, m%4, m%5
66 %endmacro
67
68 ; %1/%2=src1/dst1, %3/%4=dst2, %5/%6=src2, %7=shift
69 ; action: %3/%4 = %1/%2 - %5/%6; %1/%2 += %5/%6
70 ;         %1/%2/%3/%4 >>= %7; dword -> word (in %1/%3)
71 %macro SUMSUB_SHPK 7
72     psubd       %3,  %1,  %5       ; { a0 - b0 }[0-3]
73     psubd       %4,  %2,  %6       ; { a0 - b0 }[4-7]
74     paddd       %1,  %5            ; { a0 + b0 }[0-3]
75     paddd       %2,  %6            ; { a0 + b0 }[4-7]
76     psrad       %1,  %7
77     psrad       %2,  %7
78     psrad       %3,  %7
79     psrad       %4,  %7
80     packssdw    %1,  %2            ; row[0]
81     packssdw    %3,  %4            ; row[7]
82 %endmacro
83
84 ; %1 = row or col (for rounding variable)
85 ; %2 = number of bits to shift at the end
86 %macro IDCT_1D 2
87     ; a0 = (W4 * row[0]) + (1 << (15 - 1));
88     ; a1 = a0;
89     ; a2 = a0;
90     ; a3 = a0;
91     ; a0 += W2 * row[2];
92     ; a1 += W6 * row[2];
93     ; a2 -= W6 * row[2];
94     ; a3 -= W2 * row[2];
95 %ifidn %1, col
96     paddw       m10,[pw_88]
97 %endif
98 %ifidn %1, row
99     paddw       m10,[pw_1]
100 %endif
101     SBUTTERFLY3 wd,  0,  1, 10,  8 ; { row[0], row[2] }[0-3]/[4-7]
102     pmaddwd     m2,  m0, [w4_plus_w6]
103     pmaddwd     m3,  m1, [w4_plus_w6]
104     pmaddwd     m4,  m0, [w4_min_w6]
105     pmaddwd     m5,  m1, [w4_min_w6]
106     pmaddwd     m6,  m0, [w4_min_w2]
107     pmaddwd     m7,  m1, [w4_min_w2]
108     pmaddwd     m0, [w4_plus_w2]
109     pmaddwd     m1, [w4_plus_w2]
110
111     ; a0: -1*row[0]-1*row[2]
112     ; a1: -1*row[0]
113     ; a2: -1*row[0]
114     ; a3: -1*row[0]+1*row[2]
115
116     ; a0 +=   W4*row[4] + W6*row[6]; i.e. -1*row[4]
117     ; a1 -=   W4*row[4] + W2*row[6]; i.e. -1*row[4]-1*row[6]
118     ; a2 -=   W4*row[4] - W2*row[6]; i.e. -1*row[4]+1*row[6]
119     ; a3 +=   W4*row[4] - W6*row[6]; i.e. -1*row[4]
120     SBUTTERFLY3 wd,  8,  9, 13, 12 ; { row[4], row[6] }[0-3]/[4-7]
121     pmaddwd     m10, m8, [w4_plus_w6]
122     pmaddwd     m11, m9, [w4_plus_w6]
123     paddd       m0,  m10            ; a0[0-3]
124     paddd       m1,  m11            ; a0[4-7]
125     pmaddwd     m10, m8, [w4_min_w6]
126     pmaddwd     m11, m9, [w4_min_w6]
127     paddd       m6,  m10           ; a3[0-3]
128     paddd       m7,  m11           ; a3[4-7]
129     pmaddwd     m10, m8, [w4_min_w2]
130     pmaddwd     m11, m9, [w4_min_w2]
131     pmaddwd     m8, [w4_plus_w2]
132     pmaddwd     m9, [w4_plus_w2]
133     psubd       m4,  m10           ; a2[0-3] intermediate
134     psubd       m5,  m11           ; a2[4-7] intermediate
135     psubd       m2,  m8            ; a1[0-3] intermediate
136     psubd       m3,  m9            ; a1[4-7] intermediate
137
138     ; load/store
139     mova   [r2+  0], m0
140     mova   [r2+ 32], m2
141     mova   [r2+ 64], m4
142     mova   [r2+ 96], m6
143     mova        m10,[r2+ 16]       ; { row[1] }[0-7]
144     mova        m8, [r2+ 48]       ; { row[3] }[0-7]
145     mova        m13,[r2+ 80]       ; { row[5] }[0-7]
146     mova        m14,[r2+112]       ; { row[7] }[0-7]
147     mova   [r2+ 16], m1
148     mova   [r2+ 48], m3
149     mova   [r2+ 80], m5
150     mova   [r2+112], m7
151 %ifidn %1, row
152     pmullw      m10,[r3+ 16]
153     pmullw      m8, [r3+ 48]
154     pmullw      m13,[r3+ 80]
155     pmullw      m14,[r3+112]
156 %endif
157
158     ; b0 = MUL(W1, row[1]);
159     ; MAC(b0, W3, row[3]);
160     ; b1 = MUL(W3, row[1]);
161     ; MAC(b1, -W7, row[3]);
162     ; b2 = MUL(W5, row[1]);
163     ; MAC(b2, -W1, row[3]);
164     ; b3 = MUL(W7, row[1]);
165     ; MAC(b3, -W5, row[3]);
166     SBUTTERFLY3 wd,  0,  1, 10, 8  ; { row[1], row[3] }[0-3]/[4-7]
167     pmaddwd     m2,  m0, [w3_min_w7]
168     pmaddwd     m3,  m1, [w3_min_w7]
169     pmaddwd     m4,  m0, [w5_min_w1]
170     pmaddwd     m5,  m1, [w5_min_w1]
171     pmaddwd     m6,  m0, [w7_min_w5]
172     pmaddwd     m7,  m1, [w7_min_w5]
173     pmaddwd     m0, [w1_plus_w3]
174     pmaddwd     m1, [w1_plus_w3]
175
176     ; b0: +1*row[1]+2*row[3]
177     ; b1: +2*row[1]-1*row[3]
178     ; b2: -1*row[1]-1*row[3]
179     ; b3: +1*row[1]+1*row[3]
180
181     ; MAC(b0,  W5, row[5]);
182     ; MAC(b0,  W7, row[7]);
183     ; MAC(b1, -W1, row[5]);
184     ; MAC(b1, -W5, row[7]);
185     ; MAC(b2,  W7, row[5]);
186     ; MAC(b2,  W3, row[7]);
187     ; MAC(b3,  W3, row[5]);
188     ; MAC(b3, -W1, row[7]);
189     SBUTTERFLY3 wd,  8,  9, 13, 14 ; { row[5], row[7] }[0-3]/[4-7]
190
191     ; b0: -1*row[5]+1*row[7]
192     ; b1: -1*row[5]+1*row[7]
193     ; b2: +1*row[5]+2*row[7]
194     ; b3: +2*row[5]-1*row[7]
195
196     pmaddwd     m10, m8, [w1_plus_w5]
197     pmaddwd     m11, m9, [w1_plus_w5]
198     pmaddwd     m12, m8, [w5_plus_w7]
199     pmaddwd     m13, m9, [w5_plus_w7]
200     psubd       m2,  m10           ; b1[0-3]
201     psubd       m3,  m11           ; b1[4-7]
202     paddd       m0,  m12            ; b0[0-3]
203     paddd       m1,  m13            ; b0[4-7]
204     pmaddwd     m12, m8, [w7_plus_w3]
205     pmaddwd     m13, m9, [w7_plus_w3]
206     pmaddwd     m8, [w3_min_w1]
207     pmaddwd     m9, [w3_min_w1]
208     paddd       m4,  m12           ; b2[0-3]
209     paddd       m5,  m13           ; b2[4-7]
210     paddd       m6,  m8            ; b3[0-3]
211     paddd       m7,  m9            ; b3[4-7]
212
213     ; row[0] = (a0 + b0) >> 15;
214     ; row[7] = (a0 - b0) >> 15;
215     ; row[1] = (a1 + b1) >> 15;
216     ; row[6] = (a1 - b1) >> 15;
217     ; row[2] = (a2 + b2) >> 15;
218     ; row[5] = (a2 - b2) >> 15;
219     ; row[3] = (a3 + b3) >> 15;
220     ; row[4] = (a3 - b3) >> 15;
221     mova        m8, [r2+ 0]        ; a0[0-3]
222     mova        m9, [r2+16]        ; a0[4-7]
223     SUMSUB_SHPK m8,  m9,  m10, m11, m0,  m1,  %2
224     mova        m0, [r2+32]        ; a1[0-3]
225     mova        m1, [r2+48]        ; a1[4-7]
226     SUMSUB_SHPK m0,  m1,  m9,  m11, m2,  m3,  %2
227     mova        m1, [r2+64]        ; a2[0-3]
228     mova        m2, [r2+80]        ; a2[4-7]
229     SUMSUB_SHPK m1,  m2,  m11, m3,  m4,  m5,  %2
230     mova        m2, [r2+96]        ; a3[0-3]
231     mova        m3, [r2+112]       ; a3[4-7]
232     SUMSUB_SHPK m2,  m3,  m4,  m5,  m6,  m7,  %2
233 %endmacro
234
235 ; void prores_idct_put_10_<opt>(uint8_t *pixels, int stride,
236 ;                               DCTELEM *block, const int16_t *qmat);
237 %macro idct_put_fn 1
238 cglobal prores_idct_put_10, 4, 4, %1
239     movsxd      r1,  r1d
240     pxor        m15, m15           ; zero
241
242     ; for (i = 0; i < 8; i++)
243     ;     idctRowCondDC(block + i*8);
244     mova        m10,[r2+ 0]        ; { row[0] }[0-7]
245     mova        m8, [r2+32]        ; { row[2] }[0-7]
246     mova        m13,[r2+64]        ; { row[4] }[0-7]
247     mova        m12,[r2+96]        ; { row[6] }[0-7]
248
249     pmullw      m10,[r3+ 0]
250     pmullw      m8, [r3+32]
251     pmullw      m13,[r3+64]
252     pmullw      m12,[r3+96]
253
254     IDCT_1D     row, 15
255
256     ; transpose for second part of IDCT
257     TRANSPOSE8x8W 8, 0, 1, 2, 4, 11, 9, 10, 3
258     mova   [r2+ 16], m0
259     mova   [r2+ 48], m2
260     mova   [r2+ 80], m11
261     mova   [r2+112], m10
262     SWAP         8,  10
263     SWAP         1,   8
264     SWAP         4,  13
265     SWAP         9,  12
266
267     ; for (i = 0; i < 8; i++)
268     ;     idctSparseColAdd(dest + i, line_size, block + i);
269     IDCT_1D     col, 18
270
271     ; clip/store
272     mova        m3, [pw_4]
273     mova        m5, [pw_1019]
274     pmaxsw      m8,  m3
275     pmaxsw      m0,  m3
276     pmaxsw      m1,  m3
277     pmaxsw      m2,  m3
278     pmaxsw      m4,  m3
279     pmaxsw      m11, m3
280     pmaxsw      m9,  m3
281     pmaxsw      m10, m3
282     pminsw      m8,  m5
283     pminsw      m0,  m5
284     pminsw      m1,  m5
285     pminsw      m2,  m5
286     pminsw      m4,  m5
287     pminsw      m11, m5
288     pminsw      m9,  m5
289     pminsw      m10, m5
290
291     lea         r2, [r1*3]
292     mova  [r0     ], m8
293     mova  [r0+r1  ], m0
294     mova  [r0+r1*2], m1
295     mova  [r0+r2  ], m2
296     lea         r0, [r0+r1*4]
297     mova  [r0     ], m4
298     mova  [r0+r1  ], m11
299     mova  [r0+r1*2], m9
300     mova  [r0+r2  ], m10
301     RET
302 %endmacro
303
304 %macro SIGNEXTEND 2-3
305 %if cpuflag(sse4) ; dstlow, dsthigh
306     movhlps     %2,  %1
307     pmovsxwd    %1,  %1
308     pmovsxwd    %2,  %2
309 %elif cpuflag(sse2) ; dstlow, dsthigh, tmp
310     pxor        %3,  %3
311     pcmpgtw     %3,  %1
312     mova        %2,  %1
313     punpcklwd   %1,  %3
314     punpckhwd   %2,  %3
315 %endif
316 %endmacro
317
318 INIT_XMM sse2
319 idct_put_fn 16
320 INIT_XMM sse4
321 idct_put_fn 16
322 %if HAVE_AVX
323 INIT_XMM avx
324 idct_put_fn 16
325 %endif
326
327 %endif