blob: 40d97775d630ee91255d544044a0e17abb710979 [file] [log] [blame]
Chris Craikb50c2172013-07-29 15:28:30 -07001
2/* filter_neon.S - NEON optimised filter functions
3 *
4 * Copyright (c) 2013 Glenn Randers-Pehrson
5 * Written by Mans Rullgard, 2011.
Sireesh Tripurarib478e662014-05-09 15:15:10 +05306 * Last changed in libpng 1.6.8 [December 19, 2013]
Chris Craikb50c2172013-07-29 15:28:30 -07007 *
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
Sireesh Tripurarib478e662014-05-09 15:15:10 +053014 * includes the definition (or not) of PNG_ARM_NEON_OPT and
15 * PNG_ARM_NEON_IMPLEMENTATION.
Chris Craikb50c2172013-07-29 15:28:30 -070016 */
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
Sireesh Tripurarib478e662014-05-09 15:15:10 +053024/* 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
Chris Craikb50c2172013-07-29 15:28:30 -070031#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
45ELF .size \name, . - \name
46 .endfunc
47 .purgem endfunc
48 .endm
49 .text
50 .if \export
51 .global \name
52 .endif
53ELF .type \name, STT_FUNC
54 .func \name
55\name:
56.endm
57
58func png_read_filter_row_sub4_neon, export=1
59 ldr r3, [r0, #4] @ rowbytes
60 vmov.i8 d3, #0
611:
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
72endfunc
73
74func 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
811:
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
98endfunc
99
100func png_read_filter_row_up_neon, export=1
101 ldr r3, [r0, #4] @ rowbytes
1021:
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
111endfunc
112
113func png_read_filter_row_avg4_neon, export=1
114 ldr r12, [r0, #4] @ rowbytes
115 vmov.i8 d3, #0
1161:
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
132endfunc
133
134func 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
1421:
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}
167endfunc
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
185func png_read_filter_row_paeth4_neon, export=1
186 ldr r12, [r0, #4] @ rowbytes
187 vmov.i8 d3, #0
188 vmov.i8 d20, #0
1891:
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
206endfunc
207
208func 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
2171:
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}
243endfunc
244#endif /* PNG_ARM_NEON_OPT > 0 */
245#endif /* PNG_READ_SUPPORTED */
Sireesh Tripurarib478e662014-05-09 15:15:10 +0530246#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */