1 /*
2  * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
3  *           (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
4  *
5  * This file is part of lsp-plugins
6  * Created on: 17 сент. 2018 г.
7  *
8  * lsp-plugins is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * any later version.
12  *
13  * lsp-plugins is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #ifndef DSP_ARCH_ARM_NEON_D32_GRAPHICS_H_
23 #define DSP_ARCH_ARM_NEON_D32_GRAPHICS_H_
24 
25 #ifndef DSP_ARCH_ARM_NEON_32_IMPL
26     #error "This header should not be included directly"
27 #endif /* DSP_ARCH_ARM_NEON_32_IMPL */
28 
29 namespace neon_d32
30 {
axis_apply_log1(float * x,const float * v,float zero,float norm_x,size_t count)31     void axis_apply_log1(float *x, const float *v, float zero, float norm_x, size_t count)
32     {
33         IF_ARCH_ARM(
34             float params[8] __lsp_aligned16;
35             params[0] = zero;
36             params[1] = norm_x;
37             const uint32_t *iptr = &LOG_IARGS[4];
38             const float *fptr = LOG_FARGS;
39         );
40 
41         //---------------------------------------------------------------
42         // Prepare constants
43         ARCH_ARM_ASM
44         (
45             __ASM_EMIT("vld1.32         {d0}, [%[params]]")
46             __ASM_EMIT("vdup.32         q1, d0[1]")                     // q2 = norm_x
47             __ASM_EMIT("vdup.32         q0, d0[0]")                     // q0 = zero
48             __ASM_EMIT("vst1.32         {q0-q1}, [%[params]]")
49 
50             __ASM_EMIT("subs            %[count], $16")
51             __ASM_EMIT("blo             2f")
52 
53             // Do 16x blocks
54             __ASM_EMIT("1:")
55             __ASM_EMIT("vld1.32         {q4-q5}, [%[v]]!")              // q4  = v, q5 = v, v += 8
56             __ASM_EMIT("vld1.32         {q6-q7}, [%[v]]!")
57             __ASM_EMIT("vld1.32         {q12}, [%[fptr]]!")             // q12 = X_AMP, fptr += 4
58             __ASM_EMIT("vabs.f32        q4, q4")                        // q4  = abs(v)
59             __ASM_EMIT("vabs.f32        q5, q5")
60             __ASM_EMIT("vabs.f32        q6, q6")
61             __ASM_EMIT("vabs.f32        q7, q7")
62             __ASM_EMIT("vld1.32         {q13}, [%[params]]")            // q13 = zero
63             __ASM_EMIT("vmax.f32        q4, q12")                       // q12 = max(X_AMP, abs(v)), ignores denormalized values
64             __ASM_EMIT("vmax.f32        q5, q12")
65             __ASM_EMIT("vmax.f32        q6, q12")
66             __ASM_EMIT("vmax.f32        q7, q12")
67             __ASM_EMIT("vmul.f32        q0, q4, q13")                   // q13 = max(X_AMP, abs(v)) * zero
68             __ASM_EMIT("vmul.f32        q1, q5, q13")
69             __ASM_EMIT("vmul.f32        q2, q6, q13")
70             __ASM_EMIT("vmul.f32        q3, q7, q13")
71             // Step 2: parse float value
72             __ASM_EMIT("vld1.32         {q12-q13}, [%[iptr]]")          // q12 = MANT_MASK, q13 = FRAC_SUB = 127
73             __ASM_EMIT("vshr.u32        q4, q0, $23")                   // q4  = frac(v)
74             __ASM_EMIT("vshr.u32        q5, q1, $23")
75             __ASM_EMIT("vshr.u32        q6, q2, $23")
76             __ASM_EMIT("vshr.u32        q7, q3, $23")
77             __ASM_EMIT("vand.u32        q8, q0, q12")                   // q8  = mant(v)
78             __ASM_EMIT("vand.u32        q9, q1, q12")
79             __ASM_EMIT("vand.u32        q10, q2, q12")
80             __ASM_EMIT("vand.u32        q11, q3, q12")
81             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14 = 0.5f, q15 = sqrt(1/2), fptr += 8
82             __ASM_EMIT("vsub.i32        q4, q4, q13")                   // q4  = frac(v) - 127
83             __ASM_EMIT("vsub.i32        q5, q5, q13")
84             __ASM_EMIT("vsub.i32        q6, q6, q13")
85             __ASM_EMIT("vsub.i32        q7, q7, q13")
86             __ASM_EMIT("vorr.i32        q8, q8, q14")                   // q8  = V = mant(v)+0.5
87             __ASM_EMIT("vorr.i32        q9, q9, q14")
88             __ASM_EMIT("vorr.i32        q10, q10, q14")
89             __ASM_EMIT("vorr.i32        q11, q11, q14")
90             __ASM_EMIT("vcvt.f32.s32    q4, q4")                        // q4  = E = float(frac(v)-127)
91             __ASM_EMIT("vcvt.f32.s32    q5, q5")
92             __ASM_EMIT("vcvt.f32.s32    q6, q6")
93             __ASM_EMIT("vcvt.f32.s32    q7, q7")
94             // Prepare logarithm approximation calculations
95             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = 1.0, q13 = L0 , fptr += 4
96             __ASM_EMIT("vclt.f32        q0, q8, q15")                   // q0   = [ V < sqrt(1/2) ]
97             __ASM_EMIT("vclt.f32        q1, q9, q15")
98             __ASM_EMIT("vclt.f32        q2, q10, q15")
99             __ASM_EMIT("vclt.f32        q3, q11, q15")
100             __ASM_EMIT("vand.u32        q0, q0, q8")                    // q0   = V * [ V < sqrt(1/2) ]
101             __ASM_EMIT("vand.u32        q1, q1, q9")
102             __ASM_EMIT("vand.u32        q2, q2, q10")
103             __ASM_EMIT("vand.u32        q3, q3, q11")
104             __ASM_EMIT("vadd.f32        q0, q0, q8")                    // q0   = V + V * [ V < sqrt(1/2) ]
105             __ASM_EMIT("vadd.f32        q1, q1, q9")
106             __ASM_EMIT("vadd.f32        q2, q2, q10")
107             __ASM_EMIT("vadd.f32        q3, q3, q11")
108             __ASM_EMIT("vclt.f32        q8, q8, q15")                   // q8   = [ V < sqrt(1/2) ]
109             __ASM_EMIT("vclt.f32        q9, q9, q15")
110             __ASM_EMIT("vclt.f32        q10, q10, q15")
111             __ASM_EMIT("vclt.f32        q11, q11, q15")
112             __ASM_EMIT("vsub.f32        q0, q0, q12")                   // q0   = A = V + V & [ V < sqrt(1/2) ] - 1.0
113             __ASM_EMIT("vsub.f32        q1, q1, q12")
114             __ASM_EMIT("vsub.f32        q2, q2, q12")
115             __ASM_EMIT("vsub.f32        q3, q3, q12")
116             __ASM_EMIT("vbic.u32        q8, q12, q8")                   // q8   = 1.0 & [ V >= sqrt(1/2) ]
117             __ASM_EMIT("vbic.u32        q9, q12, q9")
118             __ASM_EMIT("vbic.u32        q10, q12, q10")
119             __ASM_EMIT("vbic.u32        q11, q12, q11")
120             __ASM_EMIT("vadd.f32        q4, q4, q8")                    // q4   = B = E + 1.0 & [ V >= sqrt(1/2) ]
121             __ASM_EMIT("vadd.f32        q5, q5, q9")
122             __ASM_EMIT("vadd.f32        q6, q6, q10")
123             __ASM_EMIT("vadd.f32        q7, q7, q11")
124             // Calculate logarithmic values
125             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14  = L1, q15 = L2, fptr += 8
126             __ASM_EMIT("vmul.f32        q8, q0, q13")                   // q8   = L0*A
127             __ASM_EMIT("vmul.f32        q9, q1, q13")
128             __ASM_EMIT("vmul.f32        q10, q2, q13")
129             __ASM_EMIT("vmul.f32        q11, q3, q13")
130             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L1+L0*A
131             __ASM_EMIT("vadd.f32        q9, q9, q14")
132             __ASM_EMIT("vadd.f32        q10, q10, q14")
133             __ASM_EMIT("vadd.f32        q11, q11, q14")
134             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = L3, q13 = L4, fptr += 8
135             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L1+L0*A)
136             __ASM_EMIT("vmul.f32        q9, q9, q1")
137             __ASM_EMIT("vmul.f32        q10, q10, q2")
138             __ASM_EMIT("vmul.f32        q11, q11, q3")
139             __ASM_EMIT("vadd.f32        q8, q8, q15")                   // q8   = L2+A*(L1+L0*A)
140             __ASM_EMIT("vadd.f32        q9, q9, q15")
141             __ASM_EMIT("vadd.f32        q10, q10, q15")
142             __ASM_EMIT("vadd.f32        q11, q11, q15")
143             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L2+A*(L1+L0*A))
144             __ASM_EMIT("vmul.f32        q9, q9, q1")
145             __ASM_EMIT("vmul.f32        q10, q10, q2")
146             __ASM_EMIT("vmul.f32        q11, q11, q3")
147             __ASM_EMIT("vadd.f32        q8, q8, q12")                   // q8   = L3+A*(L2+A*(L1+L0*A))
148             __ASM_EMIT("vadd.f32        q9, q9, q12")
149             __ASM_EMIT("vadd.f32        q10, q10, q12")
150             __ASM_EMIT("vadd.f32        q11, q11, q12")
151             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14  = L5, q15 = L6, fptr += 8
152             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L3+A*(L2+A*(L1+L0*A)))
153             __ASM_EMIT("vmul.f32        q9, q9, q1")
154             __ASM_EMIT("vmul.f32        q10, q10, q2")
155             __ASM_EMIT("vmul.f32        q11, q11, q3")
156             __ASM_EMIT("vadd.f32        q8, q8, q13")                   // q8   = L4+A*(L3+A*(L2+A*(L1+L0*A)))
157             __ASM_EMIT("vadd.f32        q9, q9, q13")
158             __ASM_EMIT("vadd.f32        q10, q10, q13")
159             __ASM_EMIT("vadd.f32        q11, q11, q13")
160             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
161             __ASM_EMIT("vmul.f32        q9, q9, q1")
162             __ASM_EMIT("vmul.f32        q10, q10, q2")
163             __ASM_EMIT("vmul.f32        q11, q11, q3")
164             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
165             __ASM_EMIT("vadd.f32        q9, q9, q14")
166             __ASM_EMIT("vadd.f32        q10, q10, q14")
167             __ASM_EMIT("vadd.f32        q11, q11, q14")
168             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = L7, q13 = L8, fptr += 8
169             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
170             __ASM_EMIT("vmul.f32        q9, q9, q1")
171             __ASM_EMIT("vmul.f32        q10, q10, q2")
172             __ASM_EMIT("vmul.f32        q11, q11, q3")
173             __ASM_EMIT("vadd.f32        q8, q8, q15")                   // q8   = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
174             __ASM_EMIT("vadd.f32        q9, q9, q15")
175             __ASM_EMIT("vadd.f32        q10, q10, q15")
176             __ASM_EMIT("vadd.f32        q11, q11, q15")
177             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
178             __ASM_EMIT("vmul.f32        q9, q9, q1")
179             __ASM_EMIT("vmul.f32        q10, q10, q2")
180             __ASM_EMIT("vmul.f32        q11, q11, q3")
181             __ASM_EMIT("vadd.f32        q8, q8, q12")                   // q8   = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
182             __ASM_EMIT("vadd.f32        q9, q9, q12")
183             __ASM_EMIT("vadd.f32        q10, q10, q12")
184             __ASM_EMIT("vadd.f32        q11, q11, q12")
185             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]")          // q14  = L9, q15 = (LXE + LN2), fptr += 8
186             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
187             __ASM_EMIT("vmul.f32        q9, q9, q1")
188             __ASM_EMIT("vmul.f32        q10, q10, q2")
189             __ASM_EMIT("vmul.f32        q11, q11, q3")
190             __ASM_EMIT("vadd.f32        q8, q8, q13")                   // q8   = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
191             __ASM_EMIT("vadd.f32        q9, q9, q13")
192             __ASM_EMIT("vadd.f32        q10, q10, q13")
193             __ASM_EMIT("vadd.f32        q11, q11, q13")
194             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
195             __ASM_EMIT("vmul.f32        q9, q9, q1")
196             __ASM_EMIT("vmul.f32        q10, q10, q2")
197             __ASM_EMIT("vmul.f32        q11, q11, q3")
198             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
199             __ASM_EMIT("vadd.f32        q9, q9, q14")
200             __ASM_EMIT("vadd.f32        q10, q10, q14")
201             __ASM_EMIT("vadd.f32        q11, q11, q14")
202             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
203             __ASM_EMIT("vmul.f32        q9, q9, q1")
204             __ASM_EMIT("vmul.f32        q10, q10, q2")
205             __ASM_EMIT("vmul.f32        q11, q11, q3")
206             __ASM_EMIT("sub             %[fptr], $0xd0")                // fptr -= 52
207             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
208             __ASM_EMIT("vmul.f32        q9, q9, q1")
209             __ASM_EMIT("vmul.f32        q10, q10, q2")
210             __ASM_EMIT("vmul.f32        q11, q11, q3")
211             __ASM_EMIT("vmla.f32        q8, q4, q15")                   // q8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
212             __ASM_EMIT("vmla.f32        q9, q5, q15")
213             __ASM_EMIT("vmla.f32        q10, q6, q15")
214             __ASM_EMIT("vmla.f32        q11, q7, q15")
215             __ASM_EMIT("vadd.f32        q8, q8, q0")                    // q8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A
216             __ASM_EMIT("vadd.f32        q9, q9, q1")
217             __ASM_EMIT("vadd.f32        q10, q10, q2")
218             __ASM_EMIT("vadd.f32        q11, q11, q3")
219             // Apply values to axes, q0 = log(abs(v*zero))
220             __ASM_EMIT("vldm            %[x], {q4-q7}")                 // q4-q7 = x
221             __ASM_EMIT("vld1.32         {q12-q13}, [%[params]]")        // q12 = zero, q13 = norm_x
222             __ASM_EMIT("vmla.f32        q4, q8, q13")                   // q4 = x + log(abs(v*zero)) * norm_x
223             __ASM_EMIT("vmla.f32        q5, q9, q13")
224             __ASM_EMIT("vmla.f32        q6, q10, q13")
225             __ASM_EMIT("vmla.f32        q7, q11, q13")
226             __ASM_EMIT("subs            %[count], $16")
227             __ASM_EMIT("vstm            %[x]!, {q4-q7}")                // x += 8
228             __ASM_EMIT("bge             1b")
229 
230             // Do 8x block
231             __ASM_EMIT("2:")
232             __ASM_EMIT("adds            %[count], $8")
233             __ASM_EMIT("blt             4f")
234 
235             __ASM_EMIT("vld1.32         {q4-q5}, [%[v]]!")              // q4  = v, q5 = v, v += 8
236             __ASM_EMIT("vld1.32         {q12}, [%[fptr]]!")             // q12 = X_AMP, fptr += 4
237             __ASM_EMIT("vabs.f32        q4, q4")                        // q4  = abs(v)
238             __ASM_EMIT("vabs.f32        q5, q5")
239             __ASM_EMIT("vld1.32         {q13}, [%[params]]")            // q13 = zero, params += 4
240             __ASM_EMIT("vmax.f32        q4, q12")                       // q12 = max(X_AMP, abs(v)), ignores denormalized values
241             __ASM_EMIT("vmax.f32        q5, q12")
242             __ASM_EMIT("vmul.f32        q0, q4, q13")                   // q13 = max(X_AMP, abs(v)) * zero
243             __ASM_EMIT("vmul.f32        q1, q5, q13")
244             // Step 2: parse float value
245             __ASM_EMIT("vld1.32         {q12-q13}, [%[iptr]]")          // q12 = MANT_MASK, q13 = FRAC_SUB = 127
246             __ASM_EMIT("vshr.u32        q4, q0, $23")                   // q4  = frac(v)
247             __ASM_EMIT("vshr.u32        q5, q1, $23")
248             __ASM_EMIT("vand.u32        q8, q0, q12")                   // q8  = mant(v)
249             __ASM_EMIT("vand.u32        q9, q1, q12")
250             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14 = 0.5f, q15 = sqrt(1/2), fptr += 8
251             __ASM_EMIT("vsub.i32        q4, q4, q13")                   // q4  = frac(v) - 127
252             __ASM_EMIT("vsub.i32        q5, q5, q13")
253             __ASM_EMIT("vorr.i32        q8, q8, q14")                   // q8  = V = mant(v)+0.5
254             __ASM_EMIT("vorr.i32        q9, q9, q14")
255             __ASM_EMIT("vcvt.f32.s32    q4, q4")                        // q4  = E = float(frac(v)-127)
256             __ASM_EMIT("vcvt.f32.s32    q5, q5")
257             // Prepare logarithm approximation calculations
258             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = 1.0, q13 = L0 , fptr += 4
259             __ASM_EMIT("vclt.f32        q0, q8, q15")                   // q0   = [ V < sqrt(1/2) ]
260             __ASM_EMIT("vclt.f32        q1, q9, q15")
261             __ASM_EMIT("vand.u32        q0, q0, q8")                    // q0   = V & [ V < sqrt(1/2) ]
262             __ASM_EMIT("vand.u32        q1, q1, q9")
263             __ASM_EMIT("vadd.f32        q0, q0, q8")                    // q0   = V + V & [ V < sqrt(1/2) ]
264             __ASM_EMIT("vadd.f32        q1, q1, q9")
265             __ASM_EMIT("vclt.f32        q8, q8, q15")                   // q8   = [ V < sqrt(1/2) ]
266             __ASM_EMIT("vclt.f32        q9, q9, q15")
267             __ASM_EMIT("vsub.f32        q0, q0, q12")                   // q0   = A = V + V & [ V < sqrt(1/2) ] - 1.0
268             __ASM_EMIT("vsub.f32        q1, q1, q12")
269             __ASM_EMIT("vbic.u32        q8, q12, q8")                   // q8   = 1.0 & [ V >= sqrt(1/2) ]
270             __ASM_EMIT("vbic.u32        q9, q12, q9")
271             __ASM_EMIT("vadd.f32        q4, q4, q8")                    // q4   = B = E + 1.0 & [ V >= sqrt(1/2) ]
272             __ASM_EMIT("vadd.f32        q5, q5, q9")
273             // Calculate logarithmic values
274             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14  = L1, q15 = L2, fptr += 8
275             __ASM_EMIT("vmul.f32        q8, q0, q13")                   // q8   = L0*A
276             __ASM_EMIT("vmul.f32        q9, q1, q13")
277             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L1+L0*A
278             __ASM_EMIT("vadd.f32        q9, q9, q14")
279             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = L3, q13 = L4, fptr += 8
280             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L1+L0*A)
281             __ASM_EMIT("vmul.f32        q9, q9, q1")
282             __ASM_EMIT("vadd.f32        q8, q8, q15")                   // q8   = L2+A*(L1+L0*A)
283             __ASM_EMIT("vadd.f32        q9, q9, q15")
284             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L2+A*(L1+L0*A))
285             __ASM_EMIT("vmul.f32        q9, q9, q1")
286             __ASM_EMIT("vadd.f32        q8, q8, q12")                   // q8   = L3+A*(L2+A*(L1+L0*A))
287             __ASM_EMIT("vadd.f32        q9, q9, q12")
288             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14  = L5, q15 = L6, fptr += 8
289             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L3+A*(L2+A*(L1+L0*A)))
290             __ASM_EMIT("vmul.f32        q9, q9, q1")
291             __ASM_EMIT("vadd.f32        q8, q8, q13")                   // q8   = L4+A*(L3+A*(L2+A*(L1+L0*A)))
292             __ASM_EMIT("vadd.f32        q9, q9, q13")
293             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
294             __ASM_EMIT("vmul.f32        q9, q9, q1")
295             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
296             __ASM_EMIT("vadd.f32        q9, q9, q14")
297             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = L7, q13 = L8, fptr += 8
298             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
299             __ASM_EMIT("vmul.f32        q9, q9, q1")
300             __ASM_EMIT("vadd.f32        q8, q8, q15")                   // q8   = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
301             __ASM_EMIT("vadd.f32        q9, q9, q15")
302             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
303             __ASM_EMIT("vmul.f32        q9, q9, q1")
304             __ASM_EMIT("vadd.f32        q8, q8, q12")                   // q8   = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
305             __ASM_EMIT("vadd.f32        q9, q9, q12")
306             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]")          // q14  = L9, q15 = (LXE + LN2), fptr += 8
307             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
308             __ASM_EMIT("vmul.f32        q9, q9, q1")
309             __ASM_EMIT("vadd.f32        q8, q8, q13")                   // q8   = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
310             __ASM_EMIT("vadd.f32        q9, q9, q13")
311             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
312             __ASM_EMIT("vmul.f32        q9, q9, q1")
313             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
314             __ASM_EMIT("vadd.f32        q9, q9, q14")
315             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
316             __ASM_EMIT("vmul.f32        q9, q9, q1")
317             __ASM_EMIT("sub             %[fptr], $0xd0")                // fptr -= 52
318             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
319             __ASM_EMIT("vmul.f32        q9, q9, q1")
320             __ASM_EMIT("vmla.f32        q8, q4, q15")                   // q8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
321             __ASM_EMIT("vmla.f32        q9, q5, q15")
322             __ASM_EMIT("vadd.f32        q8, q8, q0")                    // q8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A
323             __ASM_EMIT("vadd.f32        q9, q9, q1")
324             // Apply values to axes, q0 = log(abs(v*zero))
325             __ASM_EMIT("vld1.32         {q4-q5}, [%[x]]")               // q4 = x, q5 = x
326             __ASM_EMIT("vld1.32         {q12-q13}, [%[params]]")        // q12 = zero, q13 = norm_x
327             __ASM_EMIT("vmla.f32        q4, q8, q13")                   // q4 = x + log(abs(v*zero)) * norm_x
328             __ASM_EMIT("vmla.f32        q5, q9, q13")
329             __ASM_EMIT("sub             %[count], $8")
330             __ASM_EMIT("vst1.32         {q4-q5}, [%[x]]!")              // x += 8
331 
332             // Do x4 block
333             __ASM_EMIT("4:")
334             __ASM_EMIT("adds            %[count], $4")
335             __ASM_EMIT("blt             6f")
336 
337             __ASM_EMIT("vld1.32         {q4}, [%[v]]!")                 // q4  = v, v += 4
338             __ASM_EMIT("vld1.32         {q12}, [%[fptr]]!")             // q12 = X_AMP, fptr += 4
339             __ASM_EMIT("vabs.f32        q4, q4")                        // q4  = abs(v)
340             __ASM_EMIT("vld1.32         {q13}, [%[params]]")            // q13 = zero, params += 4
341             __ASM_EMIT("vmax.f32        q4, q12")                       // q4  = max(X_AMP, abs(v)), ignores denormalized values
342             __ASM_EMIT("vmul.f32        q0, q4, q13")                   // q0  = max(X_AMP, abs(v)) * zero
343             // Step 2: parse float value
344             __ASM_EMIT("vld1.32         {q12-q13}, [%[iptr]]")          // q12 = MANT_MASK, q13 = FRAC_SUB = 127
345             __ASM_EMIT("vshr.u32        q4, q0, $23")                   // q4  = frac(v)
346             __ASM_EMIT("vand.u32        q8, q0, q12")                   // q8  = mant(v)
347             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14 = 0.5f, q15 = sqrt(1/2), fptr += 8
348             __ASM_EMIT("vsub.i32        q4, q4, q13")                   // q4  = frac(v) - 127
349             __ASM_EMIT("vorr.i32        q8, q8, q14")                   // q8  = V = mant(v)+0.5
350             __ASM_EMIT("vcvt.f32.s32    q4, q4")                        // q4  = E = float(frac(v)-127)
351             // Prepare logarithm approximation calculations
352             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = 1.0, q13 = L0 , fptr += 4
353             __ASM_EMIT("vclt.f32        q0, q8, q15")                   // q0   = [ V < sqrt(1/2) ]
354             __ASM_EMIT("vand.u32        q0, q0, q8")                    // q0   = V & [ V < sqrt(1/2) ]
355             __ASM_EMIT("vadd.f32        q0, q0, q8")                    // q0   = V + V * [ V < sqrt(1/2) ]
356             __ASM_EMIT("vclt.f32        q8, q8, q15")                   // q8   = [ V < sqrt(1/2) ]
357             __ASM_EMIT("vsub.f32        q0, q0, q12")                   // q0   = A = V + V & [ V < sqrt(1/2) ] - 1.0
358             __ASM_EMIT("vbic.u32        q8, q12, q8")                   // q8   = 1.0 & [ V >= sqrt(1/2) ]
359             __ASM_EMIT("vadd.f32        q4, q4, q8")                    // q4   = B = E + 1.0 & [ V >= sqrt(1/2) ]
360             // Calculate logarithmic values
361             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14  = L1, q15 = L2, fptr += 8
362             __ASM_EMIT("vmul.f32        q8, q0, q13")                   // q8   = L0*A
363             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L1+L0*A
364             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = L3, q13 = L4, fptr += 8
365             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L1+L0*A)
366             __ASM_EMIT("vadd.f32        q8, q8, q15")                   // q8   = L2+A*(L1+L0*A)
367             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L2+A*(L1+L0*A))
368             __ASM_EMIT("vadd.f32        q8, q8, q12")                   // q8   = L3+A*(L2+A*(L1+L0*A))
369             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14  = L5, q15 = L6, fptr += 8
370             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L3+A*(L2+A*(L1+L0*A)))
371             __ASM_EMIT("vadd.f32        q8, q8, q13")                   // q8   = L4+A*(L3+A*(L2+A*(L1+L0*A)))
372             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
373             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
374             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = L7, q13 = L8, fptr += 8
375             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
376             __ASM_EMIT("vadd.f32        q8, q8, q15")                   // q8   = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
377             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
378             __ASM_EMIT("vadd.f32        q8, q8, q12")                   // q8   = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
379             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]")          // q14  = L9, q15 = (LXE + LN2), fptr += 8
380             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
381             __ASM_EMIT("vadd.f32        q8, q8, q13")                   // q8   = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
382             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
383             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
384             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
385             __ASM_EMIT("sub             %[fptr], $0xd0")                // fptr -= 52
386             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
387             __ASM_EMIT("vmla.f32        q8, q4, q15")                   // q8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
388             __ASM_EMIT("vadd.f32        q8, q8, q0")                    // q8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A
389             // Apply values to axes, q0 = log(abs(v*zero))
390             __ASM_EMIT("vld1.32         {q4}, [%[x]]")                  // q4 = x
391             __ASM_EMIT("vld1.32         {q12-q13}, [%[params]]")        // q12 = zero, q13 = norm_x
392             __ASM_EMIT("vmla.f32        q4, q8, q13")                   // q4 = x + log(abs(v*zero)) * norm_x
393             __ASM_EMIT("sub             %[count], $4")
394             __ASM_EMIT("vst1.32         {q4}, [%[x]]!")                 // x += 4
395 
396             // Do x1 blocks
397             __ASM_EMIT("6:")
398             __ASM_EMIT("adds            %[count], $3")
399             __ASM_EMIT("blt             8f")
400 
401             __ASM_EMIT("7:")
402             __ASM_EMIT("vldm            %[v]!, {s8}")                   // d4  = v, v += 4
403             __ASM_EMIT("vld1.32         {q6}, [%[fptr]]!")              // d12 = X_AMP, fptr += 4
404             __ASM_EMIT("vabs.f32        d4, d4")                        // d4  = abs(v)
405             __ASM_EMIT("vld1.32         {q7}, [%[params]]")             // d14 = zero, params += 4
406             __ASM_EMIT("vmax.f32        d4, d12")                       // d4  = max(X_AMP, abs(v)), ignores denormalized values
407             __ASM_EMIT("vmul.f32        d0, d4, d14")                   // d0  = max(X_AMP, abs(v)) * zero
408             // Step 2: parse float value
409             __ASM_EMIT("vld1.32         {q6-q7}, [%[iptr]]")            // d12 = MANT_MASK, d14 = FRAC_SUB = 127
410             __ASM_EMIT("vshr.u32        d4, d0, $23")                   // d4  = frac(v)
411             __ASM_EMIT("vand.u32        d8, d0, d12")                   // d8  = mant(v)
412             __ASM_EMIT("vld1.32         {q8-q9}, [%[fptr]]!")           // d16 = 0.5f, d18 = sqrt(1/2), fptr += 8
413             __ASM_EMIT("vsub.i32        d4, d4, d14")                   // d4  = frac(v) - 127
414             __ASM_EMIT("vorr.i32        d8, d8, d16")                   // d8  = V = mant(v)+0.5
415             __ASM_EMIT("vcvt.f32.s32    d4, d4")                        // d4  = E = float(frac(v)-127)
416             // Prepare logarithm approximation calculations
417             __ASM_EMIT("vld1.32         {q6-q7}, [%[fptr]]!")           // d12  = 1.0, d14 = L0 , fptr += 4
418             __ASM_EMIT("vclt.f32        d0, d8, d18")                   // d0   = [ V < sqrt(1/2) ]
419             __ASM_EMIT("vand.u32        d0, d0, d8")                    // d0   = V & [ V < sqrt(1/2) ]
420             __ASM_EMIT("vadd.f32        d0, d0, d8")                    // d0   = V + V & [ V < sqrt(1/2) ]
421             __ASM_EMIT("vclt.f32        d8, d8, d18")                   // d8   = [ V < sqrt(1/2) ]
422             __ASM_EMIT("vsub.f32        d0, d0, d12")                   // d0   = A = V + V & [ V < sqrt(1/2) ] - 1.0
423             __ASM_EMIT("vbic.u32        d8, d12, d8")                   // d8   = 1.0 & [ V >= sqrt(1/2) ]
424             __ASM_EMIT("vadd.f32        d4, d4, d8")                    // d4   = B = E + 1.0 & [ V >= sqrt(1/2) ]
425             // Calculate logarithmic values
426             __ASM_EMIT("vld1.32         {q8-q9}, [%[fptr]]!")           // d16  = L1, d18 = L2, fptr += 8
427             __ASM_EMIT("vmul.f32        d8, d0, d14")                   // d8   = L0*A
428             __ASM_EMIT("vadd.f32        d8, d8, d16")                   // d8   = L1+L0*A
429             __ASM_EMIT("vld1.32         {q6-q7}, [%[fptr]]!")           // d12  = L3, d14 = L4, fptr += 8
430             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L1+L0*A)
431             __ASM_EMIT("vadd.f32        d8, d8, d18")                   // d8   = L2+A*(L1+L0*A)
432             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L2+A*(L1+L0*A))
433             __ASM_EMIT("vadd.f32        d8, d8, d12")                   // d8   = L3+A*(L2+A*(L1+L0*A))
434             __ASM_EMIT("vld1.32         {q8-q9}, [%[fptr]]!")           // d16  = L5, d18 = L6, fptr += 8
435             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L3+A*(L2+A*(L1+L0*A)))
436             __ASM_EMIT("vadd.f32        d8, d8, d14")                   // d8   = L4+A*(L3+A*(L2+A*(L1+L0*A)))
437             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
438             __ASM_EMIT("vadd.f32        d8, d8, d16")                   // d8   = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
439             __ASM_EMIT("vld1.32         {q6-q7}, [%[fptr]]!")           // d12  = L7, d14 = L8, fptr += 8
440             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
441             __ASM_EMIT("vadd.f32        d8, d8, d18")                   // d8   = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
442             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
443             __ASM_EMIT("vadd.f32        d8, d8, d12")                   // d8   = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
444             __ASM_EMIT("vld1.32         {q8-q9}, [%[fptr]]")            // d16  = L9, d18 = (LXE + LN2), fptr += 8
445             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
446             __ASM_EMIT("vadd.f32        d8, d8, d14")                   // d8   = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
447             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
448             __ASM_EMIT("vadd.f32        d8, d8, d16")                   // d8   = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
449             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
450             __ASM_EMIT("sub             %[fptr], $0xd0")                // fptr -= 52
451             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
452             __ASM_EMIT("vmla.f32        d8, d4, d18")                   // d8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
453             __ASM_EMIT("vadd.f32        d8, d8, d0")                    // d8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A
454             // Apply values to axes, d0 = log(abs(v*zero))
455             __ASM_EMIT("vldm            %[x], {s8}")                    // d4 = x
456             __ASM_EMIT("vld1.32         {q6-q7}, [%[params]]")          // d12 = zero, d14 = norm_x
457             __ASM_EMIT("vmla.f32        d4, d8, d14")                   // d4 = x + log(abs(v*zero)) * norm_x
458             __ASM_EMIT("subs            %[count], $1")
459             __ASM_EMIT("vstm            %[x]!, {s8}")                   // x++
460             __ASM_EMIT("bge             7b")
461 
462             __ASM_EMIT("8:")
463 
464             : [v] "+r" (v), [x] "+r" (x),
465               [count] "+r" (count),
466               [iptr] "+r" (iptr), [fptr] "+r" (fptr)
467             : [params] "r" (params)
468             : "cc", "memory",
469               "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7",
470               "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
471         );
472     }
473 
axis_apply_log2(float * x,float * y,const float * v,float zero,float norm_x,float norm_y,size_t count)474     void axis_apply_log2(float *x, float *y, const float *v, float zero, float norm_x, float norm_y, size_t count)
475     {
476         IF_ARCH_ARM(
477             float params[12] __lsp_aligned16;
478             params[0] = zero;
479             params[1] = norm_x;
480             params[2] = norm_y;
481             const uint32_t *iptr = &LOG_IARGS[4];
482             const float *fptr = LOG_FARGS;
483         );
484 
485         //---------------------------------------------------------------
486         // Prepare constants
487         ARCH_ARM_ASM
488         (
489             __ASM_EMIT("vld1.32         {q0}, [%[params]]")
490             __ASM_EMIT("vdup.32         q3, d1[0]")                     // q3 = norm_y
491             __ASM_EMIT("vdup.32         q2, d0[1]")                     // q2 = norm_x
492             __ASM_EMIT("vdup.32         q0, d0[0]")                     // q0 = zero
493             __ASM_EMIT("vst1.32         {q0}, [%[params]]!")            // params += 4
494             __ASM_EMIT("vst1.32         {q2-q3}, [%[params]]")
495 
496             __ASM_EMIT("subs            %[count], $16")
497             __ASM_EMIT("blo             2f")
498 
499             // Do 16x blocks
500             __ASM_EMIT("1:")
501             __ASM_EMIT("vld1.32         {q4-q5}, [%[v]]!")              // q4  = v, q5 = v, v += 8
502             __ASM_EMIT("sub             %[params], $0x10")              // params -= 4
503             __ASM_EMIT("vld1.32         {q6-q7}, [%[v]]!")
504             __ASM_EMIT("vld1.32         {q12}, [%[fptr]]!")             // q12 = X_AMP, fptr += 4
505             __ASM_EMIT("vabs.f32        q4, q4")                        // q4  = abs(v)
506             __ASM_EMIT("vabs.f32        q5, q5")
507             __ASM_EMIT("vabs.f32        q6, q6")
508             __ASM_EMIT("vabs.f32        q7, q7")
509             __ASM_EMIT("vld1.32         {q13}, [%[params]]!")           // q13 = zero, params += 4
510             __ASM_EMIT("vmax.f32        q4, q12")                       // q12 = max(X_AMP, abs(v)), ignores denormalized values
511             __ASM_EMIT("vmax.f32        q5, q12")
512             __ASM_EMIT("vmax.f32        q6, q12")
513             __ASM_EMIT("vmax.f32        q7, q12")
514             __ASM_EMIT("vmul.f32        q0, q4, q13")                   // q13 = max(X_AMP, abs(v)) * zero
515             __ASM_EMIT("vmul.f32        q1, q5, q13")
516             __ASM_EMIT("vmul.f32        q2, q6, q13")
517             __ASM_EMIT("vmul.f32        q3, q7, q13")
518             // Step 2: parse float value
519             __ASM_EMIT("vld1.32         {q12-q13}, [%[iptr]]")          // q12 = MANT_MASK, q13 = FRAC_SUB = 127
520             __ASM_EMIT("vshr.u32        q4, q0, $23")                   // q4  = frac(v)
521             __ASM_EMIT("vshr.u32        q5, q1, $23")
522             __ASM_EMIT("vshr.u32        q6, q2, $23")
523             __ASM_EMIT("vshr.u32        q7, q3, $23")
524             __ASM_EMIT("vand.u32        q8, q0, q12")                   // q8  = mant(v)
525             __ASM_EMIT("vand.u32        q9, q1, q12")
526             __ASM_EMIT("vand.u32        q10, q2, q12")
527             __ASM_EMIT("vand.u32        q11, q3, q12")
528             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14 = 0.5f, q15 = sqrt(1/2), fptr += 8
529             __ASM_EMIT("vsub.i32        q4, q4, q13")                   // q4  = frac(v) - 127
530             __ASM_EMIT("vsub.i32        q5, q5, q13")
531             __ASM_EMIT("vsub.i32        q6, q6, q13")
532             __ASM_EMIT("vsub.i32        q7, q7, q13")
533             __ASM_EMIT("vorr.i32        q8, q8, q14")                   // q8  = V = mant(v)+0.5
534             __ASM_EMIT("vorr.i32        q9, q9, q14")
535             __ASM_EMIT("vorr.i32        q10, q10, q14")
536             __ASM_EMIT("vorr.i32        q11, q11, q14")
537             __ASM_EMIT("vcvt.f32.s32    q4, q4")                        // q4  = E = float(frac(v)-127)
538             __ASM_EMIT("vcvt.f32.s32    q5, q5")
539             __ASM_EMIT("vcvt.f32.s32    q6, q6")
540             __ASM_EMIT("vcvt.f32.s32    q7, q7")
541             // Prepare logarithm approximation calculations
542             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = 1.0, q13 = L0 , fptr += 4
543             __ASM_EMIT("vclt.f32        q0, q8, q15")                   // q0   = [ V < sqrt(1/2) ]
544             __ASM_EMIT("vclt.f32        q1, q9, q15")
545             __ASM_EMIT("vclt.f32        q2, q10, q15")
546             __ASM_EMIT("vclt.f32        q3, q11, q15")
547             __ASM_EMIT("vand.u32        q0, q0, q8")                    // q0   = V * [ V < sqrt(1/2) ]
548             __ASM_EMIT("vand.u32        q1, q1, q9")
549             __ASM_EMIT("vand.u32        q2, q2, q10")
550             __ASM_EMIT("vand.u32        q3, q3, q11")
551             __ASM_EMIT("vadd.f32        q0, q0, q8")                    // q0   = V + V * [ V < sqrt(1/2) ]
552             __ASM_EMIT("vadd.f32        q1, q1, q9")
553             __ASM_EMIT("vadd.f32        q2, q2, q10")
554             __ASM_EMIT("vadd.f32        q3, q3, q11")
555             __ASM_EMIT("vclt.f32        q8, q8, q15")                   // q8   = [ V < sqrt(1/2) ]
556             __ASM_EMIT("vclt.f32        q9, q9, q15")
557             __ASM_EMIT("vclt.f32        q10, q10, q15")
558             __ASM_EMIT("vclt.f32        q11, q11, q15")
559             __ASM_EMIT("vsub.f32        q0, q0, q12")                   // q0   = A = V + V & [ V < sqrt(1/2) ] - 1.0
560             __ASM_EMIT("vsub.f32        q1, q1, q12")
561             __ASM_EMIT("vsub.f32        q2, q2, q12")
562             __ASM_EMIT("vsub.f32        q3, q3, q12")
563             __ASM_EMIT("vbic.u32        q8, q12, q8")                   // q8   = 1.0 & [ V >= sqrt(1/2) ]
564             __ASM_EMIT("vbic.u32        q9, q12, q9")
565             __ASM_EMIT("vbic.u32        q10, q12, q10")
566             __ASM_EMIT("vbic.u32        q11, q12, q11")
567             __ASM_EMIT("vadd.f32        q4, q4, q8")                    // q4   = B = E + 1.0 & [ V >= sqrt(1/2) ]
568             __ASM_EMIT("vadd.f32        q5, q5, q9")
569             __ASM_EMIT("vadd.f32        q6, q6, q10")
570             __ASM_EMIT("vadd.f32        q7, q7, q11")
571             // Calculate logarithmic values
572             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14  = L1, q15 = L2, fptr += 8
573             __ASM_EMIT("vmul.f32        q8, q0, q13")                   // q8   = L0*A
574             __ASM_EMIT("vmul.f32        q9, q1, q13")
575             __ASM_EMIT("vmul.f32        q10, q2, q13")
576             __ASM_EMIT("vmul.f32        q11, q3, q13")
577             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L1+L0*A
578             __ASM_EMIT("vadd.f32        q9, q9, q14")
579             __ASM_EMIT("vadd.f32        q10, q10, q14")
580             __ASM_EMIT("vadd.f32        q11, q11, q14")
581             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = L3, q13 = L4, fptr += 8
582             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L1+L0*A)
583             __ASM_EMIT("vmul.f32        q9, q9, q1")
584             __ASM_EMIT("vmul.f32        q10, q10, q2")
585             __ASM_EMIT("vmul.f32        q11, q11, q3")
586             __ASM_EMIT("vadd.f32        q8, q8, q15")                   // q8   = L2+A*(L1+L0*A)
587             __ASM_EMIT("vadd.f32        q9, q9, q15")
588             __ASM_EMIT("vadd.f32        q10, q10, q15")
589             __ASM_EMIT("vadd.f32        q11, q11, q15")
590             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L2+A*(L1+L0*A))
591             __ASM_EMIT("vmul.f32        q9, q9, q1")
592             __ASM_EMIT("vmul.f32        q10, q10, q2")
593             __ASM_EMIT("vmul.f32        q11, q11, q3")
594             __ASM_EMIT("vadd.f32        q8, q8, q12")                   // q8   = L3+A*(L2+A*(L1+L0*A))
595             __ASM_EMIT("vadd.f32        q9, q9, q12")
596             __ASM_EMIT("vadd.f32        q10, q10, q12")
597             __ASM_EMIT("vadd.f32        q11, q11, q12")
598             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14  = L5, q15 = L6, fptr += 8
599             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L3+A*(L2+A*(L1+L0*A)))
600             __ASM_EMIT("vmul.f32        q9, q9, q1")
601             __ASM_EMIT("vmul.f32        q10, q10, q2")
602             __ASM_EMIT("vmul.f32        q11, q11, q3")
603             __ASM_EMIT("vadd.f32        q8, q8, q13")                   // q8   = L4+A*(L3+A*(L2+A*(L1+L0*A)))
604             __ASM_EMIT("vadd.f32        q9, q9, q13")
605             __ASM_EMIT("vadd.f32        q10, q10, q13")
606             __ASM_EMIT("vadd.f32        q11, q11, q13")
607             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
608             __ASM_EMIT("vmul.f32        q9, q9, q1")
609             __ASM_EMIT("vmul.f32        q10, q10, q2")
610             __ASM_EMIT("vmul.f32        q11, q11, q3")
611             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
612             __ASM_EMIT("vadd.f32        q9, q9, q14")
613             __ASM_EMIT("vadd.f32        q10, q10, q14")
614             __ASM_EMIT("vadd.f32        q11, q11, q14")
615             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = L7, q13 = L8, fptr += 8
616             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
617             __ASM_EMIT("vmul.f32        q9, q9, q1")
618             __ASM_EMIT("vmul.f32        q10, q10, q2")
619             __ASM_EMIT("vmul.f32        q11, q11, q3")
620             __ASM_EMIT("vadd.f32        q8, q8, q15")                   // q8   = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
621             __ASM_EMIT("vadd.f32        q9, q9, q15")
622             __ASM_EMIT("vadd.f32        q10, q10, q15")
623             __ASM_EMIT("vadd.f32        q11, q11, q15")
624             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
625             __ASM_EMIT("vmul.f32        q9, q9, q1")
626             __ASM_EMIT("vmul.f32        q10, q10, q2")
627             __ASM_EMIT("vmul.f32        q11, q11, q3")
628             __ASM_EMIT("vadd.f32        q8, q8, q12")                   // q8   = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
629             __ASM_EMIT("vadd.f32        q9, q9, q12")
630             __ASM_EMIT("vadd.f32        q10, q10, q12")
631             __ASM_EMIT("vadd.f32        q11, q11, q12")
632             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]")          // q14  = L9, q15 = (LXE + LN2), fptr += 8
633             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
634             __ASM_EMIT("vmul.f32        q9, q9, q1")
635             __ASM_EMIT("vmul.f32        q10, q10, q2")
636             __ASM_EMIT("vmul.f32        q11, q11, q3")
637             __ASM_EMIT("vadd.f32        q8, q8, q13")                   // q8   = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
638             __ASM_EMIT("vadd.f32        q9, q9, q13")
639             __ASM_EMIT("vadd.f32        q10, q10, q13")
640             __ASM_EMIT("vadd.f32        q11, q11, q13")
641             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
642             __ASM_EMIT("vmul.f32        q9, q9, q1")
643             __ASM_EMIT("vmul.f32        q10, q10, q2")
644             __ASM_EMIT("vmul.f32        q11, q11, q3")
645             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
646             __ASM_EMIT("vadd.f32        q9, q9, q14")
647             __ASM_EMIT("vadd.f32        q10, q10, q14")
648             __ASM_EMIT("vadd.f32        q11, q11, q14")
649             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
650             __ASM_EMIT("vmul.f32        q9, q9, q1")
651             __ASM_EMIT("vmul.f32        q10, q10, q2")
652             __ASM_EMIT("vmul.f32        q11, q11, q3")
653             __ASM_EMIT("sub             %[fptr], $0xd0")                // fptr -= 52
654             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
655             __ASM_EMIT("vmul.f32        q9, q9, q1")
656             __ASM_EMIT("vmul.f32        q10, q10, q2")
657             __ASM_EMIT("vmul.f32        q11, q11, q3")
658             __ASM_EMIT("vmla.f32        q8, q4, q15")                   // q8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
659             __ASM_EMIT("vmla.f32        q9, q5, q15")
660             __ASM_EMIT("vmla.f32        q10, q6, q15")
661             __ASM_EMIT("vmla.f32        q11, q7, q15")
662             __ASM_EMIT("vadd.f32        q8, q8, q0")                    // q8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A
663             __ASM_EMIT("vadd.f32        q9, q9, q1")
664             __ASM_EMIT("vadd.f32        q10, q10, q2")
665             __ASM_EMIT("vadd.f32        q11, q11, q3")
666             // Apply values to axes, q0 = log(abs(v*zero))
667             __ASM_EMIT("vldm            %[x], {q4-q7}")                 // q4 = x, q5 = x, q6 = x, q7 = x
668             __ASM_EMIT("vldm            %[y], {q0-q3}")                 // q0 = y, q1 = y, q2 = y, q3 = y
669             __ASM_EMIT("vld1.32         {q12-q13}, [%[params]]")        // q12 = norm_x, q13 = norm_y
670             __ASM_EMIT("vmla.f32        q4, q8, q12")                   // q4 = x + log(abs(v*zero)) * norm_x
671             __ASM_EMIT("vmla.f32        q5, q9, q12")
672             __ASM_EMIT("vmla.f32        q6, q10, q12")
673             __ASM_EMIT("vmla.f32        q7, q11, q12")
674             __ASM_EMIT("vmla.f32        q0, q8, q13")                   // q0 = y + log(abs(v*zero)) * norm_y
675             __ASM_EMIT("vmla.f32        q1, q9, q13")
676             __ASM_EMIT("vmla.f32        q2, q10, q13")
677             __ASM_EMIT("vmla.f32        q3, q11, q13")
678             __ASM_EMIT("subs            %[count], $16")
679             __ASM_EMIT("vstm            %[x]!, {q4-q7}")                // x += 16
680             __ASM_EMIT("vstm            %[y]!, {q0-q3}")                // y += 16
681             __ASM_EMIT("bge             1b")
682 
683             // Do 8x block
684             __ASM_EMIT("2:")
685             __ASM_EMIT("adds            %[count], $8")
686             __ASM_EMIT("blt             4f")
687 
688             __ASM_EMIT("sub             %[params], $0x10")              // params -= 4
689             __ASM_EMIT("vld1.32         {q4-q5}, [%[v]]!")              // q4  = v, q5 = v, v += 8
690             __ASM_EMIT("vld1.32         {q12}, [%[fptr]]!")             // q12 = X_AMP, fptr += 4
691             __ASM_EMIT("vabs.f32        q4, q4")                        // q4  = abs(v)
692             __ASM_EMIT("vabs.f32        q5, q5")
693             __ASM_EMIT("vld1.32         {q13}, [%[params]]!")           // q13 = zero, params += 4
694             __ASM_EMIT("vmax.f32        q4, q12")                       // q12 = max(X_AMP, abs(v)), ignores denormalized values
695             __ASM_EMIT("vmax.f32        q5, q12")
696             __ASM_EMIT("vmul.f32        q0, q4, q13")                   // q13 = max(X_AMP, abs(v)) * zero
697             __ASM_EMIT("vmul.f32        q1, q5, q13")
698             // Step 2: parse float value
699             __ASM_EMIT("vld1.32         {q12-q13}, [%[iptr]]")          // q12 = MANT_MASK, q13 = FRAC_SUB = 127
700             __ASM_EMIT("vshr.u32        q4, q0, $23")                   // q4  = frac(v)
701             __ASM_EMIT("vshr.u32        q5, q1, $23")
702             __ASM_EMIT("vand.u32        q8, q0, q12")                   // q8  = mant(v)
703             __ASM_EMIT("vand.u32        q9, q1, q12")
704             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14 = 0.5f, q15 = sqrt(1/2), fptr += 8
705             __ASM_EMIT("vsub.i32        q4, q4, q13")                   // q4  = frac(v) - 127
706             __ASM_EMIT("vsub.i32        q5, q5, q13")
707             __ASM_EMIT("vorr.i32        q8, q8, q14")                   // q8  = V = mant(v)+0.5
708             __ASM_EMIT("vorr.i32        q9, q9, q14")
709             __ASM_EMIT("vcvt.f32.s32    q4, q4")                        // q4  = E = float(frac(v)-127)
710             __ASM_EMIT("vcvt.f32.s32    q5, q5")
711             // Prepare logarithm approximation calculations
712             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = 1.0, q13 = L0 , fptr += 4
713             __ASM_EMIT("vclt.f32        q0, q8, q15")                   // q0   = [ V < sqrt(1/2) ]
714             __ASM_EMIT("vclt.f32        q1, q9, q15")
715             __ASM_EMIT("vand.u32        q0, q0, q8")                    // q0   = V & [ V < sqrt(1/2) ]
716             __ASM_EMIT("vand.u32        q1, q1, q9")
717             __ASM_EMIT("vadd.f32        q0, q0, q8")                    // q0   = V + V & [ V < sqrt(1/2) ]
718             __ASM_EMIT("vadd.f32        q1, q1, q9")
719             __ASM_EMIT("vclt.f32        q8, q8, q15")                   // q8   = [ V < sqrt(1/2) ]
720             __ASM_EMIT("vclt.f32        q9, q9, q15")
721             __ASM_EMIT("vsub.f32        q0, q0, q12")                   // q0   = A = V + V & [ V < sqrt(1/2) ] - 1.0
722             __ASM_EMIT("vsub.f32        q1, q1, q12")
723             __ASM_EMIT("vbic.u32        q8, q12, q8")                   // q8   = 1.0 & [ V >= sqrt(1/2) ]
724             __ASM_EMIT("vbic.u32        q9, q12, q9")
725             __ASM_EMIT("vadd.f32        q4, q4, q8")                    // q4   = B = E + 1.0 & [ V >= sqrt(1/2) ]
726             __ASM_EMIT("vadd.f32        q5, q5, q9")
727             // Calculate logarithmic values
728             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14  = L1, q15 = L2, fptr += 8
729             __ASM_EMIT("vmul.f32        q8, q0, q13")                   // q8   = L0*A
730             __ASM_EMIT("vmul.f32        q9, q1, q13")
731             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L1+L0*A
732             __ASM_EMIT("vadd.f32        q9, q9, q14")
733             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = L3, q13 = L4, fptr += 8
734             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L1+L0*A)
735             __ASM_EMIT("vmul.f32        q9, q9, q1")
736             __ASM_EMIT("vadd.f32        q8, q8, q15")                   // q8   = L2+A*(L1+L0*A)
737             __ASM_EMIT("vadd.f32        q9, q9, q15")
738             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L2+A*(L1+L0*A))
739             __ASM_EMIT("vmul.f32        q9, q9, q1")
740             __ASM_EMIT("vadd.f32        q8, q8, q12")                   // q8   = L3+A*(L2+A*(L1+L0*A))
741             __ASM_EMIT("vadd.f32        q9, q9, q12")
742             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14  = L5, q15 = L6, fptr += 8
743             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L3+A*(L2+A*(L1+L0*A)))
744             __ASM_EMIT("vmul.f32        q9, q9, q1")
745             __ASM_EMIT("vadd.f32        q8, q8, q13")                   // q8   = L4+A*(L3+A*(L2+A*(L1+L0*A)))
746             __ASM_EMIT("vadd.f32        q9, q9, q13")
747             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
748             __ASM_EMIT("vmul.f32        q9, q9, q1")
749             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
750             __ASM_EMIT("vadd.f32        q9, q9, q14")
751             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = L7, q13 = L8, fptr += 8
752             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
753             __ASM_EMIT("vmul.f32        q9, q9, q1")
754             __ASM_EMIT("vadd.f32        q8, q8, q15")                   // q8   = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
755             __ASM_EMIT("vadd.f32        q9, q9, q15")
756             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
757             __ASM_EMIT("vmul.f32        q9, q9, q1")
758             __ASM_EMIT("vadd.f32        q8, q8, q12")                   // q8   = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
759             __ASM_EMIT("vadd.f32        q9, q9, q12")
760             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]")          // q14  = L9, q15 = (LXE + LN2), fptr += 8
761             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
762             __ASM_EMIT("vmul.f32        q9, q9, q1")
763             __ASM_EMIT("vadd.f32        q8, q8, q13")                   // q8   = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
764             __ASM_EMIT("vadd.f32        q9, q9, q13")
765             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
766             __ASM_EMIT("vmul.f32        q9, q9, q1")
767             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
768             __ASM_EMIT("vadd.f32        q9, q9, q14")
769             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
770             __ASM_EMIT("vmul.f32        q9, q9, q1")
771             __ASM_EMIT("sub             %[fptr], $0xd0")                // fptr -= 52
772             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
773             __ASM_EMIT("vmul.f32        q9, q9, q1")
774             __ASM_EMIT("vmla.f32        q8, q4, q15")                   // q8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
775             __ASM_EMIT("vmla.f32        q9, q5, q15")
776             __ASM_EMIT("vadd.f32        q8, q8, q0")                    // q8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A
777             __ASM_EMIT("vadd.f32        q9, q9, q1")
778             // Apply values to axes, q0 = log(abs(v*zero))
779             __ASM_EMIT("vld1.32         {q4-q5}, [%[x]]")               // q4 = x, q5 = x
780             __ASM_EMIT("vld1.32         {q0-q1}, [%[y]]")               // q0 = y, q1 = y
781             __ASM_EMIT("vld1.32         {q12-q13}, [%[params]]")        // q12 = norm_x, q13 = norm_y
782             __ASM_EMIT("vmla.f32        q4, q8, q12")                   // q4 = x + log(abs(v*zero)) * norm_x
783             __ASM_EMIT("vmla.f32        q5, q9, q12")
784             __ASM_EMIT("vmla.f32        q0, q8, q13")                   // q0 = y + log(abs(v*zero)) * norm_y
785             __ASM_EMIT("vmla.f32        q1, q9, q13")
786             __ASM_EMIT("sub             %[count], $8")
787             __ASM_EMIT("vst1.32         {q4-q5}, [%[x]]!")              // x += 8
788             __ASM_EMIT("vst1.32         {q0-q1}, [%[y]]!")              // y += 8
789 
790             // Do x4 block
791             __ASM_EMIT("4:")
792             __ASM_EMIT("adds            %[count], $4")
793             __ASM_EMIT("blt             6f")
794 
795             __ASM_EMIT("sub             %[params], $0x10")              // params -= 4
796             __ASM_EMIT("vld1.32         {q4}, [%[v]]!")                 // q4  = v, v += 4
797             __ASM_EMIT("vld1.32         {q12}, [%[fptr]]!")             // q12 = X_AMP, fptr += 4
798             __ASM_EMIT("vabs.f32        q4, q4")                        // q4  = abs(v)
799             __ASM_EMIT("vld1.32         {q13}, [%[params]]!")           // q13 = zero, params += 4
800             __ASM_EMIT("vmax.f32        q4, q12")                       // q4  = max(X_AMP, abs(v)), ignores denormalized values
801             __ASM_EMIT("vmul.f32        q0, q4, q13")                   // q0  = max(X_AMP, abs(v)) * zero
802             // Step 2: parse float value
803             __ASM_EMIT("vld1.32         {q12-q13}, [%[iptr]]")          // q12 = MANT_MASK, q13 = FRAC_SUB = 127
804             __ASM_EMIT("vshr.u32        q4, q0, $23")                   // q4  = frac(v)
805             __ASM_EMIT("vand.u32        q8, q0, q12")                   // q8  = mant(v)
806             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14 = 0.5f, q15 = sqrt(1/2), fptr += 8
807             __ASM_EMIT("vsub.i32        q4, q4, q13")                   // q4  = frac(v) - 127
808             __ASM_EMIT("vorr.i32        q8, q8, q14")                   // q8  = V = mant(v)+0.5
809             __ASM_EMIT("vcvt.f32.s32    q4, q4")                        // q4  = E = float(frac(v)-127)
810             // Prepare logarithm approximation calculations
811             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = 1.0, q13 = L0 , fptr += 4
812             __ASM_EMIT("vclt.f32        q0, q8, q15")                   // q0   = [ V < sqrt(1/2) ]
813             __ASM_EMIT("vand.u32        q0, q0, q8")                    // q0   = V & [ V < sqrt(1/2) ]
814             __ASM_EMIT("vadd.f32        q0, q0, q8")                    // q0   = V + V * [ V < sqrt(1/2) ]
815             __ASM_EMIT("vclt.f32        q8, q8, q15")                   // q8   = [ V < sqrt(1/2) ]
816             __ASM_EMIT("vsub.f32        q0, q0, q12")                   // q0   = A = V + V & [ V < sqrt(1/2) ] - 1.0
817             __ASM_EMIT("vbic.u32        q8, q12, q8")                   // q8   = 1.0 & [ V >= sqrt(1/2) ]
818             __ASM_EMIT("vadd.f32        q4, q4, q8")                    // q4   = B = E + 1.0 & [ V >= sqrt(1/2) ]
819             // Calculate logarithmic values
820             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14  = L1, q15 = L2, fptr += 8
821             __ASM_EMIT("vmul.f32        q8, q0, q13")                   // q8   = L0*A
822             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L1+L0*A
823             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = L3, q13 = L4, fptr += 8
824             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L1+L0*A)
825             __ASM_EMIT("vadd.f32        q8, q8, q15")                   // q8   = L2+A*(L1+L0*A)
826             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L2+A*(L1+L0*A))
827             __ASM_EMIT("vadd.f32        q8, q8, q12")                   // q8   = L3+A*(L2+A*(L1+L0*A))
828             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]!")         // q14  = L5, q15 = L6, fptr += 8
829             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L3+A*(L2+A*(L1+L0*A)))
830             __ASM_EMIT("vadd.f32        q8, q8, q13")                   // q8   = L4+A*(L3+A*(L2+A*(L1+L0*A)))
831             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
832             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
833             __ASM_EMIT("vld1.32         {q12-q13}, [%[fptr]]!")         // q12  = L7, q13 = L8, fptr += 8
834             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
835             __ASM_EMIT("vadd.f32        q8, q8, q15")                   // q8   = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
836             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
837             __ASM_EMIT("vadd.f32        q8, q8, q12")                   // q8   = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
838             __ASM_EMIT("vld1.32         {q14-q15}, [%[fptr]]")          // q14  = L9, q15 = (LXE + LN2), fptr += 8
839             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
840             __ASM_EMIT("vadd.f32        q8, q8, q13")                   // q8   = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
841             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
842             __ASM_EMIT("vadd.f32        q8, q8, q14")                   // q8   = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
843             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
844             __ASM_EMIT("sub             %[fptr], $0xd0")                // fptr -= 52
845             __ASM_EMIT("vmul.f32        q8, q8, q0")                    // q8   = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
846             __ASM_EMIT("vmla.f32        q8, q4, q15")                   // q8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
847             __ASM_EMIT("vadd.f32        q8, q8, q0")                    // q8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A
848             // Apply values to axes, q0 = log(abs(v*zero))
849             __ASM_EMIT("vld1.32         {q4}, [%[x]]")                  // q4 = x
850             __ASM_EMIT("vld1.32         {q0}, [%[y]]")                  // q0 = y
851             __ASM_EMIT("vld1.32         {q12-q13}, [%[params]]")        // q12 = norm_x, q13 = norm_y
852             __ASM_EMIT("vmla.f32        q4, q8, q12")                   // q4 = x + log(abs(v*zero)) * norm_x
853             __ASM_EMIT("vmla.f32        q0, q8, q13")                   // q0 = y + log(abs(v*zero)) * norm_y
854             __ASM_EMIT("sub             %[count], $4")
855             __ASM_EMIT("vst1.32         {q4}, [%[x]]!")                 // x += 4
856             __ASM_EMIT("vst1.32         {q0}, [%[y]]!")                 // y += 4
857 
858             // Do x1 block
859             __ASM_EMIT("6:")
860             __ASM_EMIT("adds            %[count], $3")
861             __ASM_EMIT("blt             8f")
862 
863             __ASM_EMIT("7:")
864             __ASM_EMIT("sub             %[params], $0x10")              // params -= 4
865             __ASM_EMIT("vldm            %[v]!, {s8}")                   // d4  = v, v += 4
866             __ASM_EMIT("vld1.32         {q6}, [%[fptr]]!")              // d12 = X_AMP, fptr += 4
867             __ASM_EMIT("vabs.f32        d4, d4")                        // d4  = abs(v)
868             __ASM_EMIT("vld1.32         {q7}, [%[params]]!")            // d14 = zero, params += 4
869             __ASM_EMIT("vmax.f32        d4, d12")                       // d4  = max(X_AMP, abs(v)), ignores denormalized values
870             __ASM_EMIT("vmul.f32        d0, d4, d14")                   // d0  = max(X_AMP, abs(v)) * zero
871             // Step 2: parse float value
872             __ASM_EMIT("vld1.32         {q6-q7}, [%[iptr]]")            // d12 = MANT_MASK, d14 = FRAC_SUB = 127
873             __ASM_EMIT("vshr.u32        d4, d0, $23")                   // d4  = frac(v)
874             __ASM_EMIT("vand.u32        d8, d0, d12")                   // d8  = mant(v)
875             __ASM_EMIT("vld1.32         {q8-q9}, [%[fptr]]!")           // d16 = 0.5f, d18 = sqrt(1/2), fptr += 8
876             __ASM_EMIT("vsub.i32        d4, d4, d14")                   // d4  = frac(v) - 127
877             __ASM_EMIT("vorr.i32        d8, d8, d16")                   // d8  = V = mant(v)+0.5
878             __ASM_EMIT("vcvt.f32.s32    d4, d4")                        // d4  = E = float(frac(v)-127)
879             // Prepare logarithm approximation calculations
880             __ASM_EMIT("vld1.32         {q6-q7}, [%[fptr]]!")           // d12  = 1.0, d14 = L0 , fptr += 4
881             __ASM_EMIT("vclt.f32        d0, d8, d18")                   // d0   = [ V < sqrt(1/2) ]
882             __ASM_EMIT("vand.u32        d0, d0, d8")                    // d0   = V & [ V < sqrt(1/2) ]
883             __ASM_EMIT("vadd.f32        d0, d0, d8")                    // d0   = V + V & [ V < sqrt(1/2) ]
884             __ASM_EMIT("vclt.f32        d8, d8, d18")                   // d8   = [ V < sqrt(1/2) ]
885             __ASM_EMIT("vsub.f32        d0, d0, d12")                   // d0   = A = V + V & [ V < sqrt(1/2) ] - 1.0
886             __ASM_EMIT("vbic.u32        d8, d12, d8")                   // d8   = 1.0 & [ V >= sqrt(1/2) ]
887             __ASM_EMIT("vadd.f32        d4, d4, d8")                    // d4   = B = E + 1.0 & [ V >= sqrt(1/2) ]
888             // Calculate logarithmic values
889             __ASM_EMIT("vld1.32         {q8-q9}, [%[fptr]]!")           // d16  = L1, d18 = L2, fptr += 8
890             __ASM_EMIT("vmul.f32        d8, d0, d14")                   // d8   = L0*A
891             __ASM_EMIT("vadd.f32        d8, d8, d16")                   // d8   = L1+L0*A
892             __ASM_EMIT("vld1.32         {q6-q7}, [%[fptr]]!")           // d12  = L3, d14 = L4, fptr += 8
893             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L1+L0*A)
894             __ASM_EMIT("vadd.f32        d8, d8, d18")                   // d8   = L2+A*(L1+L0*A)
895             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L2+A*(L1+L0*A))
896             __ASM_EMIT("vadd.f32        d8, d8, d12")                   // d8   = L3+A*(L2+A*(L1+L0*A))
897             __ASM_EMIT("vld1.32         {q8-q9}, [%[fptr]]!")           // d16  = L5, d18 = L6, fptr += 8
898             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L3+A*(L2+A*(L1+L0*A)))
899             __ASM_EMIT("vadd.f32        d8, d8, d14")                   // d8   = L4+A*(L3+A*(L2+A*(L1+L0*A)))
900             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
901             __ASM_EMIT("vadd.f32        d8, d8, d16")                   // d8   = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))
902             __ASM_EMIT("vld1.32         {q6-q7}, [%[fptr]]!")           // d12  = L7, d14 = L8, fptr += 8
903             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
904             __ASM_EMIT("vadd.f32        d8, d8, d18")                   // d8   = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))
905             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
906             __ASM_EMIT("vadd.f32        d8, d8, d12")                   // d8   = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))
907             __ASM_EMIT("vld1.32         {q8-q9}, [%[fptr]]")            // d16  = L9, d18 = (LXE + LN2), fptr += 8
908             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
909             __ASM_EMIT("vadd.f32        d8, d8, d14")                   // d8   = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))
910             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
911             __ASM_EMIT("vadd.f32        d8, d8, d16")                   // d8   = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))
912             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
913             __ASM_EMIT("sub             %[fptr], $0xd0")                // fptr -= 52
914             __ASM_EMIT("vmul.f32        d8, d8, d0")                    // d8   = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
915             __ASM_EMIT("vmla.f32        d8, d4, d18")                   // d8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))))
916             __ASM_EMIT("vadd.f32        d8, d8, d0")                    // d8   = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A
917             // Apply values to axes, d0 = log(abs(v*zero))
918             __ASM_EMIT("vldm            %[x], {s8}")                    // d4 = x
919             __ASM_EMIT("vldm            %[y], {s0}")                    // d0 = y
920             __ASM_EMIT("vld1.32         {q6-q7}, [%[params]]")          // d12 = norm_x, d14 = norm_y
921             __ASM_EMIT("vmla.f32        d4, d8, d12")                   // d4 = x + log(abs(v*zero)) * norm_x
922             __ASM_EMIT("vmla.f32        d0, d8, d14")                   // d0 = y + log(abs(v*zero)) * norm_y
923             __ASM_EMIT("subs            %[count], $1")
924             __ASM_EMIT("vstm            %[x]!, {s8}")                   // x++
925             __ASM_EMIT("vstm            %[y]!, {s0}")                   // y++
926             __ASM_EMIT("bge             7b")
927 
928             __ASM_EMIT("8:")
929 
930             : [v] "+r" (v), [x] "+r" (x) , [y] "+r" (y),
931               [count] "+r" (count),
932               [iptr] "+r" (iptr), [fptr] "+r" (fptr)
933             : [params] "r" (params)
934             : "cc", "memory",
935               "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7",
936               "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
937         );
938     }
939 
rgba32_to_bgra32(void * dst,const void * src,size_t count)940     void rgba32_to_bgra32(void *dst, const void *src, size_t count)
941     {
942         IF_ARCH_ARM(
943             uint32_t mask;
944             uint32_t t1, t2;
945         );
946 
947         ARCH_ARM_ASM(
948             // 64x blocks
949             __ASM_EMIT("subs        %[count], $64")
950             __ASM_EMIT("blo         2f")
951             __ASM_EMIT("1:")
952             __ASM_EMIT("vld4.8      {q0-q1}, [%[src]]!") // d0 = R, d1 = G, d2 = B, d3 = A
953             __ASM_EMIT("vld4.8      {q2-q3}, [%[src]]!")
954             __ASM_EMIT("vswp        d0, d2")
955             __ASM_EMIT("vld4.8      {q4-q5}, [%[src]]!")
956             __ASM_EMIT("vst4.8      {q0-q1}, [%[dst]]!")
957             __ASM_EMIT("vswp        d4, d6")
958             __ASM_EMIT("vld4.8      {q6-q7}, [%[src]]!")
959             __ASM_EMIT("vst4.8      {q2-q3}, [%[dst]]!")
960             __ASM_EMIT("vswp        d8, d10")
961             __ASM_EMIT("vld4.8      {q8-q9}, [%[src]]!")
962             __ASM_EMIT("vst4.8      {q4-q5}, [%[dst]]!")
963             __ASM_EMIT("vswp        d12, d14")
964             __ASM_EMIT("vld4.8      {q10-q11}, [%[src]]!")
965             __ASM_EMIT("vst4.8      {q6-q7}, [%[dst]]!")
966             __ASM_EMIT("vswp        d16, d18")
967             __ASM_EMIT("vld4.8      {q12-q13}, [%[src]]!")
968             __ASM_EMIT("vst4.8      {q8-q9}, [%[dst]]!")
969             __ASM_EMIT("vswp        d20, d22")
970             __ASM_EMIT("vld4.8      {q14-q15}, [%[src]]!")
971             __ASM_EMIT("vst4.8      {q10-q11}, [%[dst]]!")
972             __ASM_EMIT("vswp        d24, d26")
973             __ASM_EMIT("vswp        d28, d30")
974             __ASM_EMIT("vst4.8      {q12-q13}, [%[dst]]!")
975             __ASM_EMIT("vst4.8      {q14-q15}, [%[dst]]!")
976             __ASM_EMIT("subs        %[count], $64")
977             __ASM_EMIT("bhs         1b")
978 
979             // 32x blocks
980             __ASM_EMIT("2:")
981             __ASM_EMIT("adds        %[count], $32")
982             __ASM_EMIT("blt         4f")
983             __ASM_EMIT("vld4.8      {q0-q1}, [%[src]]!") // d0 = R, d1 = G, d2 = B, d3 = A
984             __ASM_EMIT("vld4.8      {q2-q3}, [%[src]]!")
985             __ASM_EMIT("vswp        d0, d2")
986             __ASM_EMIT("vld4.8      {q4-q5}, [%[src]]!")
987             __ASM_EMIT("vst4.8      {q0-q1}, [%[dst]]!")
988             __ASM_EMIT("vswp        d4, d6")
989             __ASM_EMIT("vld4.8      {q6-q7}, [%[src]]!")
990             __ASM_EMIT("vst4.8      {q2-q3}, [%[dst]]!")
991             __ASM_EMIT("vswp        d8, d10")
992             __ASM_EMIT("vswp        d12, d14")
993             __ASM_EMIT("vst4.8      {q4-q5}, [%[dst]]!")
994             __ASM_EMIT("vst4.8      {q6-q7}, [%[dst]]!")
995             __ASM_EMIT("sub         %[count], $32")
996 
997             // 16x blocks
998             __ASM_EMIT("4:")
999             __ASM_EMIT("adds        %[count], $16")
1000             __ASM_EMIT("blt         6f")
1001             __ASM_EMIT("vld4.8      {q0-q1}, [%[src]]!") // d0 = R, d1 = G, d2 = B, d3 = A
1002             __ASM_EMIT("vld4.8      {q2-q3}, [%[src]]!")
1003             __ASM_EMIT("vswp        d0, d2")
1004             __ASM_EMIT("vswp        d4, d6")
1005             __ASM_EMIT("vst4.8      {q0-q1}, [%[dst]]!")
1006             __ASM_EMIT("vst4.8      {q2-q3}, [%[dst]]!")
1007             __ASM_EMIT("sub         %[count], $16")
1008 
1009             // 8x blocks
1010             __ASM_EMIT("6:")
1011             __ASM_EMIT("adds        %[count], $8")
1012             __ASM_EMIT("blt         8f")
1013             __ASM_EMIT("vld4.8      {q0-q1}, [%[src]]!") // d0 = R, d1 = G, d2 = B, d3 = A
1014             __ASM_EMIT("vswp        d0, d2")
1015             __ASM_EMIT("vst4.8      {q0-q1}, [%[dst]]!")
1016             __ASM_EMIT("sub         %[count], $8")
1017 
1018             // 4x blocks
1019             __ASM_EMIT("8:")
1020             __ASM_EMIT("adds        %[count], $4")
1021             __ASM_EMIT("blt         10f")
1022             __ASM_EMIT("vld2.8      {q0}, [%[src]]!") // d0 = RB, d1 = GA
1023             __ASM_EMIT("vshl.i16    d2, d0, $8")
1024             __ASM_EMIT("vshr.u16    d0, d0, $8")
1025             __ASM_EMIT("vorr        d0, d2")
1026             __ASM_EMIT("vst2.8      {q0}, [%[dst]]!")
1027             __ASM_EMIT("sub         %[count], $4")
1028 
1029             // 1x blocks
1030             __ASM_EMIT("10:")
1031             __ASM_EMIT("adds        %[count], $3")
1032             __ASM_EMIT("blt         12f")
1033             __ASM_EMIT("mov         %[mask], $0xff")
1034             __ASM_EMIT("orr         %[mask], $0xff0000")           // mask = ff 00 ff 00
1035             __ASM_EMIT("11:")
1036             __ASM_EMIT("ldr         %[t1], [%[src]], $4")               // t1 = R G B A
1037             __ASM_EMIT("and         %[t2], %[t1], %[mask]")             // t2 = R 0 B 0
1038             __ASM_EMIT("and         %[t1], %[t1], %[mask], lsl $8")     // t1 = 0 G 0 A
1039             __ASM_EMIT("orr         %[t1], %[t1], %[t2], ror $16")      // t1 = B G R A
1040             __ASM_EMIT("str         %[t1], [%[dst]], $4")
1041             __ASM_EMIT("subs        %[count], $1")
1042             __ASM_EMIT("bge         11b")
1043 
1044             __ASM_EMIT("12:")
1045             : [src] "+r" (src), [dst] "+r" (dst), [count] "+r" (count),
1046               [t1] "=&r" (t1), [t2] "=&r" (t2), [mask] "=&r" (mask)
1047             :
1048             : "cc", "memory",
1049               "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7",
1050               "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
1051         );
1052     }
1053 
1054 #define FILL4_CORE \
1055     __ASM_EMIT("vld1.32     {q0}, [%[c4]]")     /* q0 = c0 c1 c2 c3 */ \
1056     __ASM_EMIT("vmov        q1, q0")            /* q1 = c0 c1 c2 c3 */ \
1057     __ASM_EMIT("vmov        q2, q0")            /* q2 = c0 c1 c2 c3 */ \
1058     __ASM_EMIT("vmov        q3, q1")            /* q3 = c0 c1 c2 c3 */ \
1059     \
1060     /* 8x blocks */ \
1061     __ASM_EMIT("subs        %[count], $8") \
1062     __ASM_EMIT("blo         2f") \
1063     __ASM_EMIT("vmov        q4, q0")            /* q4 = c0 c1 c2 c3 */ \
1064     __ASM_EMIT("vmov        q5, q1")            /* q5 = c0 c1 c2 c3 */ \
1065     __ASM_EMIT("vmov        q6, q2")            /* q6 = c0 c1 c2 c3 */ \
1066     __ASM_EMIT("vmov        q7, q3")            /* q7 = c0 c1 c2 c3 */ \
1067     __ASM_EMIT("1:") \
1068     __ASM_EMIT("vstm        %[dst], {q0-q7}") \
1069     __ASM_EMIT("subs        %[count], $8") \
1070     __ASM_EMIT("add         %[dst], $0x80") \
1071     __ASM_EMIT("bhs         1b") \
1072     /* 4x block */ \
1073     __ASM_EMIT("2:") \
1074     __ASM_EMIT("adds        %[count], $4") \
1075     __ASM_EMIT("blt         4f") \
1076     __ASM_EMIT("vstm        %[dst], {q0-q3}") \
1077     __ASM_EMIT("sub         %[count], $4") \
1078     __ASM_EMIT("add         %[dst], $0x40") \
1079     /* 2x block */ \
1080     __ASM_EMIT("4:") \
1081     __ASM_EMIT("adds        %[count], $2") \
1082     __ASM_EMIT("blt         6f") \
1083     __ASM_EMIT("vst1.32     {q0-q1}, [%[dst]]") \
1084     __ASM_EMIT("sub         %[count], $2") \
1085     __ASM_EMIT("add         %[dst], $0x20") \
1086     /* 1x block */ \
1087     __ASM_EMIT("6:") \
1088     __ASM_EMIT("adds        %[count], $1") \
1089     __ASM_EMIT("blt         8f") \
1090     __ASM_EMIT("vst1.32     {q0}, [%[dst]]") \
1091     __ASM_EMIT("8:")
1092 
fill_rgba(float * dst,float r,float g,float b,float a,size_t count)1093     void fill_rgba(float *dst, float r, float g, float b, float a, size_t count)
1094     {
1095         IF_ARCH_ARM(
1096             float c4[4] __lsp_aligned16;
1097             c4[0] = r;
1098             c4[1] = g;
1099             c4[2] = b;
1100             c4[3] = a;
1101         )
1102 
1103         ARCH_ARM_ASM
1104         (
1105             FILL4_CORE
1106             : [dst] "+r" (dst), [count] "+r" (count)
1107             : [c4] "r" (&c4[0])
1108             : "cc", "memory",
1109               "q0", "q1", "q2", "q3",
1110               "q4", "q5", "q6", "q7"
1111         );
1112     }
1113 
fill_hsla(float * dst,float h,float s,float l,float a,size_t count)1114     void fill_hsla(float *dst, float h, float s, float l, float a, size_t count)
1115     {
1116         IF_ARCH_ARM(
1117             float c4[4] __lsp_aligned16;
1118             c4[0] = h;
1119             c4[1] = s;
1120             c4[2] = l;
1121             c4[3] = a;
1122         );
1123 
1124         ARCH_ARM_ASM
1125         (
1126             FILL4_CORE
1127             : [dst] "+r" (dst), [count] "+r" (count)
1128             : [c4] "r" (&c4[0])
1129             : "cc", "memory",
1130               "q0", "q1", "q2", "q3",
1131               "q4", "q5", "q6", "q7"
1132         );
1133     }
1134 
1135 #undef FILL4_CORE
1136 
1137 #define FVEC4(x)    x, x, x, x
1138 
1139 IF_ARCH_ARM(
1140     static const float HSL_RGB[] =
1141     {
1142         FVEC4(0.5f),                // 1/2
1143         FVEC4(0.333333333333f),     // 1/3
1144         FVEC4(1.0f),                // 1
1145         FVEC4(6.0f),                // 6
1146         FVEC4(0.166666666667f),     // 1/6
1147         FVEC4(0.666666666667f)      // 2/3
1148     };
1149 
1150     static const float RGB_HSL[] =
1151     {
1152         FVEC4(4.0f),
1153         FVEC4(2.0f),
1154         FVEC4(6.0f),
1155         FVEC4(1.0f),
1156         FVEC4(0.5f),
1157         FVEC4(0.166666666667f)      // 1/6
1158     };
1159 
1160     static const float RGBA_TO_BGRA32[] =
1161     {
1162         FVEC4(255.0f),
1163         FVEC4(255.0f)
1164     };
1165 )
1166 
1167 #undef FVEC4
1168 
1169 #define HSLA_TO_RGBA_CORE   \
1170     /*  q10 = 1/2, q11 = 1/3, q12 = 1, q13 = 6, q14 = 1/6, q15 = 2/3 */ \
1171     /*  q0 = h0 h1 h2 h3 = H */ \
1172     /*  q1 = l0 l1 l2 l3 = L */ \
1173     /*  q2 = s0 s1 s2 s3 = S */ \
1174     /*  q3 = a0 a1 a2 a3 = A */ \
1175     /*  Calc temp1 (T1) and temp2 (T2) */ \
1176     __ASM_EMIT("vadd.f32        q4, q2, q1")                /* q4 = L+S */ \
1177     __ASM_EMIT("vadd.f32        q9, q1, q1")                /* q9 = L+L */ \
1178     __ASM_EMIT("vmul.f32        q5, q2, q1")                /* q5 = L*S */ \
1179     __ASM_EMIT("vsub.f32        q4, q4, q5")                /* q4 = L+S - L*S */ \
1180     __ASM_EMIT("vadd.f32        q7, q1, q5")                /* q7 = L + L*S */ \
1181     __ASM_EMIT("vclt.f32        q8, q1, q10")               /* q8 = [L < 0.5] */ \
1182     __ASM_EMIT("vbit            q4, q7, q8")                /* q4 = T2 = (L+L*S) & [L<0.5]) | (((L+S-L*S) & [L>=0.5]) */ \
1183     __ASM_EMIT("vmov            q2, q0")                    /* q2 = TG = H */ \
1184     __ASM_EMIT("vsub.f32        q5, q9, q4")                /* q5 = T1 = L+L-T2 */ \
1185     __ASM_EMIT("vadd.f32        q0, q0, q11")               /* q0 = H + 1/3 */ \
1186     __ASM_EMIT("vsub.f32        q1, q2, q11")               /* q1 = H - 1/3 */ \
1187     __ASM_EMIT("vcgt.f32        q9, q0, q12")               /* q9 = [H+1/3 > 1] */ \
1188     __ASM_EMIT("veor            q8, q8")                    /* q8 = 0 */ \
1189     __ASM_EMIT("vsub.f32        q6, q0, q12")               /* q6 = H + 1/3 - 1 */ \
1190     __ASM_EMIT("vadd.f32        q7, q2, q12")               /* q7 = H - 1/3 + 1 */ \
1191     __ASM_EMIT("vclt.f32        q8, q1, q8")                /* q8 = [H-1/3 < 0] */ \
1192     __ASM_EMIT("vbit            q0, q6, q9")                /* q0 = TR = ((H+1/3) & [H+1/3 <= 1]) | ((H+1/3-1) & [H+1/3 > 1]) */ \
1193     __ASM_EMIT("vbit            q1, q7, q8")                /* q1 = TB = ((H-1/3) & [H-1/3 >= 0]) | ((H-1/3+1) & [H-1/3 < 0]) */ \
1194     __ASM_EMIT("vsub.f32        q6, q4, q5")                /* q6 = T2 - T1 */ \
1195     __ASM_EMIT("vmul.f32        q6, q6, q13")               /* q6 = K = (T2 - T1)*6 */ \
1196     /* q0 = TR */ \
1197     /* q2 = TG */ \
1198     /* q1 = TB */ \
1199     /* q3 = A */ \
1200     /* q4 = T2 */ \
1201     /* q5 = T1 */ \
1202     /* q6 = K */ \
1203     /* Process red color */ \
1204     __ASM_EMIT("vmov            q7, q5")                    /* q7 = T1 */ \
1205     __ASM_EMIT("vmov            q8, q5")                    /* q8 = T1 */ \
1206     __ASM_EMIT("vsub.f32        q9, q15, q0")               /* q9 = 2/3 - TR */ \
1207     __ASM_EMIT("vmla.f32        q7, q6, q0")                /* q7 = KTR = T1 + K*TR */ \
1208     __ASM_EMIT("vmla.f32        q8, q6, q9")                /* q8 = RTR = T1 + K*(2/3-TR) */ \
1209     __ASM_EMIT("vclt.f32        q9, q0, q14")               /* q9 = [TR < 1/6] */ \
1210     __ASM_EMIT("vbif            q7, q4, q9")                /* q7 = (KTR & [TR < 1/6]) | ((T2) & (TR >= 1/6)) */ \
1211     __ASM_EMIT("vclt.f32        q9, q0, q15")               /* q9 = [TR < 2/3] */ \
1212     __ASM_EMIT("vbif            q8, q5, q9")                /* q8 = (RTR & [TR < 2/3]) | ((T1) & (TR >= 2/3)) */ \
1213     __ASM_EMIT("vclt.f32        q9, q0, q10")               /* q9 = [TR < 1/2] */ \
1214     __ASM_EMIT("vand            q0, q7, q9")                /* q0 = (KTR & [TR < 1/6] & [TR < 1/2]) | ((T2) & (TR >= 1/6) & [TR < 1/2]) */ \
1215     __ASM_EMIT("vbif            q0, q8, q9")                /* q0 = (KTR & [TR < 1/6] & [TR < 1/2]) | ((T2) & (TR >= 1/6) & [TR < 1/2]) | (RTR & [TR < 2/3] & [TR >= 1/2]) | ((T1) & (TR >= 2/3) & [TR >= 1/2]) */ \
1216     /* Process green color */ \
1217     __ASM_EMIT("vmov            q7, q5")                    /* q7 = T1 */ \
1218     __ASM_EMIT("vmov            q8, q5")                    /* q8 = T1 */ \
1219     __ASM_EMIT("vsub.f32        q9, q15, q2")               /* q9 = 2/3 - TG */ \
1220     __ASM_EMIT("vmla.f32        q7, q6, q2")                /* q7 = KTG = T1 + K*TG */ \
1221     __ASM_EMIT("vmla.f32        q8, q6, q9")                /* q8 = RTG = T1 + K*(2/3-TG) */ \
1222     __ASM_EMIT("vclt.f32        q9, q2, q14")               /* q9 = [TG < 1/6] */ \
1223     __ASM_EMIT("vbif            q7, q4, q9")                /* q7 = (KTG & [TG < 1/6]) | ((T2) & (TG >= 1/6)) */ \
1224     __ASM_EMIT("vclt.f32        q9, q2, q15")               /* q9 = [TG < 2/3] */ \
1225     __ASM_EMIT("vbif            q8, q5, q9")                /* q8 = (RTG & [TG < 2/3]) | ((T1) & (TG >= 2/3)) */ \
1226     __ASM_EMIT("vclt.f32        q9, q2, q10")               /* q9 = [TG < 1/2] */ \
1227     __ASM_EMIT("vand            q2, q7, q9")                /* q2 = (KTG & [TG < 1/6] & [TG < 1/2]) | ((T2) & (TG >= 1/6) & [TG < 1/2]) */ \
1228     __ASM_EMIT("vbif            q2, q8, q9")                /* q2 = (KTG & [TG < 1/6] & [TG < 1/2]) | ((T2) & (TG >= 1/6) & [TG < 1/2]) | (RTG & [TG < 2/3] & [TG >= 1/2]) | ((T1) & (TG >= 2/3) & [TG >= 1/2]) */ \
1229     /* Process blue color */ \
1230     __ASM_EMIT("vmov            q7, q5")                    /* q7 = T1 */ \
1231     __ASM_EMIT("vmov            q8, q5")                    /* q8 = T1 */ \
1232     __ASM_EMIT("vsub.f32        q9, q15, q1")               /* q9 = 2/3 - TB */ \
1233     __ASM_EMIT("vmla.f32        q7, q6, q1")                /* q7 = KTB = T1 + K*TB */ \
1234     __ASM_EMIT("vmla.f32        q8, q6, q9")                /* q8 = RTB = T1 + K*(2/3-TB) */ \
1235     __ASM_EMIT("vclt.f32        q9, q1, q14")               /* q9 = [TB < 1/6] */ \
1236     __ASM_EMIT("vbif            q7, q4, q9")                /* q7 = (KTB & [TB < 1/6]) | ((T2) & (TB >= 1/6)) */ \
1237     __ASM_EMIT("vclt.f32        q9, q1, q15")               /* q9 = [TB < 2/3] */ \
1238     __ASM_EMIT("vbif            q8, q5, q9")                /* q8 = (RTB & [TB < 2/3]) | ((T1) & (TB >= 2/3)) */ \
1239     __ASM_EMIT("vclt.f32        q9, q1, q10")               /* q9 = [TB < 1/2] */ \
1240     __ASM_EMIT("vand            q1, q7, q9")                /* q1 = (KTB & [TB < 1/6] & [TB < 1/2]) | ((T2) & (TB >= 1/6) & [TB < 1/2]) */ \
1241     __ASM_EMIT("vbif            q1, q8, q9")                /* q1 = (KTB & [TB < 1/6] & [TB < 1/2]) | ((T2) & (TB >= 1/6) & [TB < 1/2]) | (RTB & [TB < 2/3] & [TB >= 1/2]) | ((T1) & (TB >= 2/3) & [TB >= 1/2]) */ \
1242     /*  q0 = R */ \
1243     /*  q1 = B */ \
1244     /*  q2 = G */ \
1245     /*  q3 = A */ \
1246 
1247 /*
1248         //Set the temporary values
1249         if  (L < HSL_RGB_0_5)
1250             temp2 = L + (L * S);
1251         else
1252             temp2 = (L + S) - (L * S);
1253 
1254         temp1 = L + L - temp2;
1255 
1256         tempr = H + HSL_RGB_1_3;
1257         tempg = H;
1258         tempb = H - HSL_RGB_1_3;
1259 
1260         if (tempr > 1.0f)
1261             tempr   -= 1.0f;
1262         if (tempb < 0.0f)
1263             tempb   += 1.0f;
1264 
1265         k = (temp2 - temp1) * 6.0f;
1266 
1267         //Red
1268         if (tempr < HSL_RGB_0_5)
1269             R = (tempr < HSL_RGB_1_6) ? temp1 + k * tempr : temp2;
1270         else
1271             R = (tempr < HSL_RGB_2_3) ? temp1 + k * (HSL_RGB_2_3 - tempr) : temp1;
1272 
1273         //Green
1274         if (tempg < HSL_RGB_0_5)
1275             G = (tempg < HSL_RGB_1_6) ? temp1 + k * tempg : temp2;
1276         else
1277             G = (tempg < HSL_RGB_2_3) ? temp1 + k * (HSL_RGB_2_3 - tempg) : temp1;
1278 
1279         //Blue
1280         if (tempb < HSL_RGB_0_5)
1281             B = (tempb < HSL_RGB_1_6) ? temp1 + k * tempb : temp2;
1282         else
1283             B = (tempb < HSL_RGB_2_3) ? temp1 + k * (HSL_RGB_2_3 - tempb) : temp1;
1284 */
1285 
1286 
1287 
hsla_to_rgba(float * dst,const float * src,size_t count)1288     void hsla_to_rgba(float *dst, const float *src, size_t count)
1289     {
1290         ARCH_ARM_ASM
1291         (
1292             __ASM_EMIT("vldm            %[XC], {q10-q15}")          // q10 = 1/2, q11 = 1/3, q12 = 1, q13 = 6, q14 = 1/6, q15 = 2/3
1293             __ASM_EMIT("subs            %[count], $4")
1294             __ASM_EMIT("blo             2f")
1295 
1296             //-----------------------------------------------------------------
1297             // 4x blocks
1298             __ASM_EMIT("1:")
1299             __ASM_EMIT("vld4.32         {q0-q1}, [%[src]]!")        // q0 = h0 h1 s0 s1, q1 = l0 l1 a0 a1
1300             __ASM_EMIT("vld4.32         {q2-q3}, [%[src]]!")        // q2 = h2 h3 s2 s3, q3 = l2 l3 a2 a3
1301             __ASM_EMIT("vswp            d1, d4")                    // q0 = h0 h1 h2 h3, q2 = s0 s1 s2 s3
1302             __ASM_EMIT("vswp            d3, d6")                    // q1 = l0 l1 l2 l3, q3 = a0 a1 a2 a3
1303 
1304             HSLA_TO_RGBA_CORE
1305 
1306             __ASM_EMIT("vswp            d1, d4")                    // q0 = r0 r1 g0 g1, q2 = r2 r3 g2 g3
1307             __ASM_EMIT("vswp            d3, d6")                    // q1 = b0 b1 a0 a1, q3 = b2 b3 a2 a3
1308             __ASM_EMIT("vst4.32         {q0-q1}, [%[dst]]!")
1309             __ASM_EMIT("vst4.32         {q2-q3}, [%[dst]]!")
1310             __ASM_EMIT("subs            %[count], $4")
1311             __ASM_EMIT("bhs             1b")
1312 
1313             __ASM_EMIT("2:")
1314             __ASM_EMIT("adds            %[count], $4")
1315             __ASM_EMIT("bls             10f")
1316 
1317             //-----------------------------------------------------------------
1318             // 1x-3x block
1319             __ASM_EMIT("tst             %[count], $2")
1320             __ASM_EMIT("beq             4f")
1321             __ASM_EMIT("vld1.32         {q0-q1}, [%[src]]!")        // q0 = h0 s0 l0 a0, q1 = h1 s1 l1 a1
1322             __ASM_EMIT("4:")
1323             __ASM_EMIT("tst             %[count], $1")
1324             __ASM_EMIT("beq             6f")
1325             __ASM_EMIT("vld1.32         {q2}, [%[src]]")            // q2 = h2 s2 l2 a2, q3 = ? ? ? ?
1326             __ASM_EMIT("6:")
1327 
1328             __ASM_EMIT("vtrn.32         q0, q1")                    // q0 = h0 h1 l0 l1, q1 = s0 s1 a0 a1
1329             __ASM_EMIT("vtrn.32         q2, q3")                    // q2 = h2  ? l2  ?, q3 = s2  ? a2  ?
1330             __ASM_EMIT("vswp            d1, d4")                    // q0 = h0 h1 h2  ?, q2 = l0 l1 l2  ?
1331             __ASM_EMIT("vswp            d3, d6")                    // q1 = s0 s1 s2  ?, q3 = a0 a1 a2  ?
1332 
1333             __ASM_EMIT("vswp            q1, q2")                    // q1 = l0 l1 l2  ?, q2 = s0 s1 s2  ?
1334             HSLA_TO_RGBA_CORE
1335             __ASM_EMIT("vswp            q1, q2")
1336 
1337             __ASM_EMIT("vtrn.32         q0, q1")
1338             __ASM_EMIT("vtrn.32         q2, q3")
1339             __ASM_EMIT("vswp            d1, d4")
1340             __ASM_EMIT("vswp            d3, d6")
1341 
1342             __ASM_EMIT("tst             %[count], $2")
1343             __ASM_EMIT("beq             8f")
1344             __ASM_EMIT("vst1.32         {q0-q1}, [%[dst]]!")
1345             __ASM_EMIT("8:")
1346             __ASM_EMIT("tst             %[count], $1")
1347             __ASM_EMIT("beq             10f")
1348             __ASM_EMIT("vst1.32         {q2}, [%[dst]]")
1349 
1350             __ASM_EMIT("10:")
1351 
1352             : [dst] "+r" (dst), [src] "+r" (src), [count] "+r" (count)
1353             : [XC] "r" (&HSL_RGB[0])
1354             : "cc", "memory",
1355               "q0", "q1", "q2", "q3",
1356               "q4", "q5", "q6", "q7",
1357               "q8", "q9", "q10", "q11",
1358               "q12", "q13", "q14", "q15"
1359         );
1360     }
1361 
1362 #undef HSLA_TO_RGBA_CORE
1363 
1364 #define RGBA_TO_HSLA_CORE \
1365     /*  q0   = R */ \
1366     /*  q1   = B */ \
1367     /*  q2   = G */ \
1368     /*  q3   = A */ \
1369     /*  q10  = 4, q11 = 2, q12 = 6, q13 = 1, q14 = 1/2, q15 = 1/6 */ \
1370     __ASM_EMIT("vmax.f32        q4, q0, q1") \
1371     __ASM_EMIT("vmin.f32        q5, q0, q1") \
1372     __ASM_EMIT("vmax.f32        q4, q4, q2")                /* q4 = CMAX */ \
1373     __ASM_EMIT("vmin.f32        q5, q5, q2")                /* q5 = CMIN */ \
1374     __ASM_EMIT("vsub.f32        q6, q4, q5")                /* q6 = D = CMAX - CMIN */ \
1375     __ASM_EMIT("vadd.f32        q5, q4, q5")                /* q5 = CMAX + CMIN */ \
1376     __ASM_EMIT("vstm            %[RGBA], {q0-q3}")          /* store R, B, G, A */ \
1377     \
1378     __ASM_EMIT("vrecpe.f32      q9, q6")                    /* q9 = RD */ \
1379     __ASM_EMIT("vrecps.f32      q8, q9, q6")                /* q8 = (2 - RD*D) */ \
1380     __ASM_EMIT("vmul.f32        q9, q8, q9")                /* q9 = d' = RD * (2 - RD*D) */ \
1381     __ASM_EMIT("vrecps.f32      q8, q9, q6")                /* q8 = (2 - RD*d') */ \
1382     __ASM_EMIT("vmul.f32        q9, q8, q9")                /* q9 = 1/D = d' * (2 - RD*d') */  \
1383     \
1384     /* q0  = R */ \
1385     /* q1  = B */ \
1386     /* q2  = G */ \
1387     /* q3  = A */ \
1388     /* q4  = CMAX */ \
1389     /* q5  = CMAX + CMIN */ \
1390     /* q6  = D */ \
1391     /* q9  = 1/D */ \
1392     __ASM_EMIT("vsub.f32        q7, q1, q0")                /* q7 = B-R */ \
1393     __ASM_EMIT("vsub.f32        q8, q0, q2")                /* q8 = R-G */ \
1394     __ASM_EMIT("vsub.f32        q0, q2, q1")                /* q0 = G-B */ \
1395     __ASM_EMIT("vmul.f32        q7, q7, q9")                /* q7 = (B-R)/D */ \
1396     __ASM_EMIT("veor            q1, q1")                    /* q1 = 0 */ \
1397     __ASM_EMIT("vmul.f32        q0, q0, q9")                /* q0 = (G-B)/D */ \
1398     __ASM_EMIT("vmul.f32        q8, q8, q9")                /* q8 = (R-G)/D */ \
1399     __ASM_EMIT("vclt.f32        q1, q0, q1")                /* q1 = [(G-B)/D < 0] */ \
1400     __ASM_EMIT("vadd.f32        q7, q7, q11")               /* q7 = HG = (B-R)/D + 2 */ \
1401     __ASM_EMIT("vand            q1, q12")                   /* q1 = [(G-B)/D < 0] & 6 */ \
1402     __ASM_EMIT("vadd.f32        q8, q8, q10")               /* q8 = HB = (R-G)/D + 4 */ \
1403     __ASM_EMIT("vadd.f32        q9, q0, q1")                /* q9 = HR = (G-B)/D + [(G-B)/D < 0] & 6 */ \
1404     __ASM_EMIT("vldm            %[RGBA], {q0-q3}")          /* load R, B, G, A */ \
1405     /* q0  = R */ \
1406     /* q1  = B */ \
1407     /* q2  = G */ \
1408     /* q3  = A */ \
1409     /* q4  = CMAX */ \
1410     /* q5  = CMAX + CMIN */ \
1411     /* q6  = D */ \
1412     /* q7  = HG */ \
1413     /* q8  = HB */ \
1414     /* q9  = HR */ \
1415     __ASM_EMIT("vceq.f32        q2, q2, q4")                /* q2 = [G == CMAX] */ \
1416     __ASM_EMIT("vceq.f32        q0, q0, q4")                /* q0 = [R == CMAX] */ \
1417     __ASM_EMIT("vbsl            q2, q7, q8")                /* q2 = (HG & [G == CMAX]) | (HB & [G != CMAX]) */ \
1418     __ASM_EMIT("veor            q4, q4")                    /* q4 = 0 */ \
1419     __ASM_EMIT("vbsl            q0, q9, q2")                /* q0 = (HR & [R == CMAX]) | (HG & [G == CMAX] & [R != CMAX]) | (HB & [G != CMAX] & [R != CMAX]) */ \
1420     __ASM_EMIT("vceq.f32        q4, q4, q6")                /* q4 = [ D == 0 ] */ \
1421     __ASM_EMIT("vmul.f32        q1, q5, q14")               /* q1 = L = (CMAX + CMIN) * 0.5 */ \
1422     __ASM_EMIT("vsub.f32        q2, q13, q1")               /* q2 = X = 1 - L */ \
1423     __ASM_EMIT("vbic            q0, q0, q4")                /* q0 = H = [D != 0] & ((HR & [R == CMAX]) | (HG & [G == CMAX] & [R != CMAX]) | (HB & [G != CMAX] & [R != CMAX])) */ \
1424     \
1425     __ASM_EMIT("vrecpe.f32      q5, q1")                    /* q5 = RL */ \
1426     __ASM_EMIT("vrecpe.f32      q9, q2")                    /* q9 = RX */ \
1427     __ASM_EMIT("vrecps.f32      q4, q5, q1")                /* q4 = (2 - RL*L) */ \
1428     __ASM_EMIT("vrecps.f32      q8, q9, q2")                /* q8 = (2 - RX*X) */ \
1429     __ASM_EMIT("vmul.f32        q5, q4, q5")                /* q5 = l' = L * (2 - RL*L) */ \
1430     __ASM_EMIT("vmul.f32        q9, q8, q9")                /* q9 = x' = X * (2 - RX*X) */ \
1431     __ASM_EMIT("vrecps.f32      q4, q5, q1")                /* q4 = (2 - RL*l') */ \
1432     __ASM_EMIT("vrecps.f32      q8, q9, q2")                /* q8 = (2 - RX*X') */ \
1433     __ASM_EMIT("vmul.f32        q5, q4, q5")                /* q5 = 1/L = l' * (2 - RL*l') */  \
1434     __ASM_EMIT("vmul.f32        q9, q8, q9")                /* q9 = 1/X = x' * (2 - RX*x') */  \
1435     __ASM_EMIT("vmul.f32        q2, q6, q5")                /* q2 = D/L */ \
1436     __ASM_EMIT("vmul.f32        q4, q6, q9")                /* q4 = D/X */ \
1437     __ASM_EMIT("veor            q5, q5")                    /* q5 = 0 */ \
1438     \
1439     __ASM_EMIT("vclt.f32        q6, q1, q13")               /* q6 = [L < 1] */ \
1440     __ASM_EMIT("vceq.f32        q7, q1, q5")                /* q7 = [L == 0] */ \
1441     __ASM_EMIT("vcgt.f32        q8, q1, q13")               /* q8 = [L > 1] */ \
1442     __ASM_EMIT("vbit            q6, q5, q7")                /* q6 = [L < 1] & [L != 0] */ \
1443     __ASM_EMIT("vand            q8, q8, q4")                /* q8 = D/X & [L > 1] */ \
1444     __ASM_EMIT("vand            q6, q6, q2")                /* q6 = D/L & [L < 1] & [L != 0] */ \
1445     __ASM_EMIT("vorr            q2, q8, q6")                /* q2 = S = (D/L & [L < 1] & [L != 0]) | (D/X & [L > 1]) */ \
1446     __ASM_EMIT("vmul.f32        q0, q0, q15")               /* q0 = H * 1/6 */ \
1447     __ASM_EMIT("vmul.f32        q2, q2, q14")               /* q2 = S * 1/2 */ \
1448 
1449 /*
1450     float cmax = (R < G) ? ((B < G) ? G : B) : ((B < R) ? R : B);
1451     float cmin = (R < G) ? ((B < R) ? B : R) : ((B < G) ? B : G);
1452     float d = cmax - cmin;
1453 
1454     H = 0.0f;
1455     S = 0.0f;
1456     L = HSL_RGB_0_5 * (cmax + cmin);
1457 
1458     // Calculate hue
1459     if (R == cmax)
1460     {
1461         H = (G - B) / d;
1462         if (H < 0.0f)
1463             H += 6.0f;
1464     }
1465     else if (G == cmax)
1466         H = (B - R) / d + 2.0f;
1467     else
1468         H = (R - G) / d + 4.0f;
1469 
1470     // Calculate saturation
1471     if (L < 1.0f)
1472         S = (L != 0.0f) ? d / L : 0.0f;
1473     else
1474         S = (L != 1.0f) ? d / (1.0f - L) : 0.0f;
1475 
1476     // Normalize hue and saturation
1477     H  *= HSL_RGB_1_6;
1478     S  *= HSL_RGB_0_5;
1479  */
1480 
rgba_to_hsla(float * dst,const float * src,size_t count)1481     void rgba_to_hsla(float *dst, const float *src, size_t count)
1482     {
1483 #pragma pack(push, 1)
1484         IF_ARCH_ARM(
1485             struct
1486             {
1487                 float r[4], g[4], b[4], a[4];
1488             } rgba __lsp_aligned16;
1489         );
1490 #pragma pack(pop)
1491 
1492         ARCH_ARM_ASM
1493         (
1494             __ASM_EMIT("vldm            %[XC], {q10-q15}")
1495             __ASM_EMIT("subs            %[count], $4")
1496             __ASM_EMIT("blo             2f")
1497 
1498             //-----------------------------------------------------------------
1499             // 4x blocks
1500             __ASM_EMIT("1:")
1501             __ASM_EMIT("vld4.32         {q0-q1}, [%[src]]!")
1502             __ASM_EMIT("vld4.32         {q2-q3}, [%[src]]!")
1503             __ASM_EMIT("vswp            d1, d4")
1504             __ASM_EMIT("vswp            d3, d6")
1505 
1506             RGBA_TO_HSLA_CORE
1507 
1508             __ASM_EMIT("vswp            d1, d4")
1509             __ASM_EMIT("vswp            d3, d6")
1510             __ASM_EMIT("vst4.32         {q0-q1}, [%[dst]]!")
1511             __ASM_EMIT("vst4.32         {q2-q3}, [%[dst]]!")
1512             __ASM_EMIT("subs            %[count], $4")
1513             __ASM_EMIT("bhs             1b")
1514 
1515             __ASM_EMIT("2:")
1516             __ASM_EMIT("adds            %[count], $4")
1517             __ASM_EMIT("bls             10f")
1518 
1519             //-----------------------------------------------------------------
1520             // 1x-3x block
1521             __ASM_EMIT("tst             %[count], $2")
1522             __ASM_EMIT("beq             4f")
1523             __ASM_EMIT("vld1.32         {q0-q1}, [%[src]]!")
1524             __ASM_EMIT("4:")
1525             __ASM_EMIT("tst             %[count], $1")
1526             __ASM_EMIT("beq             6f")
1527             __ASM_EMIT("vld1.32         {q2}, [%[src]]")
1528             __ASM_EMIT("6:")
1529 
1530             __ASM_EMIT("vtrn.32         q0, q1")
1531             __ASM_EMIT("vtrn.32         q2, q3")
1532             __ASM_EMIT("vswp            d1, d4")
1533             __ASM_EMIT("vswp            d3, d6")
1534 
1535             __ASM_EMIT("vswp            q1, q2")
1536             RGBA_TO_HSLA_CORE
1537             __ASM_EMIT("vswp            q1, q2")
1538 
1539             __ASM_EMIT("vtrn.32         q0, q1")
1540             __ASM_EMIT("vtrn.32         q2, q3")
1541             __ASM_EMIT("vswp            d1, d4")
1542             __ASM_EMIT("vswp            d3, d6")
1543 
1544             __ASM_EMIT("tst             %[count], $2")
1545             __ASM_EMIT("beq             8f")
1546             __ASM_EMIT("vst1.32         {q0-q1}, [%[dst]]!")
1547             __ASM_EMIT("8:")
1548             __ASM_EMIT("tst             %[count], $1")
1549             __ASM_EMIT("beq             10f")
1550             __ASM_EMIT("vst1.32         {q2}, [%[dst]]")
1551 
1552             __ASM_EMIT("10:")
1553 
1554             : [dst] "+r" (dst), [src] "+r" (src), [count] "+r" (count)
1555             : [XC] "r" (&RGB_HSL[0]), [RGBA] "r" (&rgba)
1556             : "cc", "memory",
1557               "q0", "q1", "q2", "q3",
1558               "q4", "q5", "q6", "q7",
1559               "q8", "q9", "q10", "q11",
1560               "q12", "q13", "q14", "q15"
1561         );
1562     }
1563 
1564 #undef RGBA_TO_HSLA_CORE
1565 
1566 #define RGBA_TO_BGRA32_CORE_X8 \
1567     /* Transpose */ \
1568     __ASM_EMIT("vtrn.32         q0, q1") \
1569     __ASM_EMIT("vtrn.32         q2, q3") \
1570     __ASM_EMIT("vtrn.32         q4, q5") \
1571     __ASM_EMIT("vtrn.32         q6, q7") \
1572     __ASM_EMIT("vswp            d4, d1") \
1573     __ASM_EMIT("vswp            d12, d9") \
1574     __ASM_EMIT("vswp            d6, d3") \
1575     __ASM_EMIT("vswp            d14, d11") \
1576     \
1577     /* q0 = r, q1 = g, q2 = b, q3 = a */ \
1578     __ASM_EMIT("vswp            q0, q2")                        /* q0   = b, q2 = r */ \
1579     __ASM_EMIT("vswp            q4, q6") \
1580     __ASM_EMIT("vmul.f32        q8, q3, q14")                   /* q8   = a * 255 */ \
1581     __ASM_EMIT("vmul.f32        q9, q7, q15") \
1582     __ASM_EMIT("vsub.f32        q3, q14, q8")                   /* q3   = A = 255 - a*255 * */ \
1583     __ASM_EMIT("vsub.f32        q7, q15, q9") \
1584     __ASM_EMIT("veor            q12, q12")                      /* q12  = 0 */ \
1585     __ASM_EMIT("veor            q13, q13") \
1586     __ASM_EMIT("vmul.f32        q0, q0, q3")                    /* q0   = B = b * A */ \
1587     __ASM_EMIT("vmul.f32        q4, q4, q7") \
1588     __ASM_EMIT("vmul.f32        q1, q1, q3")                    /* q1   = G = g * A */ \
1589     __ASM_EMIT("vmul.f32        q5, q5, q7") \
1590     __ASM_EMIT("vmul.f32        q2, q2, q3")                    /* q2   = R = r * A */ \
1591     __ASM_EMIT("vmul.f32        q6, q6, q7") \
1592     __ASM_EMIT("vcge.f32        q8, q0, q12")                   /* q8   = [B >= 0] */ \
1593     __ASM_EMIT("vcge.f32        q9, q4, q13") \
1594     __ASM_EMIT("vcge.f32        q10, q1, q12")                  /* q10  = [G >= 0] */ \
1595     __ASM_EMIT("vcge.f32        q11, q5, q13") \
1596     __ASM_EMIT("vcge.f32        q12, q2, q12")                  /* q11  = [R >= 0] */ \
1597     __ASM_EMIT("vcge.f32        q13, q6, q13") \
1598     __ASM_EMIT("vand            q0, q0, q8")                    /* q0   = B & [B >= 0] */ \
1599     __ASM_EMIT("vand            q4, q4, q9") \
1600     __ASM_EMIT("vand            q1, q1, q10")                   /* q1   = G & [G >= 0] */ \
1601     __ASM_EMIT("vand            q5, q5, q11") \
1602     __ASM_EMIT("vand            q2, q2, q12")                   /* q2   = R & [R >= 0] */ \
1603     __ASM_EMIT("vand            q6, q6, q13") \
1604     \
1605     /* Transpose back */ \
1606     __ASM_EMIT("vtrn.32         q0, q1") \
1607     __ASM_EMIT("vtrn.32         q2, q3") \
1608     __ASM_EMIT("vtrn.32         q4, q5") \
1609     __ASM_EMIT("vtrn.32         q6, q7") \
1610     __ASM_EMIT("vswp            d4, d1") \
1611     __ASM_EMIT("vswp            d12, d9") \
1612     __ASM_EMIT("vswp            d6, d3") \
1613     __ASM_EMIT("vswp            d14, d11") \
1614     /* q0     = b0 g0 r0 a0 */ \
1615     /* q1     = b1 g1 r1 a1 */ \
1616     /* q2     = b2 g2 r2 a2 */ \
1617     /* q3     = b3 g3 r3 a3 */ \
1618     \
1619     __ASM_EMIT("vcvt.u32.f32    q0, q0")                        /* q0 = int(b0 g0 r0 a0) */ \
1620     __ASM_EMIT("vcvt.u32.f32    q4, q4") \
1621     __ASM_EMIT("vcvt.u32.f32    q1, q1")                        /* q1 = int(b1 g1 r1 a1) */ \
1622     __ASM_EMIT("vcvt.u32.f32    q5, q5") \
1623     __ASM_EMIT("vcvt.u32.f32    q2, q2")                        /* q2 = int(b2 g2 r2 a2) */ \
1624     __ASM_EMIT("vcvt.u32.f32    q6, q6") \
1625     __ASM_EMIT("vcvt.u32.f32    q3, q3")                        /* q3 = int(b3 g3 r3 a3) */ \
1626     __ASM_EMIT("vcvt.u32.f32    q7, q7") \
1627     __ASM_EMIT("vqmovn.u32      d0, q0") \
1628     __ASM_EMIT("vqmovn.u32      d1, q1") \
1629     __ASM_EMIT("vqmovn.u32      d2, q2") \
1630     __ASM_EMIT("vqmovn.u32      d3, q3") \
1631     __ASM_EMIT("vqmovn.u32      d4, q4") \
1632     __ASM_EMIT("vqmovn.u32      d5, q5") \
1633     __ASM_EMIT("vqmovn.u32      d6, q6") \
1634     __ASM_EMIT("vqmovn.u32      d7, q7") \
1635     __ASM_EMIT("vqmovn.u16      d0, q0") \
1636     __ASM_EMIT("vqmovn.u16      d1, q1") \
1637     __ASM_EMIT("vqmovn.u16      d2, q2") \
1638     __ASM_EMIT("vqmovn.u16      d3, q3")
1639 
1640 #define RGBA_TO_BGRA32_CORE_X4 \
1641     /* Transpose */ \
1642     __ASM_EMIT("vtrn.32         q0, q1") \
1643     __ASM_EMIT("vtrn.32         q2, q3") \
1644     __ASM_EMIT("vswp            d4, d1") \
1645     __ASM_EMIT("vswp            d6, d3") \
1646     \
1647     /* q0 = r, q1 = g, q2 = b, q3 = a */ \
1648     __ASM_EMIT("vswp            q0, q2")                        /* q0   = b, q2 = r */ \
1649     __ASM_EMIT("vmul.f32        q8, q3, q14")                   /* q8   = a * 255 */ \
1650     __ASM_EMIT("vsub.f32        q3, q14, q8")                   /* q3   = A = 255 - a*255 * */ \
1651     __ASM_EMIT("veor            q12, q12")                      /* q12  = 0 */ \
1652     __ASM_EMIT("vmul.f32        q0, q0, q3")                    /* q0   = B = b * A */ \
1653     __ASM_EMIT("vmul.f32        q1, q1, q3")                    /* q1   = G = g * A */ \
1654     __ASM_EMIT("vmul.f32        q2, q2, q3")                    /* q2   = R = r * A */ \
1655     __ASM_EMIT("vcge.f32        q8, q0, q12")                   /* q8   = [B >= 0] */ \
1656     __ASM_EMIT("vcge.f32        q10, q1, q12")                  /* q10  = [G >= 0] */ \
1657     __ASM_EMIT("vcge.f32        q12, q2, q12")                  /* q11  = [R >= 0] */ \
1658     __ASM_EMIT("vand            q0, q0, q8")                    /* q0   = B & [B >= 0] */ \
1659     __ASM_EMIT("vand            q1, q1, q10")                   /* q1   = G & [G >= 0] */ \
1660     __ASM_EMIT("vand            q2, q2, q12")                   /* q2   = R & [R >= 0] */ \
1661     \
1662     /* Transpose back */ \
1663     __ASM_EMIT("vtrn.32         q0, q1") \
1664     __ASM_EMIT("vtrn.32         q2, q3") \
1665     __ASM_EMIT("vswp            d4, d1") \
1666     __ASM_EMIT("vswp            d6, d3") \
1667     /* q0     = b0 g0 r0 a0 */ \
1668     /* q1     = b1 g1 r1 a1 */ \
1669     /* q2     = b2 g2 r2 a2 */ \
1670     /* q3     = b3 g3 r3 a3 */ \
1671     \
1672     __ASM_EMIT("vcvt.u32.f32    q0, q0")                        /* q0 = int(b0 g0 r0 a0) */ \
1673     __ASM_EMIT("vcvt.u32.f32    q1, q1")                        /* q1 = int(b1 g1 r1 a1) */ \
1674     __ASM_EMIT("vcvt.u32.f32    q2, q2")                        /* q2 = int(b2 g2 r2 a2) */ \
1675     __ASM_EMIT("vcvt.u32.f32    q3, q3")                        /* q3 = int(b3 g3 r3 a3) */ \
1676     __ASM_EMIT("vqmovn.u32      d0, q0") \
1677     __ASM_EMIT("vqmovn.u32      d1, q1") \
1678     __ASM_EMIT("vqmovn.u32      d2, q2") \
1679     __ASM_EMIT("vqmovn.u32      d3, q3") \
1680     __ASM_EMIT("vqmovn.u16      d0, q0") \
1681     __ASM_EMIT("vqmovn.u16      d1, q1")
1682 
rgba_to_bgra32(void * dst,const float * src,size_t count)1683     void rgba_to_bgra32(void *dst, const float *src, size_t count)
1684     {
1685         IF_ARCH_ARM( uint32_t fpscr, b_fpscr; )
1686 
1687         ARCH_ARM_ASM
1688         (
1689             // Set-up rounding mode
1690             __ASM_EMIT("vmsr            FPSCR, %[bfp]")
1691             __ASM_EMIT("orr             %[fp], %[bfp], $0xc00000")
1692             __ASM_EMIT("vmrs            %[fp], FPSCR")
1693 
1694             __ASM_EMIT("vld1.32         {q14-q15}, [%[XC]]")
1695             __ASM_EMIT("subs            %[count], $8")
1696             __ASM_EMIT("blo             2f")
1697 
1698             //-----------------------------------------------------------------
1699             // 8x blocks
1700             __ASM_EMIT("1:")
1701             __ASM_EMIT("vldm            %[src]!, {q0-q7}")
1702             RGBA_TO_BGRA32_CORE_X8
1703             __ASM_EMIT("subs            %[count], $8")
1704             __ASM_EMIT("vstm            %[dst]!, {q0-q1}")
1705             __ASM_EMIT("bhs             1b")
1706 
1707             __ASM_EMIT("2:")
1708             __ASM_EMIT("adds            %[count], $4")
1709             __ASM_EMIT("blt             4f")
1710 
1711             //-----------------------------------------------------------------
1712             // 4x blocks
1713             __ASM_EMIT("vldm            %[src]!, {q0-q3}")
1714             RGBA_TO_BGRA32_CORE_X4
1715             __ASM_EMIT("sub             %[count], $4")
1716             __ASM_EMIT("vstm            %[dst]!, {q0}")
1717 
1718             __ASM_EMIT("4:")
1719             __ASM_EMIT("adds            %[count], $4")
1720             __ASM_EMIT("bls             12f")
1721 
1722             //-----------------------------------------------------------------
1723             // 1x-3x block
1724             __ASM_EMIT("tst             %[count], $2")
1725             __ASM_EMIT("beq             6f")
1726             __ASM_EMIT("vld1.32         {q0-q1}, [%[src]]!")
1727             __ASM_EMIT("6:")
1728             __ASM_EMIT("tst             %[count], $1")
1729             __ASM_EMIT("beq             8f")
1730             __ASM_EMIT("vld1.32         {q2}, [%[src]]")
1731             __ASM_EMIT("8:")
1732             RGBA_TO_BGRA32_CORE_X4
1733             __ASM_EMIT("tst             %[count], $2")
1734             __ASM_EMIT("beq             10f")
1735             __ASM_EMIT("vst1.32         {d0}, [%[dst]]!")
1736             __ASM_EMIT("10:")
1737             __ASM_EMIT("tst             %[count], $1")
1738             __ASM_EMIT("beq             12f")
1739             __ASM_EMIT("vstm            %[dst], {s2}")
1740 
1741             __ASM_EMIT("12:")
1742 
1743             // Restore rounding mode
1744             __ASM_EMIT("vmrs            %[bfp], FPSCR")
1745 
1746             : [dst] "+r" (dst), [src] "+r" (src), [count] "+r" (count),
1747               [fp] "=&r" (fpscr), [bfp] "=&r" (b_fpscr)
1748             : [XC] "r" (&RGBA_TO_BGRA32[0])
1749             : "cc", "memory",
1750               "q0", "q1", "q2", "q3",
1751               "q4", "q5", "q6", "q7",
1752               "q8", "q9", "q10", "q11",
1753               "q12", "q13", "q14", "q15"
1754         );
1755     }
1756 
1757 #undef RGBA_TO_BGRA32_CORE_X8
1758 #undef RGBA_TO_BGRA32_CORE_X4
1759 
1760 }
1761 
1762 
1763 #endif /* DSP_ARCH_ARM_NEON_D32_GRAPHICS_H_ */
1764