]> 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 ; %3 = optimization
87 %macro IDCT_1D 3
88     ; a0 = (W4 * row[0]) + (1 << (15 - 1));
89     ; a1 = a0;
90     ; a2 = a0;
91     ; a3 = a0;
92     ; a0 += W2 * row[2];
93     ; a1 += W6 * row[2];
94     ; a2 -= W6 * row[2];
95     ; a3 -= W2 * row[2];
96 %ifidn %1, col
97     paddw       m10,[pw_88]
98 %endif
99 %ifidn %1, row
100     paddw       m10,[pw_1]
101 %endif
102     SBUTTERFLY3 wd,  0,  1, 10,  8 ; { row[0], row[2] }[0-3]/[4-7]
103     pmaddwd     m2,  m0, [w4_plus_w6]
104     pmaddwd     m3,  m1, [w4_plus_w6]
105     pmaddwd     m4,  m0, [w4_min_w6]
106     pmaddwd     m5,  m1, [w4_min_w6]
107     pmaddwd     m6,  m0, [w4_min_w2]
108     pmaddwd     m7,  m1, [w4_min_w2]
109     pmaddwd     m0, [w4_plus_w2]
110     pmaddwd     m1, [w4_plus_w2]
111
112     ; a0: -1*row[0]-1*row[2]
113     ; a1: -1*row[0]
114     ; a2: -1*row[0]
115     ; a3: -1*row[0]+1*row[2]
116
117     ; a0 +=   W4*row[4] + W6*row[6]; i.e. -1*row[4]
118     ; a1 -=   W4*row[4] + W2*row[6]; i.e. -1*row[4]-1*row[6]
119     ; a2 -=   W4*row[4] - W2*row[6]; i.e. -1*row[4]+1*row[6]
120     ; a3 +=   W4*row[4] - W6*row[6]; i.e. -1*row[4]
121     SBUTTERFLY3 wd,  8,  9, 13, 12 ; { row[4], row[6] }[0-3]/[4-7]
122     pmaddwd     m10, m8, [w4_plus_w6]
123     pmaddwd     m11, m9, [w4_plus_w6]
124     paddd       m0,  m10            ; a0[0-3]
125     paddd       m1,  m11            ; a0[4-7]
126     pmaddwd     m10, m8, [w4_min_w6]
127     pmaddwd     m11, m9, [w4_min_w6]
128     paddd       m6,  m10           ; a3[0-3]
129     paddd       m7,  m11           ; a3[4-7]
130     pmaddwd     m10, m8, [w4_min_w2]
131     pmaddwd     m11, m9, [w4_min_w2]
132     pmaddwd     m8, [w4_plus_w2]
133     pmaddwd     m9, [w4_plus_w2]
134     psubd       m4,  m10           ; a2[0-3] intermediate
135     psubd       m5,  m11           ; a2[4-7] intermediate
136     psubd       m2,  m8            ; a1[0-3] intermediate
137     psubd       m3,  m9            ; a1[4-7] intermediate
138
139     ; load/store
140     mova   [r2+  0], m0
141     mova   [r2+ 32], m2
142     mova   [r2+ 64], m4
143     mova   [r2+ 96], m6
144     mova        m10,[r2+ 16]       ; { row[1] }[0-7]
145     mova        m8, [r2+ 48]       ; { row[3] }[0-7]
146     mova        m13,[r2+ 80]       ; { row[5] }[0-7]
147     mova        m14,[r2+112]       ; { row[7] }[0-7]
148     mova   [r2+ 16], m1
149     mova   [r2+ 48], m3
150     mova   [r2+ 80], m5
151     mova   [r2+112], m7
152 %ifidn %1, row
153     pmullw      m10,[r3+ 16]
154     pmullw      m8, [r3+ 48]
155     pmullw      m13,[r3+ 80]
156     pmullw      m14,[r3+112]
157 %endif
158
159     ; b0 = MUL(W1, row[1]);
160     ; MAC(b0, W3, row[3]);
161     ; b1 = MUL(W3, row[1]);
162     ; MAC(b1, -W7, row[3]);
163     ; b2 = MUL(W5, row[1]);
164     ; MAC(b2, -W1, row[3]);
165     ; b3 = MUL(W7, row[1]);
166     ; MAC(b3, -W5, row[3]);
167     SBUTTERFLY3 wd,  0,  1, 10, 8  ; { row[1], row[3] }[0-3]/[4-7]
168     pmaddwd     m2,  m0, [w3_min_w7]
169     pmaddwd     m3,  m1, [w3_min_w7]
170     pmaddwd     m4,  m0, [w5_min_w1]
171     pmaddwd     m5,  m1, [w5_min_w1]
172     pmaddwd     m6,  m0, [w7_min_w5]
173     pmaddwd     m7,  m1, [w7_min_w5]
174     pmaddwd     m0, [w1_plus_w3]
175     pmaddwd     m1, [w1_plus_w3]
176
177     ; b0: +1*row[1]+2*row[3]
178     ; b1: +2*row[1]-1*row[3]
179     ; b2: -1*row[1]-1*row[3]
180     ; b3: +1*row[1]+1*row[3]
181
182     ; MAC(b0,  W5, row[5]);
183     ; MAC(b0,  W7, row[7]);
184     ; MAC(b1, -W1, row[5]);
185     ; MAC(b1, -W5, row[7]);
186     ; MAC(b2,  W7, row[5]);
187     ; MAC(b2,  W3, row[7]);
188     ; MAC(b3,  W3, row[5]);
189     ; MAC(b3, -W1, row[7]);
190     SBUTTERFLY3 wd,  8,  9, 13, 14 ; { row[5], row[7] }[0-3]/[4-7]
191
192     ; b0: -1*row[5]+1*row[7]
193     ; b1: -1*row[5]+1*row[7]
194     ; b2: +1*row[5]+2*row[7]
195     ; b3: +2*row[5]-1*row[7]
196
197     pmaddwd     m10, m8, [w1_plus_w5]
198     pmaddwd     m11, m9, [w1_plus_w5]
199     pmaddwd     m12, m8, [w5_plus_w7]
200     pmaddwd     m13, m9, [w5_plus_w7]
201     psubd       m2,  m10           ; b1[0-3]
202     psubd       m3,  m11           ; b1[4-7]
203     paddd       m0,  m12            ; b0[0-3]
204     paddd       m1,  m13            ; b0[4-7]
205     pmaddwd     m12, m8, [w7_plus_w3]
206     pmaddwd     m13, m9, [w7_plus_w3]
207     pmaddwd     m8, [w3_min_w1]
208     pmaddwd     m9, [w3_min_w1]
209     paddd       m4,  m12           ; b2[0-3]
210     paddd       m5,  m13           ; b2[4-7]
211     paddd       m6,  m8            ; b3[0-3]
212     paddd       m7,  m9            ; b3[4-7]
213
214     ; row[0] = (a0 + b0) >> 15;
215     ; row[7] = (a0 - b0) >> 15;
216     ; row[1] = (a1 + b1) >> 15;
217     ; row[6] = (a1 - b1) >> 15;
218     ; row[2] = (a2 + b2) >> 15;
219     ; row[5] = (a2 - b2) >> 15;
220     ; row[3] = (a3 + b3) >> 15;
221     ; row[4] = (a3 - b3) >> 15;
222     mova        m8, [r2+ 0]        ; a0[0-3]
223     mova        m9, [r2+16]        ; a0[4-7]
224     SUMSUB_SHPK m8,  m9,  m10, m11, m0,  m1,  %2
225     mova        m0, [r2+32]        ; a1[0-3]
226     mova        m1, [r2+48]        ; a1[4-7]
227     SUMSUB_SHPK m0,  m1,  m9,  m11, m2,  m3,  %2
228     mova        m1, [r2+64]        ; a2[0-3]
229     mova        m2, [r2+80]        ; a2[4-7]
230     SUMSUB_SHPK m1,  m2,  m11, m3,  m4,  m5,  %2
231     mova        m2, [r2+96]        ; a3[0-3]
232     mova        m3, [r2+112]       ; a3[4-7]
233     SUMSUB_SHPK m2,  m3,  m4,  m5,  m6,  m7,  %2
234 %endmacro
235
236 ; void prores_idct_put_10_<opt>(uint8_t *pixels, int stride,
237 ;                               DCTELEM *block, const int16_t *qmat);
238 %macro idct_put_fn 2
239 cglobal prores_idct_put_10_%1, 4, 4, %2
240     movsxd      r1,  r1d
241     pxor        m15, m15           ; zero
242
243     ; for (i = 0; i < 8; i++)
244     ;     idctRowCondDC(block + i*8);
245     mova        m10,[r2+ 0]        ; { row[0] }[0-7]
246     mova        m8, [r2+32]        ; { row[2] }[0-7]
247     mova        m13,[r2+64]        ; { row[4] }[0-7]
248     mova        m12,[r2+96]        ; { row[6] }[0-7]
249
250     pmullw      m10,[r3+ 0]
251     pmullw      m8, [r3+32]
252     pmullw      m13,[r3+64]
253     pmullw      m12,[r3+96]
254
255     IDCT_1D     row, 15,  %1
256
257     ; transpose for second part of IDCT
258     TRANSPOSE8x8W 8, 0, 1, 2, 4, 11, 9, 10, 3
259     mova   [r2+ 16], m0
260     mova   [r2+ 48], m2
261     mova   [r2+ 80], m11
262     mova   [r2+112], m10
263     SWAP         8,  10
264     SWAP         1,   8
265     SWAP         4,  13
266     SWAP         9,  12
267
268     ; for (i = 0; i < 8; i++)
269     ;     idctSparseColAdd(dest + i, line_size, block + i);
270     IDCT_1D     col, 18,  %1
271
272     ; clip/store
273     mova        m3, [pw_4]
274     mova        m5, [pw_1019]
275     pmaxsw      m8,  m3
276     pmaxsw      m0,  m3
277     pmaxsw      m1,  m3
278     pmaxsw      m2,  m3
279     pmaxsw      m4,  m3
280     pmaxsw      m11, m3
281     pmaxsw      m9,  m3
282     pmaxsw      m10, m3
283     pminsw      m8,  m5
284     pminsw      m0,  m5
285     pminsw      m1,  m5
286     pminsw      m2,  m5
287     pminsw      m4,  m5
288     pminsw      m11, m5
289     pminsw      m9,  m5
290     pminsw      m10, m5
291
292     lea         r2, [r1*3]
293     mova  [r0     ], m8
294     mova  [r0+r1  ], m0
295     mova  [r0+r1*2], m1
296     mova  [r0+r2  ], m2
297     lea         r0, [r0+r1*4]
298     mova  [r0     ], m4
299     mova  [r0+r1  ], m11
300     mova  [r0+r1*2], m9
301     mova  [r0+r2  ], m10
302     RET
303 %endmacro
304
305 INIT_XMM
306 idct_put_fn sse2, 16
307 INIT_XMM
308 idct_put_fn sse4, 16
309 %ifdef HAVE_AVX
310 INIT_AVX
311 idct_put_fn avx,  16
312 %endif
313
314 %endif