idct32x32_1_add_neon.c revision 7ce0a1d1337c01056ba24006efab21f00e179e04
1/*
2 *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
3 *
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.
9 */
10
11#include <arm_neon.h>
12
13#include "./vpx_config.h"
14
15#include "vpx_dsp/inv_txfm.h"
16#include "vpx_ports/mem.h"
17
18static INLINE void LD_16x8(
19        uint8_t *d,
20        int d_stride,
21        uint8x16_t *q8u8,
22        uint8x16_t *q9u8,
23        uint8x16_t *q10u8,
24        uint8x16_t *q11u8,
25        uint8x16_t *q12u8,
26        uint8x16_t *q13u8,
27        uint8x16_t *q14u8,
28        uint8x16_t *q15u8) {
29    *q8u8 = vld1q_u8(d);
30    d += d_stride;
31    *q9u8 = vld1q_u8(d);
32    d += d_stride;
33    *q10u8 = vld1q_u8(d);
34    d += d_stride;
35    *q11u8 = vld1q_u8(d);
36    d += d_stride;
37    *q12u8 = vld1q_u8(d);
38    d += d_stride;
39    *q13u8 = vld1q_u8(d);
40    d += d_stride;
41    *q14u8 = vld1q_u8(d);
42    d += d_stride;
43    *q15u8 = vld1q_u8(d);
44    return;
45}
46
47static INLINE void ADD_DIFF_16x8(
48        uint8x16_t qdiffu8,
49        uint8x16_t *q8u8,
50        uint8x16_t *q9u8,
51        uint8x16_t *q10u8,
52        uint8x16_t *q11u8,
53        uint8x16_t *q12u8,
54        uint8x16_t *q13u8,
55        uint8x16_t *q14u8,
56        uint8x16_t *q15u8) {
57    *q8u8 = vqaddq_u8(*q8u8, qdiffu8);
58    *q9u8 = vqaddq_u8(*q9u8, qdiffu8);
59    *q10u8 = vqaddq_u8(*q10u8, qdiffu8);
60    *q11u8 = vqaddq_u8(*q11u8, qdiffu8);
61    *q12u8 = vqaddq_u8(*q12u8, qdiffu8);
62    *q13u8 = vqaddq_u8(*q13u8, qdiffu8);
63    *q14u8 = vqaddq_u8(*q14u8, qdiffu8);
64    *q15u8 = vqaddq_u8(*q15u8, qdiffu8);
65    return;
66}
67
68static INLINE void SUB_DIFF_16x8(
69        uint8x16_t qdiffu8,
70        uint8x16_t *q8u8,
71        uint8x16_t *q9u8,
72        uint8x16_t *q10u8,
73        uint8x16_t *q11u8,
74        uint8x16_t *q12u8,
75        uint8x16_t *q13u8,
76        uint8x16_t *q14u8,
77        uint8x16_t *q15u8) {
78    *q8u8 = vqsubq_u8(*q8u8, qdiffu8);
79    *q9u8 = vqsubq_u8(*q9u8, qdiffu8);
80    *q10u8 = vqsubq_u8(*q10u8, qdiffu8);
81    *q11u8 = vqsubq_u8(*q11u8, qdiffu8);
82    *q12u8 = vqsubq_u8(*q12u8, qdiffu8);
83    *q13u8 = vqsubq_u8(*q13u8, qdiffu8);
84    *q14u8 = vqsubq_u8(*q14u8, qdiffu8);
85    *q15u8 = vqsubq_u8(*q15u8, qdiffu8);
86    return;
87}
88
89static INLINE void ST_16x8(
90        uint8_t *d,
91        int d_stride,
92        uint8x16_t *q8u8,
93        uint8x16_t *q9u8,
94        uint8x16_t *q10u8,
95        uint8x16_t *q11u8,
96        uint8x16_t *q12u8,
97        uint8x16_t *q13u8,
98        uint8x16_t *q14u8,
99        uint8x16_t *q15u8) {
100    vst1q_u8(d, *q8u8);
101    d += d_stride;
102    vst1q_u8(d, *q9u8);
103    d += d_stride;
104    vst1q_u8(d, *q10u8);
105    d += d_stride;
106    vst1q_u8(d, *q11u8);
107    d += d_stride;
108    vst1q_u8(d, *q12u8);
109    d += d_stride;
110    vst1q_u8(d, *q13u8);
111    d += d_stride;
112    vst1q_u8(d, *q14u8);
113    d += d_stride;
114    vst1q_u8(d, *q15u8);
115    return;
116}
117
118void vpx_idct32x32_1_add_neon(
119        int16_t *input,
120        uint8_t *dest,
121        int dest_stride) {
122    uint8x16_t q0u8, q8u8, q9u8, q10u8, q11u8, q12u8, q13u8, q14u8, q15u8;
123    int i, j, dest_stride8;
124    uint8_t *d;
125    int16_t a1, cospi_16_64 = 11585;
126    int16_t out = dct_const_round_shift(input[0] * cospi_16_64);
127
128    out = dct_const_round_shift(out * cospi_16_64);
129    a1 = ROUND_POWER_OF_TWO(out, 6);
130
131    dest_stride8 = dest_stride * 8;
132    if (a1 >= 0) {  // diff_positive_32_32
133        a1 = a1 < 0 ? 0 : a1 > 255 ? 255 : a1;
134        q0u8 = vdupq_n_u8(a1);
135        for (i = 0; i < 2; i++, dest += 16) {  // diff_positive_32_32_loop
136            d = dest;
137            for (j = 0; j < 4; j++) {
138                LD_16x8(d, dest_stride, &q8u8, &q9u8, &q10u8, &q11u8,
139                                        &q12u8, &q13u8, &q14u8, &q15u8);
140                ADD_DIFF_16x8(q0u8, &q8u8, &q9u8, &q10u8, &q11u8,
141                                    &q12u8, &q13u8, &q14u8, &q15u8);
142                ST_16x8(d, dest_stride, &q8u8, &q9u8, &q10u8, &q11u8,
143                                        &q12u8, &q13u8, &q14u8, &q15u8);
144                d += dest_stride8;
145            }
146        }
147    } else {  // diff_negative_32_32
148        a1 = -a1;
149        a1 = a1 < 0 ? 0 : a1 > 255 ? 255 : a1;
150        q0u8 = vdupq_n_u8(a1);
151        for (i = 0; i < 2; i++, dest += 16) {  // diff_negative_32_32_loop
152            d = dest;
153            for (j = 0; j < 4; j++) {
154                LD_16x8(d, dest_stride, &q8u8, &q9u8, &q10u8, &q11u8,
155                                        &q12u8, &q13u8, &q14u8, &q15u8);
156                SUB_DIFF_16x8(q0u8, &q8u8, &q9u8, &q10u8, &q11u8,
157                                    &q12u8, &q13u8, &q14u8, &q15u8);
158                ST_16x8(d, dest_stride, &q8u8, &q9u8, &q10u8, &q11u8,
159                                        &q12u8, &q13u8, &q14u8, &q15u8);
160                d += dest_stride8;
161            }
162        }
163    }
164    return;
165}
166