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