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