blob: b8aef10539e2cc9f1feda7e068f7eb5c0079626d [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.
6 * Last changed in libpng 1.5.17 [July 18, 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.
15 */
16#define PNG_VERSION_INFO_ONLY
17#include "../pngpriv.h"
18
19#if defined(__linux__) && defined(__ELF__)
20.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */
21#endif
22
23#ifdef PNG_READ_SUPPORTED
24#if PNG_ARM_NEON_OPT > 0
25
26#ifdef __ELF__
27# define ELF
28#else
29# define ELF @
30#endif
31
32 .arch armv7-a
33 .fpu neon
34
35.macro func name, export=0
36 .macro endfunc
37ELF .size \name, . - \name
38 .endfunc
39 .purgem endfunc
40 .endm
41 .text
42 .if \export
43 .global \name
44 .endif
45ELF .type \name, STT_FUNC
46 .func \name
47\name:
48.endm
49
50func png_read_filter_row_sub4_neon, export=1
51 ldr r3, [r0, #4] @ rowbytes
52 vmov.i8 d3, #0
531:
54 vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
55 vadd.u8 d0, d3, d4
56 vadd.u8 d1, d0, d5
57 vadd.u8 d2, d1, d6
58 vadd.u8 d3, d2, d7
59 vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
60 subs r3, r3, #16
61 bgt 1b
62
63 bx lr
64endfunc
65
66func png_read_filter_row_sub3_neon, export=1
67 ldr r3, [r0, #4] @ rowbytes
68 vmov.i8 d3, #0
69 mov r0, r1
70 mov r2, #3
71 mov r12, #12
72 vld1.8 {q11}, [r0], r12
731:
74 vext.8 d5, d22, d23, #3
75 vadd.u8 d0, d3, d22
76 vext.8 d6, d22, d23, #6
77 vadd.u8 d1, d0, d5
78 vext.8 d7, d23, d23, #1
79 vld1.8 {q11}, [r0], r12
80 vst1.32 {d0[0]}, [r1,:32], r2
81 vadd.u8 d2, d1, d6
82 vst1.32 {d1[0]}, [r1], r2
83 vadd.u8 d3, d2, d7
84 vst1.32 {d2[0]}, [r1], r2
85 vst1.32 {d3[0]}, [r1], r2
86 subs r3, r3, #12
87 bgt 1b
88
89 bx lr
90endfunc
91
92func png_read_filter_row_up_neon, export=1
93 ldr r3, [r0, #4] @ rowbytes
941:
95 vld1.8 {q0}, [r1,:128]
96 vld1.8 {q1}, [r2,:128]!
97 vadd.u8 q0, q0, q1
98 vst1.8 {q0}, [r1,:128]!
99 subs r3, r3, #16
100 bgt 1b
101
102 bx lr
103endfunc
104
105func png_read_filter_row_avg4_neon, export=1
106 ldr r12, [r0, #4] @ rowbytes
107 vmov.i8 d3, #0
1081:
109 vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
110 vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
111 vhadd.u8 d0, d3, d16
112 vadd.u8 d0, d0, d4
113 vhadd.u8 d1, d0, d17
114 vadd.u8 d1, d1, d5
115 vhadd.u8 d2, d1, d18
116 vadd.u8 d2, d2, d6
117 vhadd.u8 d3, d2, d19
118 vadd.u8 d3, d3, d7
119 vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
120 subs r12, r12, #16
121 bgt 1b
122
123 bx lr
124endfunc
125
126func png_read_filter_row_avg3_neon, export=1
127 push {r4,lr}
128 ldr r12, [r0, #4] @ rowbytes
129 vmov.i8 d3, #0
130 mov r0, r1
131 mov r4, #3
132 mov lr, #12
133 vld1.8 {q11}, [r0], lr
1341:
135 vld1.8 {q10}, [r2], lr
136 vext.8 d5, d22, d23, #3
137 vhadd.u8 d0, d3, d20
138 vext.8 d17, d20, d21, #3
139 vadd.u8 d0, d0, d22
140 vext.8 d6, d22, d23, #6
141 vhadd.u8 d1, d0, d17
142 vext.8 d18, d20, d21, #6
143 vadd.u8 d1, d1, d5
144 vext.8 d7, d23, d23, #1
145 vld1.8 {q11}, [r0], lr
146 vst1.32 {d0[0]}, [r1,:32], r4
147 vhadd.u8 d2, d1, d18
148 vst1.32 {d1[0]}, [r1], r4
149 vext.8 d19, d21, d21, #1
150 vadd.u8 d2, d2, d6
151 vhadd.u8 d3, d2, d19
152 vst1.32 {d2[0]}, [r1], r4
153 vadd.u8 d3, d3, d7
154 vst1.32 {d3[0]}, [r1], r4
155 subs r12, r12, #12
156 bgt 1b
157
158 pop {r4,pc}
159endfunc
160
161.macro paeth rx, ra, rb, rc
162 vaddl.u8 q12, \ra, \rb @ a + b
163 vaddl.u8 q15, \rc, \rc @ 2*c
164 vabdl.u8 q13, \rb, \rc @ pa
165 vabdl.u8 q14, \ra, \rc @ pb
166 vabd.u16 q15, q12, q15 @ pc
167 vcle.u16 q12, q13, q14 @ pa <= pb
168 vcle.u16 q13, q13, q15 @ pa <= pc
169 vcle.u16 q14, q14, q15 @ pb <= pc
170 vand q12, q12, q13 @ pa <= pb && pa <= pc
171 vmovn.u16 d28, q14
172 vmovn.u16 \rx, q12
173 vbsl d28, \rb, \rc
174 vbsl \rx, \ra, d28
175.endm
176
177func png_read_filter_row_paeth4_neon, export=1
178 ldr r12, [r0, #4] @ rowbytes
179 vmov.i8 d3, #0
180 vmov.i8 d20, #0
1811:
182 vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
183 vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
184 paeth d0, d3, d16, d20
185 vadd.u8 d0, d0, d4
186 paeth d1, d0, d17, d16
187 vadd.u8 d1, d1, d5
188 paeth d2, d1, d18, d17
189 vadd.u8 d2, d2, d6
190 paeth d3, d2, d19, d18
191 vmov d20, d19
192 vadd.u8 d3, d3, d7
193 vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
194 subs r12, r12, #16
195 bgt 1b
196
197 bx lr
198endfunc
199
200func png_read_filter_row_paeth3_neon, export=1
201 push {r4,lr}
202 ldr r12, [r0, #4] @ rowbytes
203 vmov.i8 d3, #0
204 vmov.i8 d4, #0
205 mov r0, r1
206 mov r4, #3
207 mov lr, #12
208 vld1.8 {q11}, [r0], lr
2091:
210 vld1.8 {q10}, [r2], lr
211 paeth d0, d3, d20, d4
212 vext.8 d5, d22, d23, #3
213 vadd.u8 d0, d0, d22
214 vext.8 d17, d20, d21, #3
215 paeth d1, d0, d17, d20
216 vst1.32 {d0[0]}, [r1,:32], r4
217 vext.8 d6, d22, d23, #6
218 vadd.u8 d1, d1, d5
219 vext.8 d18, d20, d21, #6
220 paeth d2, d1, d18, d17
221 vext.8 d7, d23, d23, #1
222 vld1.8 {q11}, [r0], lr
223 vst1.32 {d1[0]}, [r1], r4
224 vadd.u8 d2, d2, d6
225 vext.8 d19, d21, d21, #1
226 paeth d3, d2, d19, d18
227 vst1.32 {d2[0]}, [r1], r4
228 vmov d4, d19
229 vadd.u8 d3, d3, d7
230 vst1.32 {d3[0]}, [r1], r4
231 subs r12, r12, #12
232 bgt 1b
233
234 pop {r4,pc}
235endfunc
236#endif /* PNG_ARM_NEON_OPT > 0 */
237#endif /* PNG_READ_SUPPORTED */