Add packaging files for Tizen
[profile/ivi/pixman.git] / pixman / pixman-arm-neon-asm-bilinear.S
1 /*
2  * Copyright © 2011 SCore Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Author:  Siarhei Siamashka (siarhei.siamashka@nokia.com)
24  * Author:  Taekyun Kim (tkq.kim@samsung.com)
25  */
26
27 /*
28  * This file contains scaled bilinear scanline functions implemented
29  * using older siarhei's bilinear macro template.
30  *
31  * << General scanline function procedures >>
32  *  1. bilinear interpolate source pixels
33  *  2. load mask pixels
34  *  3. load destination pixels
35  *  4. duplicate mask to fill whole register
36  *  5. interleave source & destination pixels
37  *  6. apply mask to source pixels
38  *  7. combine source & destination pixels
39  *  8, Deinterleave final result
40  *  9. store destination pixels
41  *
42  * All registers with single number (i.e. src0, tmp0) are 64-bits registers.
43  * Registers with double numbers(src01, dst01) are 128-bits registers.
44  * All temp registers can be used freely outside the code block.
45  * Assume that symbol(register .req) OUT and MASK are defined at caller of these macro blocks.
46  *
47  * Remarks
48  *  There can be lots of pipeline stalls inside code block and between code blocks.
49  *  Further optimizations will be done by new macro templates using head/tail_head/tail scheme.
50  */
51
52 /* Prevent the stack from becoming executable for no reason... */
53 #if defined(__linux__) && defined (__ELF__)
54 .section .note.GNU-stack,"",%progbits
55 #endif
56
57 .text
58 .fpu neon
59 .arch armv7a
60 .object_arch armv4
61 .eabi_attribute 10, 0
62 .eabi_attribute 12, 0
63 .arm
64 .altmacro
65 .p2align 2
66
67 #include "pixman-arm-neon-asm.h"
68
69 /*
70  * Bilinear macros from pixman-arm-neon-asm.S
71  */
72
73 /* Supplementary macro for setting function attributes */
74 .macro pixman_asm_function fname
75     .func fname
76     .global fname
77 #ifdef __ELF__
78     .hidden fname
79     .type fname, %function
80 #endif
81 fname:
82 .endm
83
84 /*
85  * Bilinear scaling support code which tries to provide pixel fetching, color
86  * format conversion, and interpolation as separate macros which can be used
87  * as the basic building blocks for constructing bilinear scanline functions.
88  */
89
90 .macro bilinear_load_8888 reg1, reg2, tmp
91     mov       TMP1, X, asr #16
92     add       X, X, UX
93     add       TMP1, TOP, TMP1, asl #2
94     vld1.32   {reg1}, [TMP1], STRIDE
95     vld1.32   {reg2}, [TMP1]
96 .endm
97
98 .macro bilinear_load_0565 reg1, reg2, tmp
99     mov       TMP1, X, asr #16
100     add       X, X, UX
101     add       TMP1, TOP, TMP1, asl #1
102     vld1.32   {reg2[0]}, [TMP1], STRIDE
103     vld1.32   {reg2[1]}, [TMP1]
104     convert_four_0565_to_x888_packed reg2, reg1, reg2, tmp
105 .endm
106
107 .macro bilinear_load_and_vertical_interpolate_two_8888 \
108                     acc1, acc2, reg1, reg2, reg3, reg4, tmp1, tmp2
109
110     bilinear_load_8888 reg1, reg2, tmp1
111     vmull.u8  acc1, reg1, d28
112     vmlal.u8  acc1, reg2, d29
113     bilinear_load_8888 reg3, reg4, tmp2
114     vmull.u8  acc2, reg3, d28
115     vmlal.u8  acc2, reg4, d29
116 .endm
117
118 .macro bilinear_load_and_vertical_interpolate_four_8888 \
119                 xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi \
120                 yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi
121
122     bilinear_load_and_vertical_interpolate_two_8888 \
123                 xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi
124     bilinear_load_and_vertical_interpolate_two_8888 \
125                 yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi
126 .endm
127
128 .macro bilinear_load_and_vertical_interpolate_two_0565 \
129                 acc1, acc2, reg1, reg2, reg3, reg4, acc2lo, acc2hi
130
131     mov       TMP1, X, asr #16
132     add       X, X, UX
133     add       TMP1, TOP, TMP1, asl #1
134     mov       TMP2, X, asr #16
135     add       X, X, UX
136     add       TMP2, TOP, TMP2, asl #1
137     vld1.32   {acc2lo[0]}, [TMP1], STRIDE
138     vld1.32   {acc2hi[0]}, [TMP2], STRIDE
139     vld1.32   {acc2lo[1]}, [TMP1]
140     vld1.32   {acc2hi[1]}, [TMP2]
141     convert_0565_to_x888 acc2, reg3, reg2, reg1
142     vzip.u8   reg1, reg3
143     vzip.u8   reg2, reg4
144     vzip.u8   reg3, reg4
145     vzip.u8   reg1, reg2
146     vmull.u8  acc1, reg1, d28
147     vmlal.u8  acc1, reg2, d29
148     vmull.u8  acc2, reg3, d28
149     vmlal.u8  acc2, reg4, d29
150 .endm
151
152 .macro bilinear_load_and_vertical_interpolate_four_0565 \
153                 xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi \
154                 yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi
155
156     mov       TMP1, X, asr #16
157     add       X, X, UX
158     add       TMP1, TOP, TMP1, asl #1
159     mov       TMP2, X, asr #16
160     add       X, X, UX
161     add       TMP2, TOP, TMP2, asl #1
162     vld1.32   {xacc2lo[0]}, [TMP1], STRIDE
163     vld1.32   {xacc2hi[0]}, [TMP2], STRIDE
164     vld1.32   {xacc2lo[1]}, [TMP1]
165     vld1.32   {xacc2hi[1]}, [TMP2]
166     convert_0565_to_x888 xacc2, xreg3, xreg2, xreg1
167     mov       TMP1, X, asr #16
168     add       X, X, UX
169     add       TMP1, TOP, TMP1, asl #1
170     mov       TMP2, X, asr #16
171     add       X, X, UX
172     add       TMP2, TOP, TMP2, asl #1
173     vld1.32   {yacc2lo[0]}, [TMP1], STRIDE
174     vzip.u8   xreg1, xreg3
175     vld1.32   {yacc2hi[0]}, [TMP2], STRIDE
176     vzip.u8   xreg2, xreg4
177     vld1.32   {yacc2lo[1]}, [TMP1]
178     vzip.u8   xreg3, xreg4
179     vld1.32   {yacc2hi[1]}, [TMP2]
180     vzip.u8   xreg1, xreg2
181     convert_0565_to_x888 yacc2, yreg3, yreg2, yreg1
182     vmull.u8  xacc1, xreg1, d28
183     vzip.u8   yreg1, yreg3
184     vmlal.u8  xacc1, xreg2, d29
185     vzip.u8   yreg2, yreg4
186     vmull.u8  xacc2, xreg3, d28
187     vzip.u8   yreg3, yreg4
188     vmlal.u8  xacc2, xreg4, d29
189     vzip.u8   yreg1, yreg2
190     vmull.u8  yacc1, yreg1, d28
191     vmlal.u8  yacc1, yreg2, d29
192     vmull.u8  yacc2, yreg3, d28
193     vmlal.u8  yacc2, yreg4, d29
194 .endm
195
196 .macro bilinear_store_8888 numpix, tmp1, tmp2
197 .if numpix == 4
198     vst1.32   {d0, d1}, [OUT]!
199 .elseif numpix == 2
200     vst1.32   {d0}, [OUT]!
201 .elseif numpix == 1
202     vst1.32   {d0[0]}, [OUT, :32]!
203 .else
204     .error bilinear_store_8888 numpix is unsupported
205 .endif
206 .endm
207
208 .macro bilinear_store_0565 numpix, tmp1, tmp2
209     vuzp.u8 d0, d1
210     vuzp.u8 d2, d3
211     vuzp.u8 d1, d3
212     vuzp.u8 d0, d2
213     convert_8888_to_0565 d2, d1, d0, q1, tmp1, tmp2
214 .if numpix == 4
215     vst1.16   {d2}, [OUT]!
216 .elseif numpix == 2
217     vst1.32   {d2[0]}, [OUT]!
218 .elseif numpix == 1
219     vst1.16   {d2[0]}, [OUT]!
220 .else
221     .error bilinear_store_0565 numpix is unsupported
222 .endif
223 .endm
224
225
226 /*
227  * Macros for loading mask pixels into register 'mask'.
228  * vdup must be done in somewhere else.
229  */
230 .macro bilinear_load_mask_x numpix, mask
231 .endm
232
233 .macro bilinear_load_mask_8 numpix, mask
234 .if numpix == 4
235     vld1.32     {mask[0]}, [MASK]!
236 .elseif numpix == 2
237     vld1.16     {mask[0]}, [MASK]!
238 .elseif numpix == 1
239     vld1.8      {mask[0]}, [MASK]!
240 .else
241     .error bilinear_load_mask_8 numpix is unsupported
242 .endif
243     pld         [MASK, #prefetch_offset]
244 .endm
245
246 .macro bilinear_load_mask mask_fmt, numpix, mask
247     bilinear_load_mask_&mask_fmt numpix, mask
248 .endm
249
250
251 /*
252  * Macros for loading destination pixels into register 'dst0' and 'dst1'.
253  * Interleave should be done somewhere else.
254  */
255 .macro bilinear_load_dst_0565_src numpix, dst0, dst1, dst01
256 .endm
257
258 .macro bilinear_load_dst_8888_src numpix, dst0, dst1, dst01
259 .endm
260
261 .macro bilinear_load_dst_8888 numpix, dst0, dst1, dst01
262 .if numpix == 4
263     vld1.32     {dst0, dst1}, [OUT]
264 .elseif numpix == 2
265     vld1.32     {dst0}, [OUT]
266 .elseif numpix == 1
267     vld1.32     {dst0[0]}, [OUT]
268 .else
269     .error bilinear_load_dst_8888 numpix is unsupported
270 .endif
271     pld         [OUT, #(prefetch_offset * 4)]
272 .endm
273
274 .macro bilinear_load_dst_8888_over numpix, dst0, dst1, dst01
275     bilinear_load_dst_8888 numpix, dst0, dst1, dst01
276 .endm
277
278 .macro bilinear_load_dst_8888_add numpix, dst0, dst1, dst01
279     bilinear_load_dst_8888 numpix, dst0, dst1, dst01
280 .endm
281
282 .macro bilinear_load_dst dst_fmt, op, numpix, dst0, dst1, dst01
283     bilinear_load_dst_&dst_fmt&_&op numpix, dst0, dst1, dst01
284 .endm
285
286 /*
287  * Macros for duplicating partially loaded mask to fill entire register.
288  * We will apply mask to interleaved source pixels, that is
289  *  (r0, r1, r2, r3, g0, g1, g2, g3) x (m0, m1, m2, m3, m0, m1, m2, m3)
290  *  (b0, b1, b2, b3, a0, a1, a2, a3) x (m0, m1, m2, m3, m0, m1, m2, m3)
291  * So, we need to duplicate loaded mask into whole register.
292  *
293  * For two pixel case
294  *  (r0, r1, x, x, g0, g1, x, x) x (m0, m1, m0, m1, m0, m1, m0, m1)
295  *  (b0, b1, x, x, a0, a1, x, x) x (m0, m1, m0, m1, m0, m1, m0, m1)
296  * We can do some optimizations for this including last pixel cases.
297  */
298 .macro bilinear_duplicate_mask_x numpix, mask
299 .endm
300
301 .macro bilinear_duplicate_mask_8 numpix, mask
302 .if numpix == 4
303     vdup.32     mask, mask[0]
304 .elseif numpix == 2
305     vdup.16     mask, mask[0]
306 .elseif numpix == 1
307     vdup.8      mask, mask[0]
308 .else
309     .error bilinear_duplicate_mask_8 is unsupported
310 .endif
311 .endm
312
313 .macro bilinear_duplicate_mask mask_fmt, numpix, mask
314     bilinear_duplicate_mask_&mask_fmt numpix, mask
315 .endm
316
317 /*
318  * Macros for interleaving src and dst pixels to rrrr gggg bbbb aaaa form.
319  * Interleave should be done when maks is enabled or operator is 'over'.
320  */
321 .macro bilinear_interleave src0, src1, dst0, dst1
322     vuzp.8      src0, src1
323     vuzp.8      dst0, dst1
324     vuzp.8      src0, src1
325     vuzp.8      dst0, dst1
326 .endm
327
328 .macro bilinear_interleave_src_dst_x_src \
329                 numpix, src0, src1, src01, dst0, dst1, dst01
330 .endm
331
332 .macro bilinear_interleave_src_dst_x_over \
333                 numpix, src0, src1, src01, dst0, dst1, dst01
334
335     bilinear_interleave src0, src1, dst0, dst1
336 .endm
337
338 .macro bilinear_interleave_src_dst_x_add \
339                 numpix, src0, src1, src01, dst0, dst1, dst01
340 .endm
341
342 .macro bilinear_interleave_src_dst_8_src \
343                 numpix, src0, src1, src01, dst0, dst1, dst01
344
345     bilinear_interleave src0, src1, dst0, dst1
346 .endm
347
348 .macro bilinear_interleave_src_dst_8_over \
349                 numpix, src0, src1, src01, dst0, dst1, dst01
350
351     bilinear_interleave src0, src1, dst0, dst1
352 .endm
353
354 .macro bilinear_interleave_src_dst_8_add \
355                 numpix, src0, src1, src01, dst0, dst1, dst01
356
357     bilinear_interleave src0, src1, dst0, dst1
358 .endm
359
360 .macro bilinear_interleave_src_dst \
361                 mask_fmt, op, numpix, src0, src1, src01, dst0, dst1, dst01
362
363     bilinear_interleave_src_dst_&mask_fmt&_&op \
364                 numpix, src0, src1, src01, dst0, dst1, dst01
365 .endm
366
367
368 /*
369  * Macros for applying masks to src pixels. (see combine_mask_u() function)
370  * src, dst should be in interleaved form.
371  * mask register should be in form (m0, m1, m2, m3).
372  */
373 .macro bilinear_apply_mask_to_src_x \
374                 numpix, src0, src1, src01, mask, \
375                 tmp01, tmp23, tmp45, tmp67
376 .endm
377
378 .macro bilinear_apply_mask_to_src_8 \
379                 numpix, src0, src1, src01, mask, \
380                 tmp01, tmp23, tmp45, tmp67
381
382     vmull.u8        tmp01, src0, mask
383     vmull.u8        tmp23, src1, mask
384     /* bubbles */
385     vrshr.u16       tmp45, tmp01, #8
386     vrshr.u16       tmp67, tmp23, #8
387     /* bubbles */
388     vraddhn.u16     src0, tmp45, tmp01
389     vraddhn.u16     src1, tmp67, tmp23
390 .endm
391
392 .macro bilinear_apply_mask_to_src \
393                 mask_fmt, numpix, src0, src1, src01, mask, \
394                 tmp01, tmp23, tmp45, tmp67
395
396     bilinear_apply_mask_to_src_&mask_fmt \
397                 numpix, src0, src1, src01, mask, \
398                 tmp01, tmp23, tmp45, tmp67
399 .endm
400
401
402 /*
403  * Macros for combining src and destination pixels.
404  * Interleave or not is depending on operator 'op'.
405  */
406 .macro bilinear_combine_src \
407                 numpix, src0, src1, src01, dst0, dst1, dst01, \
408                 tmp01, tmp23, tmp45, tmp67, tmp8
409 .endm
410
411 .macro bilinear_combine_over \
412                 numpix, src0, src1, src01, dst0, dst1, dst01, \
413                 tmp01, tmp23, tmp45, tmp67, tmp8
414
415     vdup.32     tmp8, src1[1]
416     /* bubbles */
417     vmvn.8      tmp8, tmp8
418     /* bubbles */
419     vmull.u8    tmp01, dst0, tmp8
420     /* bubbles */
421     vmull.u8    tmp23, dst1, tmp8
422     /* bubbles */
423     vrshr.u16   tmp45, tmp01, #8
424     vrshr.u16   tmp67, tmp23, #8
425     /* bubbles */
426     vraddhn.u16 dst0, tmp45, tmp01
427     vraddhn.u16 dst1, tmp67, tmp23
428     /* bubbles */
429     vqadd.u8    src01, dst01, src01
430 .endm
431
432 .macro bilinear_combine_add \
433                 numpix, src0, src1, src01, dst0, dst1, dst01, \
434                 tmp01, tmp23, tmp45, tmp67, tmp8
435
436     vqadd.u8    src01, dst01, src01
437 .endm
438
439 .macro bilinear_combine \
440                 op, numpix, src0, src1, src01, dst0, dst1, dst01, \
441                 tmp01, tmp23, tmp45, tmp67, tmp8
442
443     bilinear_combine_&op \
444                 numpix, src0, src1, src01, dst0, dst1, dst01, \
445                 tmp01, tmp23, tmp45, tmp67, tmp8
446 .endm
447
448 /*
449  * Macros for final deinterleaving of destination pixels if needed.
450  */
451 .macro bilinear_deinterleave numpix, dst0, dst1, dst01
452     vuzp.8      dst0, dst1
453     /* bubbles */
454     vuzp.8      dst0, dst1
455 .endm
456
457 .macro bilinear_deinterleave_dst_x_src numpix, dst0, dst1, dst01
458 .endm
459
460 .macro bilinear_deinterleave_dst_x_over numpix, dst0, dst1, dst01
461     bilinear_deinterleave numpix, dst0, dst1, dst01
462 .endm
463
464 .macro bilinear_deinterleave_dst_x_add numpix, dst0, dst1, dst01
465 .endm
466
467 .macro bilinear_deinterleave_dst_8_src numpix, dst0, dst1, dst01
468     bilinear_deinterleave numpix, dst0, dst1, dst01
469 .endm
470
471 .macro bilinear_deinterleave_dst_8_over numpix, dst0, dst1, dst01
472     bilinear_deinterleave numpix, dst0, dst1, dst01
473 .endm
474
475 .macro bilinear_deinterleave_dst_8_add numpix, dst0, dst1, dst01
476     bilinear_deinterleave numpix, dst0, dst1, dst01
477 .endm
478
479 .macro bilinear_deinterleave_dst mask_fmt, op, numpix, dst0, dst1, dst01
480     bilinear_deinterleave_dst_&mask_fmt&_&op numpix, dst0, dst1, dst01
481 .endm
482
483
484 .macro bilinear_interpolate_last_pixel src_fmt, mask_fmt, dst_fmt, op
485     bilinear_load_&src_fmt d0, d1, d2
486     bilinear_load_mask mask_fmt, 1, d4
487     bilinear_load_dst dst_fmt, op, 1, d18, d19, q9
488     vmull.u8  q1, d0, d28
489     vmlal.u8  q1, d1, d29
490     /* 5 cycles bubble */
491     vshll.u16 q0, d2, #8
492     vmlsl.u16 q0, d2, d30
493     vmlal.u16 q0, d3, d30
494     /* 5 cycles bubble */
495     bilinear_duplicate_mask mask_fmt, 1, d4
496     vshrn.u32 d0, q0, #16
497     /* 3 cycles bubble */
498     vmovn.u16 d0, q0
499     /* 1 cycle bubble */
500     bilinear_interleave_src_dst \
501                 mask_fmt, op, 1, d0, d1, q0, d18, d19, q9
502     bilinear_apply_mask_to_src \
503                 mask_fmt, 1, d0, d1, q0, d4, \
504                 q3, q8, q10, q11
505     bilinear_combine \
506                 op, 1, d0, d1, q0, d18, d19, q9, \
507                 q3, q8, q10, q11, d5
508     bilinear_deinterleave_dst mask_fmt, op, 1, d0, d1, q0
509     bilinear_store_&dst_fmt 1, q2, q3
510 .endm
511
512 .macro bilinear_interpolate_two_pixels src_fmt, mask_fmt, dst_fmt, op
513     bilinear_load_and_vertical_interpolate_two_&src_fmt \
514                 q1, q11, d0, d1, d20, d21, d22, d23
515     bilinear_load_mask mask_fmt, 2, d4
516     bilinear_load_dst dst_fmt, op, 2, d18, d19, q9
517     vshll.u16 q0, d2, #8
518     vmlsl.u16 q0, d2, d30
519     vmlal.u16 q0, d3, d30
520     vshll.u16 q10, d22, #8
521     vmlsl.u16 q10, d22, d31
522     vmlal.u16 q10, d23, d31
523     vshrn.u32 d0, q0, #16
524     vshrn.u32 d1, q10, #16
525     bilinear_duplicate_mask mask_fmt, 2, d4
526     vshr.u16  q15, q12, #8
527     vadd.u16  q12, q12, q13
528     vmovn.u16 d0, q0
529     bilinear_interleave_src_dst \
530                 mask_fmt, op, 2, d0, d1, q0, d18, d19, q9
531     bilinear_apply_mask_to_src \
532                 mask_fmt, 2, d0, d1, q0, d4, \
533                 q3, q8, q10, q11
534     bilinear_combine \
535                 op, 2, d0, d1, q0, d18, d19, q9, \
536                 q3, q8, q10, q11, d5
537     bilinear_deinterleave_dst mask_fmt, op, 2, d0, d1, q0
538     bilinear_store_&dst_fmt 2, q2, q3
539 .endm
540
541 .macro bilinear_interpolate_four_pixels src_fmt, mask_fmt, dst_fmt, op
542     bilinear_load_and_vertical_interpolate_four_&src_fmt \
543                 q1, q11, d0, d1, d20, d21, d22, d23 \
544                 q3, q9,  d4, d5, d16, d17, d18, d19
545     pld       [TMP1, PF_OFFS]
546     sub       TMP1, TMP1, STRIDE
547     vshll.u16 q0, d2, #8
548     vmlsl.u16 q0, d2, d30
549     vmlal.u16 q0, d3, d30
550     vshll.u16 q10, d22, #8
551     vmlsl.u16 q10, d22, d31
552     vmlal.u16 q10, d23, d31
553     vshr.u16  q15, q12, #8
554     vshll.u16 q2, d6, #8
555     vmlsl.u16 q2, d6, d30
556     vmlal.u16 q2, d7, d30
557     vshll.u16 q8, d18, #8
558     bilinear_load_mask mask_fmt, 4, d22
559     bilinear_load_dst dst_fmt, op, 4, d2, d3, q1
560     pld       [TMP1, PF_OFFS]
561     vmlsl.u16 q8, d18, d31
562     vmlal.u16 q8, d19, d31
563     vadd.u16  q12, q12, q13
564     vshrn.u32 d0, q0, #16
565     vshrn.u32 d1, q10, #16
566     vshrn.u32 d4, q2, #16
567     vshrn.u32 d5, q8, #16
568     bilinear_duplicate_mask mask_fmt, 4, d22
569     vshr.u16  q15, q12, #8
570     vmovn.u16 d0, q0
571     vmovn.u16 d1, q2
572     vadd.u16  q12, q12, q13
573     bilinear_interleave_src_dst \
574                 mask_fmt, op, 4, d0, d1, q0, d2, d3, q1
575     bilinear_apply_mask_to_src \
576                 mask_fmt, 4, d0, d1, q0, d22, \
577                 q3, q8, q9, q10
578     bilinear_combine \
579                 op, 4, d0, d1, q0, d2, d3, q1, \
580                 q3, q8, q9, q10, d23
581     bilinear_deinterleave_dst mask_fmt, op, 4, d0, d1, q0
582     bilinear_store_&dst_fmt 4, q2, q3
583 .endm
584
585 .set BILINEAR_FLAG_USE_MASK,            1
586 .set BILINEAR_FLAG_USE_ALL_NEON_REGS,   2
587
588 /*
589  * Main template macro for generating NEON optimized bilinear scanline functions.
590  *
591  * Bilinear scanline generator macro take folling arguments:
592  *  fname                       - name of the function to generate
593  *  src_fmt                     - source color format (8888 or 0565)
594  *  dst_fmt                     - destination color format (8888 or 0565)
595  *  src/dst_bpp_shift           - (1 << bpp_shift) is the size of src/dst pixel in bytes
596  *  process_last_pixel          - code block that interpolate one pixel and does not
597  *                                update horizontal weight
598  *  process_two_pixels          - code block that interpolate two pixels and update
599  *                                horizontal weight
600  *  process_four_pixels         - code block that interpolate four pixels and update
601  *                                horizontal weight
602  *  process_pixblock_head       - head part of middle loop
603  *  process_pixblock_tail       - tail part of middle loop
604  *  process_pixblock_tail_head  - tail_head of middle loop
605  *  pixblock_size               - number of pixels processed in a single middle loop
606  *  prefetch_distance           - prefetch in the source image by that many pixels ahead
607  */
608
609 .macro generate_bilinear_scanline_func \
610         fname, \
611         src_fmt, dst_fmt, src_bpp_shift, dst_bpp_shift, \
612         bilinear_process_last_pixel, \
613         bilinear_process_two_pixels, \
614         bilinear_process_four_pixels, \
615         bilinear_process_pixblock_head, \
616         bilinear_process_pixblock_tail, \
617         bilinear_process_pixblock_tail_head, \
618         pixblock_size, \
619         prefetch_distance, \
620         flags
621
622 pixman_asm_function fname
623 .if pixblock_size == 8
624 .elseif pixblock_size == 4
625 .else
626     .error unsupported pixblock size
627 .endif
628
629 .if ((flags) & BILINEAR_FLAG_USE_MASK) == 0
630     OUT       .req    r0
631     TOP       .req    r1
632     BOTTOM    .req    r2
633     WT        .req    r3
634     WB        .req    r4
635     X         .req    r5
636     UX        .req    r6
637     WIDTH     .req    ip
638     TMP1      .req    r3
639     TMP2      .req    r4
640     PF_OFFS   .req    r7
641     TMP3      .req    r8
642     TMP4      .req    r9
643     STRIDE    .req    r2
644
645     mov         ip, sp
646     push        {r4, r5, r6, r7, r8, r9}
647     mov         PF_OFFS, #prefetch_distance
648     ldmia       ip, {WB, X, UX, WIDTH}
649 .else
650     OUT       .req      r0
651     MASK      .req      r1
652     TOP       .req      r2
653     BOTTOM    .req      r3
654     WT        .req      r4
655     WB        .req      r5
656     X         .req      r6
657     UX        .req      r7
658     WIDTH     .req      ip
659     TMP1      .req      r4
660     TMP2      .req      r5
661     PF_OFFS   .req      r8
662     TMP3      .req      r9
663     TMP4      .req      r10
664     STRIDE    .req      r3
665
666     .set prefetch_offset, prefetch_distance
667
668     mov       ip, sp
669     push      {r4, r5, r6, r7, r8, r9, r10, ip}
670     mov       PF_OFFS, #prefetch_distance
671     ldmia     ip, {WT, WB, X, UX, WIDTH}
672 .endif
673
674     mul       PF_OFFS, PF_OFFS, UX
675
676 .if ((flags) & BILINEAR_FLAG_USE_ALL_NEON_REGS) != 0
677     vpush     {d8-d15}
678 .endif
679
680     sub       STRIDE, BOTTOM, TOP
681     .unreq    BOTTOM
682
683     cmp       WIDTH, #0
684     ble       3f
685
686     vdup.u16  q12, X
687     vdup.u16  q13, UX
688     vdup.u8   d28, WT
689     vdup.u8   d29, WB
690     vadd.u16  d25, d25, d26
691
692     /* ensure good destination alignment  */
693     cmp       WIDTH, #1
694     blt       0f
695     tst       OUT, #(1 << dst_bpp_shift)
696     beq       0f
697     vshr.u16  q15, q12, #8
698     vadd.u16  q12, q12, q13
699     bilinear_process_last_pixel
700     sub       WIDTH, WIDTH, #1
701 0:
702     vadd.u16  q13, q13, q13
703     vshr.u16  q15, q12, #8
704     vadd.u16  q12, q12, q13
705
706     cmp       WIDTH, #2
707     blt       0f
708     tst       OUT, #(1 << (dst_bpp_shift + 1))
709     beq       0f
710     bilinear_process_two_pixels
711     sub       WIDTH, WIDTH, #2
712 0:
713 .if pixblock_size == 8
714     cmp       WIDTH, #4
715     blt       0f
716     tst       OUT, #(1 << (dst_bpp_shift + 2))
717     beq       0f
718     bilinear_process_four_pixels
719     sub       WIDTH, WIDTH, #4
720 0:
721 .endif
722     subs      WIDTH, WIDTH, #pixblock_size
723     blt       1f
724     mov       PF_OFFS, PF_OFFS, asr #(16 - src_bpp_shift)
725     bilinear_process_pixblock_head
726     subs      WIDTH, WIDTH, #pixblock_size
727     blt       5f
728 0:
729     bilinear_process_pixblock_tail_head
730     subs      WIDTH, WIDTH, #pixblock_size
731     bge       0b
732 5:
733     bilinear_process_pixblock_tail
734 1:
735 .if pixblock_size == 8
736     tst       WIDTH, #4
737     beq       2f
738     bilinear_process_four_pixels
739 2:
740 .endif
741     /* handle the remaining trailing pixels */
742     tst       WIDTH, #2
743     beq       2f
744     bilinear_process_two_pixels
745 2:
746     tst       WIDTH, #1
747     beq       3f
748     bilinear_process_last_pixel
749 3:
750 .if ((flags) & BILINEAR_FLAG_USE_ALL_NEON_REGS) != 0
751     vpop      {d8-d15}
752 .endif
753
754 .if ((flags) & BILINEAR_FLAG_USE_MASK) == 0
755     pop       {r4, r5, r6, r7, r8, r9}
756 .else
757     pop       {r4, r5, r6, r7, r8, r9, r10, ip}
758 .endif
759     bx        lr
760
761     .unreq    OUT
762     .unreq    TOP
763     .unreq    WT
764     .unreq    WB
765     .unreq    X
766     .unreq    UX
767     .unreq    WIDTH
768     .unreq    TMP1
769     .unreq    TMP2
770     .unreq    PF_OFFS
771     .unreq    TMP3
772     .unreq    TMP4
773     .unreq    STRIDE
774 .if ((flags) & BILINEAR_FLAG_USE_MASK) != 0
775     .unreq    MASK
776 .endif
777
778 .endfunc
779
780 .endm
781
782 /* src_8888_8_8888 */
783 .macro bilinear_src_8888_8_8888_process_last_pixel
784     bilinear_interpolate_last_pixel 8888, 8, 8888, src
785 .endm
786
787 .macro bilinear_src_8888_8_8888_process_two_pixels
788     bilinear_interpolate_two_pixels 8888, 8, 8888, src
789 .endm
790
791 .macro bilinear_src_8888_8_8888_process_four_pixels
792     bilinear_interpolate_four_pixels 8888, 8, 8888, src
793 .endm
794
795 .macro bilinear_src_8888_8_8888_process_pixblock_head
796     bilinear_src_8888_8_8888_process_four_pixels
797 .endm
798
799 .macro bilinear_src_8888_8_8888_process_pixblock_tail
800 .endm
801
802 .macro bilinear_src_8888_8_8888_process_pixblock_tail_head
803     bilinear_src_8888_8_8888_process_pixblock_tail
804     bilinear_src_8888_8_8888_process_pixblock_head
805 .endm
806
807 /* src_8888_8_0565 */
808 .macro bilinear_src_8888_8_0565_process_last_pixel
809     bilinear_interpolate_last_pixel 8888, 8, 0565, src
810 .endm
811
812 .macro bilinear_src_8888_8_0565_process_two_pixels
813     bilinear_interpolate_two_pixels 8888, 8, 0565, src
814 .endm
815
816 .macro bilinear_src_8888_8_0565_process_four_pixels
817     bilinear_interpolate_four_pixels 8888, 8, 0565, src
818 .endm
819
820 .macro bilinear_src_8888_8_0565_process_pixblock_head
821     bilinear_src_8888_8_0565_process_four_pixels
822 .endm
823
824 .macro bilinear_src_8888_8_0565_process_pixblock_tail
825 .endm
826
827 .macro bilinear_src_8888_8_0565_process_pixblock_tail_head
828     bilinear_src_8888_8_0565_process_pixblock_tail
829     bilinear_src_8888_8_0565_process_pixblock_head
830 .endm
831
832 /* src_0565_8_x888 */
833 .macro bilinear_src_0565_8_x888_process_last_pixel
834     bilinear_interpolate_last_pixel 0565, 8, 8888, src
835 .endm
836
837 .macro bilinear_src_0565_8_x888_process_two_pixels
838     bilinear_interpolate_two_pixels 0565, 8, 8888, src
839 .endm
840
841 .macro bilinear_src_0565_8_x888_process_four_pixels
842     bilinear_interpolate_four_pixels 0565, 8, 8888, src
843 .endm
844
845 .macro bilinear_src_0565_8_x888_process_pixblock_head
846     bilinear_src_0565_8_x888_process_four_pixels
847 .endm
848
849 .macro bilinear_src_0565_8_x888_process_pixblock_tail
850 .endm
851
852 .macro bilinear_src_0565_8_x888_process_pixblock_tail_head
853     bilinear_src_0565_8_x888_process_pixblock_tail
854     bilinear_src_0565_8_x888_process_pixblock_head
855 .endm
856
857 /* src_0565_8_0565 */
858 .macro bilinear_src_0565_8_0565_process_last_pixel
859     bilinear_interpolate_last_pixel 0565, 8, 0565, src
860 .endm
861
862 .macro bilinear_src_0565_8_0565_process_two_pixels
863     bilinear_interpolate_two_pixels 0565, 8, 0565, src
864 .endm
865
866 .macro bilinear_src_0565_8_0565_process_four_pixels
867     bilinear_interpolate_four_pixels 0565, 8, 0565, src
868 .endm
869
870 .macro bilinear_src_0565_8_0565_process_pixblock_head
871     bilinear_src_0565_8_0565_process_four_pixels
872 .endm
873
874 .macro bilinear_src_0565_8_0565_process_pixblock_tail
875 .endm
876
877 .macro bilinear_src_0565_8_0565_process_pixblock_tail_head
878     bilinear_src_0565_8_0565_process_pixblock_tail
879     bilinear_src_0565_8_0565_process_pixblock_head
880 .endm
881
882 /* over_8888_8888 */
883 .macro bilinear_over_8888_8888_process_last_pixel
884     bilinear_interpolate_last_pixel 8888, x, 8888, over
885 .endm
886
887 .macro bilinear_over_8888_8888_process_two_pixels
888     bilinear_interpolate_two_pixels 8888, x, 8888, over
889 .endm
890
891 .macro bilinear_over_8888_8888_process_four_pixels
892     bilinear_interpolate_four_pixels 8888, x, 8888, over
893 .endm
894
895 .macro bilinear_over_8888_8888_process_pixblock_head
896     mov         TMP1, X, asr #16
897     add         X, X, UX
898     add         TMP1, TOP, TMP1, asl #2
899     mov         TMP2, X, asr #16
900     add         X, X, UX
901     add         TMP2, TOP, TMP2, asl #2
902
903     vld1.32     {d22}, [TMP1], STRIDE
904     vld1.32     {d23}, [TMP1]
905     mov         TMP3, X, asr #16
906     add         X, X, UX
907     add         TMP3, TOP, TMP3, asl #2
908     vmull.u8    q8, d22, d28
909     vmlal.u8    q8, d23, d29
910
911     vld1.32     {d22}, [TMP2], STRIDE
912     vld1.32     {d23}, [TMP2]
913     mov         TMP4, X, asr #16
914     add         X, X, UX
915     add         TMP4, TOP, TMP4, asl #2
916     vmull.u8    q9, d22, d28
917     vmlal.u8    q9, d23, d29
918
919     vld1.32     {d22}, [TMP3], STRIDE
920     vld1.32     {d23}, [TMP3]
921     vmull.u8    q10, d22, d28
922     vmlal.u8    q10, d23, d29
923
924     vshll.u16   q0, d16, #8
925     vmlsl.u16   q0, d16, d30
926     vmlal.u16   q0, d17, d30
927
928     pld         [TMP4, PF_OFFS]
929     vld1.32     {d16}, [TMP4], STRIDE
930     vld1.32     {d17}, [TMP4]
931     pld         [TMP4, PF_OFFS]
932     vmull.u8    q11, d16, d28
933     vmlal.u8    q11, d17, d29
934
935     vshll.u16   q1, d18, #8
936     vmlsl.u16   q1, d18, d31
937     vmlal.u16   q1, d19, d31
938     vshr.u16    q15, q12, #8
939     vadd.u16    q12, q12, q13
940 .endm
941
942 .macro bilinear_over_8888_8888_process_pixblock_tail
943     vshll.u16   q2, d20, #8
944     vmlsl.u16   q2, d20, d30
945     vmlal.u16   q2, d21, d30
946     vshll.u16   q3, d22, #8
947     vmlsl.u16   q3, d22, d31
948     vmlal.u16   q3, d23, d31
949     vshrn.u32   d0, q0, #16
950     vshrn.u32   d1, q1, #16
951     vld1.32     {d2, d3}, [OUT, :128]
952     pld         [OUT, #(prefetch_offset * 4)]
953     vshrn.u32   d4, q2, #16
954     vshr.u16    q15, q12, #8
955     vshrn.u32   d5, q3, #16
956     vmovn.u16   d6, q0
957     vmovn.u16   d7, q2
958     vuzp.8      d6, d7
959     vuzp.8      d2, d3
960     vuzp.8      d6, d7
961     vuzp.8      d2, d3
962     vdup.32     d4, d7[1]
963     vmvn.8      d4, d4
964     vmull.u8    q11, d2, d4
965     vmull.u8    q2, d3, d4
966     vrshr.u16   q1, q11, #8
967     vrshr.u16   q10, q2, #8
968     vraddhn.u16 d2, q1, q11
969     vraddhn.u16 d3, q10, q2
970     vqadd.u8    q3, q1, q3
971     vuzp.8      d6, d7
972     vuzp.8      d6, d7
973     vadd.u16    q12, q12, q13
974     vst1.32     {d6, d7}, [OUT, :128]!
975 .endm
976
977 .macro bilinear_over_8888_8888_process_pixblock_tail_head
978                                             vshll.u16   q2, d20, #8
979     mov         TMP1, X, asr #16
980     add         X, X, UX
981     add         TMP1, TOP, TMP1, asl #2
982                                             vmlsl.u16   q2, d20, d30
983     mov         TMP2, X, asr #16
984     add         X, X, UX
985     add         TMP2, TOP, TMP2, asl #2
986                                             vmlal.u16   q2, d21, d30
987                                             vshll.u16   q3, d22, #8
988     vld1.32     {d20}, [TMP1], STRIDE
989                                             vmlsl.u16   q3, d22, d31
990                                             vmlal.u16   q3, d23, d31
991     vld1.32     {d21}, [TMP1]
992     vmull.u8    q8, d20, d28
993     vmlal.u8    q8, d21, d29
994                                             vshrn.u32   d0, q0, #16
995                                             vshrn.u32   d1, q1, #16
996                                             vld1.32     {d2, d3}, [OUT, :128]
997                                             pld         [OUT, PF_OFFS]
998                                             vshrn.u32   d4, q2, #16
999                                             vshr.u16    q15, q12, #8
1000     vld1.32     {d22}, [TMP2], STRIDE
1001                                             vshrn.u32   d5, q3, #16
1002                                             vmovn.u16   d6, q0
1003     vld1.32     {d23}, [TMP2]
1004     vmull.u8    q9, d22, d28
1005     mov         TMP3, X, asr #16
1006     add         X, X, UX
1007     add         TMP3, TOP, TMP3, asl #2
1008     mov         TMP4, X, asr #16
1009     add         X, X, UX
1010     add         TMP4, TOP, TMP4, asl #2
1011     vmlal.u8    q9, d23, d29
1012                                             vmovn.u16   d7, q2
1013     vld1.32     {d22}, [TMP3], STRIDE
1014                                             vuzp.8      d6, d7
1015                                             vuzp.8      d2, d3
1016                                             vuzp.8      d6, d7
1017                                             vuzp.8      d2, d3
1018                                             vdup.32     d4, d7[1]
1019     vld1.32     {d23}, [TMP3]
1020                                             vmvn.8      d4, d4
1021     vmull.u8    q10, d22, d28
1022     vmlal.u8    q10, d23, d29
1023                                             vmull.u8    q11, d2, d4
1024                                             vmull.u8    q2, d3, d4
1025     vshll.u16   q0, d16, #8
1026     vmlsl.u16   q0, d16, d30
1027                                             vrshr.u16   q1, q11, #8
1028     vmlal.u16   q0, d17, d30
1029                                             vrshr.u16   q8, q2, #8
1030                                             vraddhn.u16 d2, q1, q11
1031                                             vraddhn.u16 d3, q8, q2
1032     pld         [TMP4, PF_OFFS]
1033     vld1.32     {d16}, [TMP4], STRIDE
1034                                             vqadd.u8    q3, q1, q3
1035     vld1.32     {d17}, [TMP4]
1036     pld         [TMP4, PF_OFFS]
1037     vmull.u8    q11, d16, d28
1038     vmlal.u8    q11, d17, d29
1039                                             vuzp.8      d6, d7
1040     vshll.u16   q1, d18, #8
1041                                             vuzp.8      d6, d7
1042     vmlsl.u16   q1, d18, d31
1043                                             vadd.u16    q12, q12, q13
1044     vmlal.u16   q1, d19, d31
1045     vshr.u16    q15, q12, #8
1046     vadd.u16    q12, q12, q13
1047                                             vst1.32     {d6, d7}, [OUT, :128]!
1048 .endm
1049
1050 /* over_8888_8_8888 */
1051 .macro bilinear_over_8888_8_8888_process_last_pixel
1052     bilinear_interpolate_last_pixel 8888, 8, 8888, over
1053 .endm
1054
1055 .macro bilinear_over_8888_8_8888_process_two_pixels
1056     bilinear_interpolate_two_pixels 8888, 8, 8888, over
1057 .endm
1058
1059 .macro bilinear_over_8888_8_8888_process_four_pixels
1060     bilinear_interpolate_four_pixels 8888, 8, 8888, over
1061 .endm
1062
1063 .macro bilinear_over_8888_8_8888_process_pixblock_head
1064     mov         TMP1, X, asr #16
1065     add         X, X, UX
1066     add         TMP1, TOP, TMP1, asl #2
1067     vld1.32     {d0}, [TMP1], STRIDE
1068     mov         TMP2, X, asr #16
1069     add         X, X, UX
1070     add         TMP2, TOP, TMP2, asl #2
1071     vld1.32     {d1}, [TMP1]
1072     mov         TMP3, X, asr #16
1073     add         X, X, UX
1074     add         TMP3, TOP, TMP3, asl #2
1075     vld1.32     {d2}, [TMP2], STRIDE
1076     mov         TMP4, X, asr #16
1077     add         X, X, UX
1078     add         TMP4, TOP, TMP4, asl #2
1079     vld1.32     {d3}, [TMP2]
1080     vmull.u8    q2, d0, d28
1081     vmull.u8    q3, d2, d28
1082     vmlal.u8    q2, d1, d29
1083     vmlal.u8    q3, d3, d29
1084     vshll.u16   q0, d4, #8
1085     vshll.u16   q1, d6, #8
1086     vmlsl.u16   q0, d4, d30
1087     vmlsl.u16   q1, d6, d31
1088     vmlal.u16   q0, d5, d30
1089     vmlal.u16   q1, d7, d31
1090     vshrn.u32   d0, q0, #16
1091     vshrn.u32   d1, q1, #16
1092     vld1.32     {d2}, [TMP3], STRIDE
1093     vld1.32     {d3}, [TMP3]
1094     pld         [TMP4, PF_OFFS]
1095     vld1.32     {d4}, [TMP4], STRIDE
1096     vld1.32     {d5}, [TMP4]
1097     pld         [TMP4, PF_OFFS]
1098     vmull.u8    q3, d2, d28
1099     vmlal.u8    q3, d3, d29
1100     vmull.u8    q1, d4, d28
1101     vmlal.u8    q1, d5, d29
1102     vshr.u16    q15, q12, #8
1103     vld1.32     {d22[0]}, [MASK]!
1104     pld         [MASK, #prefetch_offset]
1105     vadd.u16    q12, q12, q13
1106     vmovn.u16   d16, q0
1107 .endm
1108
1109 .macro bilinear_over_8888_8_8888_process_pixblock_tail
1110     vshll.u16   q9, d6, #8
1111     vshll.u16   q10, d2, #8
1112     vmlsl.u16   q9, d6, d30
1113     vmlsl.u16   q10, d2, d31
1114     vmlal.u16   q9, d7, d30
1115     vmlal.u16   q10, d3, d31
1116     vshr.u16    q15, q12, #8
1117     vadd.u16    q12, q12, q13
1118     vdup.32     d22, d22[0]
1119     vshrn.u32   d18, q9, #16
1120     vshrn.u32   d19, q10, #16
1121     vmovn.u16   d17, q9
1122     vld1.32     {d18, d19}, [OUT, :128]
1123     pld         [OUT, PF_OFFS]
1124     vuzp.8      d16, d17
1125     vuzp.8      d18, d19
1126     vuzp.8      d16, d17
1127     vuzp.8      d18, d19
1128     vmull.u8    q10, d16, d22
1129     vmull.u8    q11, d17, d22
1130     vrsra.u16   q10, q10, #8
1131     vrsra.u16   q11, q11, #8
1132     vrshrn.u16  d16, q10, #8
1133     vrshrn.u16  d17, q11, #8
1134     vdup.32     d22, d17[1]
1135     vmvn.8      d22, d22
1136     vmull.u8    q10, d18, d22
1137     vmull.u8    q11, d19, d22
1138     vrshr.u16   q9, q10, #8
1139     vrshr.u16   q0, q11, #8
1140     vraddhn.u16 d18, q9, q10
1141     vraddhn.u16 d19, q0, q11
1142     vqadd.u8    q9, q8, q9
1143     vuzp.8      d18, d19
1144     vuzp.8      d18, d19
1145     vst1.32     {d18, d19}, [OUT, :128]!
1146 .endm
1147
1148 .macro bilinear_over_8888_8_8888_process_pixblock_tail_head
1149                                             vshll.u16   q9, d6, #8
1150     mov         TMP1, X, asr #16
1151     add         X, X, UX
1152     add         TMP1, TOP, TMP1, asl #2
1153                                             vshll.u16   q10, d2, #8
1154     vld1.32     {d0}, [TMP1], STRIDE
1155     mov         TMP2, X, asr #16
1156     add         X, X, UX
1157     add         TMP2, TOP, TMP2, asl #2
1158                                             vmlsl.u16   q9, d6, d30
1159                                             vmlsl.u16   q10, d2, d31
1160     vld1.32     {d1}, [TMP1]
1161     mov         TMP3, X, asr #16
1162     add         X, X, UX
1163     add         TMP3, TOP, TMP3, asl #2
1164                                             vmlal.u16   q9, d7, d30
1165                                             vmlal.u16   q10, d3, d31
1166     vld1.32     {d2}, [TMP2], STRIDE
1167     mov         TMP4, X, asr #16
1168     add         X, X, UX
1169     add         TMP4, TOP, TMP4, asl #2
1170                                             vshr.u16    q15, q12, #8
1171                                             vadd.u16    q12, q12, q13
1172     vld1.32     {d3}, [TMP2]
1173                                             vdup.32     d22, d22[0]
1174                                             vshrn.u32   d18, q9, #16
1175                                             vshrn.u32   d19, q10, #16
1176     vmull.u8    q2, d0, d28
1177     vmull.u8    q3, d2, d28
1178                                             vmovn.u16   d17, q9
1179                                             vld1.32     {d18, d19}, [OUT, :128]
1180                                             pld         [OUT, #(prefetch_offset * 4)]
1181     vmlal.u8    q2, d1, d29
1182     vmlal.u8    q3, d3, d29
1183                                             vuzp.8      d16, d17
1184                                             vuzp.8      d18, d19
1185     vshll.u16   q0, d4, #8
1186     vshll.u16   q1, d6, #8
1187                                             vuzp.8      d16, d17
1188                                             vuzp.8      d18, d19
1189     vmlsl.u16   q0, d4, d30
1190     vmlsl.u16   q1, d6, d31
1191                                             vmull.u8    q10, d16, d22
1192                                             vmull.u8    q11, d17, d22
1193     vmlal.u16   q0, d5, d30
1194     vmlal.u16   q1, d7, d31
1195                                             vrsra.u16   q10, q10, #8
1196                                             vrsra.u16   q11, q11, #8
1197     vshrn.u32   d0, q0, #16
1198     vshrn.u32   d1, q1, #16
1199                                             vrshrn.u16  d16, q10, #8
1200                                             vrshrn.u16  d17, q11, #8
1201     vld1.32     {d2}, [TMP3], STRIDE
1202                                             vdup.32     d22, d17[1]
1203     vld1.32     {d3}, [TMP3]
1204                                             vmvn.8      d22, d22
1205     pld         [TMP4, PF_OFFS]
1206     vld1.32     {d4}, [TMP4], STRIDE
1207                                             vmull.u8    q10, d18, d22
1208                                             vmull.u8    q11, d19, d22
1209     vld1.32     {d5}, [TMP4]
1210     pld         [TMP4, PF_OFFS]
1211     vmull.u8    q3, d2, d28
1212                                             vrshr.u16   q9, q10, #8
1213                                             vrshr.u16   q15, q11, #8
1214     vmlal.u8    q3, d3, d29
1215     vmull.u8    q1, d4, d28
1216                                             vraddhn.u16 d18, q9, q10
1217                                             vraddhn.u16 d19, q15, q11
1218     vmlal.u8    q1, d5, d29
1219     vshr.u16    q15, q12, #8
1220                                             vqadd.u8    q9, q8, q9
1221     vld1.32     {d22[0]}, [MASK]!
1222                                             vuzp.8      d18, d19
1223     vadd.u16    q12, q12, q13
1224                                             vuzp.8      d18, d19
1225     vmovn.u16   d16, q0
1226                                             vst1.32     {d18, d19}, [OUT, :128]!
1227 .endm
1228
1229 /* add_8888_8888 */
1230 .macro bilinear_add_8888_8888_process_last_pixel
1231     bilinear_interpolate_last_pixel 8888, x, 8888, add
1232 .endm
1233
1234 .macro bilinear_add_8888_8888_process_two_pixels
1235     bilinear_interpolate_two_pixels 8888, x, 8888, add
1236 .endm
1237
1238 .macro bilinear_add_8888_8888_process_four_pixels
1239     bilinear_interpolate_four_pixels 8888, x, 8888, add
1240 .endm
1241
1242 .macro bilinear_add_8888_8888_process_pixblock_head
1243     bilinear_add_8888_8888_process_four_pixels
1244 .endm
1245
1246 .macro bilinear_add_8888_8888_process_pixblock_tail
1247 .endm
1248
1249 .macro bilinear_add_8888_8888_process_pixblock_tail_head
1250     bilinear_add_8888_8888_process_pixblock_tail
1251     bilinear_add_8888_8888_process_pixblock_head
1252 .endm
1253
1254 /* add_8888_8_8888 */
1255 .macro bilinear_add_8888_8_8888_process_last_pixel
1256     bilinear_interpolate_last_pixel 8888, 8, 8888, add
1257 .endm
1258
1259 .macro bilinear_add_8888_8_8888_process_two_pixels
1260     bilinear_interpolate_two_pixels 8888, 8, 8888, add
1261 .endm
1262
1263 .macro bilinear_add_8888_8_8888_process_four_pixels
1264     bilinear_interpolate_four_pixels 8888, 8, 8888, add
1265 .endm
1266
1267 .macro bilinear_add_8888_8_8888_process_pixblock_head
1268     bilinear_add_8888_8_8888_process_four_pixels
1269 .endm
1270
1271 .macro bilinear_add_8888_8_8888_process_pixblock_tail
1272 .endm
1273
1274 .macro bilinear_add_8888_8_8888_process_pixblock_tail_head
1275     bilinear_add_8888_8_8888_process_pixblock_tail
1276     bilinear_add_8888_8_8888_process_pixblock_head
1277 .endm
1278
1279
1280 /* Bilinear scanline functions */
1281 generate_bilinear_scanline_func \
1282     pixman_scaled_bilinear_scanline_8888_8_8888_SRC_asm_neon, \
1283     8888, 8888, 2, 2, \
1284     bilinear_src_8888_8_8888_process_last_pixel, \
1285     bilinear_src_8888_8_8888_process_two_pixels, \
1286     bilinear_src_8888_8_8888_process_four_pixels, \
1287     bilinear_src_8888_8_8888_process_pixblock_head, \
1288     bilinear_src_8888_8_8888_process_pixblock_tail, \
1289     bilinear_src_8888_8_8888_process_pixblock_tail_head, \
1290     4, 28, BILINEAR_FLAG_USE_MASK
1291
1292 generate_bilinear_scanline_func \
1293     pixman_scaled_bilinear_scanline_8888_8_0565_SRC_asm_neon, \
1294     8888, 0565, 2, 1, \
1295     bilinear_src_8888_8_0565_process_last_pixel, \
1296     bilinear_src_8888_8_0565_process_two_pixels, \
1297     bilinear_src_8888_8_0565_process_four_pixels, \
1298     bilinear_src_8888_8_0565_process_pixblock_head, \
1299     bilinear_src_8888_8_0565_process_pixblock_tail, \
1300     bilinear_src_8888_8_0565_process_pixblock_tail_head, \
1301     4, 28, BILINEAR_FLAG_USE_MASK
1302
1303 generate_bilinear_scanline_func \
1304     pixman_scaled_bilinear_scanline_0565_8_x888_SRC_asm_neon, \
1305     0565, 8888, 1, 2, \
1306     bilinear_src_0565_8_x888_process_last_pixel, \
1307     bilinear_src_0565_8_x888_process_two_pixels, \
1308     bilinear_src_0565_8_x888_process_four_pixels, \
1309     bilinear_src_0565_8_x888_process_pixblock_head, \
1310     bilinear_src_0565_8_x888_process_pixblock_tail, \
1311     bilinear_src_0565_8_x888_process_pixblock_tail_head, \
1312     4, 28, BILINEAR_FLAG_USE_MASK
1313
1314 generate_bilinear_scanline_func \
1315     pixman_scaled_bilinear_scanline_0565_8_0565_SRC_asm_neon, \
1316     0565, 0565, 1, 1, \
1317     bilinear_src_0565_8_0565_process_last_pixel, \
1318     bilinear_src_0565_8_0565_process_two_pixels, \
1319     bilinear_src_0565_8_0565_process_four_pixels, \
1320     bilinear_src_0565_8_0565_process_pixblock_head, \
1321     bilinear_src_0565_8_0565_process_pixblock_tail, \
1322     bilinear_src_0565_8_0565_process_pixblock_tail_head, \
1323     4, 28, BILINEAR_FLAG_USE_MASK
1324
1325 generate_bilinear_scanline_func \
1326     pixman_scaled_bilinear_scanline_8888_8888_OVER_asm_neon, \
1327     8888, 8888, 2, 2, \
1328     bilinear_over_8888_8888_process_last_pixel, \
1329     bilinear_over_8888_8888_process_two_pixels, \
1330     bilinear_over_8888_8888_process_four_pixels, \
1331     bilinear_over_8888_8888_process_pixblock_head, \
1332     bilinear_over_8888_8888_process_pixblock_tail, \
1333     bilinear_over_8888_8888_process_pixblock_tail_head, \
1334     4, 28, 0
1335
1336 generate_bilinear_scanline_func \
1337     pixman_scaled_bilinear_scanline_8888_8_8888_OVER_asm_neon, \
1338     8888, 8888, 2, 2, \
1339     bilinear_over_8888_8_8888_process_last_pixel, \
1340     bilinear_over_8888_8_8888_process_two_pixels, \
1341     bilinear_over_8888_8_8888_process_four_pixels, \
1342     bilinear_over_8888_8_8888_process_pixblock_head, \
1343     bilinear_over_8888_8_8888_process_pixblock_tail, \
1344     bilinear_over_8888_8_8888_process_pixblock_tail_head, \
1345     4, 28, BILINEAR_FLAG_USE_MASK
1346
1347 generate_bilinear_scanline_func \
1348     pixman_scaled_bilinear_scanline_8888_8888_ADD_asm_neon, \
1349     8888, 8888, 2, 2, \
1350     bilinear_add_8888_8888_process_last_pixel, \
1351     bilinear_add_8888_8888_process_two_pixels, \
1352     bilinear_add_8888_8888_process_four_pixels, \
1353     bilinear_add_8888_8888_process_pixblock_head, \
1354     bilinear_add_8888_8888_process_pixblock_tail, \
1355     bilinear_add_8888_8888_process_pixblock_tail_head, \
1356     4, 28, 0
1357
1358 generate_bilinear_scanline_func \
1359     pixman_scaled_bilinear_scanline_8888_8_8888_ADD_asm_neon, \
1360     8888, 8888, 2, 2, \
1361     bilinear_add_8888_8_8888_process_last_pixel, \
1362     bilinear_add_8888_8_8888_process_two_pixels, \
1363     bilinear_add_8888_8_8888_process_four_pixels, \
1364     bilinear_add_8888_8_8888_process_pixblock_head, \
1365     bilinear_add_8888_8_8888_process_pixblock_tail, \
1366     bilinear_add_8888_8_8888_process_pixblock_tail_head, \
1367     4, 28, BILINEAR_FLAG_USE_MASK