| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| |
| |
| #include <machine/cpu-features.h> |
| #include <machine/asm.h> |
| |
| /* |
| r0 = dst |
| r1 = y0 base pointer |
| r2 = y1 base pointer |
| r3 = y2 base pointer |
| sp = coeffs |
| sp = length / 2 |
| */ |
| |
| ENTRY(rsdIntrinsicConvolve3x3_K) |
| push {r4-r8, r10, r11, lr} |
| vpush {q4-q7} |
| |
| /* Get the coeffs pointer from the stack and load the |
| coefficients in the q0, q1 NEON registers */ |
| ldr r4, [sp, #32+64] |
| vld1.16 {q0, q1}, [r4] |
| |
| /* Get count from the stack */ |
| ldr r4, [sp, #36+64] |
| |
| /* Load the frequently used immediate in a register */ |
| mov r5, #8 |
| |
| 1: |
| /* Load and post-increase the address by r5=#8 */ |
| vld1.8 {q13}, [r1], r5 |
| vld1.8 {q14}, [r2], r5 |
| vld1.8 {q15}, [r3], r5 |
| |
| /* Signal memory for data that will be used in the loop after the next */ |
| PLD (r1, r5) |
| PLD (r2, r5) |
| PLD (r3, r5) |
| |
| vmovl.u8 q2, d26 |
| vmovl.u8 q3, d27 |
| vmovl.u8 q4, d28 |
| vmovl.u8 q5, d29 |
| vmovl.u8 q6, d30 |
| vmovl.u8 q7, d31 |
| |
| /* |
| The two pixel source array is |
| d4, d5, d6, d7 |
| d8, d9, d10, d11 |
| d12, d13, d14, d15 |
| */ |
| |
| vmull.s16 q8, d4, d0[0] |
| vmlal.s16 q8, d5, d0[1] |
| vmlal.s16 q8, d6, d0[2] |
| vmlal.s16 q8, d8, d0[3] |
| vmlal.s16 q8, d9, d1[0] |
| vmlal.s16 q8, d10, d1[1] |
| vmlal.s16 q8, d12, d1[2] |
| vmlal.s16 q8, d13, d1[3] |
| vmlal.s16 q8, d14, d2[0] |
| |
| vmull.s16 q9, d5, d0[0] |
| vmlal.s16 q9, d6, d0[1] |
| vmlal.s16 q9, d7, d0[2] |
| vmlal.s16 q9, d9, d0[3] |
| vmlal.s16 q9, d10, d1[0] |
| vmlal.s16 q9, d11, d1[1] |
| vmlal.s16 q9, d13, d1[2] |
| vmlal.s16 q9, d14, d1[3] |
| vmlal.s16 q9, d15, d2[0] |
| |
| vshrn.i32 d16, q8, #8 |
| vshrn.i32 d17, q9, #8 |
| |
| vqmovun.s16 d16, q8 |
| vst1.8 d16, [r0]! |
| |
| /* Are we done yet? */ |
| subs r4, r4, #1 |
| bne 1b |
| |
| /* We're done, bye! */ |
| vpop {q4-q7} |
| pop {r4-r8, r10, r11, lr} |
| bx lr |
| END(rsdIntrinsicConvolve3x3_K) |
| |
| /* |
| r0 = dst |
| r1 = src |
| r2 = matrix |
| r3 = length |
| */ |
| ENTRY(rsdIntrinsicColorMatrix4x4_K) |
| stmfd sp!, {r4, lr} |
| vpush {q4-q7} |
| |
| vld1.16 {q2}, [r2]! |
| vld1.16 {q3}, [r2]! |
| |
| 1: |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]! |
| |
| vmovl.u8 q12, d0 /* R */ |
| vmovl.u8 q13, d1 /* G */ |
| vmovl.u8 q14, d2 /* B */ |
| vmovl.u8 q15, d3 /* A */ |
| |
| vmull.s16 q8, d24, d4[0] |
| vmull.s16 q9, d24, d4[1] |
| vmull.s16 q10, d24, d4[2] |
| vmull.s16 q11, d24, d4[3] |
| |
| vmlal.s16 q8, d26, d5[0] |
| vmlal.s16 q9, d26, d5[1] |
| vmlal.s16 q10, d26, d5[2] |
| vmlal.s16 q11, d26, d5[3] |
| |
| vmlal.s16 q8, d28, d6[0] |
| vmlal.s16 q9, d28, d6[1] |
| vmlal.s16 q10, d28, d6[2] |
| vmlal.s16 q11, d28, d6[3] |
| |
| vmlal.s16 q8, d30, d7[0] |
| vmlal.s16 q9, d30, d7[1] |
| vmlal.s16 q10, d30, d7[2] |
| vmlal.s16 q11, d30, d7[3] |
| |
| vshrn.i32 d24, q8, #8 |
| vshrn.i32 d26, q9, #8 |
| vshrn.i32 d28, q10, #8 |
| vshrn.i32 d30, q11, #8 |
| |
| vqmovun.s16 d0, q12 |
| vqmovun.s16 d1, q13 |
| vqmovun.s16 d2, q14 |
| vqmovun.s16 d3, q15 |
| |
| vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]! |
| vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]! |
| vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]! |
| vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]! |
| |
| subs r3, r3, #1 |
| bne 1b |
| |
| vpop {q4-q7} |
| ldmfd sp!, {r4, lr} |
| bx lr |
| END(rsdIntrinsicColorMatrix4x4_K) |
| |
| /* |
| r0 = dst |
| r1 = src |
| r2 = matrix |
| r3 = length |
| */ |
| ENTRY(rsdIntrinsicColorMatrix3x3_K) |
| stmfd sp!, {r4, lr} |
| vpush {q4-q7} |
| |
| vld1.16 {q2}, [r2]! |
| vld1.16 {q3}, [r2]! |
| |
| 1: |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]! |
| |
| vmovl.u8 q12, d0 |
| vmovl.u8 q13, d1 |
| vmovl.u8 q14, d2 |
| |
| vmull.s16 q8, d24, d4[0] |
| vmull.s16 q9, d24, d4[1] |
| vmull.s16 q10, d24, d4[2] |
| |
| vmlal.s16 q8, d26, d5[0] |
| vmlal.s16 q9, d26, d5[1] |
| vmlal.s16 q10, d26, d5[2] |
| |
| vmlal.s16 q8, d28, d6[0] |
| vmlal.s16 q9, d28, d6[1] |
| vmlal.s16 q10, d28, d6[2] |
| |
| vshrn.i32 d24, q8, #8 |
| vshrn.i32 d26, q9, #8 |
| vshrn.i32 d28, q10, #8 |
| |
| vqmovun.s16 d0, q12 |
| vqmovun.s16 d1, q13 |
| vqmovun.s16 d2, q14 |
| |
| vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]! |
| vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]! |
| vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]! |
| vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]! |
| |
| subs r3, r3, #1 |
| bne 1b |
| |
| vpop {q4-q7} |
| ldmfd sp!, {r4, lr} |
| bx lr |
| END(rsdIntrinsicColorMatrix3x3_K) |
| |
| /* |
| r0 = dst |
| r1 = src |
| r2 = matrix |
| r3 = length |
| */ |
| ENTRY(rsdIntrinsicColorMatrixDot_K) |
| stmfd sp!, {r4, lr} |
| vpush {q4-q7} |
| |
| vld1.16 {q2}, [r2]! |
| vld1.16 {q3}, [r2]! |
| |
| 1: |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]! |
| |
| vmovl.u8 q12, d0 |
| vmovl.u8 q13, d1 |
| vmovl.u8 q14, d2 |
| |
| vmull.s16 q8, d24, d4[0] |
| vmlal.s16 q8, d26, d5[0] |
| vmlal.s16 q8, d28, d6[0] |
| vshrn.i32 d24, q8, #8 |
| vqmovun.s16 d0, q12 |
| vmov.u8 d1, d0 |
| vmov.u8 d2, d0 |
| |
| vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]! |
| vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]! |
| vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]! |
| vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]! |
| |
| subs r3, r3, #1 |
| bne 1b |
| |
| vpop {q4-q7} |
| ldmfd sp!, {r4, lr} |
| bx lr |
| END(rsdIntrinsicColorMatrixDot_K) |
| |
| |
| /* |
| static void OneVF(float4 *out, const uchar *ptrIn, int iStride, |
| const float* gPtr, int iradius, int x1, int x2) |
| |
| r0 = out |
| r1 = pin |
| r2 = stride |
| r3 = gptr |
| r4 = sp, ct |
| r5 = sp+4, x1 |
| r6 = sp+8, x2 |
| */ |
| ENTRY(rsdIntrinsicBlurVFU4_K) |
| push {r4-r8, r10, r11, lr} |
| vpush {q4-q7} |
| |
| ldr r4, [sp, #32+64] |
| ldr r5, [sp, #32+64 + 4] |
| ldr r6, [sp, #32+64 + 8] |
| |
| 1: |
| veor q10, q10, q10 /* float4 blurredPixel = 0; */ |
| veor q11, q11, q11 /* float4 blurredPixel = 0; */ |
| add r7, r1, r5, lsl #2 /* const uchar *pi = ptrIn + x1 * 4; */ |
| mov r10, r3 |
| |
| mov r11, r4 |
| |
| 2: |
| vld1.32 {d2}, [r7] |
| vmovl.u8 q1, d2 |
| vmovl.u16 q3, d2 |
| vmovl.u16 q4, d3 |
| vcvt.f32.s32 q3, q3 |
| vcvt.f32.s32 q4, q4 |
| vld1.32 {d0[0]}, [r10]! |
| add r7, r7, r2 |
| vmla.f32 q10, q3, d0[0] |
| vmla.f32 q11, q4, d0[0] |
| subs r11, r11, #1 |
| bne 2b |
| |
| vst1.32 {q10}, [r0]! |
| vst1.32 {q11}, [r0]! |
| add r5, r5, #2 |
| cmp r5, r6 |
| bne 1b |
| |
| |
| vpop {q4-q7} |
| pop {r4-r8, r10, r11, lr} |
| bx lr |
| END(rsdIntrinsicBlurVFU4_K) |
| |
| /* |
| static void OneVF(float4 *out, const uchar *ptrIn, int iStride, |
| const float* gPtr, int iradius, int x1, int x2) |
| |
| r0 = out |
| r1 = pin |
| r2 = gptr |
| r3 = ct |
| r4 = sp, x1 |
| r5 = sp+4, x2 |
| */ |
| ENTRY(rsdIntrinsicBlurHFU4_K) |
| push {r4-r8, r10, r11, lr} |
| vpush {q4-q7} |
| |
| ldr r4, [sp, #32+64] |
| ldr r5, [sp, #32+64 + 4] |
| |
| 1: |
| add r7, r1, r4, lsl #4 /* const uchar *pi = ptrIn + x1 * 4; */ |
| mov r10, r2 |
| mov r11, r3 |
| |
| vld1.32 {q1}, [r7]! |
| vld1.32 {d6[0]}, [r10]! |
| vmul.f32 q0, q1, d6[0] |
| sub r11, r11, #1 |
| |
| 2: |
| vld1.32 {q1}, [r7]! |
| vld1.32 {q2}, [r7]! |
| vld1.32 {d6}, [r10]! |
| vmla.f32 q0, q1, d6[0] |
| vmla.f32 q0, q2, d6[1] |
| subs r11, r11, #2 |
| bne 2b |
| |
| vcvt.s32.f32 q0, q0 |
| vmovn.u32 d0, q0 |
| vmovn.u16 d0, q0 |
| |
| vst1.32 {d0[0]}, [r0]! |
| add r4, r4, #1 |
| cmp r4, r5 |
| bne 1b |
| |
| vpop {q4-q7} |
| pop {r4-r8, r10, r11, lr} |
| bx lr |
| END(rsdIntrinsicBlurHFU4_K) |
| |
| ENTRY(rsdIntrinsicBlurHFU1_K) |
| push {r4-r8, r10, r11, lr} |
| vpush {q4-q7} |
| |
| ldr r4, [sp, #32+64] |
| ldr r5, [sp, #32+64 + 4] |
| |
| 1: |
| add r7, r1, r4, lsl #2 /* const uchar *pi = ptrIn + x1 * 4; */ |
| mov r10, r2 |
| mov r11, r3 |
| |
| veor q0, q0 |
| |
| 2: |
| vld1.32 {q1}, [r7] |
| add r7, r7, #4 |
| vld1.32 {d4[0]}, [r10]! |
| vmla.f32 q0, q1, d4[0] |
| subs r11, r11, #1 |
| bne 2b |
| |
| vcvt.s32.f32 q0, q0 |
| vmovn.u32 d0, q0 |
| vmovn.u16 d0, q0 |
| |
| vst1.32 {d0[0]}, [r0]! |
| add r4, r4, #4 |
| cmp r4, r5 |
| bne 1b |
| |
| vpop {q4-q7} |
| pop {r4-r8, r10, r11, lr} |
| bx lr |
| END(rsdIntrinsicBlurHFU1_K) |
| |
| /* |
| Function called with the following arguments: dst, Y, vu, len, YuvCoeff |
| r0 = dst |
| r1 = Y |
| r2 = VU |
| r3 = length (pixels / 8) |
| ---- Args below will be in the stack ---- |
| sp = YuvCoeff |
| |
| This function converts 8 pixels per iteration |
| */ |
| ENTRY(rsdIntrinsicYuv_K) |
| push {r4, r5, lr} @ preserve clobbered int registers |
| vpush {Q4-Q7} @ preserve Vregisters we clobber |
| |
| mov r5, #16 @ Integer 16 in r5; used as an incrementing value |
| |
| ldr r4, [sp, #64+12] @ load the coeffs address in memory in r4 (16*4 + 4*3) |
| vld1.16 {Q2}, [r4]! @ load the multipliers from the coeffs matrix (r4) in Q2 |
| vld1.8 {d6[]}, [r4], r5 @ load y offset 16 from the coeffs matrix (r4) in d6 |
| vld1.8 {d8[]}, [r4], r5 @ load V and U offset of 128 from the coeffs matrix (r4) in d8 |
| |
| mov r4, #8 @ Integer 8 in r4; used as an incrementing value |
| |
| vdup.8 d3, d5[1] @ d3 = 255 (alpha) from the multipliers line in |
| @ the coeffs matrix (Q2) |
| |
| 1: |
| vld1.8 {d10}, [r1]! @ get Y (r1->Y) |
| vld2.8 {d12, d14}, [r2], r4 @ split V from U (r2 -> VU) and increase pointer by 8 (in r4) |
| pld [r1, #64] @ preloading data from address y(r1) + 64 for subsequent loops |
| pld [r2, #64] @ preloading data from address vu(r2) + 64 for subsequent loops |
| |
| vsubl.u8 Q5, d10, d6 @ Y to 16 bit - 16 (in 16bit) (n to n+7) |
| vmull.s16 Q8, d10, d4[0] @ Y(n,n+1,n+2,n+3) * 298 = Q8 (to 32bit) |
| vmull.s16 Q11, d11, d4[0] @ Y(n+4,n+5,n+6,n+7) * 298 = Q11 (to 32bit) |
| |
| vsubl.u8 Q5, d12, d8 @ V to 16 bit - 128 = Q5 // V(n, n+1, n+2,n+3) |
| vsubl.u8 Q6, d14, d8 @ U to 16 bit - 128 = Q6 // U(n, n+1, n+2,n+3) |
| vmov.u16 d11, d10 @ Copying V to d11 |
| vmov.u16 d13, d12 @ Copying U to d13 |
| vzip.u16 d10, d11 @ Q5 = V (n,n n+1, n+1) V(n+2, n+2, n+3, n+3) |
| vzip.u16 d12, d13 @ Q5 = U (n,n n+1, n+1) U(n+2, n+2, n+3, n+3) |
| |
| |
| vmov Q9, Q8 @ Copy Q8(Y: n, n+1, n+2, n+3) to Q9 |
| vmov Q10, Q8 @ Copy Q8(Y: n, n+1, n+2, n+3) to Q10 |
| vmov Q12, Q11 @ Copy Q11(Y: n+5, n+6, n+6, n+7) to Q12 |
| vmov Q13, Q11 @ Copy Q11(Y: n+5, n+6, n+6, n+7) to Q13 |
| |
| @ R G B |
| @ Pixel(0-3) Q8, Q9, Q10 |
| @ Pixel(4-7) Q11, Q12, Q13 |
| @ |
| |
| @ Pixel(0-3) |
| vmlal.s16 Q8, d10, d4[1] @ R : Q8 = Q8(Y-16) + (V-128) * 409 |
| vmlal.s16 Q9, d10, d5[0] @ G : Q9 = Q9(Y-16) + (V-128) * (-208) |
| vmlal.s16 Q9, d12, d4[2] @ + (U-128) * (-100) |
| vmlal.s16 Q10, d12, d4[3] @ B : Q10 = Q10(Y-16) + (U-128) * 516 |
| |
| @ Pixel(4-7) |
| vmlal.s16 Q11, d11, d4[1] @ R : Q11 = Q11(Y-16) + (V-128) * 409 |
| vmlal.s16 Q12, d11, d5[0] @ G : Q12 = Q12(Y-16) + (V-128) * (-208) |
| vmlal.s16 Q12, d13, d4[2] @ + (U-128) * (-100) |
| vmlal.s16 Q13, d13, d4[3] @ B : Q13 = Q13(Y-16) + (U-128) * 516 |
| |
| @ Pixel(0-3) |
| vrshrn.i32 d16, Q8, #8 @ d16 : R shifted right by 8 rounded'n narrowed to 16bit |
| vrshrn.i32 d18, Q9, #8 @ d18 : G shifted right by 8 rounded'n narrowed to 16bit |
| vrshrn.i32 d20, Q10, #8 @ d20 : B shifted right by 8 rounded'n narrowed to 16bit |
| |
| @ Pixel(4-7) |
| vrshrn.i32 d17, Q11, #8 @ d17 : R shifted right by 8 rounded'n narrowed to 16bit |
| vrshrn.i32 d19, Q12, #8 @ d19 : G shifted right by 8 rounded'n narrowed to 16bit |
| vrshrn.i32 d21, Q13, #8 @ d21 : B shifted right by 8 rounded'n narrowed to 16bit |
| |
| vqmovun.s16 d0, Q8 @ r = d0 (saturated, unsigned and narrowed to 8bit) |
| vqmovun.s16 d1, Q9 @ g = d1 (saturated, unsigned and narrowed to 8bit) |
| vqmovun.s16 d2, Q10 @ b = d2 (saturated, unsigned and narrowed to 8bit) |
| |
| subs r3, r3, #1 @ Checking length (r3) |
| vst4.8 {d0, d1, d2, d3}, [r0]! @ Writing out 8 RGBA values to dst (r0) |
| |
| bne 1b @ if not done with length, loop |
| |
| vpop {Q4-Q7} @ Restore Vregisters |
| pop {r4, r5, lr} @ Restore int registers |
| bx lr |
| END(rsdIntrinsicYuv_K) |
| |
| /* |
| Function called with the following arguments: dst, Y, v, u, len, YuvCoeff |
| r0 = dst |
| r1 = Y |
| r2 = V, |
| r3 = U |
| ---- Args below will be in the stack ---- |
| sp = length (pixels / 8) |
| sp+4 = YuvCoeff |
| |
| This function converts 8 pixels per iteration |
| */ |
| ENTRY(rsdIntrinsicYuv2_K) |
| push {r4, r5, r6, lr} @ preserve clobbered int registers |
| vpush {Q4-Q7} @ preserve Vregisters we clobber |
| |
| mov r5, #16 @ Integer 16 in r5; used as an incrementing value |
| |
| ldr r4, [sp, #64+16+4] @ load the coeffs address in memory in r4 (16*4 + 4*4 + 4) |
| ldr r6, [sp, #64+16] @ load the length in r6 (16*4 + 4*4) |
| vld1.16 {Q2}, [r4]! @ load the multipliers from the coeffs matrix (r4) in Q2 |
| vld1.8 {d6[]}, [r4], r5 @ load y offset 16 from the coeffs matrix (r4) in d6 |
| vld1.8 {d8[]}, [r4], r5 @ load V and U offset of 128 from the coeffs matrix (r4) in d8 |
| |
| mov r4, #4 @ Integer 8 in r4; used as an incrementing value |
| |
| vdup.8 d3, d5[1] @ d3 = 255 (alpha) from the multipliers line in |
| @ the coeffs matrix (Q2) |
| |
| 1: |
| vld1.8 {d10}, [r1]! @ get Y (r1->Y) |
| vld1.8 {d12}, [r3], r4 @ split V from U (r2 -> VU) and increase pointer by 4 (in r4) |
| vld1.8 {d14}, [r2], r4 @ split V from U (r2 -> VU) and increase pointer by 4 (in r4) |
| pld [r1, #64] @ preloading data from address y(r1) + 64 for subsequent loops |
| pld [r2, #64] @ preloading data from address vu(r2) + 64 for subsequent loops |
| |
| vsubl.u8 Q5, d10, d6 @ Y to 16 bit - 16 (in 16bit) (n to n+7) |
| vmull.s16 Q8, d10, d4[0] @ Y(n,n+1,n+2,n+3) * 298 = Q8 (to 32bit) |
| vmull.s16 Q11, d11, d4[0] @ Y(n+4,n+5,n+6,n+7) * 298 = Q11 (to 32bit) |
| |
| vsubl.u8 Q5, d12, d8 @ V to 16 bit - 128 = Q5 // V(n, n+1, n+2,n+3) |
| vsubl.u8 Q6, d14, d8 @ U to 16 bit - 128 = Q6 // U(n, n+1, n+2,n+3) |
| vmov.u16 d11, d10 @ Copying V to d11 |
| vmov.u16 d13, d12 @ Copying U to d13 |
| vzip.u16 d10, d11 @ Q5 = V (n,n n+1, n+1) V(n+2, n+2, n+3, n+3) |
| vzip.u16 d12, d13 @ Q5 = U (n,n n+1, n+1) U(n+2, n+2, n+3, n+3) |
| |
| |
| vmov Q9, Q8 @ Copy Q8(Y: n, n+1, n+2, n+3) to Q9 |
| vmov Q10, Q8 @ Copy Q8(Y: n, n+1, n+2, n+3) to Q10 |
| vmov Q12, Q11 @ Copy Q11(Y: n+5, n+6, n+6, n+7) to Q12 |
| vmov Q13, Q11 @ Copy Q11(Y: n+5, n+6, n+6, n+7) to Q13 |
| |
| @ R G B |
| @ Pixel(0-3) Q8, Q9, Q10 |
| @ Pixel(4-7) Q11, Q12, Q13 |
| @ |
| |
| @ Pixel(0-3) |
| vmlal.s16 Q8, d10, d4[1] @ R : Q8 = Q8(Y-16) + (V-128) * 409 |
| vmlal.s16 Q9, d10, d5[0] @ G : Q9 = Q9(Y-16) + (V-128) * (-208) |
| vmlal.s16 Q9, d12, d4[2] @ + (U-128) * (-100) |
| vmlal.s16 Q10, d12, d4[3] @ B : Q10 = Q10(Y-16) + (U-128) * 516 |
| |
| @ Pixel(4-7) |
| vmlal.s16 Q11, d11, d4[1] @ R : Q11 = Q11(Y-16) + (V-128) * 409 |
| vmlal.s16 Q12, d11, d5[0] @ G : Q12 = Q12(Y-16) + (V-128) * (-208) |
| vmlal.s16 Q12, d13, d4[2] @ + (U-128) * (-100) |
| vmlal.s16 Q13, d13, d4[3] @ B : Q13 = Q13(Y-16) + (U-128) * 516 |
| |
| @ Pixel(0-3) |
| vrshrn.i32 d16, Q8, #8 @ d16 : R shifted right by 8 rounded'n narrowed to 16bit |
| vrshrn.i32 d18, Q9, #8 @ d18 : G shifted right by 8 rounded'n narrowed to 16bit |
| vrshrn.i32 d20, Q10, #8 @ d20 : B shifted right by 8 rounded'n narrowed to 16bit |
| |
| @ Pixel(4-7) |
| vrshrn.i32 d17, Q11, #8 @ d17 : R shifted right by 8 rounded'n narrowed to 16bit |
| vrshrn.i32 d19, Q12, #8 @ d19 : G shifted right by 8 rounded'n narrowed to 16bit |
| vrshrn.i32 d21, Q13, #8 @ d21 : B shifted right by 8 rounded'n narrowed to 16bit |
| |
| vqmovun.s16 d0, Q8 @ r = d0 (saturated, unsigned and narrowed to 8bit) |
| vqmovun.s16 d1, Q9 @ g = d1 (saturated, unsigned and narrowed to 8bit) |
| vqmovun.s16 d2, Q10 @ b = d2 (saturated, unsigned and narrowed to 8bit) |
| |
| subs r6, r6, #1 @ Checking length (r6) |
| vst4.8 {d0, d1, d2, d3}, [r0]! @ Writing out 8 RGBA values to dst (r0) |
| |
| bne 1b @ if not done with length, loop |
| |
| vpop {Q4-Q7} @ Restore Vregisters |
| pop {r4, r5, r6, lr} @ Restore int registers |
| bx lr |
| END(rsdIntrinsicYuv2_K) |
| |
| /* Convolve 5x5 */ |
| |
| /* |
| r0 = dst |
| r1 = y0 base pointer |
| r2 = y1 base pointer |
| r3 = y2 base pointer |
| r4 = y3 base pointer |
| r5 = y4 base pointer |
| r6 = coeffs |
| r7 = length |
| */ |
| ENTRY(rsdIntrinsicConvolve5x5_K) |
| push {r4-r7, lr} |
| vpush {q4-q7} |
| |
| /* load y3 in r4 */ |
| ldr r4, [sp, #20 + 64] |
| |
| /* load y4 in r5 */ |
| ldr r5, [sp, #24 + 64] |
| |
| /* Load the coefficients pointer */ |
| ldr r6, [sp, #28 + 64] |
| |
| /* Create the coefficients vector */ |
| vld1.16 {d0, d1, d2, d3}, [r6]! |
| vld1.16 {d4, d5, d6}, [r6] |
| |
| vmov.u32 q15, #0x7f |
| |
| /* load the count */ |
| ldr r6, [sp, #32 + 64] |
| |
| /* Load the frequently used immediate in a register */ |
| mov r7, #8 |
| |
| 1: |
| /* Load the y base pointers in Qregs and post-increase the address by r7=#8 */ |
| vld1.8 {d24, d25, d26}, [r1], r7 @ y0 ( y - 2 ) |
| vld1.8 {d27, d28, d29}, [r2], r7 @ y0 ( y - 1 ) |
| |
| /* Signal memory for data that will be used in the loop after the next */ |
| PLD (r1, r7) |
| PLD (r2, r7) |
| |
| /* Promoting the 8bit channels to 16bit */ |
| vmovl.u8 q9, d24 |
| vmovl.u8 q10, d25 |
| vmovl.u8 q11, d26 |
| vmovl.u8 q12, d27 |
| vmovl.u8 q13, d28 |
| vmovl.u8 q14, d29 |
| |
| /* |
| d18, d19, d20, d21, d22, d23, |
| d24, d25 |
| */ |
| vmull.s16 q4, d18, d0[0] |
| vmlal.s16 q4, d19, d0[1] |
| vmlal.s16 q4, d20, d0[2] |
| vmlal.s16 q4, d21, d0[3] |
| vmlal.s16 q4, d22, d1[0] |
| |
| vmlal.s16 q4, d24, d1[1] |
| vmlal.s16 q4, d25, d1[2] |
| vmlal.s16 q4, d26, d1[3] |
| vmlal.s16 q4, d27, d2[0] |
| vmlal.s16 q4, d28, d2[1] |
| |
| vmull.s16 q5, d19, d0[0] |
| vmlal.s16 q5, d20, d0[1] |
| vmlal.s16 q5, d21, d0[2] |
| vmlal.s16 q5, d22, d0[3] |
| vmlal.s16 q5, d23, d1[0] |
| |
| vmlal.s16 q5, d25, d1[1] |
| vmlal.s16 q5, d26, d1[2] |
| vmlal.s16 q5, d27, d1[3] |
| vmlal.s16 q5, d28, d2[0] |
| vmlal.s16 q5, d29, d2[1] |
| |
| |
| /* Next 2 rows */ |
| /* Load the y base pointers in Qregs and post-increase the address by r7=#8 */ |
| vld1.8 {d24, d25, d26}, [r3], r7 @ y0 ( y ) |
| vld1.8 {d27, d28, d29}, [r4], r7 @ y0 ( y + 1 ) |
| |
| /* Signal memory for data that will be used in the loop after the next */ |
| PLD (r3, r7) |
| PLD (r4, r7) |
| |
| /* Promoting the 8bit channels to 16bit */ |
| vmovl.u8 q9, d24 |
| vmovl.u8 q10, d25 |
| vmovl.u8 q11, d26 |
| vmovl.u8 q12, d27 |
| vmovl.u8 q13, d28 |
| vmovl.u8 q14, d29 |
| |
| /* |
| d18, d19, d20, d21, d22, d23, |
| d24, d25 |
| */ |
| vmlal.s16 q4, d18, d2[2] |
| vmlal.s16 q4, d19, d2[3] |
| vmlal.s16 q4, d20, d3[0] |
| vmlal.s16 q4, d21, d3[1] |
| vmlal.s16 q4, d22, d3[2] |
| |
| vmlal.s16 q4, d24, d3[3] |
| vmlal.s16 q4, d25, d4[0] |
| vmlal.s16 q4, d26, d4[1] |
| vmlal.s16 q4, d27, d4[2] |
| vmlal.s16 q4, d28, d4[3] |
| |
| vmlal.s16 q5, d19, d2[2] |
| vmlal.s16 q5, d20, d2[3] |
| vmlal.s16 q5, d21, d3[0] |
| vmlal.s16 q5, d22, d3[1] |
| vmlal.s16 q5, d23, d3[2] |
| |
| vmlal.s16 q5, d25, d3[3] |
| vmlal.s16 q5, d26, d4[0] |
| vmlal.s16 q5, d27, d4[1] |
| vmlal.s16 q5, d28, d4[2] |
| vmlal.s16 q5, d29, d4[3] |
| |
| /* Last row */ |
| /* Load the y base pointers in Qregs and post-increase the address by r7=#8 */ |
| vld1.8 {d24, d25, d26}, [r5], r7 @ y0 ( y + 2 ) |
| |
| /* Signal memory for data that will be used in the loop after the next */ |
| PLD (r5, r7) |
| |
| /* Promoting the 8bit channels to 16bit */ |
| vmovl.u8 q9, d24 |
| vmovl.u8 q10, d25 |
| vmovl.u8 q11, d26 |
| |
| /* |
| d18, d19, d20, d21, d22, d23, |
| d24, d25 |
| */ |
| |
| vmlal.s16 q4, d18, d5[0] |
| vmlal.s16 q4, d19, d5[1] |
| vmlal.s16 q4, d20, d5[2] |
| vmlal.s16 q4, d21, d5[3] |
| vmlal.s16 q4, d22, d6[0] |
| |
| vmlal.s16 q5, d19, d5[0] |
| vmlal.s16 q5, d20, d5[1] |
| vmlal.s16 q5, d21, d5[2] |
| vmlal.s16 q5, d22, d5[3] |
| vmlal.s16 q5, d23, d6[0] |
| |
| |
| |
| vadd.i32 q4, q4, q15 |
| vadd.i32 q5, q5, q15 |
| |
| /* Narrow it to a d-reg 32 -> 16 bit */ |
| vrshrn.i32 d8, q4, #8 |
| vrshrn.i32 d9, q5, #8 |
| |
| |
| /* Pack 16 -> 8 bit, saturate, put two pixels into D reg */ |
| vqmovun.s16 d8, q4 |
| |
| vst1.8 d8, [r0]! @ return the output and increase the address of r0 |
| |
| /* Are we done? */ |
| subs r6, r6, #1 |
| bne 1b |
| |
| /* Yup, bye */ |
| vpop {q4-q7} |
| pop {r4-r7, lr} |
| bx lr |
| |
| END(rsdIntrinsicConvolve5x5_K) |
| |
| |
| |
| |
| /* |
| dst = src + dst * (1.0 - src.a) |
| |
| r0 = dst |
| r1 = src |
| r2 = length |
| */ |
| ENTRY(rsdIntrinsicBlendSrcOver_K) |
| .save {r4, lr} |
| stmfd sp!, {r4, lr} |
| vpush {q4-q7} |
| |
| mov r4, #255 |
| vdup.16 q7, r4 |
| |
| mov r4, r0 |
| 1: |
| |
| /* src */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]! |
| vshll.u8 q12, d0, #8 |
| vshll.u8 q13, d1, #8 |
| vshll.u8 q14, d2, #8 |
| vmovl.u8 q6, d3 |
| vsub.i16 q6, q7, q6 // q6 = 1 - src.a |
| vshll.u8 q15, d3, #8 |
| |
| /* dst */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]! |
| vmovl.u8 q8, d0 |
| vmovl.u8 q9, d1 |
| vmovl.u8 q10, d2 |
| vmovl.u8 q11, d3 |
| |
| vmla.i16 q12, q8, q6 |
| vmla.i16 q13, q9, q6 |
| vmla.i16 q14, q10, q6 |
| vmla.i16 q15, q11, q6 |
| |
| vshrn.i16 d0, q12, #8 |
| vshrn.i16 d1, q13, #8 |
| vshrn.i16 d2, q14, #8 |
| vshrn.i16 d3, q15, #8 |
| vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]! |
| vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]! |
| vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]! |
| vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]! |
| vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]! |
| vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]! |
| vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]! |
| vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]! |
| |
| subs r2, r2, #1 |
| bne 1b |
| |
| vpop {q4-q7} |
| ldmfd sp!, {r4, lr} |
| bx lr |
| END(rsdIntrinsicBlendSrcOver_K) |
| |
| /* |
| dst = dst + src * (1.0 - dst.a) |
| |
| r0 = dst |
| r1 = src |
| r2 = length |
| */ |
| ENTRY(rsdIntrinsicBlendDstOver_K) |
| .save {r4, lr} |
| stmfd sp!, {r4, lr} |
| vpush {q4-q7} |
| |
| mov r4, #255 |
| vdup.16 q7, r4 |
| |
| mov r4, r0 |
| 1: |
| |
| /* src */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]! |
| vmovl.u8 q12, d0 |
| vmovl.u8 q13, d1 |
| vmovl.u8 q14, d2 |
| vmovl.u8 q15, d3 |
| |
| /* dst */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]! |
| vshll.u8 q8, d0, #8 |
| vshll.u8 q9, d1, #8 |
| vshll.u8 q10, d2, #8 |
| vmovl.u8 q6, d3 |
| vsub.i16 q6, q7, q6 // q6 = 1 - dst.a |
| vshll.u8 q11, d3, #8 |
| |
| |
| vmla.i16 q8, q12, q6 |
| vmla.i16 q9, q13, q6 |
| vmla.i16 q10, q14, q6 |
| vmla.i16 q11, q15, q6 |
| |
| vshrn.i16 d0, q8, #8 |
| vshrn.i16 d1, q9, #8 |
| vshrn.i16 d2, q10, #8 |
| vshrn.i16 d3, q11, #8 |
| vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]! |
| vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]! |
| vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]! |
| vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]! |
| vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]! |
| vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]! |
| vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]! |
| vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]! |
| |
| subs r2, r2, #1 |
| bne 1b |
| |
| vpop {q4-q7} |
| ldmfd sp!, {r4, lr} |
| bx lr |
| END(rsdIntrinsicBlendDstOver_K) |
| |
| /* |
| dst = src * dst.a |
| |
| r0 = dst |
| r1 = src |
| r2 = length |
| */ |
| ENTRY(rsdIntrinsicBlendSrcIn_K) |
| .save {r4, lr} |
| stmfd sp!, {r4, lr} |
| vpush {q4-q7} |
| |
| mov r4, r0 |
| 1: |
| |
| /* src */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]! |
| vmovl.u8 q12, d0 |
| vmovl.u8 q13, d1 |
| vmovl.u8 q14, d2 |
| vmovl.u8 q15, d3 |
| |
| /* dst */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]! |
| //vmovl.u8 q8, d0 |
| //vmovl.u8 q9, d1 |
| //vmovl.u8 q10, d2 |
| vmovl.u8 q11, d3 |
| |
| vmul.i16 q12, q12, q11 |
| vmul.i16 q13, q13, q11 |
| vmul.i16 q14, q14, q11 |
| vmul.i16 q15, q15, q11 |
| |
| vshrn.i16 d0, q12, #8 |
| vshrn.i16 d1, q13, #8 |
| vshrn.i16 d2, q14, #8 |
| vshrn.i16 d3, q15, #8 |
| vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]! |
| vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]! |
| vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]! |
| vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]! |
| vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]! |
| vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]! |
| vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]! |
| vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]! |
| |
| subs r2, r2, #1 |
| bne 1b |
| |
| vpop {q4-q7} |
| ldmfd sp!, {r4, lr} |
| bx lr |
| END(rsdIntrinsicBlendSrcIn_K) |
| |
| /* |
| dst = dst * src.a |
| |
| r0 = dst |
| r1 = src |
| r2 = length |
| */ |
| ENTRY(rsdIntrinsicBlendDstIn_K) |
| .save {r4, lr} |
| stmfd sp!, {r4, lr} |
| vpush {q4-q7} |
| |
| mov r4, r0 |
| 1: |
| |
| /* src */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]! |
| //vmovl.u8 q12, d0 |
| //vmovl.u8 q13, d1 |
| //vmovl.u8 q14, d2 |
| vmovl.u8 q15, d3 |
| |
| /* dst */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]! |
| vmovl.u8 q8, d0 |
| vmovl.u8 q9, d1 |
| vmovl.u8 q10, d2 |
| vmovl.u8 q11, d3 |
| |
| vmul.i16 q8, q8, q15 |
| vmul.i16 q9, q9, q15 |
| vmul.i16 q10, q10, q15 |
| vmul.i16 q11, q11, q15 |
| |
| vshrn.i16 d0, q8, #8 |
| vshrn.i16 d1, q9, #8 |
| vshrn.i16 d2, q10, #8 |
| vshrn.i16 d3, q11, #8 |
| vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]! |
| vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]! |
| vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]! |
| vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]! |
| vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]! |
| vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]! |
| vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]! |
| vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]! |
| |
| subs r2, r2, #1 |
| bne 1b |
| |
| vpop {q4-q7} |
| ldmfd sp!, {r4, lr} |
| bx lr |
| END(rsdIntrinsicBlendDstIn_K) |
| |
| |
| |
| /* |
| dst = src * (1.0 - dst.a) |
| |
| r0 = dst |
| r1 = src |
| r2 = length |
| */ |
| ENTRY(rsdIntrinsicBlendSrcOut_K) |
| .save {r4, lr} |
| stmfd sp!, {r4, lr} |
| vpush {q4-q7} |
| |
| mov r4, #255 |
| vdup.16 q7, r4 |
| |
| mov r4, r0 |
| 1: |
| |
| /* src */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]! |
| vmovl.u8 q12, d0 |
| vmovl.u8 q13, d1 |
| vmovl.u8 q14, d2 |
| vmovl.u8 q15, d3 |
| |
| /* dst */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]! |
| //vmovl.u8 q8, d0 |
| //vmovl.u8 q9, d1 |
| //vmovl.u8 q10, d2 |
| vmovl.u8 q11, d3 |
| |
| |
| vsub.i16 q6, q7, q11 // q6 = 1 - dst.a |
| vmul.i16 q12, q12, q6 |
| vmul.i16 q13, q13, q6 |
| vmul.i16 q14, q14, q6 |
| vmul.i16 q15, q15, q6 |
| |
| vshrn.i16 d0, q12, #8 |
| vshrn.i16 d1, q13, #8 |
| vshrn.i16 d2, q14, #8 |
| vshrn.i16 d3, q15, #8 |
| vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]! |
| vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]! |
| vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]! |
| vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]! |
| vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]! |
| vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]! |
| vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]! |
| vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]! |
| |
| subs r2, r2, #1 |
| bne 1b |
| |
| vpop {q4-q7} |
| ldmfd sp!, {r4, lr} |
| bx lr |
| END(rsdIntrinsicBlendSrcOut_K) |
| |
| |
| /* |
| dst = dst * (1.0 - src.a) |
| |
| r0 = dst |
| r1 = src |
| r2 = length |
| */ |
| ENTRY(rsdIntrinsicBlendDstOut_K) |
| .save {r4, lr} |
| stmfd sp!, {r4, lr} |
| vpush {q4-q7} |
| |
| mov r4, #255 |
| vdup.16 q7, r4 |
| |
| mov r4, r0 |
| 1: |
| |
| /* src */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]! |
| //vmovl.u8 q12, d0 |
| //vmovl.u8 q13, d1 |
| //vmovl.u8 q14, d2 |
| vmovl.u8 q15, d3 |
| |
| /* dst */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]! |
| vmovl.u8 q8, d0 |
| vmovl.u8 q9, d1 |
| vmovl.u8 q10, d2 |
| vmovl.u8 q11, d3 |
| |
| |
| vsub.i16 q6, q7, q15 // q6 = 1 - src.a |
| vmul.i16 q12, q8, q6 |
| vmul.i16 q13, q9, q6 |
| vmul.i16 q14, q10, q6 |
| vmul.i16 q15, q11, q6 |
| |
| vshrn.i16 d0, q12, #8 |
| vshrn.i16 d1, q13, #8 |
| vshrn.i16 d2, q14, #8 |
| vshrn.i16 d3, q15, #8 |
| vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]! |
| vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]! |
| vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]! |
| vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]! |
| vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]! |
| vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]! |
| vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]! |
| vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]! |
| |
| subs r2, r2, #1 |
| bne 1b |
| |
| vpop {q4-q7} |
| ldmfd sp!, {r4, lr} |
| bx lr |
| END(rsdIntrinsicBlendDstOut_K) |
| |
| |
| /* |
| dst.rgb = src.rgb * dst.a + (1.0 - src.a) * dst.rgb |
| dst.a = dst.a |
| |
| r0 = dst |
| r1 = src |
| r2 = length |
| */ |
| ENTRY(rsdIntrinsicBlendSrcAtop_K) |
| .save {r4, lr} |
| stmfd sp!, {r4, lr} |
| vpush {q4-q7} |
| |
| mov r4, #255 |
| vdup.16 q7, r4 |
| |
| mov r4, r0 |
| 1: |
| |
| /* src */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]! |
| vmovl.u8 q12, d0 |
| vmovl.u8 q13, d1 |
| vmovl.u8 q14, d2 |
| vmovl.u8 q15, d3 |
| |
| /* dst */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]! |
| vmovl.u8 q8, d0 |
| vmovl.u8 q9, d1 |
| vmovl.u8 q10, d2 |
| vmovl.u8 q11, d3 |
| |
| |
| vsub.i16 q6, q7, q15 // q6 = 1 - src.a |
| vmul.i16 q8, q8, q6 |
| vmul.i16 q9, q9, q6 |
| vmul.i16 q10, q10, q6 |
| |
| vmla.i16 q8, q12, q11 |
| vmla.i16 q9, q13, q11 |
| vmla.i16 q10, q14, q11 |
| |
| |
| vshrn.i16 d0, q8, #8 |
| vshrn.i16 d1, q9, #8 |
| vshrn.i16 d2, q10, #8 |
| //vshrn.i16 d3, q15, #8 |
| vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]! |
| vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]! |
| vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]! |
| vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]! |
| vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]! |
| vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]! |
| vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]! |
| vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]! |
| |
| subs r2, r2, #1 |
| bne 1b |
| |
| vpop {q4-q7} |
| ldmfd sp!, {r4, lr} |
| bx lr |
| END(rsdIntrinsicBlendSrcAtop_K) |
| |
| /* |
| dst = dst.rgb * src.a + (1.0 - dst.a) * src.rgb |
| dst.a = src.a |
| |
| r0 = dst |
| r1 = src |
| r2 = length |
| */ |
| ENTRY(rsdIntrinsicBlendDstAtop_K) |
| .save {r4, lr} |
| stmfd sp!, {r4, lr} |
| vpush {q4-q7} |
| |
| mov r4, #255 |
| vdup.16 q7, r4 |
| |
| mov r4, r0 |
| 1: |
| |
| /* src */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]! |
| vmovl.u8 q12, d0 |
| vmovl.u8 q13, d1 |
| vmovl.u8 q14, d2 |
| vmovl.u8 q15, d3 |
| |
| /* dst */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]! |
| vmovl.u8 q8, d0 |
| vmovl.u8 q9, d1 |
| vmovl.u8 q10, d2 |
| vmovl.u8 q11, d3 |
| |
| |
| vsub.i16 q6, q7, q11 // q6 = 1 - dst.a |
| vmul.i16 q12, q12, q6 |
| vmul.i16 q13, q13, q6 |
| vmul.i16 q14, q14, q6 |
| |
| vmla.i16 q12, q8, q15 |
| vmla.i16 q13, q9, q15 |
| vmla.i16 q14, q10, q15 |
| |
| |
| vshrn.i16 d0, q12, #8 |
| vshrn.i16 d1, q13, #8 |
| vshrn.i16 d2, q14, #8 |
| //vshrn.i16 d3, q15, #8 |
| vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]! |
| vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]! |
| vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]! |
| vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]! |
| vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]! |
| vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]! |
| vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]! |
| vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]! |
| |
| subs r2, r2, #1 |
| bne 1b |
| |
| vpop {q4-q7} |
| ldmfd sp!, {r4, lr} |
| bx lr |
| END(rsdIntrinsicBlendDstAtop_K) |
| |
| /* |
| dst = dst ^ src |
| |
| r0 = dst |
| r1 = src |
| r2 = length |
| */ |
| ENTRY(rsdIntrinsicBlendXor_K) |
| .save {r4, lr} |
| stmfd sp!, {r4, lr} |
| vpush {q4-q7} |
| |
| mov r4, #255 |
| vdup.16 q7, r4 |
| |
| mov r4, r0 |
| 1: |
| |
| /* src */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]! |
| vmov.u8 d4, d0 |
| vmov.u8 d5, d1 |
| vmov.u8 d6, d2 |
| vmov.u8 d7, d3 |
| |
| /* dst */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]! |
| |
| veor d0, d0, d4 |
| veor d1, d1, d5 |
| veor d2, d2, d6 |
| veor d3, d3, d7 |
| |
| vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]! |
| vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]! |
| vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]! |
| vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]! |
| vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]! |
| vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]! |
| vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]! |
| vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]! |
| |
| subs r2, r2, #1 |
| bne 1b |
| |
| vpop {q4-q7} |
| ldmfd sp!, {r4, lr} |
| bx lr |
| END(rsdIntrinsicBlendXor_K) |
| |
| /* |
| dst = dst * src |
| |
| r0 = dst |
| r1 = src |
| r2 = length |
| */ |
| ENTRY(rsdIntrinsicBlendMultiply_K) |
| .save {r4, lr} |
| stmfd sp!, {r4, lr} |
| vpush {q4-q7} |
| |
| mov r4, #255 |
| vdup.16 q7, r4 |
| |
| mov r4, r0 |
| 1: |
| |
| /* src */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]! |
| vmovl.u8 q12, d0 |
| vmovl.u8 q13, d1 |
| vmovl.u8 q14, d2 |
| vmovl.u8 q15, d3 |
| |
| /* dst */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]! |
| vmovl.u8 q8, d0 |
| vmovl.u8 q9, d1 |
| vmovl.u8 q10, d2 |
| vmovl.u8 q11, d3 |
| |
| |
| vmul.i16 q8, q8, q12 |
| vmul.i16 q9, q9, q13 |
| vmul.i16 q10, q10, q14 |
| vmul.i16 q11, q11, q15 |
| |
| vshrn.i16 d0, q8, #8 |
| vshrn.i16 d1, q9, #8 |
| vshrn.i16 d2, q10, #8 |
| vshrn.i16 d3, q11, #8 |
| vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]! |
| vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]! |
| vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]! |
| vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]! |
| vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]! |
| vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]! |
| vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]! |
| vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]! |
| |
| subs r2, r2, #1 |
| bne 1b |
| |
| vpop {q4-q7} |
| ldmfd sp!, {r4, lr} |
| bx lr |
| END(rsdIntrinsicBlendMultiply_K) |
| |
| /* |
| dst = min(src + dst, 1.0) |
| |
| r0 = dst |
| r1 = src |
| r2 = length |
| */ |
| ENTRY(rsdIntrinsicBlendAdd_K) |
| .save {r4, lr} |
| stmfd sp!, {r4, lr} |
| vpush {q4-q7} |
| |
| mov r4, #255 |
| vdup.16 q7, r4 |
| |
| mov r4, r0 |
| 1: |
| |
| /* src */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]! |
| vmovl.u8 q12, d0 |
| vmovl.u8 q13, d1 |
| vmovl.u8 q14, d2 |
| vmovl.u8 q15, d3 |
| |
| /* dst */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]! |
| vmovl.u8 q8, d0 |
| vmovl.u8 q9, d1 |
| vmovl.u8 q10, d2 |
| vmovl.u8 q11, d3 |
| |
| |
| vadd.i16 q8, q8, q12 |
| vadd.i16 q9, q9, q13 |
| vadd.i16 q10, q10, q14 |
| vadd.i16 q11, q11, q15 |
| |
| vqmovun.s16 d0, q8 |
| vqmovun.s16 d1, q9 |
| vqmovun.s16 d2, q10 |
| vqmovun.s16 d3, q11 |
| vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]! |
| vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]! |
| vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]! |
| vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]! |
| vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]! |
| vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]! |
| vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]! |
| vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]! |
| |
| subs r2, r2, #1 |
| bne 1b |
| |
| vpop {q4-q7} |
| ldmfd sp!, {r4, lr} |
| bx lr |
| END(rsdIntrinsicBlendAdd_K) |
| |
| |
| /* |
| dst = max(dst - src, 0.0) |
| |
| r0 = dst |
| r1 = src |
| r2 = length |
| */ |
| ENTRY(rsdIntrinsicBlendSub_K) |
| .save {r4, lr} |
| stmfd sp!, {r4, lr} |
| vpush {q4-q7} |
| |
| mov r4, #255 |
| vdup.16 q7, r4 |
| |
| mov r4, r0 |
| 1: |
| |
| /* src */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r1]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r1]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r1]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r1]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r1]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r1]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r1]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r1]! |
| vmovl.u8 q12, d0 |
| vmovl.u8 q13, d1 |
| vmovl.u8 q14, d2 |
| vmovl.u8 q15, d3 |
| |
| /* dst */ |
| vld4.8 {d0[0],d1[0],d2[0],d3[0]}, [r0]! |
| vld4.8 {d0[1],d1[1],d2[1],d3[1]}, [r0]! |
| vld4.8 {d0[2],d1[2],d2[2],d3[2]}, [r0]! |
| vld4.8 {d0[3],d1[3],d2[3],d3[3]}, [r0]! |
| vld4.8 {d0[4],d1[4],d2[4],d3[4]}, [r0]! |
| vld4.8 {d0[5],d1[5],d2[5],d3[5]}, [r0]! |
| vld4.8 {d0[6],d1[6],d2[6],d3[6]}, [r0]! |
| vld4.8 {d0[7],d1[7],d2[7],d3[7]}, [r0]! |
| vmovl.u8 q8, d0 |
| vmovl.u8 q9, d1 |
| vmovl.u8 q10, d2 |
| vmovl.u8 q11, d3 |
| |
| |
| vsub.i16 q8, q8, q12 |
| vsub.i16 q9, q9, q13 |
| vsub.i16 q10, q10, q14 |
| vsub.i16 q11, q11, q15 |
| |
| vqmovun.s16 d0, q8 |
| vqmovun.s16 d1, q9 |
| vqmovun.s16 d2, q10 |
| vqmovun.s16 d3, q11 |
| vst4.8 {d0[0],d1[0],d2[0],d3[0]}, [r4]! |
| vst4.8 {d0[1],d1[1],d2[1],d3[1]}, [r4]! |
| vst4.8 {d0[2],d1[2],d2[2],d3[2]}, [r4]! |
| vst4.8 {d0[3],d1[3],d2[3],d3[3]}, [r4]! |
| vst4.8 {d0[4],d1[4],d2[4],d3[4]}, [r4]! |
| vst4.8 {d0[5],d1[5],d2[5],d3[5]}, [r4]! |
| vst4.8 {d0[6],d1[6],d2[6],d3[6]}, [r4]! |
| vst4.8 {d0[7],d1[7],d2[7],d3[7]}, [r4]! |
| |
| subs r2, r2, #1 |
| bne 1b |
| |
| vpop {q4-q7} |
| ldmfd sp!, {r4, lr} |
| bx lr |
| END(rsdIntrinsicBlendSub_K) |
| |
| |
| /* 3D LUT */ |
| |
| /* |
| r0 = dst |
| r1 = src |
| r2 = cube base pointer |
| r3 = cube Y stride |
| r4 = cube Z stride |
| r5 = count |
| xr10 = * constants |
| |
| d0 / q0 = weight 1 p1 |
| d1 = weight 2 p1 |
| |
| d2 / q1 = weight 1 p2 |
| d3 = weight 2 p2 |
| |
| d4 / q2 = src1 |
| d5 = src2 |
| |
| d6 / q3 = baseCoord |
| d7 = baseCoord |
| |
| d8 / q4 = coord1 p1 |
| d9 = |
| |
| d10 / q5 = coord1 p2 |
| d11 = |
| |
| d12 / q6 = |
| d13 = |
| |
| d14 / q7 = |
| d15 = |
| |
| |
| d16 / q8 = x0 y0 z0 |
| d17 = x1 y0 z0 |
| d18 / q9 = x0 y1 z0 |
| d19 = x1 y1 z0 |
| d20 / q10 = x0 y0 z1 |
| d21 = x1 y0 z1 |
| d22 / q11 = x0 y1 z1 |
| d23 = x1 y1 z1 |
| |
| d24 / q12 = alpha mash |
| d25 = current pixel alpha |
| d26 / q13 = 4, y stride |
| d27 = z stride, 0 |
| d28 / q14 = 0x8000 |
| d29 = 0x7fff |
| d30 / q15 = 0, 0, 0, 0xffff |
| |
| |
| d31 = coordMult |
| */ |
| |
| ENTRY(rsdIntrinsic3DLUT_K) |
| push {r4-r8, r10, r11, lr} |
| vpush {q4-q7} |
| |
| /* load Z stride in r4 */ |
| ldr r4, [sp, #32 + 64] |
| |
| /* Load count */ |
| ldr r5, [sp, #36 + 64] |
| |
| vmov.u16 d28, #0x8000 |
| vmov.u16 d29, #0x7fff |
| vmov.u32 d24, #0xff000000 |
| |
| /* load constants using r10 */ |
| ldr r10, [sp, #40 + 64] |
| vld1.32 {d31}, [r10]! |
| vld1.32 {d30}, [r10]! |
| |
| mov r6, #4 |
| vmov d26, r6, r3 |
| mov r6, #0 |
| vmov d27, r4, r6 |
| |
| add r8, r3, r4 |
| |
| |
| |
| 1: |
| vld1.8 {d4}, [r1]! |
| vand.u8 d25, d4, d24 |
| vmovl.u8 q2, d4 |
| |
| |
| vmull.u16 q3, d4, d31 |
| vshr.u32 q4, q3, #15 // coord1 p1 |
| vmovn.u32 d1, q3 |
| vand.u16 d1, d29 // weight 2 |
| vsub.u16 d0, d28, d1 // weight 1 |
| vmul.u32 q4, q4, q13 // q4 = x*4, y*ystride, z*zstride, 0 |
| |
| vmull.u16 q3, d5, d31 |
| vshr.u32 q5, q3, #15 // coord1 p2 |
| vmovn.u32 d3, q3 |
| vand.u16 d3, d29 // weight 2 |
| vsub.u16 d2, d28, d3 // weight 1 |
| vmul.u32 q5, q5, q13 // q5 = x*4, y*ystride, z*zstride, 0 |
| |
| vpadd.u32 d8, d8, d9 |
| vpadd.u32 d9, d10, d11 |
| vpadd.u32 d8, d8, d9 |
| vmov r6, r7, d8 // base pointers |
| |
| add r6, r6, r2 |
| add r7, r7, r2 |
| |
| vld1.8 {d16}, [r6] |
| add r11, r6, r3 |
| vld1.8 {d18}, [r11] |
| add r11, r6, r4 |
| vld1.8 {d20}, [r11] |
| add r11, r6, r8 |
| vld1.8 {d22}, [r11] |
| |
| vmovl.u8 q8, d16 |
| vmovl.u8 q9, d18 |
| vmovl.u8 q10, d20 |
| vmovl.u8 q11, d22 |
| |
| vmull.u16 q6, d16, d0[0] |
| vmlal.u16 q6, d17, d1[0] |
| vshrn.u32 d16, q6, #7 |
| vmull.u16 q6, d18, d0[0] |
| vmlal.u16 q6, d19, d1[0] |
| vshrn.u32 d18, q6, #7 |
| vmull.u16 q6, d20, d0[0] |
| vmlal.u16 q6, d21, d1[0] |
| vshrn.u32 d20, q6, #7 |
| vmull.u16 q6, d22, d0[0] |
| vmlal.u16 q6, d23, d1[0] |
| vshrn.u32 d22, q6, #7 |
| |
| vmull.u16 q6, d16, d0[1] |
| vmlal.u16 q6, d18, d1[1] |
| vshrn.u32 d16, q6, #15 |
| vmull.u16 q6, d20, d0[1] |
| vmlal.u16 q6, d22, d1[1] |
| vshrn.u32 d18, q6, #15 |
| |
| vmull.u16 q6, d16, d0[2] |
| vmlal.u16 q6, d18, d1[2] |
| vshrn.u32 d14, q6, #15 |
| |
| |
| vld1.8 {d16}, [r7] |
| add r11, r7, r3 |
| vld1.8 {d18}, [r11] |
| add r11, r7, r4 |
| vld1.8 {d20}, [r11] |
| add r11, r7, r8 |
| vld1.8 {d22}, [r11] |
| vmovl.u8 q8, d16 |
| vmovl.u8 q9, d18 |
| vmovl.u8 q10, d20 |
| vmovl.u8 q11, d22 |
| |
| vmull.u16 q6, d16, d2[0] |
| vmlal.u16 q6, d17, d3[0] |
| vshrn.u32 d16, q6, #7 |
| vmull.u16 q6, d18, d2[0] |
| vmlal.u16 q6, d19, d3[0] |
| vshrn.u32 d18, q6, #7 |
| vmull.u16 q6, d20, d2[0] |
| vmlal.u16 q6, d21, d3[0] |
| vshrn.u32 d20, q6, #7 |
| vmull.u16 q6, d22, d2[0] |
| vmlal.u16 q6, d23, d3[0] |
| vshrn.u32 d22, q6, #7 |
| |
| vmull.u16 q6, d16, d2[1] |
| vmlal.u16 q6, d18, d3[1] |
| vshrn.u32 d16, q6, #15 |
| vmull.u16 q6, d20, d2[1] |
| vmlal.u16 q6, d22, d3[1] |
| vshrn.u32 d18, q6, #15 |
| |
| vmull.u16 q6, d16, d2[2] |
| vmlal.u16 q6, d18, d3[2] |
| vshrn.u32 d15, q6, #15 |
| |
| vrshrn.u16 d14, q7, #8 |
| |
| vbic.u8 d14, d14, d24 // mix in alpha |
| vorr.u8 d14, d14, d25 |
| vst1.32 {d14}, [r0]! |
| |
| |
| /* Are we done? */ |
| subs r5, r5, #1 |
| bne 1b |
| |
| /* Yup, bye */ |
| vpop {q4-q7} |
| pop {r4-r8, r10, r11, lr} |
| bx lr |
| |
| END(rsdIntrinsic3DLUT_K) |
| |
| |