Home | History | Annotate | Download | only in arm
      1 
      2 /* filter_neon.S - NEON optimised filter functions
      3  *
      4  * Copyright (c) 2013 Glenn Randers-Pehrson
      5  * Written by Mans Rullgard, 2011.
      6  * Last changed in libpng 1.6.8 [December 19, 2013]
      7  *
      8  * This code is released under the libpng license.
      9  * For conditions of distribution and use, see the disclaimer
     10  * and license in png.h
     11  */
     12 
     13 /* This is required to get the symbol renames, which are #defines, and also
     14  * includes the definition (or not) of PNG_ARM_NEON_OPT and
     15  * PNG_ARM_NEON_IMPLEMENTATION.
     16  */
     17 #define PNG_VERSION_INFO_ONLY
     18 #include "../pngpriv.h"
     19 
     20 #if defined(__linux__) && defined(__ELF__)
     21 .section .note.GNU-stack,"",%progbits /* mark stack as non-executable */
     22 #endif
     23 
     24 /* Assembler NEON support - only works for 32-bit ARM (i.e. it does not work for
     25  * ARM64).  The code in arm/filter_neon_intrinsics.c supports ARM64, however it
     26  * only works if -mfpu=neon is specified on the GCC command line.  See pngpriv.h
     27  * for the logic which sets PNG_USE_ARM_NEON_ASM:
     28  */
     29 #if PNG_ARM_NEON_IMPLEMENTATION == 2 /* hand-coded assembler */
     30 
     31 #ifdef PNG_READ_SUPPORTED
     32 #if PNG_ARM_NEON_OPT > 0
     33 
     34 #ifdef __ELF__
     35 #   define ELF
     36 #else
     37 #   define ELF @
     38 #endif
     39 
     40         .arch armv7-a
     41         .fpu  neon
     42 
     43 .macro  func    name, export=0
     44     .macro endfunc
     45 ELF     .size   \name, . - \name
     46         .endfunc
     47         .purgem endfunc
     48     .endm
     49         .text
     50     .if \export
     51         .global \name
     52     .endif
     53 ELF     .type   \name, STT_FUNC
     54         .func   \name
     55 \name:
     56 .endm
     57 
     58 func    png_read_filter_row_sub4_neon, export=1
     59         ldr             r3,  [r0, #4]           @ rowbytes
     60         vmov.i8         d3,  #0
     61 1:
     62         vld4.32         {d4[],d5[],d6[],d7[]},    [r1,:128]
     63         vadd.u8         d0,  d3,  d4
     64         vadd.u8         d1,  d0,  d5
     65         vadd.u8         d2,  d1,  d6
     66         vadd.u8         d3,  d2,  d7
     67         vst4.32         {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
     68         subs            r3,  r3,  #16
     69         bgt             1b
     70 
     71         bx              lr
     72 endfunc
     73 
     74 func    png_read_filter_row_sub3_neon, export=1
     75         ldr             r3,  [r0, #4]           @ rowbytes
     76         vmov.i8         d3,  #0
     77         mov             r0,  r1
     78         mov             r2,  #3
     79         mov             r12, #12
     80         vld1.8          {q11},    [r0], r12
     81 1:
     82         vext.8          d5,  d22, d23, #3
     83         vadd.u8         d0,  d3,  d22
     84         vext.8          d6,  d22, d23, #6
     85         vadd.u8         d1,  d0,  d5
     86         vext.8          d7,  d23, d23, #1
     87         vld1.8          {q11},    [r0], r12
     88         vst1.32         {d0[0]},  [r1,:32], r2
     89         vadd.u8         d2,  d1,  d6
     90         vst1.32         {d1[0]},  [r1], r2
     91         vadd.u8         d3,  d2,  d7
     92         vst1.32         {d2[0]},  [r1], r2
     93         vst1.32         {d3[0]},  [r1], r2
     94         subs            r3,  r3,  #12
     95         bgt             1b
     96 
     97         bx              lr
     98 endfunc
     99 
    100 func    png_read_filter_row_up_neon, export=1
    101         ldr             r3,  [r0, #4]           @ rowbytes
    102 1:
    103         vld1.8          {q0}, [r1,:128]
    104         vld1.8          {q1}, [r2,:128]!
    105         vadd.u8         q0,  q0,  q1
    106         vst1.8          {q0}, [r1,:128]!
    107         subs            r3,  r3,  #16
    108         bgt             1b
    109 
    110         bx              lr
    111 endfunc
    112 
    113 func    png_read_filter_row_avg4_neon, export=1
    114         ldr             r12, [r0, #4]           @ rowbytes
    115         vmov.i8         d3,  #0
    116 1:
    117         vld4.32         {d4[],d5[],d6[],d7[]},    [r1,:128]
    118         vld4.32         {d16[],d17[],d18[],d19[]},[r2,:128]!
    119         vhadd.u8        d0,  d3,  d16
    120         vadd.u8         d0,  d0,  d4
    121         vhadd.u8        d1,  d0,  d17
    122         vadd.u8         d1,  d1,  d5
    123         vhadd.u8        d2,  d1,  d18
    124         vadd.u8         d2,  d2,  d6
    125         vhadd.u8        d3,  d2,  d19
    126         vadd.u8         d3,  d3,  d7
    127         vst4.32         {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
    128         subs            r12, r12, #16
    129         bgt             1b
    130 
    131         bx              lr
    132 endfunc
    133 
    134 func    png_read_filter_row_avg3_neon, export=1
    135         push            {r4,lr}
    136         ldr             r12, [r0, #4]           @ rowbytes
    137         vmov.i8         d3,  #0
    138         mov             r0,  r1
    139         mov             r4,  #3
    140         mov             lr,  #12
    141         vld1.8          {q11},    [r0], lr
    142 1:
    143         vld1.8          {q10},    [r2], lr
    144         vext.8          d5,  d22, d23, #3
    145         vhadd.u8        d0,  d3,  d20
    146         vext.8          d17, d20, d21, #3
    147         vadd.u8         d0,  d0,  d22
    148         vext.8          d6,  d22, d23, #6
    149         vhadd.u8        d1,  d0,  d17
    150         vext.8          d18, d20, d21, #6
    151         vadd.u8         d1,  d1,  d5
    152         vext.8          d7,  d23, d23, #1
    153         vld1.8          {q11},    [r0], lr
    154         vst1.32         {d0[0]},  [r1,:32], r4
    155         vhadd.u8        d2,  d1,  d18
    156         vst1.32         {d1[0]},  [r1], r4
    157         vext.8          d19, d21, d21, #1
    158         vadd.u8         d2,  d2,  d6
    159         vhadd.u8        d3,  d2,  d19
    160         vst1.32         {d2[0]},  [r1], r4
    161         vadd.u8         d3,  d3,  d7
    162         vst1.32         {d3[0]},  [r1], r4
    163         subs            r12, r12, #12
    164         bgt             1b
    165 
    166         pop             {r4,pc}
    167 endfunc
    168 
    169 .macro  paeth           rx,  ra,  rb,  rc
    170         vaddl.u8        q12, \ra, \rb           @ a + b
    171         vaddl.u8        q15, \rc, \rc           @ 2*c
    172         vabdl.u8        q13, \rb, \rc           @ pa
    173         vabdl.u8        q14, \ra, \rc           @ pb
    174         vabd.u16        q15, q12, q15           @ pc
    175         vcle.u16        q12, q13, q14           @ pa <= pb
    176         vcle.u16        q13, q13, q15           @ pa <= pc
    177         vcle.u16        q14, q14, q15           @ pb <= pc
    178         vand            q12, q12, q13           @ pa <= pb && pa <= pc
    179         vmovn.u16       d28, q14
    180         vmovn.u16       \rx, q12
    181         vbsl            d28, \rb, \rc
    182         vbsl            \rx, \ra, d28
    183 .endm
    184 
    185 func    png_read_filter_row_paeth4_neon, export=1
    186         ldr             r12, [r0, #4]           @ rowbytes
    187         vmov.i8         d3,  #0
    188         vmov.i8         d20, #0
    189 1:
    190         vld4.32         {d4[],d5[],d6[],d7[]},    [r1,:128]
    191         vld4.32         {d16[],d17[],d18[],d19[]},[r2,:128]!
    192         paeth           d0,  d3,  d16, d20
    193         vadd.u8         d0,  d0,  d4
    194         paeth           d1,  d0,  d17, d16
    195         vadd.u8         d1,  d1,  d5
    196         paeth           d2,  d1,  d18, d17
    197         vadd.u8         d2,  d2,  d6
    198         paeth           d3,  d2,  d19, d18
    199         vmov            d20, d19
    200         vadd.u8         d3,  d3,  d7
    201         vst4.32         {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
    202         subs            r12, r12, #16
    203         bgt             1b
    204 
    205         bx              lr
    206 endfunc
    207 
    208 func    png_read_filter_row_paeth3_neon, export=1
    209         push            {r4,lr}
    210         ldr             r12, [r0, #4]           @ rowbytes
    211         vmov.i8         d3,  #0
    212         vmov.i8         d4,  #0
    213         mov             r0,  r1
    214         mov             r4,  #3
    215         mov             lr,  #12
    216         vld1.8          {q11},    [r0], lr
    217 1:
    218         vld1.8          {q10},    [r2], lr
    219         paeth           d0,  d3,  d20, d4
    220         vext.8          d5,  d22, d23, #3
    221         vadd.u8         d0,  d0,  d22
    222         vext.8          d17, d20, d21, #3
    223         paeth           d1,  d0,  d17, d20
    224         vst1.32         {d0[0]},  [r1,:32], r4
    225         vext.8          d6,  d22, d23, #6
    226         vadd.u8         d1,  d1,  d5
    227         vext.8          d18, d20, d21, #6
    228         paeth           d2,  d1,  d18, d17
    229         vext.8          d7,  d23, d23, #1
    230         vld1.8          {q11},    [r0], lr
    231         vst1.32         {d1[0]},  [r1], r4
    232         vadd.u8         d2,  d2,  d6
    233         vext.8          d19, d21, d21, #1
    234         paeth           d3,  d2,  d19, d18
    235         vst1.32         {d2[0]},  [r1], r4
    236         vmov            d4,  d19
    237         vadd.u8         d3,  d3,  d7
    238         vst1.32         {d3[0]},  [r1], r4
    239         subs            r12, r12, #12
    240         bgt             1b
    241 
    242         pop             {r4,pc}
    243 endfunc
    244 #endif /* PNG_ARM_NEON_OPT > 0 */
    245 #endif /* PNG_READ_SUPPORTED */
    246 #endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */
    247