mirror of
				https://git.code.sf.net/p/libpng/code.git
				synced 2025-07-10 18:04:09 +02:00 
			
		
		
		
	Allow run-time ARM NEON checking to be disabled. A new configure option: --enable-arm-neon=always will stop the run-time checks. New checks within arm/arm_init.c will cause the code not to be compiled unless __ARM_NEON__ is set. This should make it fail safe (if someone asks for it on then the build will fail if it can't be done.)
		
			
				
	
	
		
			236 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			236 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
 | 
						|
/* filter_neon.S - NEON optimised filter functions
 | 
						|
 *
 | 
						|
 * Copyright (c) 2011 Glenn Randers-Pehrson
 | 
						|
 * Written by Mans Rullgard, 2011.
 | 
						|
 * Last changed in libpng 1.5.7 [December 15, 2011]
 | 
						|
 *
 | 
						|
 * This code is released under the libpng license.
 | 
						|
 * For conditions of distribution and use, see the disclaimer
 | 
						|
 * and license in png.h
 | 
						|
 */
 | 
						|
 | 
						|
/* This is required to get the symbol renames, which are #defines, and also
 | 
						|
 * includes the value of PNG_FILTER_OPTIMIZATIONS.
 | 
						|
 */
 | 
						|
#define PNG_VERSION_INFO_ONLY
 | 
						|
#include "../pngpriv.h"
 | 
						|
 | 
						|
#if defined(PNG_FILTER_OPTIMIZATIONS) && defined(__arm__) && \
 | 
						|
   defined(__ARM_NEON__)
 | 
						|
#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
 | 
						|
#endif /* FILTER_OPTIMIZATIONS && __arm__ && __ARM_NEON__ */
 |