1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18
19#include <machine/cpu-features.h>
20#include <machine/asm.h>
21
22/*
23        r0 = dst
24        r1 = y0 base pointer
25        r2 = y1 base pointer
26        r3 = y2 base pointer
27        sp = coeffs
28        sp = length / 2
29*/
30
31ENTRY(rsdIntrinsicConvolve3x3_K)
32        push            {r4-r8, r10, r11, lr}
33        vpush           {q4-q7}
34
35        /* Get the coeffs pointer from the stack and load the
36           coefficients in the q0, q1 NEON registers */
37        ldr r4, [sp, #32+64]
38        vld1.16 {q0, q1}, [r4]
39
40        /* Get count from the stack */
41        ldr r4, [sp, #36+64]
42
43        /* Load the frequently used immediate in a register */
44        mov r5, #8
45
461:
47        /* Load and post-increase the address by r5=#8 */
48        vld1.8 {q13}, [r1], r5
49        vld1.8 {q14}, [r2], r5
50        vld1.8 {q15}, [r3], r5
51
52        /* Signal memory for data that will be used in the loop after the next */
53        PLD         (r1, r5)
54        PLD         (r2, r5)
55        PLD         (r3, r5)
56
57        vmovl.u8 q2, d26
58        vmovl.u8 q3, d27
59        vmovl.u8 q4, d28
60        vmovl.u8 q5, d29
61        vmovl.u8 q6, d30
62        vmovl.u8 q7, d31
63
64/*
65        The two pixel source array is
66        d4,  d5,  d6,  d7
67        d8,  d9,  d10, d11
68        d12, d13, d14, d15
69*/
70
71        vmull.s16 q8, d4, d0[0]
72        vmlal.s16 q8, d5, d0[1]
73        vmlal.s16 q8, d6, d0[2]
74        vmlal.s16 q8, d8, d0[3]
75        vmlal.s16 q8, d9, d1[0]
76        vmlal.s16 q8, d10, d1[1]
77        vmlal.s16 q8, d12, d1[2]
78        vmlal.s16 q8, d13, d1[3]
79        vmlal.s16 q8, d14, d2[0]
80
81        vmull.s16 q9, d5, d0[0]
82        vmlal.s16 q9, d6, d0[1]
83        vmlal.s16 q9, d7, d0[2]
84        vmlal.s16 q9, d9, d0[3]
85        vmlal.s16 q9, d10, d1[0]
86        vmlal.s16 q9, d11, d1[1]
87        vmlal.s16 q9, d13, d1[2]
88        vmlal.s16 q9, d14, d1[3]
89        vmlal.s16 q9, d15, d2[0]
90
91        vshrn.i32 d16, q8, #8
92        vshrn.i32 d17, q9, #8
93
94        vqmovun.s16 d16, q8
95        vst1.8 d16, [r0]!
96
97        /* Are we done yet? */
98        subs r4, r4, #1
99        bne 1b
100
101        /* We're done, bye! */
102        vpop            {q4-q7}
103        pop             {r4-r8, r10, r11, lr}
104        bx              lr
105END(TestConvolveK)
106
107/*
108        r0 = dst
109        r1 = src
110        r2 = matrix
111        r3 = length
112*/
113ENTRY(rsdIntrinsicColorMatrix4x4_K)
114        .save           {r4, lr}
115        stmfd           sp!, {r4, lr}
116        vpush           {q4-q7}
117
118        vld1.16 {q2}, [r2]!
119        vld1.16 {q3}, [r2]!
120
1211:
122        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]!
123        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]!
124        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]!
125        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]!
126
127        vmovl.u8 q12, d0  /* R */
128        vmovl.u8 q13, d1  /* G */
129        vmovl.u8 q14, d2  /* B */
130        vmovl.u8 q15, d3  /* A */
131
132        vmull.s16 q8,  d24, d4[0]
133        vmull.s16 q9,  d24, d4[1]
134        vmull.s16 q10, d24, d4[2]
135        vmull.s16 q11, d24, d4[3]
136
137        vmlal.s16 q8,  d26, d5[0]
138        vmlal.s16 q9,  d26, d5[1]
139        vmlal.s16 q10, d26, d5[2]
140        vmlal.s16 q11, d26, d5[3]
141
142        vmlal.s16 q8,  d28, d6[0]
143        vmlal.s16 q9,  d28, d6[1]
144        vmlal.s16 q10, d28, d6[2]
145        vmlal.s16 q11, d28, d6[3]
146
147        vmlal.s16 q8,  d30, d7[0]
148        vmlal.s16 q9,  d30, d7[1]
149        vmlal.s16 q10, d30, d7[2]
150        vmlal.s16 q11, d30, d7[3]
151
152        vshrn.i32 d24, q8, #8
153        vshrn.i32 d26, q9, #8
154        vshrn.i32 d28, q10, #8
155        vshrn.i32 d30, q11, #8
156
157        vqmovun.s16 d0, q12
158        vqmovun.s16 d1, q13
159        vqmovun.s16 d2, q14
160        vqmovun.s16 d3, q15
161
162        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
163        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
164        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
165        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
166
167        subs r3, r3, #1
168        bne 1b
169
170        vpop            {q4-q7}
171        ldmfd           sp!, {r4, lr}
172        bx              lr
173END(rsdIntrinsicColorMatrix4x4_K)
174
175/*
176        r0 = dst
177        r1 = src
178        r2 = matrix
179        r3 = length
180*/
181ENTRY(rsdIntrinsicColorMatrix3x3_K)
182        .save           {r4, lr}
183        stmfd           sp!, {r4, lr}
184        vpush           {q4-q7}
185
186        vld1.16 {q2}, [r2]!
187        vld1.16 {q3}, [r2]!
188
1891:
190        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]!
191        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]!
192        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]!
193        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]!
194
195        vmovl.u8 q12, d0
196        vmovl.u8 q13, d1
197        vmovl.u8 q14, d2
198
199        vmull.s16 q8,  d24, d4[0]
200        vmull.s16 q9,  d24, d4[1]
201        vmull.s16 q10, d24, d4[2]
202
203        vmlal.s16 q8,  d26, d5[0]
204        vmlal.s16 q9,  d26, d5[1]
205        vmlal.s16 q10, d26, d5[2]
206
207        vmlal.s16 q8,  d28, d6[0]
208        vmlal.s16 q9,  d28, d6[1]
209        vmlal.s16 q10, d28, d6[2]
210
211        vshrn.i32 d24, q8, #8
212        vshrn.i32 d26, q9, #8
213        vshrn.i32 d28, q10, #8
214
215        vqmovun.s16 d0, q12
216        vqmovun.s16 d1, q13
217        vqmovun.s16 d2, q14
218
219        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
220        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
221        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
222        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
223
224        subs r3, r3, #1
225        bne 1b
226
227        vpop            {q4-q7}
228        ldmfd           sp!, {r4, lr}
229        bx              lr
230END(rsdIntrinsicColorMatrix3x3_K)
231
232/*
233        r0 = dst
234        r1 = src
235        r2 = matrix
236        r3 = length
237*/
238ENTRY(rsdIntrinsicColorMatrixDot_K)
239        .save           {r4, lr}
240        stmfd           sp!, {r4, lr}
241        vpush           {q4-q7}
242
243        vld1.16 {q2}, [r2]!
244        vld1.16 {q3}, [r2]!
245
2461:
247        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]!
248        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]!
249        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]!
250        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]!
251
252        vmovl.u8 q12, d0
253        vmovl.u8 q13, d1
254        vmovl.u8 q14, d2
255
256        vmull.s16 q8,  d24, d4[0]
257        vmlal.s16 q8,  d26, d5[0]
258        vmlal.s16 q8,  d28, d6[0]
259        vshrn.i32 d24, q8, #8
260        vqmovun.s16 d0, q12
261        vmov.u8 d1, d0
262        vmov.u8 d2, d0
263
264        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
265        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
266        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
267        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
268
269        subs r3, r3, #1
270        bne 1b
271
272        vpop            {q4-q7}
273        ldmfd           sp!, {r4, lr}
274        bx              lr
275END(rsdIntrinsicColorMatrixDot_K)
276
277
278/*
279static void OneVF(float4 *out, const uchar *ptrIn, int iStride,
280                  const float* gPtr, int iradius, int x1, int x2)
281
282    r0 = out
283    r1 = pin
284    r2 = stride
285    r3 = gptr
286    r4 = sp, ct
287    r5 = sp+4, x1
288    r6 = sp+8, x2
289*/
290ENTRY(rsdIntrinsicBlurVF_K)
291        push            {r4-r8, r10, r11, lr}
292        vpush           {q4-q7}
293
294        ldr r4, [sp, #32+64]
295        ldr r5, [sp, #32+64 + 4]
296        ldr r6, [sp, #32+64 + 8]
297
2981:
299        veor q10, q10, q10         /* float4 blurredPixel = 0; */
300        veor q11, q11, q11         /* float4 blurredPixel = 0; */
301        add r7, r1, r5, lsl #2  /* const uchar *pi = ptrIn + x1 * 4; */
302        mov r10, r3
303
304        mov r11, r4
305
3062:
307        vld1.32 {d2}, [r7]
308        vmovl.u8 q1, d2
309        vmovl.u16 q3, d2
310        vmovl.u16 q4, d3
311        vcvt.f32.s32 q3, q3
312        vcvt.f32.s32 q4, q4
313        vld1.32 {d0[0]}, [r10]!
314        add r7, r7, r2
315        vmla.f32 q10, q3, d0[0]
316        vmla.f32 q11, q4, d0[0]
317        subs r11, r11, #1
318        bne 2b
319
320        vst1.32 {q10}, [r0]!
321        vst1.32 {q11}, [r0]!
322        add r5, r5, #2
323        cmp r5, r6
324        bne 1b
325
326
327        vpop            {q4-q7}
328        pop             {r4-r8, r10, r11, lr}
329        bx              lr
330END(rsdIntrinsicBlurVF_K)
331
332/*
333static void OneVF(float4 *out, const uchar *ptrIn, int iStride,
334                  const float* gPtr, int iradius, int x1, int x2)
335
336    r0 = out
337    r1 = pin
338    r2 = gptr
339    r3 = ct
340    r4 = sp, x1
341    r5 = sp+4, x2
342*/
343ENTRY(rsdIntrinsicBlurHF_K)
344        push            {r4-r8, r10, r11, lr}
345        vpush           {q4-q7}
346
347        ldr r4, [sp, #32+64]
348        ldr r5, [sp, #32+64 + 4]
349
3501:
351        add r7, r1, r4, lsl #4  /* const uchar *pi = ptrIn + x1 * 4; */
352        mov r10, r2
353        mov r11, r3
354
355        vld1.32 {q1}, [r7]!
356        vld1.32 {d6[0]}, [r10]!
357        vmul.f32 q0, q1, d6[0]
358        sub r11, r11, #1
359
3602:
361        vld1.32 {q1}, [r7]!
362        vld1.32 {q2}, [r7]!
363        vld1.32 {d6[0]}, [r10]!
364        vld1.32 {d6[1]}, [r10]!
365        vmla.f32 q0, q1, d6[0]
366        vmla.f32 q0, q2, d6[1]
367        subs r11, r11, #2
368        bne 2b
369
370        vcvt.s32.f32 q0, q0
371        vmovn.u32 d0, q0
372        vmovn.u16 d0, q0
373
374        vst1.32 {d0[0]}, [r0]!
375        add r4, r4, #1
376        cmp r4, r5
377        bne 1b
378
379        vpop            {q4-q7}
380        pop             {r4-r8, r10, r11, lr}
381        bx              lr
382END(rsdIntrinsicBlurHF_K)
383
384/*
385        r0 = dst
386        r1 = Y
387        r2 = VU
388        r3 = length (pixels / 8)
389        r4 = sp, params
390
391        This function converts 8 pixels per iteration
392*/
393ENTRY(rsdIntrinsicYuv_K)
394        push            {r4-r8, r10, r11, lr}
395        vpush           {q4-q7}
396
397        ldr r4, [sp, #32+64]
398        vld1.16 {q2}, [r4]!  // mults
399        vld1.16 {q3}, [r4]!  // y offset
400        vld1.16 {q4}, [r4]!  // 128
401        vdup.8 d3, d5[1]
402
4031:
404        vld1.8 {d10}, [r1]!
405        vld1.8 {d12}, [r2]!
406        vmovl.u8 q5, d10 // Y at .16
407        vmovl.u8 q6, d12 // vu at .16
408
409        vsub.i16 q5, q5, q3
410        vsub.i16 q6, q6, q4
411        vtrn.16 d12, d13  // d12 = u, d13 = v
412        vmov q7, q6
413        vtrn.16 d12, d14
414        vtrn.32 d12, d14
415        vtrn.16 d13, d15
416        vtrn.32 d13, d15
417
418        vmull.s16 q8, d10, d4[0]
419        vmull.s16 q11, d11, d4[0]
420        vmov q9, q8
421        vmov q10, q8
422        vmov q12, q11
423        vmov q13, q11
424
425        vmlal.s16 q8,  d12, d4[1]
426        vmlal.s16 q9,  d12, d5[0]
427        vmlal.s16 q10, d13, d4[3]
428        vmlal.s16 q9,  d13, d4[2]
429
430        vmlal.s16 q11, d14, d4[1]
431        vmlal.s16 q12, d14, d5[0]
432        vmlal.s16 q13, d15, d4[3]
433        vmlal.s16 q12, d15, d4[2]
434
435
436        vshrn.i32 d16, q8, #8
437        vshrn.i32 d18, q9, #8
438        vshrn.i32 d20, q10, #8
439        vqmovun.s16 d0, q8
440        vqmovun.s16 d1, q9
441        vqmovun.s16 d2, q10
442        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
443        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
444        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
445        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
446
447        vshrn.i32 d16, q11, #8
448        vshrn.i32 d18, q12, #8
449        vshrn.i32 d20, q13, #8
450        vqmovun.s16 d0, q8
451        vqmovun.s16 d1, q9
452        vqmovun.s16 d2, q10
453        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
454        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
455        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
456        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
457
458        subs r3, r3, #1
459        bne 1b
460
461        vpop            {q4-q7}
462        pop             {r4-r8, r10, r11, lr}
463        bx              lr
464END(rsdIntrinsicYuv_K)
465
466/* Convolve 5x5 */
467
468/*
469        r0 = dst
470        r1 = y0 base pointer
471        r2 = y1 base pointer
472        r3 = y2 base pointer
473        r4 = y3 base pointer
474        r5 = y4 base pointer
475        r6 = coeffs
476        r7 = length
477*/
478ENTRY(rsdIntrinsicConvolve5x5_K)
479        push        {r4-r7, lr}
480        vpush       {q4-q7}
481
482        /* load y3 in r4 */
483        ldr     r4, [sp, #20 + 64]
484
485        /* load y4 in r5 */
486        ldr     r5, [sp, #24 + 64]
487
488        /* Load the coefficients pointer */
489        ldr     r6, [sp, #28 + 64]
490
491        /* Create the coefficients vector */
492        vld1.16     {d0, d1, d2, d3}, [r6]!
493        vld1.16     {d4, d5, d6}, [r6]
494
495        /* load the count */
496        ldr     r6, [sp, #32 + 64]
497
498        /* Load the frequently used immediate in a register */
499        mov     r7, #8
500
5011:
502        /* Load the y base pointers in Qregs and post-increase the address by r7=#8 */
503        vld1.8  {d24, d25, d26}, [r1], r7      @  y0 ( y - 2 )
504        vld1.8  {d27, d28, d29}, [r2], r7      @  y0 ( y - 1 )
505
506        /* Signal memory for data that will be used in the loop after the next */
507        PLD         (r1, r7)
508        PLD         (r2, r7)
509
510        /* Promoting the 8bit channels to 16bit */
511        vmovl.u8 q9,  d24
512        vmovl.u8 q10, d25
513        vmovl.u8 q11, d26
514        vmovl.u8 q12, d27
515        vmovl.u8 q13, d28
516        vmovl.u8 q14, d29
517
518/*
519        d18,  d19,  d20, d21, d22, d23,
520        d24,  d25
521*/
522        vmull.s16 q4, d18, d0[0]
523        vmlal.s16 q4, d19, d0[1]
524        vmlal.s16 q4, d20, d0[2]
525        vmlal.s16 q4, d21, d0[3]
526        vmlal.s16 q4, d22, d1[0]
527
528        vmlal.s16 q4, d24, d1[1]
529        vmlal.s16 q4, d25, d1[2]
530        vmlal.s16 q4, d26, d1[3]
531        vmlal.s16 q4, d27, d2[0]
532        vmlal.s16 q4, d28, d2[1]
533
534        vmull.s16 q5, d19, d0[0]
535        vmlal.s16 q5, d20, d0[1]
536        vmlal.s16 q5, d21, d0[2]
537        vmlal.s16 q5, d22, d0[3]
538        vmlal.s16 q5, d23, d1[0]
539
540        vmlal.s16 q5, d25, d1[1]
541        vmlal.s16 q5, d26, d1[2]
542        vmlal.s16 q5, d27, d1[3]
543        vmlal.s16 q5, d28, d2[0]
544        vmlal.s16 q5, d29, d2[1]
545
546
547        /* Next 2 rows */
548        /* Load the y base pointers in Qregs and post-increase the address by r7=#8 */
549        vld1.8  {d24, d25, d26}, [r3], r7      @  y0 ( y )
550        vld1.8  {d27, d28, d29}, [r4], r7      @  y0 ( y + 1 )
551
552        /* Signal memory for data that will be used in the loop after the next */
553        PLD         (r3, r7)
554        PLD         (r4, r7)
555
556        /* Promoting the 8bit channels to 16bit */
557        vmovl.u8 q9,  d24
558        vmovl.u8 q10, d25
559        vmovl.u8 q11, d26
560        vmovl.u8 q12, d27
561        vmovl.u8 q13, d28
562        vmovl.u8 q14, d29
563
564/*
565        d18,  d19,  d20, d21, d22, d23,
566        d24,  d25
567*/
568        vmlal.s16 q4, d18, d2[2]
569        vmlal.s16 q4, d19, d2[3]
570        vmlal.s16 q4, d20, d3[0]
571        vmlal.s16 q4, d21, d3[1]
572        vmlal.s16 q4, d22, d3[2]
573
574        vmlal.s16 q4, d24, d3[3]
575        vmlal.s16 q4, d25, d4[0]
576        vmlal.s16 q4, d26, d4[1]
577        vmlal.s16 q4, d27, d4[2]
578        vmlal.s16 q4, d28, d4[3]
579
580        vmlal.s16 q5, d19, d2[2]
581        vmlal.s16 q5, d20, d2[3]
582        vmlal.s16 q5, d21, d3[0]
583        vmlal.s16 q5, d22, d3[1]
584        vmlal.s16 q5, d23, d3[2]
585
586        vmlal.s16 q5, d25, d3[3]
587        vmlal.s16 q5, d26, d4[0]
588        vmlal.s16 q5, d27, d4[1]
589        vmlal.s16 q5, d28, d4[2]
590        vmlal.s16 q5, d29, d4[3]
591
592        /* Last row */
593        /* Load the y base pointers in Qregs and post-increase the address by r7=#8 */
594        vld1.8  {d24, d25, d26}, [r5], r7      @  y0 ( y + 2 )
595
596        /* Signal memory for data that will be used in the loop after the next */
597        PLD         (r5, r7)
598
599        /* Promoting the 8bit channels to 16bit */
600        vmovl.u8 q9,  d24
601        vmovl.u8 q10, d25
602        vmovl.u8 q11, d26
603
604/*
605        d18,  d19,  d20, d21, d22, d23,
606        d24,  d25
607*/
608
609        vmlal.s16 q4, d18, d5[0]
610        vmlal.s16 q4, d19, d5[1]
611        vmlal.s16 q4, d20, d5[2]
612        vmlal.s16 q4, d21, d5[3]
613        vmlal.s16 q4, d22, d6[0]
614
615        vmlal.s16 q5, d19, d5[0]
616        vmlal.s16 q5, d20, d5[1]
617        vmlal.s16 q5, d21, d5[2]
618        vmlal.s16 q5, d22, d5[3]
619        vmlal.s16 q5, d23, d6[0]
620
621
622
623
624/*      Narrow it to a d-reg 32 -> 16 bit */
625        vshrn.i32 d8, q4, #8
626        vshrn.i32 d9, q5, #8
627
628/*      Pack 16 -> 8 bit, saturate, put two pixels into D reg */
629        vqmovun.s16 d8, q4
630
631        vst1.8 d8, [r0]!           @ return the output and increase the address of r0
632
633        /* Are we done? */
634        subs r6, r6, #1
635        bne 1b
636
637        /* Yup, bye */
638        vpop        {q4-q7}
639        pop         {r4-r7, lr}
640        bx          lr
641
642END(rsdIntrinsicConvolve5x5_K)
643
644
645
646
647/*
648        dst = src + dst * (1.0 - src.a)
649
650        r0 = dst
651        r1 = src
652        r2 = length
653*/
654ENTRY(rsdIntrinsicBlendSrcOver_K)
655        .save           {r4, lr}
656        stmfd           sp!, {r4, lr}
657        vpush           {q4-q7}
658
659        mov r4, #255
660        vdup.16 q7, r4
661
662        mov r4, r0
6631:
664
665        /* src */
666        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]!
667        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]!
668        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]!
669        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]!
670        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]!
671        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]!
672        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]!
673        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]!
674        vshll.u8 q12, d0, #8
675        vshll.u8 q13, d1, #8
676        vshll.u8 q14, d2, #8
677        vmovl.u8 q6, d3
678        vsub.i16 q6, q7, q6        // q6 = 1 - src.a
679        vshll.u8 q15, d3, #8
680
681        /* dst */
682        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
683        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
684        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
685        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
686        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]!
687        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]!
688        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]!
689        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]!
690        vmovl.u8 q8, d0
691        vmovl.u8 q9, d1
692        vmovl.u8 q10, d2
693        vmovl.u8 q11, d3
694
695        vmla.i16 q12, q8, q6
696        vmla.i16 q13, q9, q6
697        vmla.i16 q14, q10, q6
698        vmla.i16 q15, q11, q6
699
700        vshrn.i16 d0, q12, #8
701        vshrn.i16 d1, q13, #8
702        vshrn.i16 d2, q14, #8
703        vshrn.i16 d3, q15, #8
704        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]!
705        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]!
706        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]!
707        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]!
708        vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]!
709        vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]!
710        vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]!
711        vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]!
712
713        subs r2, r2, #1
714        bne 1b
715
716        vpop            {q4-q7}
717        ldmfd           sp!, {r4, lr}
718        bx              lr
719END(rsdIntrinsicBlendSrcOver_K)
720
721/*
722        dst = dst + src * (1.0 - dst.a)
723
724        r0 = dst
725        r1 = src
726        r2 = length
727*/
728ENTRY(rsdIntrinsicBlendDstOver_K)
729        .save           {r4, lr}
730        stmfd           sp!, {r4, lr}
731        vpush           {q4-q7}
732
733        mov r4, #255
734        vdup.16 q7, r4
735
736        mov r4, r0
7371:
738
739        /* src */
740        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]!
741        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]!
742        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]!
743        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]!
744        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]!
745        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]!
746        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]!
747        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]!
748        vmovl.u8 q12, d0
749        vmovl.u8 q13, d1
750        vmovl.u8 q14, d2
751        vmovl.u8 q15, d3
752
753        /* dst */
754        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
755        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
756        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
757        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
758        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]!
759        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]!
760        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]!
761        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]!
762        vshll.u8 q8, d0, #8
763        vshll.u8 q9, d1, #8
764        vshll.u8 q10, d2, #8
765        vmovl.u8 q6, d3
766        vsub.i16 q6, q7, q6        // q6 = 1 - dst.a
767        vshll.u8 q11, d3, #8
768
769
770        vmla.i16 q8, q12, q6
771        vmla.i16 q9, q13, q6
772        vmla.i16 q10, q14, q6
773        vmla.i16 q11, q15, q6
774
775        vshrn.i16 d0, q8, #8
776        vshrn.i16 d1, q9, #8
777        vshrn.i16 d2, q10, #8
778        vshrn.i16 d3, q11, #8
779        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]!
780        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]!
781        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]!
782        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]!
783        vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]!
784        vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]!
785        vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]!
786        vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]!
787
788        subs r2, r2, #1
789        bne 1b
790
791        vpop            {q4-q7}
792        ldmfd           sp!, {r4, lr}
793        bx              lr
794END(rsdIntrinsicBlendDstOver_K)
795
796/*
797        dst = src * dst.a
798
799        r0 = dst
800        r1 = src
801        r2 = length
802*/
803ENTRY(rsdIntrinsicBlendSrcIn_K)
804        .save           {r4, lr}
805        stmfd           sp!, {r4, lr}
806        vpush           {q4-q7}
807
808        mov r4, r0
8091:
810
811        /* src */
812        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]!
813        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]!
814        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]!
815        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]!
816        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]!
817        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]!
818        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]!
819        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]!
820        vmovl.u8 q12, d0
821        vmovl.u8 q13, d1
822        vmovl.u8 q14, d2
823        vmovl.u8 q15, d3
824
825        /* dst */
826        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
827        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
828        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
829        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
830        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]!
831        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]!
832        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]!
833        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]!
834        //vmovl.u8 q8, d0
835        //vmovl.u8 q9, d1
836        //vmovl.u8 q10, d2
837        vmovl.u8 q11, d3
838
839        vmul.i16 q12, q12, q11
840        vmul.i16 q13, q13, q11
841        vmul.i16 q14, q14, q11
842        vmul.i16 q15, q15, q11
843
844        vshrn.i16 d0, q12, #8
845        vshrn.i16 d1, q13, #8
846        vshrn.i16 d2, q14, #8
847        vshrn.i16 d3, q15, #8
848        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]!
849        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]!
850        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]!
851        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]!
852        vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]!
853        vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]!
854        vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]!
855        vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]!
856
857        subs r2, r2, #1
858        bne 1b
859
860        vpop            {q4-q7}
861        ldmfd           sp!, {r4, lr}
862        bx              lr
863END(rsdIntrinsicBlendSrcIn_K)
864
865/*
866        dst = dst * src.a
867
868        r0 = dst
869        r1 = src
870        r2 = length
871*/
872ENTRY(rsdIntrinsicBlendDstIn_K)
873        .save           {r4, lr}
874        stmfd           sp!, {r4, lr}
875        vpush           {q4-q7}
876
877        mov r4, r0
8781:
879
880        /* src */
881        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]!
882        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]!
883        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]!
884        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]!
885        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]!
886        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]!
887        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]!
888        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]!
889        //vmovl.u8 q12, d0
890        //vmovl.u8 q13, d1
891        //vmovl.u8 q14, d2
892        vmovl.u8 q15, d3
893
894        /* dst */
895        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
896        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
897        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
898        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
899        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]!
900        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]!
901        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]!
902        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]!
903        vmovl.u8 q8, d0
904        vmovl.u8 q9, d1
905        vmovl.u8 q10, d2
906        vmovl.u8 q11, d3
907
908        vmul.i16 q8, q8, q15
909        vmul.i16 q9, q9, q15
910        vmul.i16 q10, q10, q15
911        vmul.i16 q11, q11, q15
912
913        vshrn.i16 d0, q8, #8
914        vshrn.i16 d1, q9, #8
915        vshrn.i16 d2, q10, #8
916        vshrn.i16 d3, q11, #8
917        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]!
918        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]!
919        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]!
920        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]!
921        vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]!
922        vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]!
923        vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]!
924        vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]!
925
926        subs r2, r2, #1
927        bne 1b
928
929        vpop            {q4-q7}
930        ldmfd           sp!, {r4, lr}
931        bx              lr
932END(rsdIntrinsicBlendDstIn_K)
933
934
935
936/*
937        dst = src * (1.0 - dst.a)
938
939        r0 = dst
940        r1 = src
941        r2 = length
942*/
943ENTRY(rsdIntrinsicBlendSrcOut_K)
944        .save           {r4, lr}
945        stmfd           sp!, {r4, lr}
946        vpush           {q4-q7}
947
948        mov r4, #255
949        vdup.16 q7, r4
950
951        mov r4, r0
9521:
953
954        /* src */
955        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]!
956        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]!
957        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]!
958        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]!
959        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]!
960        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]!
961        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]!
962        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]!
963        vmovl.u8 q12, d0
964        vmovl.u8 q13, d1
965        vmovl.u8 q14, d2
966        vmovl.u8 q15, d3
967
968        /* dst */
969        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
970        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
971        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
972        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
973        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]!
974        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]!
975        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]!
976        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]!
977        //vmovl.u8 q8, d0
978        //vmovl.u8 q9, d1
979        //vmovl.u8 q10, d2
980        vmovl.u8 q11, d3
981
982
983        vsub.i16 q6, q7, q11        // q6 = 1 - dst.a
984        vmul.i16 q12, q12, q6
985        vmul.i16 q13, q13, q6
986        vmul.i16 q14, q14, q6
987        vmul.i16 q15, q15, q6
988
989        vshrn.i16 d0, q12, #8
990        vshrn.i16 d1, q13, #8
991        vshrn.i16 d2, q14, #8
992        vshrn.i16 d3, q15, #8
993        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]!
994        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]!
995        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]!
996        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]!
997        vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]!
998        vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]!
999        vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]!
1000        vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]!
1001
1002        subs r2, r2, #1
1003        bne 1b
1004
1005        vpop            {q4-q7}
1006        ldmfd           sp!, {r4, lr}
1007        bx              lr
1008END(rsdIntrinsicBlendSrcOut_K)
1009
1010
1011/*
1012        dst = dst * (1.0 - src.a)
1013
1014        r0 = dst
1015        r1 = src
1016        r2 = length
1017*/
1018ENTRY(rsdIntrinsicBlendDstOut_K)
1019        .save           {r4, lr}
1020        stmfd           sp!, {r4, lr}
1021        vpush           {q4-q7}
1022
1023        mov r4, #255
1024        vdup.16 q7, r4
1025
1026        mov r4, r0
10271:
1028
1029        /* src */
1030        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]!
1031        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]!
1032        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]!
1033        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]!
1034        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]!
1035        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]!
1036        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]!
1037        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]!
1038        //vmovl.u8 q12, d0
1039        //vmovl.u8 q13, d1
1040        //vmovl.u8 q14, d2
1041        vmovl.u8 q15, d3
1042
1043        /* dst */
1044        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
1045        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
1046        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
1047        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
1048        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]!
1049        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]!
1050        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]!
1051        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]!
1052        vmovl.u8 q8, d0
1053        vmovl.u8 q9, d1
1054        vmovl.u8 q10, d2
1055        vmovl.u8 q11, d3
1056
1057
1058        vsub.i16 q6, q7, q15        // q6 = 1 - src.a
1059        vmul.i16 q12, q8, q6
1060        vmul.i16 q13, q9, q6
1061        vmul.i16 q14, q10, q6
1062        vmul.i16 q15, q11, q6
1063
1064        vshrn.i16 d0, q12, #8
1065        vshrn.i16 d1, q13, #8
1066        vshrn.i16 d2, q14, #8
1067        vshrn.i16 d3, q15, #8
1068        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]!
1069        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]!
1070        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]!
1071        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]!
1072        vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]!
1073        vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]!
1074        vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]!
1075        vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]!
1076
1077        subs r2, r2, #1
1078        bne 1b
1079
1080        vpop            {q4-q7}
1081        ldmfd           sp!, {r4, lr}
1082        bx              lr
1083END(rsdIntrinsicBlendDstOut_K)
1084
1085
1086/*
1087        dst.rgb = src.rgb * dst.a + (1.0 - src.a) * dst.rgb
1088        dst.a = dst.a
1089
1090        r0 = dst
1091        r1 = src
1092        r2 = length
1093*/
1094ENTRY(rsdIntrinsicBlendSrcAtop_K)
1095        .save           {r4, lr}
1096        stmfd           sp!, {r4, lr}
1097        vpush           {q4-q7}
1098
1099        mov r4, #255
1100        vdup.16 q7, r4
1101
1102        mov r4, r0
11031:
1104
1105        /* src */
1106        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]!
1107        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]!
1108        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]!
1109        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]!
1110        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]!
1111        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]!
1112        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]!
1113        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]!
1114        vmovl.u8 q12, d0
1115        vmovl.u8 q13, d1
1116        vmovl.u8 q14, d2
1117        vmovl.u8 q15, d3
1118
1119        /* dst */
1120        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
1121        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
1122        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
1123        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
1124        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]!
1125        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]!
1126        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]!
1127        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]!
1128        vmovl.u8 q8, d0
1129        vmovl.u8 q9, d1
1130        vmovl.u8 q10, d2
1131        vmovl.u8 q11, d3
1132
1133
1134        vsub.i16 q6, q7, q15        // q6 = 1 - src.a
1135        vmul.i16 q8, q8, q6
1136        vmul.i16 q9, q9, q6
1137        vmul.i16 q10, q10, q6
1138
1139        vmla.i16 q8, q12, q11
1140        vmla.i16 q9, q13, q11
1141        vmla.i16 q10, q14, q11
1142
1143
1144        vshrn.i16 d0, q8, #8
1145        vshrn.i16 d1, q9, #8
1146        vshrn.i16 d2, q10, #8
1147        //vshrn.i16 d3, q15, #8
1148        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]!
1149        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]!
1150        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]!
1151        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]!
1152        vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]!
1153        vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]!
1154        vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]!
1155        vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]!
1156
1157        subs r2, r2, #1
1158        bne 1b
1159
1160        vpop            {q4-q7}
1161        ldmfd           sp!, {r4, lr}
1162        bx              lr
1163END(rsdIntrinsicBlendSrcAtop_K)
1164
1165/*
1166        dst = dst.rgb * src.a + (1.0 - dst.a) * src.rgb
1167        dst.a = src.a
1168
1169        r0 = dst
1170        r1 = src
1171        r2 = length
1172*/
1173ENTRY(rsdIntrinsicBlendDstAtop_K)
1174        .save           {r4, lr}
1175        stmfd           sp!, {r4, lr}
1176        vpush           {q4-q7}
1177
1178        mov r4, #255
1179        vdup.16 q7, r4
1180
1181        mov r4, r0
11821:
1183
1184        /* src */
1185        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]!
1186        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]!
1187        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]!
1188        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]!
1189        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]!
1190        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]!
1191        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]!
1192        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]!
1193        vmovl.u8 q12, d0
1194        vmovl.u8 q13, d1
1195        vmovl.u8 q14, d2
1196        vmovl.u8 q15, d3
1197
1198        /* dst */
1199        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
1200        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
1201        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
1202        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
1203        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]!
1204        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]!
1205        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]!
1206        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]!
1207        vmovl.u8 q8, d0
1208        vmovl.u8 q9, d1
1209        vmovl.u8 q10, d2
1210        vmovl.u8 q11, d3
1211
1212
1213        vsub.i16 q6, q7, q11        // q6 = 1 - dst.a
1214        vmul.i16 q12, q12, q6
1215        vmul.i16 q13, q13, q6
1216        vmul.i16 q14, q14, q6
1217
1218        vmla.i16 q12, q8, q15
1219        vmla.i16 q13, q9, q15
1220        vmla.i16 q14, q10, q15
1221
1222
1223        vshrn.i16 d0, q12, #8
1224        vshrn.i16 d1, q13, #8
1225        vshrn.i16 d2, q14, #8
1226        //vshrn.i16 d3, q15, #8
1227        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]!
1228        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]!
1229        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]!
1230        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]!
1231        vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]!
1232        vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]!
1233        vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]!
1234        vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]!
1235
1236        subs r2, r2, #1
1237        bne 1b
1238
1239        vpop            {q4-q7}
1240        ldmfd           sp!, {r4, lr}
1241        bx              lr
1242END(rsdIntrinsicBlendDstAtop_K)
1243
1244/*
1245        dst = dst ^ src
1246
1247        r0 = dst
1248        r1 = src
1249        r2 = length
1250*/
1251ENTRY(rsdIntrinsicBlendXor_K)
1252        .save           {r4, lr}
1253        stmfd           sp!, {r4, lr}
1254        vpush           {q4-q7}
1255
1256        mov r4, #255
1257        vdup.16 q7, r4
1258
1259        mov r4, r0
12601:
1261
1262        /* src */
1263        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]!
1264        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]!
1265        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]!
1266        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]!
1267        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]!
1268        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]!
1269        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]!
1270        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]!
1271        vmov.u8 d4, d0
1272        vmov.u8 d5, d1
1273        vmov.u8 d6, d2
1274        vmov.u8 d7, d3
1275
1276        /* dst */
1277        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
1278        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
1279        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
1280        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
1281        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]!
1282        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]!
1283        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]!
1284        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]!
1285
1286        veor d0, d0, d4
1287        veor d1, d1, d5
1288        veor d2, d2, d6
1289        veor d3, d3, d7
1290
1291        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]!
1292        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]!
1293        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]!
1294        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]!
1295        vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]!
1296        vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]!
1297        vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]!
1298        vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]!
1299
1300        subs r2, r2, #1
1301        bne 1b
1302
1303        vpop            {q4-q7}
1304        ldmfd           sp!, {r4, lr}
1305        bx              lr
1306END(rsdIntrinsicBlendXor_K)
1307
1308/*
1309        dst = dst * src
1310
1311        r0 = dst
1312        r1 = src
1313        r2 = length
1314*/
1315ENTRY(rsdIntrinsicBlendMultiply_K)
1316        .save           {r4, lr}
1317        stmfd           sp!, {r4, lr}
1318        vpush           {q4-q7}
1319
1320        mov r4, #255
1321        vdup.16 q7, r4
1322
1323        mov r4, r0
13241:
1325
1326        /* src */
1327        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]!
1328        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]!
1329        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]!
1330        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]!
1331        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]!
1332        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]!
1333        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]!
1334        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]!
1335        vmovl.u8 q12, d0
1336        vmovl.u8 q13, d1
1337        vmovl.u8 q14, d2
1338        vmovl.u8 q15, d3
1339
1340        /* dst */
1341        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
1342        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
1343        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
1344        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
1345        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]!
1346        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]!
1347        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]!
1348        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]!
1349        vmovl.u8 q8, d0
1350        vmovl.u8 q9, d1
1351        vmovl.u8 q10, d2
1352        vmovl.u8 q11, d3
1353
1354
1355        vmul.i16 q8, q8, q12
1356        vmul.i16 q9, q9, q13
1357        vmul.i16 q10, q10, q14
1358        vmul.i16 q11, q11, q15
1359
1360        vshrn.i16 d0, q8, #8
1361        vshrn.i16 d1, q9, #8
1362        vshrn.i16 d2, q10, #8
1363        vshrn.i16 d3, q11, #8
1364        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]!
1365        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]!
1366        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]!
1367        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]!
1368        vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]!
1369        vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]!
1370        vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]!
1371        vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]!
1372
1373        subs r2, r2, #1
1374        bne 1b
1375
1376        vpop            {q4-q7}
1377        ldmfd           sp!, {r4, lr}
1378        bx              lr
1379END(rsdIntrinsicBlendMultiply_K)
1380
1381/*
1382        dst = min(src + dst, 1.0)
1383
1384        r0 = dst
1385        r1 = src
1386        r2 = length
1387*/
1388ENTRY(rsdIntrinsicBlendAdd_K)
1389        .save           {r4, lr}
1390        stmfd           sp!, {r4, lr}
1391        vpush           {q4-q7}
1392
1393        mov r4, #255
1394        vdup.16 q7, r4
1395
1396        mov r4, r0
13971:
1398
1399        /* src */
1400        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]!
1401        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]!
1402        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]!
1403        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]!
1404        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]!
1405        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]!
1406        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]!
1407        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]!
1408        vmovl.u8 q12, d0
1409        vmovl.u8 q13, d1
1410        vmovl.u8 q14, d2
1411        vmovl.u8 q15, d3
1412
1413        /* dst */
1414        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
1415        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
1416        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
1417        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
1418        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]!
1419        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]!
1420        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]!
1421        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]!
1422        vmovl.u8 q8, d0
1423        vmovl.u8 q9, d1
1424        vmovl.u8 q10, d2
1425        vmovl.u8 q11, d3
1426
1427
1428        vadd.i16 q8, q8, q12
1429        vadd.i16 q9, q9, q13
1430        vadd.i16 q10, q10, q14
1431        vadd.i16 q11, q11, q15
1432
1433        vqmovun.s16 d0, q8
1434        vqmovun.s16 d1, q9
1435        vqmovun.s16 d2, q10
1436        vqmovun.s16 d3, q11
1437        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]!
1438        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]!
1439        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]!
1440        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]!
1441        vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]!
1442        vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]!
1443        vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]!
1444        vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]!
1445
1446        subs r2, r2, #1
1447        bne 1b
1448
1449        vpop            {q4-q7}
1450        ldmfd           sp!, {r4, lr}
1451        bx              lr
1452END(rsdIntrinsicBlendAdd_K)
1453
1454
1455/*
1456        dst = max(dst - src, 0.0)
1457
1458        r0 = dst
1459        r1 = src
1460        r2 = length
1461*/
1462ENTRY(rsdIntrinsicBlendSub_K)
1463        .save           {r4, lr}
1464        stmfd           sp!, {r4, lr}
1465        vpush           {q4-q7}
1466
1467        mov r4, #255
1468        vdup.16 q7, r4
1469
1470        mov r4, r0
14711:
1472
1473        /* src */
1474        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]!
1475        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]!
1476        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]!
1477        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]!
1478        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]!
1479        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]!
1480        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]!
1481        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]!
1482        vmovl.u8 q12, d0
1483        vmovl.u8 q13, d1
1484        vmovl.u8 q14, d2
1485        vmovl.u8 q15, d3
1486
1487        /* dst */
1488        vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]!
1489        vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]!
1490        vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]!
1491        vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]!
1492        vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]!
1493        vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]!
1494        vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]!
1495        vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]!
1496        vmovl.u8 q8, d0
1497        vmovl.u8 q9, d1
1498        vmovl.u8 q10, d2
1499        vmovl.u8 q11, d3
1500
1501
1502        vsub.i16 q8, q8, q12
1503        vsub.i16 q9, q9, q13
1504        vsub.i16 q10, q10, q14
1505        vsub.i16 q11, q11, q15
1506
1507        vqmovun.s16 d0, q8
1508        vqmovun.s16 d1, q9
1509        vqmovun.s16 d2, q10
1510        vqmovun.s16 d3, q11
1511        vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]!
1512        vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]!
1513        vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]!
1514        vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]!
1515        vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]!
1516        vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]!
1517        vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]!
1518        vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]!
1519
1520        subs r2, r2, #1
1521        bne 1b
1522
1523        vpop            {q4-q7}
1524        ldmfd           sp!, {r4, lr}
1525        bx              lr
1526END(rsdIntrinsicBlendSub_K)
1527
1528