swscale: make %rep unconditional.
[ffmpeg.git] / libswscale / x86 / output.asm
1 ;******************************************************************************
2 ;* x86-optimized vertical line scaling functions
3 ;* Copyright (c) 2011 Ronald S. Bultje <rsbultje@gmail.com>
4 ;*                    Kieran Kunhya <kieran@kunhya.com>
5 ;*
6 ;* This file is part of Libav.
7 ;*
8 ;* Libav is free software; you can redistribute it and/or
9 ;* modify it under the terms of the GNU Lesser General Public
10 ;* License as published by the Free Software Foundation; either
11 ;* version 2.1 of the License, or (at your option) any later version.
12 ;*
13 ;* Libav is distributed in the hope that it will be useful,
14 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 ;* Lesser General Public License for more details.
17 ;*
18 ;* You should have received a copy of the GNU Lesser General Public
19 ;* License along with Libav; if not, write to the Free Software
20 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 ;******************************************************************************
22
23 %include "x86inc.asm"
24 %include "x86util.asm"
25
26 SECTION_RODATA
27
28 minshort:      times 8 dw 0x8000
29 yuv2yuvX_16_start:  times 4 dd 0x4000 - 0x40000000
30 yuv2yuvX_10_start:  times 4 dd 0x10000
31 yuv2yuvX_9_start:   times 4 dd 0x20000
32 yuv2yuvX_10_upper:  times 8 dw 0x3ff
33 yuv2yuvX_9_upper:   times 8 dw 0x1ff
34 pd_4:          times 4 dd 4
35 pd_4min0x40000:times 4 dd 4 - (0x40000)
36 pw_16:         times 8 dw 16
37 pw_32:         times 8 dw 32
38 pw_512:        times 8 dw 512
39 pw_1024:       times 8 dw 1024
40
41 SECTION .text
42
43 ;-----------------------------------------------------------------------------
44 ; vertical line scaling
45 ;
46 ; void yuv2plane1_<output_size>_<opt>(const int16_t *src, uint8_t *dst, int dstW,
47 ;                                     const uint8_t *dither, int offset)
48 ; and
49 ; void yuv2planeX_<output_size>_<opt>(const int16_t *filter, int filterSize,
50 ;                                     const int16_t **src, uint8_t *dst, int dstW,
51 ;                                     const uint8_t *dither, int offset)
52 ;
53 ; Scale one or $filterSize lines of source data to generate one line of output
54 ; data. The input is 15-bit in int16_t if $output_size is [8,10] and 19-bit in
55 ; int32_t if $output_size is 16. $filter is 12-bits. $filterSize is a multiple
56 ; of 2. $offset is either 0 or 3. $dither holds 8 values.
57 ;-----------------------------------------------------------------------------
58
59 %macro yuv2planeX_fn 3
60
61 %if ARCH_X86_32
62 %define cntr_reg fltsizeq
63 %define movsx mov
64 %else
65 %define cntr_reg r11
66 %define movsx movsxd
67 %endif
68
69 cglobal yuv2planeX_%1, %3, 7, %2, filter, fltsize, src, dst, w, dither, offset
70 %if %1 == 8 || %1 == 9 || %1 == 10
71     pxor            m6,  m6
72 %endif ; %1 == 8/9/10
73
74 %if %1 == 8
75 %if ARCH_X86_32
76 %assign pad 0x2c - (stack_offset & 15)
77     SUB             rsp, pad
78 %define m_dith m7
79 %else ; x86-64
80 %define m_dith m9
81 %endif ; x86-32
82
83     ; create registers holding dither
84     movq        m_dith, [ditherq]        ; dither
85     test        offsetd, offsetd
86     jz              .no_rot
87 %if mmsize == 16
88     punpcklqdq  m_dith,  m_dith
89 %endif ; mmsize == 16
90     PALIGNR     m_dith,  m_dith,  3,  m0
91 .no_rot:
92 %if mmsize == 16
93     punpcklbw   m_dith,  m6
94 %if ARCH_X86_64
95     punpcklwd       m8,  m_dith,  m6
96     pslld           m8,  12
97 %else ; x86-32
98     punpcklwd       m5,  m_dith,  m6
99     pslld           m5,  12
100 %endif ; x86-32/64
101     punpckhwd   m_dith,  m6
102     pslld       m_dith,  12
103 %if ARCH_X86_32
104     mova      [rsp+ 0],  m5
105     mova      [rsp+16],  m_dith
106 %endif
107 %else ; mmsize == 8
108     punpcklbw       m5,  m_dith,  m6
109     punpckhbw   m_dith,  m6
110     punpcklwd       m4,  m5,  m6
111     punpckhwd       m5,  m6
112     punpcklwd       m3,  m_dith,  m6
113     punpckhwd   m_dith,  m6
114     pslld           m4,  12
115     pslld           m5,  12
116     pslld           m3,  12
117     pslld       m_dith,  12
118     mova      [rsp+ 0],  m4
119     mova      [rsp+ 8],  m5
120     mova      [rsp+16],  m3
121     mova      [rsp+24],  m_dith
122 %endif ; mmsize == 8/16
123 %endif ; %1 == 8
124
125     xor             r5,  r5
126
127 .pixelloop:
128 %assign %%i 0
129     ; the rep here is for the 8bit output mmx case, where dither covers
130     ; 8 pixels but we can only handle 2 pixels per register, and thus 4
131     ; pixels per iteration. In order to not have to keep track of where
132     ; we are w.r.t. dithering, we unroll the mmx/8bit loop x2.
133 %if %1 == 8
134 %assign %%repcnt 16/mmsize
135 %else
136 %assign %%repcnt 1
137 %endif
138
139 %rep %%repcnt
140
141 %if %1 == 8
142 %if ARCH_X86_32
143     mova            m2, [rsp+mmsize*(0+%%i)]
144     mova            m1, [rsp+mmsize*(1+%%i)]
145 %else ; x86-64
146     mova            m2,  m8
147     mova            m1,  m_dith
148 %endif ; x86-32/64
149 %else ; %1 == 9/10/16
150     mova            m1, [yuv2yuvX_%1_start]
151     mova            m2,  m1
152 %endif ; %1 == 8/9/10/16
153     movsx     cntr_reg,  fltsizem
154 .filterloop_ %+ %%i:
155     ; input pixels
156     mov             r6, [srcq+gprsize*cntr_reg-2*gprsize]
157 %if %1 == 16
158     mova            m3, [r6+r5*4]
159     mova            m5, [r6+r5*4+mmsize]
160 %else ; %1 == 8/9/10
161     mova            m3, [r6+r5*2]
162 %endif ; %1 == 8/9/10/16
163     mov             r6, [srcq+gprsize*cntr_reg-gprsize]
164 %if %1 == 16
165     mova            m4, [r6+r5*4]
166     mova            m6, [r6+r5*4+mmsize]
167 %else ; %1 == 8/9/10
168     mova            m4, [r6+r5*2]
169 %endif ; %1 == 8/9/10/16
170
171     ; coefficients
172     movd            m0, [filterq+2*cntr_reg-4] ; coeff[0], coeff[1]
173 %if %1 == 16
174     pshuflw         m7,  m0,  0          ; coeff[0]
175     pshuflw         m0,  m0,  0x55       ; coeff[1]
176     pmovsxwd        m7,  m7              ; word -> dword
177     pmovsxwd        m0,  m0              ; word -> dword
178
179     pmulld          m3,  m7
180     pmulld          m5,  m7
181     pmulld          m4,  m0
182     pmulld          m6,  m0
183
184     paddd           m2,  m3
185     paddd           m1,  m5
186     paddd           m2,  m4
187     paddd           m1,  m6
188 %else ; %1 == 10/9/8
189     punpcklwd       m5,  m3,  m4
190     punpckhwd       m3,  m4
191     SPLATD          m0,  m0
192
193     pmaddwd         m5,  m0
194     pmaddwd         m3,  m0
195
196     paddd           m2,  m5
197     paddd           m1,  m3
198 %endif ; %1 == 8/9/10/16
199
200     sub       cntr_reg,  2
201     jg .filterloop_ %+ %%i
202
203 %if %1 == 16
204     psrad           m2,  31 - %1
205     psrad           m1,  31 - %1
206 %else ; %1 == 10/9/8
207     psrad           m2,  27 - %1
208     psrad           m1,  27 - %1
209 %endif ; %1 == 8/9/10/16
210
211 %if %1 == 8
212     packssdw        m2,  m1
213     packuswb        m2,  m2
214     movh   [dstq+r5*1],  m2
215 %else ; %1 == 9/10/16
216 %if %1 == 16
217     packssdw        m2,  m1
218     paddw           m2, [minshort]
219 %else ; %1 == 9/10
220 %if cpuflag(sse4)
221     packusdw        m2,  m1
222 %else ; mmx2/sse2
223     packssdw        m2,  m1
224     pmaxsw          m2,  m6
225 %endif ; mmx2/sse2/sse4/avx
226     pminsw          m2, [yuv2yuvX_%1_upper]
227 %endif ; %1 == 9/10/16
228     mova   [dstq+r5*2],  m2
229 %endif ; %1 == 8/9/10/16
230
231     add             r5,  mmsize/2
232     sub             wd,  mmsize/2
233
234 %assign %%i %%i+2
235 %endrep
236     jg .pixelloop
237
238 %if %1 == 8
239 %if ARCH_X86_32
240     ADD             rsp, pad
241     RET
242 %else ; x86-64
243     REP_RET
244 %endif ; x86-32/64
245 %else ; %1 == 9/10/16
246     REP_RET
247 %endif ; %1 == 8/9/10/16
248 %endmacro
249
250 %define PALIGNR PALIGNR_MMX
251 %if ARCH_X86_32
252 INIT_MMX mmx2
253 yuv2planeX_fn  8,  0, 7
254 yuv2planeX_fn  9,  0, 5
255 yuv2planeX_fn 10,  0, 5
256 %endif
257
258 INIT_XMM sse2
259 yuv2planeX_fn  8, 10, 7
260 yuv2planeX_fn  9,  7, 5
261 yuv2planeX_fn 10,  7, 5
262
263 %define PALIGNR PALIGNR_SSSE3
264 INIT_XMM sse4
265 yuv2planeX_fn  8, 10, 7
266 yuv2planeX_fn  9,  7, 5
267 yuv2planeX_fn 10,  7, 5
268 yuv2planeX_fn 16,  8, 5
269
270 INIT_XMM avx
271 yuv2planeX_fn  8, 10, 7
272 yuv2planeX_fn  9,  7, 5
273 yuv2planeX_fn 10,  7, 5
274
275 ; %1=outout-bpc, %2=alignment (u/a)
276 %macro yuv2plane1_mainloop 2
277 .loop_%2:
278 %if %1 == 8
279     paddsw          m0, m2, [srcq+wq*2+mmsize*0]
280     paddsw          m1, m3, [srcq+wq*2+mmsize*1]
281     psraw           m0, 7
282     psraw           m1, 7
283     packuswb        m0, m1
284     mov%2    [dstq+wq], m0
285 %elif %1 == 16
286     paddd           m0, m4, [srcq+wq*4+mmsize*0]
287     paddd           m1, m4, [srcq+wq*4+mmsize*1]
288     paddd           m2, m4, [srcq+wq*4+mmsize*2]
289     paddd           m3, m4, [srcq+wq*4+mmsize*3]
290     psrad           m0, 3
291     psrad           m1, 3
292     psrad           m2, 3
293     psrad           m3, 3
294 %if cpuflag(sse4) ; avx/sse4
295     packusdw        m0, m1
296     packusdw        m2, m3
297 %else ; mmx/sse2
298     packssdw        m0, m1
299     packssdw        m2, m3
300     paddw           m0, m5
301     paddw           m2, m5
302 %endif ; mmx/sse2/sse4/avx
303     mov%2    [dstq+wq*2+mmsize*0], m0
304     mov%2    [dstq+wq*2+mmsize*1], m2
305 %else ; %1 == 9/10
306     paddsw          m0, m2, [srcq+wq*2+mmsize*0]
307     paddsw          m1, m2, [srcq+wq*2+mmsize*1]
308     psraw           m0, 15 - %1
309     psraw           m1, 15 - %1
310     pmaxsw          m0, m4
311     pmaxsw          m1, m4
312     pminsw          m0, m3
313     pminsw          m1, m3
314     mov%2    [dstq+wq*2+mmsize*0], m0
315     mov%2    [dstq+wq*2+mmsize*1], m1
316 %endif
317     add             wq, mmsize
318     jl .loop_%2
319 %endmacro
320
321 %macro yuv2plane1_fn 3
322 cglobal yuv2plane1_%1, %3, %3, %2, src, dst, w, dither, offset
323     movsxdifnidn    wq, wd
324     add             wq, mmsize - 1
325     and             wq, ~(mmsize - 1)
326 %if %1 == 8
327     add           dstq, wq
328 %else ; %1 != 8
329     lea           dstq, [dstq+wq*2]
330 %endif ; %1 == 8
331 %if %1 == 16
332     lea           srcq, [srcq+wq*4]
333 %else ; %1 != 16
334     lea           srcq, [srcq+wq*2]
335 %endif ; %1 == 16
336     neg             wq
337
338 %if %1 == 8
339     pxor            m4, m4               ; zero
340
341     ; create registers holding dither
342     movq            m3, [ditherq]        ; dither
343     test       offsetd, offsetd
344     jz              .no_rot
345 %if mmsize == 16
346     punpcklqdq      m3, m3
347 %endif ; mmsize == 16
348     PALIGNR_MMX     m3, m3, 3, m2
349 .no_rot:
350 %if mmsize == 8
351     mova            m2, m3
352     punpckhbw       m3, m4               ; byte->word
353     punpcklbw       m2, m4               ; byte->word
354 %else
355     punpcklbw       m3, m4
356     mova            m2, m3
357 %endif
358 %elif %1 == 9
359     pxor            m4, m4
360     mova            m3, [pw_512]
361     mova            m2, [pw_32]
362 %elif %1 == 10
363     pxor            m4, m4
364     mova            m3, [pw_1024]
365     mova            m2, [pw_16]
366 %else ; %1 == 16
367 %if cpuflag(sse4) ; sse4/avx
368     mova            m4, [pd_4]
369 %else ; mmx/sse2
370     mova            m4, [pd_4min0x40000]
371     mova            m5, [minshort]
372 %endif ; mmx/sse2/sse4/avx
373 %endif ; %1 == ..
374
375     ; actual pixel scaling
376 %if mmsize == 8
377     yuv2plane1_mainloop %1, a
378 %else ; mmsize == 16
379     test          dstq, 15
380     jnz .unaligned
381     yuv2plane1_mainloop %1, a
382     REP_RET
383 .unaligned:
384     yuv2plane1_mainloop %1, u
385 %endif ; mmsize == 8/16
386     REP_RET
387 %endmacro
388
389 %if ARCH_X86_32
390 INIT_MMX mmx
391 yuv2plane1_fn  8, 0, 5
392 yuv2plane1_fn 16, 0, 3
393
394 INIT_MMX mmx2
395 yuv2plane1_fn  9, 0, 3
396 yuv2plane1_fn 10, 0, 3
397 %endif
398
399 INIT_XMM sse2
400 yuv2plane1_fn  8, 5, 5
401 yuv2plane1_fn  9, 5, 3
402 yuv2plane1_fn 10, 5, 3
403 yuv2plane1_fn 16, 6, 3
404
405 INIT_XMM sse4
406 yuv2plane1_fn 16, 5, 3
407
408 INIT_XMM avx
409 yuv2plane1_fn  8, 5, 5
410 yuv2plane1_fn  9, 5, 3
411 yuv2plane1_fn 10, 5, 3
412 yuv2plane1_fn 16, 5, 3