/* filter_neon.S - NEON optimised filter functions * * Copyright (c) 2011 Mans Rullgard * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h */ #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack,"",%progbits /* mark stack as non-executable */ #endif #ifdef __ELF__ # define ELF #else # define ELF @ #endif .arch armv7-a .fpu neon .macro func name, export=0 .macro endfunc ELF .size \name, . - \name .endfunc .purgem endfunc .endm .text .if \export .global \name .endif ELF .type \name, STT_FUNC .func \name \name: .endm func png_read_filter_row_sub4_neon, export=1 ldr r3, [r0, #4] @ rowbytes vmov.i8 d3, #0 1: vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128] vadd.u8 d0, d3, d4 vadd.u8 d1, d0, d5 vadd.u8 d2, d1, d6 vadd.u8 d3, d2, d7 vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]! subs r3, r3, #16 bgt 1b bx lr endfunc func png_read_filter_row_sub3_neon, export=1 ldr r3, [r0, #4] @ rowbytes vmov.i8 d3, #0 mov r0, r1 mov r2, #3 mov r12, #12 vld1.8 {q11}, [r0], r12 1: vext.8 d5, d22, d23, #3 vadd.u8 d0, d3, d22 vext.8 d6, d22, d23, #6 vadd.u8 d1, d0, d5 vext.8 d7, d23, d23, #1 vld1.8 {q11}, [r0], r12 vst1.32 {d0[0]}, [r1,:32], r2 vadd.u8 d2, d1, d6 vst1.32 {d1[0]}, [r1], r2 vadd.u8 d3, d2, d7 vst1.32 {d2[0]}, [r1], r2 vst1.32 {d3[0]}, [r1], r2 subs r3, r3, #12 bgt 1b bx lr endfunc func png_read_filter_row_up_neon, export=1 ldr r3, [r0, #4] @ rowbytes 1: vld1.8 {q0}, [r1,:128] vld1.8 {q1}, [r2,:128]! vadd.u8 q0, q0, q1 vst1.8 {q0}, [r1,:128]! subs r3, r3, #16 bgt 1b bx lr endfunc func png_read_filter_row_avg4_neon, export=1 ldr r12, [r0, #4] @ rowbytes vmov.i8 d3, #0 1: vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128] vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]! vhadd.u8 d0, d3, d16 vadd.u8 d0, d0, d4 vhadd.u8 d1, d0, d17 vadd.u8 d1, d1, d5 vhadd.u8 d2, d1, d18 vadd.u8 d2, d2, d6 vhadd.u8 d3, d2, d19 vadd.u8 d3, d3, d7 vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]! subs r12, r12, #16 bgt 1b bx lr endfunc func png_read_filter_row_avg3_neon, export=1 push {r4,lr} ldr r12, [r0, #4] @ rowbytes vmov.i8 d3, #0 mov r0, r1 mov r4, #3 mov lr, #12 vld1.8 {q11}, [r0], lr 1: vld1.8 {q10}, [r2], lr vext.8 d5, d22, d23, #3 vhadd.u8 d0, d3, d20 vext.8 d17, d20, d21, #3 vadd.u8 d0, d0, d22 vext.8 d6, d22, d23, #6 vhadd.u8 d1, d0, d17 vext.8 d18, d20, d21, #6 vadd.u8 d1, d1, d5 vext.8 d7, d23, d23, #1 vld1.8 {q11}, [r0], lr vst1.32 {d0[0]}, [r1,:32], r4 vhadd.u8 d2, d1, d18 vst1.32 {d1[0]}, [r1], r4 vext.8 d19, d21, d21, #1 vadd.u8 d2, d2, d6 vhadd.u8 d3, d2, d19 vst1.32 {d2[0]}, [r1], r4 vadd.u8 d3, d3, d7 vst1.32 {d3[0]}, [r1], r4 subs r12, r12, #12 bgt 1b pop {r4,pc} endfunc .macro paeth rx, ra, rb, rc vaddl.u8 q12, \ra, \rb @ a + b vaddl.u8 q15, \rc, \rc @ 2*c vabdl.u8 q13, \rb, \rc @ pa vabdl.u8 q14, \ra, \rc @ pb vabd.u16 q15, q12, q15 @ pc vcle.u16 q12, q13, q14 @ pa <= pb vcle.u16 q13, q13, q15 @ pa <= pc vcle.u16 q14, q14, q15 @ pb <= pc vand q12, q12, q13 @ pa <= pb && pa <= pc vmovn.u16 d28, q14 vmovn.u16 \rx, q12 vbsl d28, \rb, \rc vbsl \rx, \ra, d28 .endm func png_read_filter_row_paeth4_neon, export=1 ldr r12, [r0, #4] @ rowbytes vmov.i8 d3, #0 vmov.i8 d20, #0 1: vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128] vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]! paeth d0, d3, d16, d20 vadd.u8 d0, d0, d4 paeth d1, d0, d17, d16 vadd.u8 d1, d1, d5 paeth d2, d1, d18, d17 vadd.u8 d2, d2, d6 paeth d3, d2, d19, d18 vmov d20, d19 vadd.u8 d3, d3, d7 vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]! subs r12, r12, #16 bgt 1b bx lr endfunc func png_read_filter_row_paeth3_neon, export=1 push {r4,lr} ldr r12, [r0, #4] @ rowbytes vmov.i8 d3, #0 vmov.i8 d4, #0 mov r0, r1 mov r4, #3 mov lr, #12 vld1.8 {q11}, [r0], lr 1: vld1.8 {q10}, [r2], lr paeth d0, d3, d20, d4 vext.8 d5, d22, d23, #3 vadd.u8 d0, d0, d22 vext.8 d17, d20, d21, #3 paeth d1, d0, d17, d20 vst1.32 {d0[0]}, [r1,:32], r4 vext.8 d6, d22, d23, #6 vadd.u8 d1, d1, d5 vext.8 d18, d20, d21, #6 paeth d2, d1, d18, d17 vext.8 d7, d23, d23, #1 vld1.8 {q11}, [r0], lr vst1.32 {d1[0]}, [r1], r4 vadd.u8 d2, d2, d6 vext.8 d19, d21, d21, #1 paeth d3, d2, d19, d18 vst1.32 {d2[0]}, [r1], r4 vmov d4, d19 vadd.u8 d3, d3, d7 vst1.32 {d3[0]}, [r1], r4 subs r12, r12, #12 bgt 1b pop {r4,pc} endfunc