- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / libwebp / dsp / enc_neon.c
1 // Copyright 2012 Google Inc. All Rights Reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the COPYING file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8 // -----------------------------------------------------------------------------
9 //
10 // ARM NEON version of speed-critical encoding functions.
11 //
12 // adapted from libvpx (http://www.webmproject.org/code/)
13
14 #include "./dsp.h"
15
16 #if defined(__cplusplus) || defined(c_plusplus)
17 extern "C" {
18 #endif
19
20 #if defined(WEBP_USE_NEON)
21
22 #include "../enc/vp8enci.h"
23
24 //------------------------------------------------------------------------------
25 // Transforms (Paragraph 14.4)
26
27 // Inverse transform.
28 // This code is pretty much the same as TransformOneNEON in the decoder, except
29 // for subtraction to *ref. See the comments there for algorithmic explanations.
30 static void ITransformOne(const uint8_t* ref,
31                           const int16_t* in, uint8_t* dst) {
32   const int kBPS = BPS;
33   const int16_t kC1C2[] = { 20091, 17734, 0, 0 };  // kC1 / (kC2 >> 1) / 0 / 0
34
35   __asm__ volatile (
36     "vld1.16         {q1, q2}, [%[in]]           \n"
37     "vld1.16         {d0}, [%[kC1C2]]            \n"
38
39     // d2: in[0]
40     // d3: in[8]
41     // d4: in[4]
42     // d5: in[12]
43     "vswp            d3, d4                      \n"
44
45     // q8 = {in[4], in[12]} * kC1 * 2 >> 16
46     // q9 = {in[4], in[12]} * kC2 >> 16
47     "vqdmulh.s16     q8, q2, d0[0]               \n"
48     "vqdmulh.s16     q9, q2, d0[1]               \n"
49
50     // d22 = a = in[0] + in[8]
51     // d23 = b = in[0] - in[8]
52     "vqadd.s16       d22, d2, d3                 \n"
53     "vqsub.s16       d23, d2, d3                 \n"
54
55     //  q8 = in[4]/[12] * kC1 >> 16
56     "vshr.s16        q8, q8, #1                  \n"
57
58     // Add {in[4], in[12]} back after the multiplication.
59     "vqadd.s16       q8, q2, q8                  \n"
60
61     // d20 = c = in[4]*kC2 - in[12]*kC1
62     // d21 = d = in[4]*kC1 + in[12]*kC2
63     "vqsub.s16       d20, d18, d17               \n"
64     "vqadd.s16       d21, d19, d16               \n"
65
66     // d2 = tmp[0] = a + d
67     // d3 = tmp[1] = b + c
68     // d4 = tmp[2] = b - c
69     // d5 = tmp[3] = a - d
70     "vqadd.s16       d2, d22, d21                \n"
71     "vqadd.s16       d3, d23, d20                \n"
72     "vqsub.s16       d4, d23, d20                \n"
73     "vqsub.s16       d5, d22, d21                \n"
74
75     "vzip.16         q1, q2                      \n"
76     "vzip.16         q1, q2                      \n"
77
78     "vswp            d3, d4                      \n"
79
80     // q8 = {tmp[4], tmp[12]} * kC1 * 2 >> 16
81     // q9 = {tmp[4], tmp[12]} * kC2 >> 16
82     "vqdmulh.s16     q8, q2, d0[0]               \n"
83     "vqdmulh.s16     q9, q2, d0[1]               \n"
84
85     // d22 = a = tmp[0] + tmp[8]
86     // d23 = b = tmp[0] - tmp[8]
87     "vqadd.s16       d22, d2, d3                 \n"
88     "vqsub.s16       d23, d2, d3                 \n"
89
90     "vshr.s16        q8, q8, #1                  \n"
91     "vqadd.s16       q8, q2, q8                  \n"
92
93     // d20 = c = in[4]*kC2 - in[12]*kC1
94     // d21 = d = in[4]*kC1 + in[12]*kC2
95     "vqsub.s16       d20, d18, d17               \n"
96     "vqadd.s16       d21, d19, d16               \n"
97
98     // d2 = tmp[0] = a + d
99     // d3 = tmp[1] = b + c
100     // d4 = tmp[2] = b - c
101     // d5 = tmp[3] = a - d
102     "vqadd.s16       d2, d22, d21                \n"
103     "vqadd.s16       d3, d23, d20                \n"
104     "vqsub.s16       d4, d23, d20                \n"
105     "vqsub.s16       d5, d22, d21                \n"
106
107     "vld1.32         d6[0], [%[ref]], %[kBPS]    \n"
108     "vld1.32         d6[1], [%[ref]], %[kBPS]    \n"
109     "vld1.32         d7[0], [%[ref]], %[kBPS]    \n"
110     "vld1.32         d7[1], [%[ref]], %[kBPS]    \n"
111
112     "sub         %[ref], %[ref], %[kBPS], lsl #2 \n"
113
114     // (val) + 4 >> 3
115     "vrshr.s16       d2, d2, #3                  \n"
116     "vrshr.s16       d3, d3, #3                  \n"
117     "vrshr.s16       d4, d4, #3                  \n"
118     "vrshr.s16       d5, d5, #3                  \n"
119
120     "vzip.16         q1, q2                      \n"
121     "vzip.16         q1, q2                      \n"
122
123     // Must accumulate before saturating
124     "vmovl.u8        q8, d6                      \n"
125     "vmovl.u8        q9, d7                      \n"
126
127     "vqadd.s16       q1, q1, q8                  \n"
128     "vqadd.s16       q2, q2, q9                  \n"
129
130     "vqmovun.s16     d0, q1                      \n"
131     "vqmovun.s16     d1, q2                      \n"
132
133     "vst1.32         d0[0], [%[dst]], %[kBPS]    \n"
134     "vst1.32         d0[1], [%[dst]], %[kBPS]    \n"
135     "vst1.32         d1[0], [%[dst]], %[kBPS]    \n"
136     "vst1.32         d1[1], [%[dst]]             \n"
137
138     : [in] "+r"(in), [dst] "+r"(dst)               // modified registers
139     : [kBPS] "r"(kBPS), [kC1C2] "r"(kC1C2), [ref] "r"(ref)  // constants
140     : "memory", "q0", "q1", "q2", "q8", "q9", "q10", "q11"  // clobbered
141   );
142 }
143
144 static void ITransform(const uint8_t* ref,
145                        const int16_t* in, uint8_t* dst, int do_two) {
146   ITransformOne(ref, in, dst);
147   if (do_two) {
148     ITransformOne(ref + 4, in + 16, dst + 4);
149   }
150 }
151
152 // Same code as dec_neon.c
153 static void ITransformWHT(const int16_t* in, int16_t* out) {
154   const int kStep = 32;  // The store is only incrementing the pointer as if we
155                          // had stored a single byte.
156   __asm__ volatile (
157     // part 1
158     // load data into q0, q1
159     "vld1.16         {q0, q1}, [%[in]]           \n"
160
161     "vaddl.s16       q2, d0, d3                  \n" // a0 = in[0] + in[12]
162     "vaddl.s16       q3, d1, d2                  \n" // a1 = in[4] + in[8]
163     "vsubl.s16       q4, d1, d2                  \n" // a2 = in[4] - in[8]
164     "vsubl.s16       q5, d0, d3                  \n" // a3 = in[0] - in[12]
165
166     "vadd.s32        q0, q2, q3                  \n" // tmp[0] = a0 + a1
167     "vsub.s32        q2, q2, q3                  \n" // tmp[8] = a0 - a1
168     "vadd.s32        q1, q5, q4                  \n" // tmp[4] = a3 + a2
169     "vsub.s32        q3, q5, q4                  \n" // tmp[12] = a3 - a2
170
171     // Transpose
172     // q0 = tmp[0, 4, 8, 12], q1 = tmp[2, 6, 10, 14]
173     // q2 = tmp[1, 5, 9, 13], q3 = tmp[3, 7, 11, 15]
174     "vswp            d1, d4                      \n" // vtrn.64 q0, q2
175     "vswp            d3, d6                      \n" // vtrn.64 q1, q3
176     "vtrn.32         q0, q1                      \n"
177     "vtrn.32         q2, q3                      \n"
178
179     "vmov.s32        q4, #3                      \n" // dc = 3
180     "vadd.s32        q0, q0, q4                  \n" // dc = tmp[0] + 3
181     "vadd.s32        q6, q0, q3                  \n" // a0 = dc + tmp[3]
182     "vadd.s32        q7, q1, q2                  \n" // a1 = tmp[1] + tmp[2]
183     "vsub.s32        q8, q1, q2                  \n" // a2 = tmp[1] - tmp[2]
184     "vsub.s32        q9, q0, q3                  \n" // a3 = dc - tmp[3]
185
186     "vadd.s32        q0, q6, q7                  \n"
187     "vshrn.s32       d0, q0, #3                  \n" // (a0 + a1) >> 3
188     "vadd.s32        q1, q9, q8                  \n"
189     "vshrn.s32       d1, q1, #3                  \n" // (a3 + a2) >> 3
190     "vsub.s32        q2, q6, q7                  \n"
191     "vshrn.s32       d2, q2, #3                  \n" // (a0 - a1) >> 3
192     "vsub.s32        q3, q9, q8                  \n"
193     "vshrn.s32       d3, q3, #3                  \n" // (a3 - a2) >> 3
194
195     // set the results to output
196     "vst1.16         d0[0], [%[out]], %[kStep]      \n"
197     "vst1.16         d1[0], [%[out]], %[kStep]      \n"
198     "vst1.16         d2[0], [%[out]], %[kStep]      \n"
199     "vst1.16         d3[0], [%[out]], %[kStep]      \n"
200     "vst1.16         d0[1], [%[out]], %[kStep]      \n"
201     "vst1.16         d1[1], [%[out]], %[kStep]      \n"
202     "vst1.16         d2[1], [%[out]], %[kStep]      \n"
203     "vst1.16         d3[1], [%[out]], %[kStep]      \n"
204     "vst1.16         d0[2], [%[out]], %[kStep]      \n"
205     "vst1.16         d1[2], [%[out]], %[kStep]      \n"
206     "vst1.16         d2[2], [%[out]], %[kStep]      \n"
207     "vst1.16         d3[2], [%[out]], %[kStep]      \n"
208     "vst1.16         d0[3], [%[out]], %[kStep]      \n"
209     "vst1.16         d1[3], [%[out]], %[kStep]      \n"
210     "vst1.16         d2[3], [%[out]], %[kStep]      \n"
211     "vst1.16         d3[3], [%[out]], %[kStep]      \n"
212
213     : [out] "+r"(out)  // modified registers
214     : [in] "r"(in), [kStep] "r"(kStep)  // constants
215     : "memory", "q0", "q1", "q2", "q3", "q4",
216       "q5", "q6", "q7", "q8", "q9" // clobbered
217   );
218 }
219
220 // Forward transform.
221
222 // adapted from vp8/encoder/arm/neon/shortfdct_neon.asm
223 static const int16_t kCoeff16[] = {
224   5352,  5352,  5352, 5352, 2217,  2217,  2217, 2217
225 };
226 static const int32_t kCoeff32[] = {
227    1812,  1812,  1812,  1812,
228     937,   937,   937,   937,
229   12000, 12000, 12000, 12000,
230   51000, 51000, 51000, 51000
231 };
232
233 static void FTransform(const uint8_t* src, const uint8_t* ref,
234                        int16_t* out) {
235   const int kBPS = BPS;
236   const uint8_t* src_ptr = src;
237   const uint8_t* ref_ptr = ref;
238   const int16_t* coeff16 = kCoeff16;
239   const int32_t* coeff32 = kCoeff32;
240
241   __asm__ volatile (
242     // load src into q4, q5 in high half
243     "vld1.8 {d8},  [%[src_ptr]], %[kBPS]      \n"
244     "vld1.8 {d10}, [%[src_ptr]], %[kBPS]      \n"
245     "vld1.8 {d9},  [%[src_ptr]], %[kBPS]      \n"
246     "vld1.8 {d11}, [%[src_ptr]]               \n"
247
248     // load ref into q6, q7 in high half
249     "vld1.8 {d12}, [%[ref_ptr]], %[kBPS]      \n"
250     "vld1.8 {d14}, [%[ref_ptr]], %[kBPS]      \n"
251     "vld1.8 {d13}, [%[ref_ptr]], %[kBPS]      \n"
252     "vld1.8 {d15}, [%[ref_ptr]]               \n"
253
254     // Pack the high values in to q4 and q6
255     "vtrn.32     q4, q5                       \n"
256     "vtrn.32     q6, q7                       \n"
257
258     // d[0-3] = src - ref
259     "vsubl.u8    q0, d8, d12                  \n"
260     "vsubl.u8    q1, d9, d13                  \n"
261
262     // load coeff16 into q8(d16=5352, d17=2217)
263     "vld1.16     {q8}, [%[coeff16]]           \n"
264
265     // load coeff32 high half into q9 = 1812, q10 = 937
266     "vld1.32     {q9, q10}, [%[coeff32]]!     \n"
267
268     // load coeff32 low half into q11=12000, q12=51000
269     "vld1.32     {q11,q12}, [%[coeff32]]      \n"
270
271     // part 1
272     // Transpose. Register dN is the same as dN in C
273     "vtrn.32         d0, d2                   \n"
274     "vtrn.32         d1, d3                   \n"
275     "vtrn.16         d0, d1                   \n"
276     "vtrn.16         d2, d3                   \n"
277
278     "vadd.s16        d4, d0, d3               \n" // a0 = d0 + d3
279     "vadd.s16        d5, d1, d2               \n" // a1 = d1 + d2
280     "vsub.s16        d6, d1, d2               \n" // a2 = d1 - d2
281     "vsub.s16        d7, d0, d3               \n" // a3 = d0 - d3
282
283     "vadd.s16        d0, d4, d5               \n" // a0 + a1
284     "vshl.s16        d0, d0, #3               \n" // temp[0+i*4] = (a0+a1) << 3
285     "vsub.s16        d2, d4, d5               \n" // a0 - a1
286     "vshl.s16        d2, d2, #3               \n" // (temp[2+i*4] = (a0-a1) << 3
287
288     "vmlal.s16       q9, d7, d16              \n" // a3*5352 + 1812
289     "vmlal.s16       q10, d7, d17             \n" // a3*2217 + 937
290     "vmlal.s16       q9, d6, d17              \n" // a2*2217 + a3*5352 + 1812
291     "vmlsl.s16       q10, d6, d16             \n" // a3*2217 + 937 - a2*5352
292
293     // temp[1+i*4] = (d2*2217 + d3*5352 + 1812) >> 9
294     // temp[3+i*4] = (d3*2217 + 937 - d2*5352) >> 9
295     "vshrn.s32       d1, q9, #9               \n"
296     "vshrn.s32       d3, q10, #9              \n"
297
298     // part 2
299     // transpose d0=ip[0], d1=ip[4], d2=ip[8], d3=ip[12]
300     "vtrn.32         d0, d2                   \n"
301     "vtrn.32         d1, d3                   \n"
302     "vtrn.16         d0, d1                   \n"
303     "vtrn.16         d2, d3                   \n"
304
305     "vmov.s16        d26, #7                  \n"
306
307     "vadd.s16        d4, d0, d3               \n" // a1 = ip[0] + ip[12]
308     "vadd.s16        d5, d1, d2               \n" // b1 = ip[4] + ip[8]
309     "vsub.s16        d6, d1, d2               \n" // c1 = ip[4] - ip[8]
310     "vadd.s16        d4, d4, d26              \n" // a1 + 7
311     "vsub.s16        d7, d0, d3               \n" // d1 = ip[0] - ip[12]
312
313     "vadd.s16        d0, d4, d5               \n" // op[0] = a1 + b1 + 7
314     "vsub.s16        d2, d4, d5               \n" // op[8] = a1 - b1 + 7
315
316     "vmlal.s16       q11, d7, d16             \n" // d1*5352 + 12000
317     "vmlal.s16       q12, d7, d17             \n" // d1*2217 + 51000
318
319     "vceq.s16        d4, d7, #0               \n"
320
321     "vshr.s16        d0, d0, #4               \n"
322     "vshr.s16        d2, d2, #4               \n"
323
324     "vmlal.s16       q11, d6, d17             \n" // c1*2217 + d1*5352 + 12000
325     "vmlsl.s16       q12, d6, d16             \n" // d1*2217 - c1*5352 + 51000
326
327     "vmvn            d4, d4                   \n" // !(d1 == 0)
328     // op[4] = (c1*2217 + d1*5352 + 12000)>>16
329     "vshrn.s32       d1, q11, #16             \n"
330     // op[4] += (d1!=0)
331     "vsub.s16        d1, d1, d4               \n"
332     // op[12]= (d1*2217 - c1*5352 + 51000)>>16
333     "vshrn.s32       d3, q12, #16             \n"
334
335     // set result to out array
336     "vst1.16         {q0, q1}, [%[out]]   \n"
337     : [src_ptr] "+r"(src_ptr), [ref_ptr] "+r"(ref_ptr),
338       [coeff32] "+r"(coeff32)          // modified registers
339     : [kBPS] "r"(kBPS), [coeff16] "r"(coeff16),
340       [out] "r"(out)                   // constants
341     : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9",
342       "q10", "q11", "q12", "q13"       // clobbered
343   );
344 }
345
346 static void FTransformWHT(const int16_t* in, int16_t* out) {
347   const int kStep = 32;
348   __asm__ volatile (
349     // d0 = in[0 * 16] , d1 = in[1 * 16]
350     // d2 = in[2 * 16] , d3 = in[3 * 16]
351     "vld1.16         d0[0], [%[in]], %[kStep]   \n"
352     "vld1.16         d1[0], [%[in]], %[kStep]   \n"
353     "vld1.16         d2[0], [%[in]], %[kStep]   \n"
354     "vld1.16         d3[0], [%[in]], %[kStep]   \n"
355     "vld1.16         d0[1], [%[in]], %[kStep]   \n"
356     "vld1.16         d1[1], [%[in]], %[kStep]   \n"
357     "vld1.16         d2[1], [%[in]], %[kStep]   \n"
358     "vld1.16         d3[1], [%[in]], %[kStep]   \n"
359     "vld1.16         d0[2], [%[in]], %[kStep]   \n"
360     "vld1.16         d1[2], [%[in]], %[kStep]   \n"
361     "vld1.16         d2[2], [%[in]], %[kStep]   \n"
362     "vld1.16         d3[2], [%[in]], %[kStep]   \n"
363     "vld1.16         d0[3], [%[in]], %[kStep]   \n"
364     "vld1.16         d1[3], [%[in]], %[kStep]   \n"
365     "vld1.16         d2[3], [%[in]], %[kStep]   \n"
366     "vld1.16         d3[3], [%[in]], %[kStep]   \n"
367
368     "vaddl.s16       q2, d0, d2                 \n" // a0=(in[0*16]+in[2*16])
369     "vaddl.s16       q3, d1, d3                 \n" // a1=(in[1*16]+in[3*16])
370     "vsubl.s16       q4, d1, d3                 \n" // a2=(in[1*16]-in[3*16])
371     "vsubl.s16       q5, d0, d2                 \n" // a3=(in[0*16]-in[2*16])
372
373     "vqadd.s32       q6, q2, q3                 \n" // a0 + a1
374     "vqadd.s32       q7, q5, q4                 \n" // a3 + a2
375     "vqsub.s32       q8, q5, q4                 \n" // a3 - a2
376     "vqsub.s32       q9, q2, q3                 \n" // a0 - a1
377
378     // Transpose
379     // q6 = tmp[0, 1,  2,  3] ; q7 = tmp[ 4,  5,  6,  7]
380     // q8 = tmp[8, 9, 10, 11] ; q9 = tmp[12, 13, 14, 15]
381     "vswp            d13, d16                   \n" // vtrn.64 q0, q2
382     "vswp            d15, d18                   \n" // vtrn.64 q1, q3
383     "vtrn.32         q6, q7                     \n"
384     "vtrn.32         q8, q9                     \n"
385
386     "vqadd.s32       q0, q6, q8                 \n" // a0 = tmp[0] + tmp[8]
387     "vqadd.s32       q1, q7, q9                 \n" // a1 = tmp[4] + tmp[12]
388     "vqsub.s32       q2, q7, q9                 \n" // a2 = tmp[4] - tmp[12]
389     "vqsub.s32       q3, q6, q8                 \n" // a3 = tmp[0] - tmp[8]
390
391     "vqadd.s32       q4, q0, q1                 \n" // b0 = a0 + a1
392     "vqadd.s32       q5, q3, q2                 \n" // b1 = a3 + a2
393     "vqsub.s32       q6, q3, q2                 \n" // b2 = a3 - a2
394     "vqsub.s32       q7, q0, q1                 \n" // b3 = a0 - a1
395
396     "vshrn.s32       d18, q4, #1                \n" // b0 >> 1
397     "vshrn.s32       d19, q5, #1                \n" // b1 >> 1
398     "vshrn.s32       d20, q6, #1                \n" // b2 >> 1
399     "vshrn.s32       d21, q7, #1                \n" // b3 >> 1
400
401     "vst1.16         {q9, q10}, [%[out]]        \n"
402
403     : [in] "+r"(in)
404     : [kStep] "r"(kStep), [out] "r"(out)
405     : "memory", "q0", "q1", "q2", "q3", "q4", "q5",
406       "q6", "q7", "q8", "q9", "q10"       // clobbered
407   ) ;
408 }
409
410 //------------------------------------------------------------------------------
411 // Texture distortion
412 //
413 // We try to match the spectral content (weighted) between source and
414 // reconstructed samples.
415
416 // Hadamard transform
417 // Returns the weighted sum of the absolute value of transformed coefficients.
418 // This uses a TTransform helper function in C
419 static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
420                     const uint16_t* const w) {
421   const int kBPS = BPS;
422   const uint8_t* A = a;
423   const uint8_t* B = b;
424   const uint16_t* W = w;
425   int sum;
426   __asm__ volatile (
427     "vld1.32         d0[0], [%[a]], %[kBPS]   \n"
428     "vld1.32         d0[1], [%[a]], %[kBPS]   \n"
429     "vld1.32         d2[0], [%[a]], %[kBPS]   \n"
430     "vld1.32         d2[1], [%[a]]            \n"
431
432     "vld1.32         d1[0], [%[b]], %[kBPS]   \n"
433     "vld1.32         d1[1], [%[b]], %[kBPS]   \n"
434     "vld1.32         d3[0], [%[b]], %[kBPS]   \n"
435     "vld1.32         d3[1], [%[b]]            \n"
436
437     // a d0/d2, b d1/d3
438     // d0/d1: 01 01 01 01
439     // d2/d3: 23 23 23 23
440     // But: it goes 01 45 23 67
441     // Notice the middle values are transposed
442     "vtrn.16         q0, q1                   \n"
443
444     // {a0, a1} = {in[0] + in[2], in[1] + in[3]}
445     "vaddl.u8        q2, d0, d2               \n"
446     "vaddl.u8        q10, d1, d3              \n"
447     // {a3, a2} = {in[0] - in[2], in[1] - in[3]}
448     "vsubl.u8        q3, d0, d2               \n"
449     "vsubl.u8        q11, d1, d3              \n"
450
451     // tmp[0] = a0 + a1
452     "vpaddl.s16      q0, q2                   \n"
453     "vpaddl.s16      q8, q10                  \n"
454
455     // tmp[1] = a3 + a2
456     "vpaddl.s16      q1, q3                   \n"
457     "vpaddl.s16      q9, q11                  \n"
458
459     // No pair subtract
460     // q2 = {a0, a3}
461     // q3 = {a1, a2}
462     "vtrn.16         q2, q3                   \n"
463     "vtrn.16         q10, q11                 \n"
464
465     // {tmp[3], tmp[2]} = {a0 - a1, a3 - a2}
466     "vsubl.s16       q12, d4, d6              \n"
467     "vsubl.s16       q13, d5, d7              \n"
468     "vsubl.s16       q14, d20, d22            \n"
469     "vsubl.s16       q15, d21, d23            \n"
470
471     // separate tmp[3] and tmp[2]
472     // q12 = tmp[3]
473     // q13 = tmp[2]
474     "vtrn.32         q12, q13                 \n"
475     "vtrn.32         q14, q15                 \n"
476
477     // Transpose tmp for a
478     "vswp            d1, d26                  \n" // vtrn.64
479     "vswp            d3, d24                  \n" // vtrn.64
480     "vtrn.32         q0, q1                   \n"
481     "vtrn.32         q13, q12                 \n"
482
483     // Transpose tmp for b
484     "vswp            d17, d30                 \n" // vtrn.64
485     "vswp            d19, d28                 \n" // vtrn.64
486     "vtrn.32         q8, q9                   \n"
487     "vtrn.32         q15, q14                 \n"
488
489     // The first Q register is a, the second b.
490     // q0/8 tmp[0-3]
491     // q13/15 tmp[4-7]
492     // q1/9 tmp[8-11]
493     // q12/14 tmp[12-15]
494
495     // These are still in 01 45 23 67 order. We fix it easily in the addition
496     // case but the subtraction propegates them.
497     "vswp            d3, d27                  \n"
498     "vswp            d19, d31                 \n"
499
500     // a0 = tmp[0] + tmp[8]
501     "vadd.s32        q2, q0, q1               \n"
502     "vadd.s32        q3, q8, q9               \n"
503
504     // a1 = tmp[4] + tmp[12]
505     "vadd.s32        q10, q13, q12            \n"
506     "vadd.s32        q11, q15, q14            \n"
507
508     // a2 = tmp[4] - tmp[12]
509     "vsub.s32        q13, q13, q12            \n"
510     "vsub.s32        q15, q15, q14            \n"
511
512     // a3 = tmp[0] - tmp[8]
513     "vsub.s32        q0, q0, q1               \n"
514     "vsub.s32        q8, q8, q9               \n"
515
516     // b0 = a0 + a1
517     "vadd.s32        q1, q2, q10              \n"
518     "vadd.s32        q9, q3, q11              \n"
519
520     // b1 = a3 + a2
521     "vadd.s32        q12, q0, q13             \n"
522     "vadd.s32        q14, q8, q15             \n"
523
524     // b2 = a3 - a2
525     "vsub.s32        q0, q0, q13              \n"
526     "vsub.s32        q8, q8, q15              \n"
527
528     // b3 = a0 - a1
529     "vsub.s32        q2, q2, q10              \n"
530     "vsub.s32        q3, q3, q11              \n"
531
532     "vld1.64         {q10, q11}, [%[w]]       \n"
533
534     // abs(b0)
535     "vabs.s32        q1, q1                   \n"
536     "vabs.s32        q9, q9                   \n"
537     // abs(b1)
538     "vabs.s32        q12, q12                 \n"
539     "vabs.s32        q14, q14                 \n"
540     // abs(b2)
541     "vabs.s32        q0, q0                   \n"
542     "vabs.s32        q8, q8                   \n"
543     // abs(b3)
544     "vabs.s32        q2, q2                   \n"
545     "vabs.s32        q3, q3                   \n"
546
547     // expand w before using.
548     "vmovl.u16       q13, d20                 \n"
549     "vmovl.u16       q15, d21                 \n"
550
551     // w[0] * abs(b0)
552     "vmul.u32        q1, q1, q13              \n"
553     "vmul.u32        q9, q9, q13              \n"
554
555     // w[4] * abs(b1)
556     "vmla.u32        q1, q12, q15             \n"
557     "vmla.u32        q9, q14, q15             \n"
558
559     // expand w before using.
560     "vmovl.u16       q13, d22                 \n"
561     "vmovl.u16       q15, d23                 \n"
562
563     // w[8] * abs(b1)
564     "vmla.u32        q1, q0, q13              \n"
565     "vmla.u32        q9, q8, q13              \n"
566
567     // w[12] * abs(b1)
568     "vmla.u32        q1, q2, q15              \n"
569     "vmla.u32        q9, q3, q15              \n"
570
571     // Sum the arrays
572     "vpaddl.u32      q1, q1                   \n"
573     "vpaddl.u32      q9, q9                   \n"
574     "vadd.u64        d2, d3                   \n"
575     "vadd.u64        d18, d19                 \n"
576
577     // Hadamard transform needs 4 bits of extra precision (2 bits in each
578     // direction) for dynamic raw. Weights w[] are 16bits at max, so the maximum
579     // precision for coeff is 8bit of input + 4bits of Hadamard transform +
580     // 16bits for w[] + 2 bits of abs() summation.
581     //
582     // This uses a maximum of 31 bits (signed). Discarding the top 32 bits is
583     // A-OK.
584
585     // sum2 - sum1
586     "vsub.u32        d0, d2, d18              \n"
587     // abs(sum2 - sum1)
588     "vabs.s32        d0, d0                   \n"
589     // abs(sum2 - sum1) >> 5
590     "vshr.u32        d0, #5                   \n"
591
592     // It would be better to move the value straight into r0 but I'm not
593     // entirely sure how this works with inline assembly.
594     "vmov.32         %[sum], d0[0]            \n"
595
596     : [sum] "=r"(sum), [a] "+r"(A), [b] "+r"(B), [w] "+r"(W)
597     : [kBPS] "r"(kBPS)
598     : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9",
599       "q10", "q11", "q12", "q13", "q14", "q15"  // clobbered
600   ) ;
601
602   return sum;
603 }
604
605 static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
606                       const uint16_t* const w) {
607   int D = 0;
608   int x, y;
609   for (y = 0; y < 16 * BPS; y += 4 * BPS) {
610     for (x = 0; x < 16; x += 4) {
611       D += Disto4x4(a + x + y, b + x + y, w);
612     }
613   }
614   return D;
615 }
616
617 #endif   // WEBP_USE_NEON
618
619 //------------------------------------------------------------------------------
620 // Entry point
621
622 extern void VP8EncDspInitNEON(void);
623
624 void VP8EncDspInitNEON(void) {
625 #if defined(WEBP_USE_NEON)
626   VP8ITransform = ITransform;
627   VP8FTransform = FTransform;
628
629   VP8ITransformWHT = ITransformWHT;
630   VP8FTransformWHT = FTransformWHT;
631
632   VP8TDisto4x4 = Disto4x4;
633   VP8TDisto16x16 = Disto16x16;
634 #endif   // WEBP_USE_NEON
635 }
636
637 #if defined(__cplusplus) || defined(c_plusplus)
638 }    // extern "C"
639 #endif