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"
13 #include "libyuv/basic_types.h"
20 #if !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__)
22 static uvec8 kVTbl4x4Transpose =
23 { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 };
25 void TransposeWx8_NEON(const uint8* src, int src_stride,
26 uint8* dst, int dst_stride,
28 const uint8* src_temp = NULL;
30 // loops are on blocks of 8. loop will stop when
31 // counter gets to or below 0. starting the counter
32 // at w-8 allow for this
35 // handle 8x8 blocks. this should be the majority of the plane
41 "vld1.8 {d0}, [%0], %2 \n"
43 "vld1.8 {d1}, [%0], %2 \n"
45 "vld1.8 {d2}, [%0], %2 \n"
47 "vld1.8 {d3}, [%0], %2 \n"
49 "vld1.8 {d4}, [%0], %2 \n"
51 "vld1.8 {d5}, [%0], %2 \n"
53 "vld1.8 {d6}, [%0], %2 \n"
55 "vld1.8 {d7}, [%0] \n"
80 "vst1.8 {d1}, [%0], %4 \n"
82 "vst1.8 {d0}, [%0], %4 \n"
84 "vst1.8 {d3}, [%0], %4 \n"
86 "vst1.8 {d2}, [%0], %4 \n"
88 "vst1.8 {d5}, [%0], %4 \n"
90 "vst1.8 {d4}, [%0], %4 \n"
92 "vst1.8 {d7}, [%0], %4 \n"
94 "vst1.8 {d6}, [%0] \n"
96 "add %1, #8 \n" // src += 8
97 "add %3, %3, %4, lsl #3 \n" // dst += 8 * dst_stride
98 "subs %5, #8 \n" // w -= 8
101 // add 8 back to counter. if the result is 0 there are
106 // some residual, so between 1 and 7 lines left to transpose
116 "vld1.32 {d0[0]}, [%0], %2 \n"
118 "vld1.32 {d0[1]}, [%0], %2 \n"
120 "vld1.32 {d1[0]}, [%0], %2 \n"
122 "vld1.32 {d1[1]}, [%0], %2 \n"
124 "vld1.32 {d2[0]}, [%0], %2 \n"
126 "vld1.32 {d2[1]}, [%0], %2 \n"
128 "vld1.32 {d3[0]}, [%0], %2 \n"
130 "vld1.32 {d3[1]}, [%0] \n"
135 "vld1.8 {q3}, [%6] \n"
137 "vtbl.8 d4, {d0, d1}, d6 \n"
138 "vtbl.8 d5, {d0, d1}, d7 \n"
139 "vtbl.8 d0, {d2, d3}, d6 \n"
140 "vtbl.8 d1, {d2, d3}, d7 \n"
142 // TODO(frkoenig): Rework shuffle above to
143 // write out with 4 instead of 8 writes.
145 "vst1.32 {d4[0]}, [%0], %4 \n"
147 "vst1.32 {d4[1]}, [%0], %4 \n"
149 "vst1.32 {d5[0]}, [%0], %4 \n"
151 "vst1.32 {d5[1]}, [%0] \n"
155 "vst1.32 {d0[0]}, [%0], %4 \n"
157 "vst1.32 {d0[1]}, [%0], %4 \n"
159 "vst1.32 {d1[0]}, [%0], %4 \n"
161 "vst1.32 {d1[1]}, [%0] \n"
163 "add %1, #4 \n" // src += 4
164 "add %3, %3, %4, lsl #2 \n" // dst += 4 * dst_stride
165 "subs %5, #4 \n" // w -= 4
168 // some residual, check to see if it includes a 2x8 block,
177 "vld1.16 {d0[0]}, [%0], %2 \n"
179 "vld1.16 {d1[0]}, [%0], %2 \n"
181 "vld1.16 {d0[1]}, [%0], %2 \n"
183 "vld1.16 {d1[1]}, [%0], %2 \n"
185 "vld1.16 {d0[2]}, [%0], %2 \n"
187 "vld1.16 {d1[2]}, [%0], %2 \n"
189 "vld1.16 {d0[3]}, [%0], %2 \n"
191 "vld1.16 {d1[3]}, [%0] \n"
198 "vst1.64 {d0}, [%0], %4 \n"
200 "vst1.64 {d1}, [%0] \n"
202 "add %1, #2 \n" // src += 2
203 "add %3, %3, %4, lsl #1 \n" // dst += 2 * dst_stride
204 "subs %5, #2 \n" // w -= 2
210 "vld1.8 {d0[0]}, [%1], %2 \n"
212 "vld1.8 {d0[1]}, [%1], %2 \n"
214 "vld1.8 {d0[2]}, [%1], %2 \n"
216 "vld1.8 {d0[3]}, [%1], %2 \n"
218 "vld1.8 {d0[4]}, [%1], %2 \n"
220 "vld1.8 {d0[5]}, [%1], %2 \n"
222 "vld1.8 {d0[6]}, [%1], %2 \n"
224 "vld1.8 {d0[7]}, [%1] \n"
227 "vst1.64 {d0}, [%3] \n"
231 : "+r"(src_temp), // %0
233 "+r"(src_stride), // %2
235 "+r"(dst_stride), // %4
237 : "r"(&kVTbl4x4Transpose) // %6
238 : "memory", "cc", "q0", "q1", "q2", "q3"
242 static uvec8 kVTbl4x4TransposeDi =
243 { 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 };
245 void TransposeUVWx8_NEON(const uint8* src, int src_stride,
246 uint8* dst_a, int dst_stride_a,
247 uint8* dst_b, int dst_stride_b,
249 const uint8* src_temp = NULL;
251 // loops are on blocks of 8. loop will stop when
252 // counter gets to or below 0. starting the counter
253 // at w-8 allow for this
256 // handle 8x8 blocks. this should be the majority of the plane
262 "vld2.8 {d0, d1}, [%0], %2 \n"
264 "vld2.8 {d2, d3}, [%0], %2 \n"
266 "vld2.8 {d4, d5}, [%0], %2 \n"
268 "vld2.8 {d6, d7}, [%0], %2 \n"
270 "vld2.8 {d16, d17}, [%0], %2 \n"
272 "vld2.8 {d18, d19}, [%0], %2 \n"
274 "vld2.8 {d20, d21}, [%0], %2 \n"
276 "vld2.8 {d22, d23}, [%0] \n"
299 "vrev16.8 q10, q10 \n"
300 "vrev16.8 q11, q11 \n"
305 "vst1.8 {d2}, [%0], %4 \n"
307 "vst1.8 {d0}, [%0], %4 \n"
309 "vst1.8 {d6}, [%0], %4 \n"
311 "vst1.8 {d4}, [%0], %4 \n"
313 "vst1.8 {d18}, [%0], %4 \n"
315 "vst1.8 {d16}, [%0], %4 \n"
317 "vst1.8 {d22}, [%0], %4 \n"
319 "vst1.8 {d20}, [%0] \n"
324 "vst1.8 {d3}, [%0], %6 \n"
326 "vst1.8 {d1}, [%0], %6 \n"
328 "vst1.8 {d7}, [%0], %6 \n"
330 "vst1.8 {d5}, [%0], %6 \n"
332 "vst1.8 {d19}, [%0], %6 \n"
334 "vst1.8 {d17}, [%0], %6 \n"
336 "vst1.8 {d23}, [%0], %6 \n"
338 "vst1.8 {d21}, [%0] \n"
340 "add %1, #8*2 \n" // src += 8*2
341 "add %3, %3, %4, lsl #3 \n" // dst_a += 8 * dst_stride_a
342 "add %5, %5, %6, lsl #3 \n" // dst_b += 8 * dst_stride_b
343 "subs %7, #8 \n" // w -= 8
346 // add 8 back to counter. if the result is 0 there are
351 // some residual, so between 1 and 7 lines left to transpose
358 // TODO(frkoenig): Clean this up
362 "vld1.64 {d0}, [%0], %2 \n"
364 "vld1.64 {d1}, [%0], %2 \n"
366 "vld1.64 {d2}, [%0], %2 \n"
368 "vld1.64 {d3}, [%0], %2 \n"
370 "vld1.64 {d4}, [%0], %2 \n"
372 "vld1.64 {d5}, [%0], %2 \n"
374 "vld1.64 {d6}, [%0], %2 \n"
376 "vld1.64 {d7}, [%0] \n"
379 "vld1.8 {q15}, [%8] \n"
384 "vtbl.8 d16, {d0, d1}, d30 \n"
385 "vtbl.8 d17, {d0, d1}, d31 \n"
386 "vtbl.8 d18, {d2, d3}, d30 \n"
387 "vtbl.8 d19, {d2, d3}, d31 \n"
388 "vtbl.8 d20, {d4, d5}, d30 \n"
389 "vtbl.8 d21, {d4, d5}, d31 \n"
390 "vtbl.8 d22, {d6, d7}, d30 \n"
391 "vtbl.8 d23, {d6, d7}, d31 \n"
396 "vst1.32 {d16[0]}, [%0], %4 \n"
398 "vst1.32 {d16[1]}, [%0], %4 \n"
400 "vst1.32 {d17[0]}, [%0], %4 \n"
402 "vst1.32 {d17[1]}, [%0], %4 \n"
406 "vst1.32 {d20[0]}, [%0], %4 \n"
408 "vst1.32 {d20[1]}, [%0], %4 \n"
410 "vst1.32 {d21[0]}, [%0], %4 \n"
412 "vst1.32 {d21[1]}, [%0] \n"
417 "vst1.32 {d18[0]}, [%0], %6 \n"
419 "vst1.32 {d18[1]}, [%0], %6 \n"
421 "vst1.32 {d19[0]}, [%0], %6 \n"
423 "vst1.32 {d19[1]}, [%0], %6 \n"
427 "vst1.32 {d22[0]}, [%0], %6 \n"
429 "vst1.32 {d22[1]}, [%0], %6 \n"
431 "vst1.32 {d23[0]}, [%0], %6 \n"
433 "vst1.32 {d23[1]}, [%0] \n"
435 "add %1, #4*2 \n" // src += 4 * 2
436 "add %3, %3, %4, lsl #2 \n" // dst_a += 4 * dst_stride_a
437 "add %5, %5, %6, lsl #2 \n" // dst_b += 4 * dst_stride_b
438 "subs %7, #4 \n" // w -= 4
441 // some residual, check to see if it includes a 2x8 block,
450 "vld2.16 {d0[0], d2[0]}, [%0], %2 \n"
452 "vld2.16 {d1[0], d3[0]}, [%0], %2 \n"
454 "vld2.16 {d0[1], d2[1]}, [%0], %2 \n"
456 "vld2.16 {d1[1], d3[1]}, [%0], %2 \n"
458 "vld2.16 {d0[2], d2[2]}, [%0], %2 \n"
460 "vld2.16 {d1[2], d3[2]}, [%0], %2 \n"
462 "vld2.16 {d0[3], d2[3]}, [%0], %2 \n"
464 "vld2.16 {d1[3], d3[3]}, [%0] \n"
472 "vst1.64 {d0}, [%0], %4 \n"
474 "vst1.64 {d2}, [%0] \n"
479 "vst1.64 {d1}, [%0], %6 \n"
481 "vst1.64 {d3}, [%0] \n"
483 "add %1, #2*2 \n" // src += 2 * 2
484 "add %3, %3, %4, lsl #1 \n" // dst_a += 2 * dst_stride_a
485 "add %5, %5, %6, lsl #1 \n" // dst_b += 2 * dst_stride_b
486 "subs %7, #2 \n" // w -= 2
492 "vld2.8 {d0[0], d1[0]}, [%1], %2 \n"
494 "vld2.8 {d0[1], d1[1]}, [%1], %2 \n"
496 "vld2.8 {d0[2], d1[2]}, [%1], %2 \n"
498 "vld2.8 {d0[3], d1[3]}, [%1], %2 \n"
500 "vld2.8 {d0[4], d1[4]}, [%1], %2 \n"
502 "vld2.8 {d0[5], d1[5]}, [%1], %2 \n"
504 "vld2.8 {d0[6], d1[6]}, [%1], %2 \n"
506 "vld2.8 {d0[7], d1[7]}, [%1] \n"
509 "vst1.64 {d0}, [%3] \n"
511 "vst1.64 {d1}, [%5] \n"
515 : "+r"(src_temp), // %0
517 "+r"(src_stride), // %2
519 "+r"(dst_stride_a), // %4
521 "+r"(dst_stride_b), // %6
523 : "r"(&kVTbl4x4TransposeDi) // %8
525 "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11"
532 } // namespace libyuv