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