d8ea0bcc6b6cda485d3d87aefa2a45705c16814d
[ffmpeg.git] / libavcodec / x86 / simple_idct10_template.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 ; add SECTION_RODATA and proper include before including this file!
26
27 %if ARCH_X86_64
28
29 %macro define_constants 1
30     %undef w4_plus_w2
31     %undef w4_min_w2
32     %undef w4_plus_w6
33     %undef w4_min_w6
34     %undef w1_plus_w3
35     %undef w3_min_w1
36     %undef w7_plus_w3
37     %undef w3_min_w7
38     %define w4_plus_w2 w4_plus_w2%1
39     %define w4_min_w2  w4_min_w2%1
40     %define w4_plus_w6 w4_plus_w6%1
41     %define w4_min_w6  w4_min_w6%1
42     %define w1_plus_w3 w1_plus_w3%1
43     %define w3_min_w1  w3_min_w1%1
44     %define w7_plus_w3 w7_plus_w3%1
45     %define w3_min_w7  w3_min_w7%1
46 %endmacro
47
48 ; interleave data while maintaining source
49 ; %1=type, %2=dstlo, %3=dsthi, %4=src, %5=interleave
50 %macro SBUTTERFLY3 5
51     punpckl%1   m%2, m%4, m%5
52     punpckh%1   m%3, m%4, m%5
53 %endmacro
54
55 ; %1/%2=src1/dst1, %3/%4=dst2, %5/%6=src2, %7=shift
56 ; action: %3/%4 = %1/%2 - %5/%6; %1/%2 += %5/%6
57 ;         %1/%2/%3/%4 >>= %7; dword -> word (in %1/%3)
58 %macro SUMSUB_SHPK 7
59     psubd       %3,  %1,  %5       ; { a0 - b0 }[0-3]
60     psubd       %4,  %2,  %6       ; { a0 - b0 }[4-7]
61     paddd       %1,  %5            ; { a0 + b0 }[0-3]
62     paddd       %2,  %6            ; { a0 + b0 }[4-7]
63     psrad       %1,  %7
64     psrad       %2,  %7
65     psrad       %3,  %7
66     psrad       %4,  %7
67     packssdw    %1,  %2            ; row[0]
68     packssdw    %3,  %4            ; row[7]
69 %endmacro
70
71 ; %1 = initial bias ("" if nop)
72 ; %2 = number of bits to shift at the end
73 ; %3 = qmat (for prores)
74 %macro IDCT_1D 2-3
75     ; a0 = (W4 * row[0]) + (1 << (15 - 1));
76     ; a1 = a0;
77     ; a2 = a0;
78     ; a3 = a0;
79     ; a0 += W2 * row[2];
80     ; a1 += W6 * row[2];
81     ; a2 -= W6 * row[2];
82     ; a3 -= W2 * row[2];
83 %ifstr %1
84     mova        m15, [pd_round_ %+ %2]
85 %else
86     paddw       m10, [%1]
87 %endif
88     SBUTTERFLY3 wd,  0,  1, 10,  8 ; { row[0], row[2] }[0-3]/[4-7]
89     pmaddwd     m2,  m0, [w4_plus_w6]
90     pmaddwd     m3,  m1, [w4_plus_w6]
91     pmaddwd     m4,  m0, [w4_min_w6]
92     pmaddwd     m5,  m1, [w4_min_w6]
93     pmaddwd     m6,  m0, [w4_min_w2]
94     pmaddwd     m7,  m1, [w4_min_w2]
95     pmaddwd     m0, [w4_plus_w2]
96     pmaddwd     m1, [w4_plus_w2]
97 %ifstr %1
98     ; Adding 1<<(%2-1) for >=15 bits values
99     paddd       m2, m15
100     paddd       m3, m15
101     paddd       m4, m15
102     paddd       m5, m15
103     paddd       m6, m15
104     paddd       m7, m15
105     paddd       m0, m15
106     paddd       m1, m15
107 %endif
108
109     ; a0: -1*row[0]-1*row[2]
110     ; a1: -1*row[0]
111     ; a2: -1*row[0]
112     ; a3: -1*row[0]+1*row[2]
113
114     ; a0 +=   W4*row[4] + W6*row[6]; i.e. -1*row[4]
115     ; a1 -=   W4*row[4] + W2*row[6]; i.e. -1*row[4]-1*row[6]
116     ; a2 -=   W4*row[4] - W2*row[6]; i.e. -1*row[4]+1*row[6]
117     ; a3 +=   W4*row[4] - W6*row[6]; i.e. -1*row[4]
118     SBUTTERFLY3 wd,  8,  9, 13, 12 ; { row[4], row[6] }[0-3]/[4-7]
119     pmaddwd     m10, m8, [w4_plus_w6]
120     pmaddwd     m11, m9, [w4_plus_w6]
121     paddd       m0,  m10            ; a0[0-3]
122     paddd       m1,  m11            ; a0[4-7]
123     pmaddwd     m10, m8, [w4_min_w6]
124     pmaddwd     m11, m9, [w4_min_w6]
125     paddd       m6,  m10           ; a3[0-3]
126     paddd       m7,  m11           ; a3[4-7]
127     pmaddwd     m10, m8, [w4_min_w2]
128     pmaddwd     m11, m9, [w4_min_w2]
129     pmaddwd     m8, [w4_plus_w2]
130     pmaddwd     m9, [w4_plus_w2]
131     psubd       m4,  m10           ; a2[0-3] intermediate
132     psubd       m5,  m11           ; a2[4-7] intermediate
133     psubd       m2,  m8            ; a1[0-3] intermediate
134     psubd       m3,  m9            ; a1[4-7] intermediate
135
136     ; load/store
137     mova   [blockq+  0], m0
138     mova   [blockq+ 32], m2
139     mova   [blockq+ 64], m4
140     mova   [blockq+ 96], m6
141     mova        m10,[blockq+ 16]       ; { row[1] }[0-7]
142     mova        m8, [blockq+ 48]       ; { row[3] }[0-7]
143     mova        m13,[blockq+ 80]       ; { row[5] }[0-7]
144     mova        m14,[blockq+112]       ; { row[7] }[0-7]
145     mova   [blockq+ 16], m1
146     mova   [blockq+ 48], m3
147     mova   [blockq+ 80], m5
148     mova   [blockq+112], m7
149 %if %0 == 3
150     pmullw      m10,[%3+ 16]
151     pmullw      m8, [%3+ 48]
152     pmullw      m13,[%3+ 80]
153     pmullw      m14,[%3+112]
154 %endif
155
156     ; b0 = MUL(W1, row[1]);
157     ; MAC(b0, W3, row[3]);
158     ; b1 = MUL(W3, row[1]);
159     ; MAC(b1, -W7, row[3]);
160     ; b2 = MUL(W5, row[1]);
161     ; MAC(b2, -W1, row[3]);
162     ; b3 = MUL(W7, row[1]);
163     ; MAC(b3, -W5, row[3]);
164     SBUTTERFLY3 wd,  0,  1, 10, 8  ; { row[1], row[3] }[0-3]/[4-7]
165     pmaddwd     m2,  m0, [w3_min_w7]
166     pmaddwd     m3,  m1, [w3_min_w7]
167     pmaddwd     m4,  m0, [w5_min_w1]
168     pmaddwd     m5,  m1, [w5_min_w1]
169     pmaddwd     m6,  m0, [w7_min_w5]
170     pmaddwd     m7,  m1, [w7_min_w5]
171     pmaddwd     m0, [w1_plus_w3]
172     pmaddwd     m1, [w1_plus_w3]
173
174     ; b0: +1*row[1]+2*row[3]
175     ; b1: +2*row[1]-1*row[3]
176     ; b2: -1*row[1]-1*row[3]
177     ; b3: +1*row[1]+1*row[3]
178
179     ; MAC(b0,  W5, row[5]);
180     ; MAC(b0,  W7, row[7]);
181     ; MAC(b1, -W1, row[5]);
182     ; MAC(b1, -W5, row[7]);
183     ; MAC(b2,  W7, row[5]);
184     ; MAC(b2,  W3, row[7]);
185     ; MAC(b3,  W3, row[5]);
186     ; MAC(b3, -W1, row[7]);
187     SBUTTERFLY3 wd,  8,  9, 13, 14 ; { row[5], row[7] }[0-3]/[4-7]
188
189     ; b0: -1*row[5]+1*row[7]
190     ; b1: -1*row[5]+1*row[7]
191     ; b2: +1*row[5]+2*row[7]
192     ; b3: +2*row[5]-1*row[7]
193
194     pmaddwd     m10, m8, [w1_plus_w5]
195     pmaddwd     m11, m9, [w1_plus_w5]
196     pmaddwd     m12, m8, [w5_plus_w7]
197     pmaddwd     m13, m9, [w5_plus_w7]
198     psubd       m2,  m10           ; b1[0-3]
199     psubd       m3,  m11           ; b1[4-7]
200     paddd       m0,  m12            ; b0[0-3]
201     paddd       m1,  m13            ; b0[4-7]
202     pmaddwd     m12, m8, [w7_plus_w3]
203     pmaddwd     m13, m9, [w7_plus_w3]
204     pmaddwd     m8, [w3_min_w1]
205     pmaddwd     m9, [w3_min_w1]
206     paddd       m4,  m12           ; b2[0-3]
207     paddd       m5,  m13           ; b2[4-7]
208     paddd       m6,  m8            ; b3[0-3]
209     paddd       m7,  m9            ; b3[4-7]
210
211     ; row[0] = (a0 + b0) >> 15;
212     ; row[7] = (a0 - b0) >> 15;
213     ; row[1] = (a1 + b1) >> 15;
214     ; row[6] = (a1 - b1) >> 15;
215     ; row[2] = (a2 + b2) >> 15;
216     ; row[5] = (a2 - b2) >> 15;
217     ; row[3] = (a3 + b3) >> 15;
218     ; row[4] = (a3 - b3) >> 15;
219     mova        m8, [blockq+ 0]        ; a0[0-3]
220     mova        m9, [blockq+16]        ; a0[4-7]
221     SUMSUB_SHPK m8,  m9,  m10, m11, m0,  m1,  %2
222     mova        m0, [blockq+32]        ; a1[0-3]
223     mova        m1, [blockq+48]        ; a1[4-7]
224     SUMSUB_SHPK m0,  m1,  m9,  m11, m2,  m3,  %2
225     mova        m1, [blockq+64]        ; a2[0-3]
226     mova        m2, [blockq+80]        ; a2[4-7]
227     SUMSUB_SHPK m1,  m2,  m11, m3,  m4,  m5,  %2
228     mova        m2, [blockq+96]        ; a3[0-3]
229     mova        m3, [blockq+112]       ; a3[4-7]
230     SUMSUB_SHPK m2,  m3,  m4,  m5,  m6,  m7,  %2
231 %endmacro
232
233 ; void ff_prores_idct_put_10_<opt>(uint8_t *pixels, ptrdiff_t stride,
234 ;                                  int16_t *block, const int16_t *qmat);
235
236 ; %1 = row shift
237 ; %2 = row bias macro
238 ; %3 = column shift
239 ; %4 = column bias macro
240 ; %5 = final action (nothing, "store", "put", "add")
241 ; %6 = min pixel value
242 ; %7 = max pixel value
243 ; %8 = qmat (for prores)
244
245 %macro IDCT_FN 4-8
246     ; for (i = 0; i < 8; i++)
247     ;     idctRowCondDC(block + i*8);
248     mova        m10,[blockq+ 0]        ; { row[0] }[0-7]
249     mova        m8, [blockq+32]        ; { row[2] }[0-7]
250     mova        m13,[blockq+64]        ; { row[4] }[0-7]
251     mova        m12,[blockq+96]        ; { row[6] }[0-7]
252
253 %if %0 == 8
254     pmullw      m10,[%8+ 0]
255     pmullw      m8, [%8+32]
256     pmullw      m13,[%8+64]
257     pmullw      m12,[%8+96]
258
259     IDCT_1D     %1, %2, %8
260 %else
261     IDCT_1D     %1, %2
262 %endif
263
264     ; transpose for second part of IDCT
265     TRANSPOSE8x8W 8, 0, 1, 2, 4, 11, 9, 10, 3
266     mova   [blockq+ 16], m0
267     mova   [blockq+ 48], m2
268     mova   [blockq+ 80], m11
269     mova   [blockq+112], m10
270     SWAP         8,  10
271     SWAP         1,   8
272     SWAP         4,  13
273     SWAP         9,  12
274
275     ; for (i = 0; i < 8; i++)
276     ;     idctSparseColAdd(dest + i, line_size, block + i);
277     IDCT_1D     %3, %4
278
279     ; clip/store
280 %if %0 >= 5
281 %ifidn %5,"store"
282     ; No clamping, means pure idct
283     mova  [blockq+  0], m8
284     mova  [blockq+ 16], m0
285     mova  [blockq+ 32], m1
286     mova  [blockq+ 48], m2
287     mova  [blockq+ 64], m4
288     mova  [blockq+ 80], m11
289     mova  [blockq+ 96], m9
290     mova  [blockq+112], m10
291 %elifidn %5,"put"
292 %ifidn %6, 0
293     pxor        m3, m3
294 %else
295     mova        m3, [%6]
296 %endif ; ifidn %6, 0
297     mova        m5, [%7]
298     pmaxsw      m8,  m3
299     pmaxsw      m0,  m3
300     pmaxsw      m1,  m3
301     pmaxsw      m2,  m3
302     pmaxsw      m4,  m3
303     pmaxsw      m11, m3
304     pmaxsw      m9,  m3
305     pmaxsw      m10, m3
306     pminsw      m8,  m5
307     pminsw      m0,  m5
308     pminsw      m1,  m5
309     pminsw      m2,  m5
310     pminsw      m4,  m5
311     pminsw      m11, m5
312     pminsw      m9,  m5
313     pminsw      m10, m5
314
315     lea         r2, [r1*3]
316     mova  [r0     ], m8
317     mova  [r0+r1  ], m0
318     mova  [r0+r1*2], m1
319     mova  [r0+r2  ], m2
320     lea         r0, [r0+r1*4]
321     mova  [r0     ], m4
322     mova  [r0+r1  ], m11
323     mova  [r0+r1*2], m9
324     mova  [r0+r2  ], m10
325 %endif ; %5 action
326 %endif; if %0 >= 5
327 %endmacro
328
329 %endif