2 * Copyright 2011 The LibYuv Project Authors. All rights reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
11 #include "libyuv/row.h"
12 #include "libyuv/rotate_row.h"
14 #include "libyuv/basic_types.h"
21 #if !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__) && \
24 static uvec8 kVTbl4x4Transpose =
25 { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 };
27 void TransposeWx8_NEON(const uint8* src, int src_stride,
28 uint8* dst, int dst_stride,
30 const uint8* src_temp = NULL;
32 // loops are on blocks of 8. loop will stop when
33 // counter gets to or below 0. starting the counter
34 // at w-8 allow for this
37 // handle 8x8 blocks. this should be the majority of the plane
43 "vld1.8 {d0}, [%0], %2 \n"
45 "vld1.8 {d1}, [%0], %2 \n"
47 "vld1.8 {d2}, [%0], %2 \n"
49 "vld1.8 {d3}, [%0], %2 \n"
51 "vld1.8 {d4}, [%0], %2 \n"
53 "vld1.8 {d5}, [%0], %2 \n"
55 "vld1.8 {d6}, [%0], %2 \n"
57 "vld1.8 {d7}, [%0] \n"
82 "vst1.8 {d1}, [%0], %4 \n"
84 "vst1.8 {d0}, [%0], %4 \n"
86 "vst1.8 {d3}, [%0], %4 \n"
88 "vst1.8 {d2}, [%0], %4 \n"
90 "vst1.8 {d5}, [%0], %4 \n"
92 "vst1.8 {d4}, [%0], %4 \n"
94 "vst1.8 {d7}, [%0], %4 \n"
96 "vst1.8 {d6}, [%0] \n"
98 "add %1, #8 \n" // src += 8
99 "add %3, %3, %4, lsl #3 \n" // dst += 8 * dst_stride
100 "subs %5, #8 \n" // w -= 8
103 // add 8 back to counter. if the result is 0 there are
108 // some residual, so between 1 and 7 lines left to transpose
118 "vld1.32 {d0[0]}, [%0], %2 \n"
120 "vld1.32 {d0[1]}, [%0], %2 \n"
122 "vld1.32 {d1[0]}, [%0], %2 \n"
124 "vld1.32 {d1[1]}, [%0], %2 \n"
126 "vld1.32 {d2[0]}, [%0], %2 \n"
128 "vld1.32 {d2[1]}, [%0], %2 \n"
130 "vld1.32 {d3[0]}, [%0], %2 \n"
132 "vld1.32 {d3[1]}, [%0] \n"
137 "vld1.8 {q3}, [%6] \n"
139 "vtbl.8 d4, {d0, d1}, d6 \n"
140 "vtbl.8 d5, {d0, d1}, d7 \n"
141 "vtbl.8 d0, {d2, d3}, d6 \n"
142 "vtbl.8 d1, {d2, d3}, d7 \n"
144 // TODO(frkoenig): Rework shuffle above to
145 // write out with 4 instead of 8 writes.
147 "vst1.32 {d4[0]}, [%0], %4 \n"
149 "vst1.32 {d4[1]}, [%0], %4 \n"
151 "vst1.32 {d5[0]}, [%0], %4 \n"
153 "vst1.32 {d5[1]}, [%0] \n"
157 "vst1.32 {d0[0]}, [%0], %4 \n"
159 "vst1.32 {d0[1]}, [%0], %4 \n"
161 "vst1.32 {d1[0]}, [%0], %4 \n"
163 "vst1.32 {d1[1]}, [%0] \n"
165 "add %1, #4 \n" // src += 4
166 "add %3, %3, %4, lsl #2 \n" // dst += 4 * dst_stride
167 "subs %5, #4 \n" // w -= 4
170 // some residual, check to see if it includes a 2x8 block,
179 "vld1.16 {d0[0]}, [%0], %2 \n"
181 "vld1.16 {d1[0]}, [%0], %2 \n"
183 "vld1.16 {d0[1]}, [%0], %2 \n"
185 "vld1.16 {d1[1]}, [%0], %2 \n"
187 "vld1.16 {d0[2]}, [%0], %2 \n"
189 "vld1.16 {d1[2]}, [%0], %2 \n"
191 "vld1.16 {d0[3]}, [%0], %2 \n"
193 "vld1.16 {d1[3]}, [%0] \n"
200 "vst1.64 {d0}, [%0], %4 \n"
202 "vst1.64 {d1}, [%0] \n"
204 "add %1, #2 \n" // src += 2
205 "add %3, %3, %4, lsl #1 \n" // dst += 2 * dst_stride
206 "subs %5, #2 \n" // w -= 2
212 "vld1.8 {d0[0]}, [%1], %2 \n"
214 "vld1.8 {d0[1]}, [%1], %2 \n"
216 "vld1.8 {d0[2]}, [%1], %2 \n"
218 "vld1.8 {d0[3]}, [%1], %2 \n"
220 "vld1.8 {d0[4]}, [%1], %2 \n"
222 "vld1.8 {d0[5]}, [%1], %2 \n"
224 "vld1.8 {d0[6]}, [%1], %2 \n"
226 "vld1.8 {d0[7]}, [%1] \n"
229 "vst1.64 {d0}, [%3] \n"
233 : "+r"(src_temp), // %0
235 "+r"(src_stride), // %2
237 "+r"(dst_stride), // %4
239 : "r"(&kVTbl4x4Transpose) // %6
240 : "memory", "cc", "q0", "q1", "q2", "q3"
244 static uvec8 kVTbl4x4TransposeDi =
245 { 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 };
247 void TransposeUVWx8_NEON(const uint8* src, int src_stride,
248 uint8* dst_a, int dst_stride_a,
249 uint8* dst_b, int dst_stride_b,
251 const uint8* src_temp = NULL;
253 // loops are on blocks of 8. loop will stop when
254 // counter gets to or below 0. starting the counter
255 // at w-8 allow for this
258 // handle 8x8 blocks. this should be the majority of the plane
264 "vld2.8 {d0, d1}, [%0], %2 \n"
266 "vld2.8 {d2, d3}, [%0], %2 \n"
268 "vld2.8 {d4, d5}, [%0], %2 \n"
270 "vld2.8 {d6, d7}, [%0], %2 \n"
272 "vld2.8 {d16, d17}, [%0], %2 \n"
274 "vld2.8 {d18, d19}, [%0], %2 \n"
276 "vld2.8 {d20, d21}, [%0], %2 \n"
278 "vld2.8 {d22, d23}, [%0] \n"
301 "vrev16.8 q10, q10 \n"
302 "vrev16.8 q11, q11 \n"
307 "vst1.8 {d2}, [%0], %4 \n"
309 "vst1.8 {d0}, [%0], %4 \n"
311 "vst1.8 {d6}, [%0], %4 \n"
313 "vst1.8 {d4}, [%0], %4 \n"
315 "vst1.8 {d18}, [%0], %4 \n"
317 "vst1.8 {d16}, [%0], %4 \n"
319 "vst1.8 {d22}, [%0], %4 \n"
321 "vst1.8 {d20}, [%0] \n"
326 "vst1.8 {d3}, [%0], %6 \n"
328 "vst1.8 {d1}, [%0], %6 \n"
330 "vst1.8 {d7}, [%0], %6 \n"
332 "vst1.8 {d5}, [%0], %6 \n"
334 "vst1.8 {d19}, [%0], %6 \n"
336 "vst1.8 {d17}, [%0], %6 \n"
338 "vst1.8 {d23}, [%0], %6 \n"
340 "vst1.8 {d21}, [%0] \n"
342 "add %1, #8*2 \n" // src += 8*2
343 "add %3, %3, %4, lsl #3 \n" // dst_a += 8 * dst_stride_a
344 "add %5, %5, %6, lsl #3 \n" // dst_b += 8 * dst_stride_b
345 "subs %7, #8 \n" // w -= 8
348 // add 8 back to counter. if the result is 0 there are
353 // some residual, so between 1 and 7 lines left to transpose
360 // TODO(frkoenig): Clean this up
364 "vld1.64 {d0}, [%0], %2 \n"
366 "vld1.64 {d1}, [%0], %2 \n"
368 "vld1.64 {d2}, [%0], %2 \n"
370 "vld1.64 {d3}, [%0], %2 \n"
372 "vld1.64 {d4}, [%0], %2 \n"
374 "vld1.64 {d5}, [%0], %2 \n"
376 "vld1.64 {d6}, [%0], %2 \n"
378 "vld1.64 {d7}, [%0] \n"
381 "vld1.8 {q15}, [%8] \n"
386 "vtbl.8 d16, {d0, d1}, d30 \n"
387 "vtbl.8 d17, {d0, d1}, d31 \n"
388 "vtbl.8 d18, {d2, d3}, d30 \n"
389 "vtbl.8 d19, {d2, d3}, d31 \n"
390 "vtbl.8 d20, {d4, d5}, d30 \n"
391 "vtbl.8 d21, {d4, d5}, d31 \n"
392 "vtbl.8 d22, {d6, d7}, d30 \n"
393 "vtbl.8 d23, {d6, d7}, d31 \n"
398 "vst1.32 {d16[0]}, [%0], %4 \n"
400 "vst1.32 {d16[1]}, [%0], %4 \n"
402 "vst1.32 {d17[0]}, [%0], %4 \n"
404 "vst1.32 {d17[1]}, [%0], %4 \n"
408 "vst1.32 {d20[0]}, [%0], %4 \n"
410 "vst1.32 {d20[1]}, [%0], %4 \n"
412 "vst1.32 {d21[0]}, [%0], %4 \n"
414 "vst1.32 {d21[1]}, [%0] \n"
419 "vst1.32 {d18[0]}, [%0], %6 \n"
421 "vst1.32 {d18[1]}, [%0], %6 \n"
423 "vst1.32 {d19[0]}, [%0], %6 \n"
425 "vst1.32 {d19[1]}, [%0], %6 \n"
429 "vst1.32 {d22[0]}, [%0], %6 \n"
431 "vst1.32 {d22[1]}, [%0], %6 \n"
433 "vst1.32 {d23[0]}, [%0], %6 \n"
435 "vst1.32 {d23[1]}, [%0] \n"
437 "add %1, #4*2 \n" // src += 4 * 2
438 "add %3, %3, %4, lsl #2 \n" // dst_a += 4 * dst_stride_a
439 "add %5, %5, %6, lsl #2 \n" // dst_b += 4 * dst_stride_b
440 "subs %7, #4 \n" // w -= 4
443 // some residual, check to see if it includes a 2x8 block,
452 "vld2.16 {d0[0], d2[0]}, [%0], %2 \n"
454 "vld2.16 {d1[0], d3[0]}, [%0], %2 \n"
456 "vld2.16 {d0[1], d2[1]}, [%0], %2 \n"
458 "vld2.16 {d1[1], d3[1]}, [%0], %2 \n"
460 "vld2.16 {d0[2], d2[2]}, [%0], %2 \n"
462 "vld2.16 {d1[2], d3[2]}, [%0], %2 \n"
464 "vld2.16 {d0[3], d2[3]}, [%0], %2 \n"
466 "vld2.16 {d1[3], d3[3]}, [%0] \n"
474 "vst1.64 {d0}, [%0], %4 \n"
476 "vst1.64 {d2}, [%0] \n"
481 "vst1.64 {d1}, [%0], %6 \n"
483 "vst1.64 {d3}, [%0] \n"
485 "add %1, #2*2 \n" // src += 2 * 2
486 "add %3, %3, %4, lsl #1 \n" // dst_a += 2 * dst_stride_a
487 "add %5, %5, %6, lsl #1 \n" // dst_b += 2 * dst_stride_b
488 "subs %7, #2 \n" // w -= 2
494 "vld2.8 {d0[0], d1[0]}, [%1], %2 \n"
496 "vld2.8 {d0[1], d1[1]}, [%1], %2 \n"
498 "vld2.8 {d0[2], d1[2]}, [%1], %2 \n"
500 "vld2.8 {d0[3], d1[3]}, [%1], %2 \n"
502 "vld2.8 {d0[4], d1[4]}, [%1], %2 \n"
504 "vld2.8 {d0[5], d1[5]}, [%1], %2 \n"
506 "vld2.8 {d0[6], d1[6]}, [%1], %2 \n"
508 "vld2.8 {d0[7], d1[7]}, [%1] \n"
511 "vst1.64 {d0}, [%3] \n"
513 "vst1.64 {d1}, [%5] \n"
517 : "+r"(src_temp), // %0
519 "+r"(src_stride), // %2
521 "+r"(dst_stride_a), // %4
523 "+r"(dst_stride_b), // %6
525 : "r"(&kVTbl4x4TransposeDi) // %8
527 "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11"
530 #endif // defined(__ARM_NEON__) && !defined(__aarch64__)
534 } // namespace libyuv