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