Coverage Report

Created: 2026-07-28 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libavif/ext/libyuv/source/row_gcc.cc
Line
Count
Source
1
/*
2
 *  Copyright 2011 The LibYuv 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 "libyuv/convert_from_argb.h"  // For ArgbConstants
12
#include "libyuv/row.h"
13
14
#ifdef __cplusplus
15
namespace libyuv {
16
extern "C" {
17
#endif
18
19
// This module is for GCC x86 and x64.
20
#if !defined(LIBYUV_DISABLE_X86) &&               \
21
    (defined(__x86_64__) || defined(__i386__)) && \
22
    !defined(LIBYUV_ENABLE_ROWWIN)
23
24
// Note: for avx and avx512 declare clobber as xmm registers due to
25
// clang for windows needing to preserve xmm registers but not saving
26
// them if declared as ymm or zmm.
27
28
#if defined(HAS_ARGBTOYROW_SSSE3) || defined(HAS_ARGBGRAYROW_SSSE3)
29
30
// Constants for ARGB
31
32
// JPeg full range.
33
static const uvec8 kARGBToYJ = {29u, 150u, 77u, 0u, 29u, 150u, 77u, 0u,
34
                                29u, 150u, 77u, 0u, 29u, 150u, 77u, 0u};
35
36
#endif  // defined(HAS_ARGBTOYROW_SSSE3) || defined(HAS_ARGBGRAYROW_SSSE3)
37
38
#if defined(HAS_ARGBTOYROW_SSSE3) || defined(HAS_I422TOARGBROW_SSSE3)
39
// Constants for BGRA
40
41
// Constants for ABGR
42
43
// Constants for RGBA.
44
// 126 (7e) - (-109..110) = 16..235
45
46
static const uvec16 kSub128 = {0x8080u, 0x8080u, 0x8080u, 0x8080u,
47
                               0x8080u, 0x8080u, 0x8080u, 0x8080u};
48
49
#endif  // defined(HAS_ARGBTOYROW_SSSE3) || defined(HAS_I422TOARGBROW_SSSE3)
50
51
#ifdef HAS_RGB24TOARGBROW_SSSE3
52
53
// Shuffle table for converting RGB24 to ARGB.
54
static const uvec8 kShuffleMaskRGB24ToARGB[2] = {
55
    {0u, 1u, 2u, 128u, 3u, 4u, 5u, 128u, 6u, 7u, 8u, 128u, 9u, 10u, 11u, 128u},
56
    {4u, 5u, 6u, 128u, 7u, 8u, 9u, 128u, 10u, 11u, 12u, 128u, 13u, 14u, 15u,
57
     128u}};
58
59
// Shuffle table for converting RAW to ARGB.
60
static const uvec8 kShuffleMaskRAWToARGB = {
61
    2u, 1u, 0u, 128u, 5u, 4u, 3u, 128u, 8u, 7u, 6u, 128u, 11u, 10u, 9u, 128u};
62
// Shuffle table for converting RAW to ARGB.  Last 12
63
static const uvec8 kShuffleMaskRAWToARGB_0 = {6u,  5u,   4u,  128u, 9u,  8u,
64
                                              7u,  128u, 12u, 11u,  10u, 128u,
65
                                              15u, 14u,  13u, 128u};
66
67
// Shuffle table for converting RAW to RGBA.
68
static const uvec8 kShuffleMaskRAWToRGBA = {
69
    128u, 2u, 1u, 0u, 128u, 5u, 4u, 3u, 128u, 8u, 7u, 6u, 128u, 11u, 10u, 9u};
70
71
// Shuffle table for converting RAW to RGB24.  First 8.
72
static const uvec8 kShuffleMaskRAWToRGB24_0 = {
73
    2u,   1u,   0u,   5u,   4u,   3u,   8u,   7u,
74
    128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u};
75
76
// Shuffle table for converting RAW to RGB24.  Middle 8.
77
static const uvec8 kShuffleMaskRAWToRGB24_1 = {
78
    2u,   7u,   6u,   5u,   10u,  9u,   8u,   13u,
79
    128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u};
80
81
// Shuffle table for converting RAW to RGB24.  Last 8.
82
static const uvec8 kShuffleMaskRAWToRGB24_2 = {
83
    8u,   7u,   12u,  11u,  10u,  15u,  14u,  13u,
84
    128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u};
85
86
// Shuffle table for converting ARGB to RGB24.
87
static const uvec8 kShuffleMaskARGBToRGB24 = {
88
    0u, 1u, 2u, 4u, 5u, 6u, 8u, 9u, 10u, 12u, 13u, 14u, 128u, 128u, 128u, 128u};
89
90
// Shuffle table for converting ARGB to RAW.
91
static const uvec8 kShuffleMaskARGBToRAW = {
92
    2u, 1u, 0u, 6u, 5u, 4u, 10u, 9u, 8u, 14u, 13u, 12u, 128u, 128u, 128u, 128u};
93
94
// Shuffle table for converting ARGBToRGB24 for I422ToRGB24.  First 8 + next 4
95
static const uvec8 kShuffleMaskARGBToRGB24_0 = {
96
    0u, 1u, 2u, 4u, 5u, 6u, 8u, 9u, 128u, 128u, 128u, 128u, 10u, 12u, 13u, 14u};
97
98
// YUY2 shuf 16 Y to 32 Y.
99
static const vec8 kShuffleYUY2Y = {0, 0, 2,  2,  4,  4,  6,  6,
100
                                   8, 8, 10, 10, 12, 12, 14, 14};
101
102
// YUY2 shuf 8 UV to 16 UV.
103
static const vec8 kShuffleYUY2UV = {1, 3,  1, 3,  5,  7,  5,  7,
104
                                    9, 11, 9, 11, 13, 15, 13, 15};
105
106
// UYVY shuf 16 Y to 32 Y.
107
static const vec8 kShuffleUYVYY = {1, 1, 3,  3,  5,  5,  7,  7,
108
                                   9, 9, 11, 11, 13, 13, 15, 15};
109
110
// UYVY shuf 8 UV to 16 UV.
111
static const vec8 kShuffleUYVYUV = {0, 2,  0, 2,  4,  6,  4,  6,
112
                                    8, 10, 8, 10, 12, 14, 12, 14};
113
114
// NV21 shuf 8 VU to 16 UV.
115
static const lvec8 kShuffleNV21 = {
116
    1, 0, 1, 0, 3, 2, 3, 2, 5, 4, 5, 4, 7, 6, 7, 6,
117
    1, 0, 1, 0, 3, 2, 3, 2, 5, 4, 5, 4, 7, 6, 7, 6,
118
};
119
#endif  // HAS_RGB24TOARGBROW_SSSE3
120
121
#if defined(HAS_J400TOARGBROW_AVX2) || defined(HAS_J400TOARGBROW_AVX512BW)
122
alignas(64) static const uint8_t kShuffleMaskJ400ToARGB[64] = {
123
    0u,  0u,   0u,  128u, 1u,  1u,   1u,  128u, 2u,  2u,   2u,  128u, 3u,  3u,
124
    3u,  128u, 4u,  4u,   4u,  128u, 5u,  5u,   5u,  128u, 6u,  6u,   6u,  128u,
125
    7u,  7u,   7u,  128u, 8u,  8u,   8u,  128u, 9u,  9u,   9u,  128u, 10u, 10u,
126
    10u, 128u, 11u, 11u,  11u, 128u, 12u, 12u,  12u, 128u, 13u, 13u,  13u, 128u,
127
    14u, 14u,  14u, 128u, 15u, 15u,  15u, 128u};
128
#endif
129
130
#ifdef HAS_J400TOARGBROW_AVX2
131
0
void J400ToARGBRow_AVX2(const uint8_t* src_y, uint8_t* dst_argb, int width) {
132
0
  asm volatile(
133
0
      "vpcmpeqb    %%ymm7,%%ymm7,%%ymm7          \n"
134
0
      "vpslld      $0x18,%%ymm7,%%ymm7           \n"
135
0
      "vmovdqa     (%3),%%ymm5                     \n"
136
0
      "vmovdqa     0x20(%3),%%ymm6                  \n"
137
138
0
      LABELALIGN
139
0
      "1:          \n"
140
0
      "vbroadcasti128 (%0),%%ymm0                \n"
141
0
      "vpshufb     %%ymm5,%%ymm0,%%ymm1          \n"
142
0
      "vpshufb     %%ymm6,%%ymm0,%%ymm2          \n"
143
0
      "vpor        %%ymm7,%%ymm1,%%ymm1          \n"
144
0
      "vpor        %%ymm7,%%ymm2,%%ymm2          \n"
145
0
      "vmovdqu     %%ymm1,(%1)                   \n"
146
0
      "vmovdqu     %%ymm2,0x20(%1)               \n"
147
0
      "lea         0x10(%0),%0                   \n"
148
0
      "lea         0x40(%1),%1                   \n"
149
0
      "sub         $0x10,%2                      \n"
150
0
      "jg          1b                            \n"
151
0
      "vzeroupper  \n"
152
0
      : "+r"(src_y),                 // %0
153
0
        "+r"(dst_argb),              // %1
154
0
        "+r"(width)                  // %2
155
0
      : "r"(kShuffleMaskJ400ToARGB)  // %3
156
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm5", "xmm6", "xmm7");
157
0
}
158
#endif  // HAS_J400TOARGBROW_AVX2
159
160
#ifdef HAS_J400TOARGBROW_AVX512BW
161
void J400ToARGBRow_AVX512BW(const uint8_t* src_y,
162
                            uint8_t* dst_argb,
163
0
                            int width) {
164
0
  asm volatile(
165
0
      "vpternlogd  $0xff,%%zmm7,%%zmm7,%%zmm7    \n"  // 0xffffffff
166
0
      "vpslld      $0x18,%%zmm7,%%zmm7           \n"  // 0xff000000
167
0
      "vmovdqa64   %3,%%zmm5                     \n"
168
169
0
      LABELALIGN
170
0
      "1:          \n"
171
0
      "vbroadcasti32x4 (%0),%%zmm0               \n"
172
0
      "vbroadcasti32x4 0x10(%0),%%zmm1          \n"
173
0
      "vpshufb     %%zmm5,%%zmm0,%%zmm0          \n"
174
0
      "vpshufb     %%zmm5,%%zmm1,%%zmm1          \n"
175
0
      "vpord       %%zmm7,%%zmm0,%%zmm0          \n"
176
0
      "vpord       %%zmm7,%%zmm1,%%zmm1          \n"
177
0
      "vmovdqu64   %%zmm0,(%1)                   \n"
178
0
      "vmovdqu64   %%zmm1,0x40(%1)               \n"
179
0
      "lea         0x20(%0),%0                   \n"
180
0
      "lea         0x80(%1),%1                   \n"
181
0
      "sub         $0x20,%2                      \n"
182
0
      "jg          1b                            \n"
183
0
      "vzeroupper  \n"
184
0
      : "+r"(src_y),                 // %0
185
0
        "+r"(dst_argb),              // %1
186
0
        "+r"(width)                  // %2
187
0
      : "m"(kShuffleMaskJ400ToARGB)  // %3
188
0
      : "memory", "cc", "xmm0", "xmm1", "xmm5", "xmm7");
189
0
}
190
#endif  // HAS_J400TOARGBROW_AVX512BW
191
192
#ifdef HAS_RGB24TOARGBROW_SSSE3
193
void RGB24ToARGBRow_SSSE3(const uint8_t* src_rgb24,
194
                          uint8_t* dst_argb,
195
0
                          int width) {
196
0
  asm volatile(
197
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"  // 0xff000000
198
0
      "pslld       $0x18,%%xmm5                  \n"
199
0
      "movdqa      %3,%%xmm4                     \n"
200
201
0
      LABELALIGN
202
0
      "1:          \n"
203
0
      "movdqu      (%0),%%xmm0                   \n"
204
0
      "movdqu      0x10(%0),%%xmm1               \n"
205
0
      "movdqu      0x20(%0),%%xmm3               \n"
206
0
      "lea         0x30(%0),%0                   \n"
207
0
      "movdqa      %%xmm3,%%xmm2                 \n"
208
0
      "palignr     $0x8,%%xmm1,%%xmm2            \n"
209
0
      "pshufb      %%xmm4,%%xmm2                 \n"
210
0
      "por         %%xmm5,%%xmm2                 \n"
211
0
      "palignr     $0xc,%%xmm0,%%xmm1            \n"
212
0
      "pshufb      %%xmm4,%%xmm0                 \n"
213
0
      "movdqu      %%xmm2,0x20(%1)               \n"
214
0
      "por         %%xmm5,%%xmm0                 \n"
215
0
      "pshufb      %%xmm4,%%xmm1                 \n"
216
0
      "movdqu      %%xmm0,(%1)                   \n"
217
0
      "por         %%xmm5,%%xmm1                 \n"
218
0
      "palignr     $0x4,%%xmm3,%%xmm3            \n"
219
0
      "pshufb      %%xmm4,%%xmm3                 \n"
220
0
      "movdqu      %%xmm1,0x10(%1)               \n"
221
0
      "por         %%xmm5,%%xmm3                 \n"
222
0
      "movdqu      %%xmm3,0x30(%1)               \n"
223
0
      "lea         0x40(%1),%1                   \n"
224
0
      "sub         $0x10,%2                      \n"
225
0
      "jg          1b                            \n"
226
0
      : "+r"(src_rgb24),                 // %0
227
0
        "+r"(dst_argb),                  // %1
228
0
        "+r"(width)                      // %2
229
0
      : "m"(kShuffleMaskRGB24ToARGB[0])  // %3
230
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
231
0
}
232
233
#ifdef HAS_RGB24TOARGBROW_AVX2
234
void RGB24ToARGBRow_AVX2(const uint8_t* src_rgb24,
235
                         uint8_t* dst_argb,
236
0
                         int width) {
237
  // Reference to prevent discarding of kShuffleMaskRGB24ToARGB[1] which is
238
  // accessed via offset in assembly.
239
0
  const uvec8* dummy = &kShuffleMaskRGB24ToARGB[1];
240
0
  (void)dummy;
241
0
  asm volatile(
242
0
      "vpcmpeqb    %%ymm6,%%ymm6,%%ymm6          \n"  // 0xff000000
243
0
      "vpslld      $0x18,%%ymm6,%%ymm6           \n"
244
0
      "vbroadcasti128 %3,%%ymm4                  \n"
245
0
      "vbroadcasti128 16+%3,%%ymm5               \n"
246
247
0
      LABELALIGN
248
0
      "1:          \n"
249
0
      "vmovdqu     (%0),%%xmm0                   \n"  // first 12
250
0
      "vinserti128 $1,12(%0),%%ymm0,%%ymm0       \n"  // second 12
251
0
      "vmovdqu     24(%0),%%xmm1                 \n"  // third 12
252
0
      "vinserti128 $1,36(%0),%%ymm1,%%ymm1       \n"  // forth 12
253
0
      "vmovdqu     48(%0),%%xmm2                 \n"  // fifth 12
254
0
      "vinserti128 $1,60(%0),%%ymm2,%%ymm2       \n"  // sixth 12
255
0
      "vmovdqu     68(%0),%%xmm3                 \n"  // seventh 12
256
0
      "vinserti128 $1,80(%0),%%ymm3,%%ymm3       \n"  // eighth 12
257
0
      "lea         96(%0),%0                     \n"
258
0
      "vpshufb     %%ymm4,%%ymm0,%%ymm0          \n"
259
0
      "vpshufb     %%ymm4,%%ymm1,%%ymm1          \n"
260
0
      "vpshufb     %%ymm4,%%ymm2,%%ymm2          \n"
261
0
      "vpshufb     %%ymm5,%%ymm3,%%ymm3          \n"
262
0
      "vpor        %%ymm6,%%ymm0,%%ymm0          \n"
263
0
      "vpor        %%ymm6,%%ymm1,%%ymm1          \n"
264
0
      "vpor        %%ymm6,%%ymm2,%%ymm2          \n"
265
0
      "vpor        %%ymm6,%%ymm3,%%ymm3          \n"
266
0
      "vmovdqu     %%ymm0,(%1)                   \n"
267
0
      "vmovdqu     %%ymm1,0x20(%1)               \n"
268
0
      "vmovdqu     %%ymm2,0x40(%1)               \n"
269
0
      "vmovdqu     %%ymm3,0x60(%1)               \n"
270
0
      "lea         0x80(%1),%1                   \n"
271
0
      "sub         $0x20,%2                      \n"
272
0
      "jg          1b                            \n"
273
0
      "vzeroupper  \n"
274
0
      : "+r"(src_rgb24),                 // %0
275
0
        "+r"(dst_argb),                  // %1
276
0
        "+r"(width)                      // %2
277
0
      : "m"(kShuffleMaskRGB24ToARGB[0])  // %3
278
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
279
0
}
280
#endif  // HAS_RGB24TOARGBROW_AVX2
281
282
0
void RAWToARGBRow_SSSE3(const uint8_t* src_raw, uint8_t* dst_argb, int width) {
283
0
  asm volatile(
284
0
      "pcmpeqb     %%xmm6,%%xmm6                 \n"  // 0xff000000
285
0
      "pslld       $0x18,%%xmm6                  \n"
286
0
      "movdqa      %3,%%xmm4                     \n"
287
0
      "movdqa      %4,%%xmm5                     \n"
288
289
0
      LABELALIGN
290
0
      "1:          \n"
291
0
      "movdqu      (%0),%%xmm0                   \n"
292
0
      "movdqu      12(%0),%%xmm1                 \n"
293
0
      "movdqu      24(%0),%%xmm2                 \n"
294
0
      "movdqu      32(%0),%%xmm3                 \n"
295
0
      "lea         0x30(%0),%0                   \n"
296
0
      "pshufb      %%xmm4,%%xmm0                 \n"
297
0
      "pshufb      %%xmm4,%%xmm1                 \n"
298
0
      "pshufb      %%xmm4,%%xmm2                 \n"
299
0
      "pshufb      %%xmm5,%%xmm3                 \n"
300
0
      "por         %%xmm6,%%xmm0                 \n"
301
0
      "por         %%xmm6,%%xmm1                 \n"
302
0
      "por         %%xmm6,%%xmm2                 \n"
303
0
      "por         %%xmm6,%%xmm3                 \n"
304
0
      "movdqu      %%xmm0,0x00(%1)               \n"
305
0
      "movdqu      %%xmm1,0x10(%1)               \n"
306
0
      "movdqu      %%xmm2,0x20(%1)               \n"
307
0
      "movdqu      %%xmm3,0x30(%1)               \n"
308
0
      "lea         0x40(%1),%1                   \n"
309
0
      "sub         $0x10,%2                      \n"
310
0
      "jg          1b                            \n"
311
0
      : "+r"(src_raw),                // %0
312
0
        "+r"(dst_argb),               // %1
313
0
        "+r"(width)                   // %2
314
0
      : "m"(kShuffleMaskRAWToARGB),   // %3
315
0
        "m"(kShuffleMaskRAWToARGB_0)  // %4
316
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
317
0
}
318
319
0
void RAWToARGBRow_AVX2(const uint8_t* src_raw, uint8_t* dst_argb, int width) {
320
0
  asm volatile(
321
0
      "vpcmpeqb    %%ymm6,%%ymm6,%%ymm6          \n"  // 0xff000000
322
0
      "vpslld      $0x18,%%ymm6,%%ymm6           \n"
323
0
      "vbroadcasti128 %3,%%ymm4                  \n"  //
324
0
      "vbroadcasti128 %4,%%ymm5                  \n"  //
325
326
      LABELALIGN  //
327
0
      "1:          \n"
328
0
      "vmovdqu     (%0),%%xmm0                   \n"  // first 12
329
0
      "vinserti128 $1,12(%0),%%ymm0,%%ymm0       \n"  // second 12
330
0
      "vmovdqu     24(%0),%%xmm1                 \n"  // third 12
331
0
      "vinserti128 $1,36(%0),%%ymm1,%%ymm1       \n"  // forth 12
332
0
      "vmovdqu     48(%0),%%xmm2                 \n"  // fifth 12
333
0
      "vinserti128 $1,60(%0),%%ymm2,%%ymm2       \n"  // sixth 12
334
0
      "vmovdqu     68(%0),%%xmm3                 \n"  // seventh 12
335
0
      "vinserti128 $1,80(%0),%%ymm3,%%ymm3       \n"  // eighth 12
336
0
      "lea         96(%0),%0                     \n"
337
0
      "vpshufb     %%ymm4,%%ymm0,%%ymm0          \n"
338
0
      "vpshufb     %%ymm4,%%ymm1,%%ymm1          \n"
339
0
      "vpshufb     %%ymm4,%%ymm2,%%ymm2          \n"
340
0
      "vpshufb     %%ymm5,%%ymm3,%%ymm3          \n"
341
0
      "vpor        %%ymm6,%%ymm0,%%ymm0          \n"
342
0
      "vpor        %%ymm6,%%ymm1,%%ymm1          \n"
343
0
      "vpor        %%ymm6,%%ymm2,%%ymm2          \n"
344
0
      "vpor        %%ymm6,%%ymm3,%%ymm3          \n"
345
0
      "vmovdqu     %%ymm0,(%1)                   \n"
346
0
      "vmovdqu     %%ymm1,0x20(%1)               \n"
347
0
      "vmovdqu     %%ymm2,0x40(%1)               \n"
348
0
      "vmovdqu     %%ymm3,0x60(%1)               \n"
349
0
      "lea         0x80(%1),%1                   \n"
350
0
      "sub         $0x20,%2                      \n"
351
0
      "jg          1b                            \n"
352
0
      "vzeroupper  \n"
353
0
      : "+r"(src_raw),                // %0
354
0
        "+r"(dst_argb),               // %1
355
0
        "+r"(width)                   // %2
356
0
      : "m"(kShuffleMaskRAWToARGB),   // %3
357
0
        "m"(kShuffleMaskRAWToARGB_0)  // %4
358
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
359
0
}
360
361
#ifdef HAS_RAWTOARGBROW_AVX512BW
362
static const uint32_t kPermdRAWToARGB_AVX512BW[16] = {
363
    0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12};
364
365
void RGBToARGBRow_AVX512BW(const uint8_t* src_raw,
366
                           uint8_t* dst_argb,
367
                           const uint32_t* shuffler,
368
0
                           int width) {
369
0
  asm volatile(
370
0
      "vpternlogd  $0xff,%%zmm6,%%zmm6,%%zmm6    \n"  // 0xffffffff
371
0
      "vpslld      $0x18,%%zmm6,%%zmm6           \n"  // 0xff000000
372
0
      "movabs      $0xffffffffffff,%%rax         \n"  // 48 bytes mask
373
0
      "kmovq       %%rax,%%k1                    \n"
374
0
      "vmovdqu32   %3,%%zmm5                     \n"
375
0
      "vbroadcasti32x4 %4,%%zmm4                 \n"
376
377
      LABELALIGN  //
378
0
      "1:          \n"
379
0
      "vmovdqu8    (%0),%%zmm0%{%%k1%}%{z%}      \n"
380
0
      "vmovdqu8    48(%0),%%zmm1%{%%k1%}%{z%}    \n"
381
0
      "vmovdqu8    96(%0),%%zmm2%{%%k1%}%{z%}    \n"
382
0
      "vmovdqu8    144(%0),%%zmm3%{%%k1%}%{z%}   \n"
383
0
      "lea         192(%0),%0                    \n"
384
0
      "vpermd      %%zmm0,%%zmm5,%%zmm0          \n"
385
0
      "vpermd      %%zmm1,%%zmm5,%%zmm1          \n"
386
0
      "vpermd      %%zmm2,%%zmm5,%%zmm2          \n"
387
0
      "vpermd      %%zmm3,%%zmm5,%%zmm3          \n"
388
0
      "vpshufb     %%zmm4,%%zmm0,%%zmm0          \n"
389
0
      "vpshufb     %%zmm4,%%zmm1,%%zmm1          \n"
390
0
      "vpshufb     %%zmm4,%%zmm2,%%zmm2          \n"
391
0
      "vpshufb     %%zmm4,%%zmm3,%%zmm3          \n"
392
0
      "vpord       %%zmm6,%%zmm0,%%zmm0          \n"
393
0
      "vpord       %%zmm6,%%zmm1,%%zmm1          \n"
394
0
      "vpord       %%zmm6,%%zmm2,%%zmm2          \n"
395
0
      "vpord       %%zmm6,%%zmm3,%%zmm3          \n"
396
0
      "vmovdqu32   %%zmm0,(%1)                   \n"
397
0
      "vmovdqu32   %%zmm1,0x40(%1)               \n"
398
0
      "vmovdqu32   %%zmm2,0x80(%1)               \n"
399
0
      "vmovdqu32   %%zmm3,0xc0(%1)               \n"
400
0
      "lea         0x100(%1),%1                  \n"
401
0
      "sub         $0x40,%2                      \n"
402
0
      "jg          1b                            \n"
403
0
      "vzeroupper  \n"
404
0
      : "+r"(src_raw),                  // %0
405
0
        "+r"(dst_argb),                 // %1
406
0
        "+r"(width)                     // %2
407
0
      : "m"(kPermdRAWToARGB_AVX512BW),  // %3
408
0
        "m"(*shuffler)                  // %4
409
0
      : "memory", "cc", "rax", "k1", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4",
410
0
        "xmm5", "xmm6");
411
0
}
412
413
void RAWToARGBRow_AVX512BW(const uint8_t* src_raw,
414
                           uint8_t* dst_argb,
415
0
                           int width) {
416
0
  RGBToARGBRow_AVX512BW(src_raw, dst_argb,
417
0
                        (const uint32_t*)&kShuffleMaskRAWToARGB, width);
418
0
}
419
420
void RGB24ToARGBRow_AVX512BW(const uint8_t* src_rgb24,
421
                             uint8_t* dst_argb,
422
0
                             int width) {
423
0
  RGBToARGBRow_AVX512BW(src_rgb24, dst_argb,
424
0
                        (const uint32_t*)&kShuffleMaskRGB24ToARGB[0], width);
425
0
}
426
#endif
427
428
// Same code as RAWToARGB with different shuffler and A in low bits
429
0
void RAWToRGBARow_SSSE3(const uint8_t* src_raw, uint8_t* dst_rgba, int width) {
430
0
  asm volatile(
431
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"  // 0x000000ff
432
0
      "psrld       $24,%%xmm5                    \n"
433
0
      "movdqa      %3,%%xmm4                     \n"
434
435
0
      LABELALIGN
436
0
      "1:          \n"
437
0
      "movdqu      (%0),%%xmm0                   \n"
438
0
      "movdqu      0x10(%0),%%xmm1               \n"
439
0
      "movdqu      0x20(%0),%%xmm3               \n"
440
0
      "lea         0x30(%0),%0                   \n"
441
0
      "movdqa      %%xmm3,%%xmm2                 \n"
442
0
      "palignr     $0x8,%%xmm1,%%xmm2            \n"
443
0
      "pshufb      %%xmm4,%%xmm2                 \n"
444
0
      "por         %%xmm5,%%xmm2                 \n"
445
0
      "palignr     $0xc,%%xmm0,%%xmm1            \n"
446
0
      "pshufb      %%xmm4,%%xmm0                 \n"
447
0
      "movdqu      %%xmm2,0x20(%1)               \n"
448
0
      "por         %%xmm5,%%xmm0                 \n"
449
0
      "pshufb      %%xmm4,%%xmm1                 \n"
450
0
      "movdqu      %%xmm0,(%1)                   \n"
451
0
      "por         %%xmm5,%%xmm1                 \n"
452
0
      "palignr     $0x4,%%xmm3,%%xmm3            \n"
453
0
      "pshufb      %%xmm4,%%xmm3                 \n"
454
0
      "movdqu      %%xmm1,0x10(%1)               \n"
455
0
      "por         %%xmm5,%%xmm3                 \n"
456
0
      "movdqu      %%xmm3,0x30(%1)               \n"
457
0
      "lea         0x40(%1),%1                   \n"
458
0
      "sub         $0x10,%2                      \n"
459
0
      "jg          1b                            \n"
460
0
      : "+r"(src_raw),              // %0
461
0
        "+r"(dst_rgba),             // %1
462
0
        "+r"(width)                 // %2
463
0
      : "m"(kShuffleMaskRAWToRGBA)  // %3
464
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
465
0
}
466
467
void RAWToRGB24Row_SSSE3(const uint8_t* src_raw,
468
                         uint8_t* dst_rgb24,
469
0
                         int width) {
470
0
  asm volatile(
471
0
      "movdqa      %3,%%xmm3                     \n"
472
0
      "movdqa      %4,%%xmm4                     \n"
473
0
      "movdqa      %5,%%xmm5                     \n"
474
475
0
      LABELALIGN
476
0
      "1:          \n"
477
0
      "movdqu      (%0),%%xmm0                   \n"
478
0
      "movdqu      0x4(%0),%%xmm1                \n"
479
0
      "movdqu      0x8(%0),%%xmm2                \n"
480
0
      "lea         0x18(%0),%0                   \n"
481
0
      "pshufb      %%xmm3,%%xmm0                 \n"
482
0
      "pshufb      %%xmm4,%%xmm1                 \n"
483
0
      "pshufb      %%xmm5,%%xmm2                 \n"
484
0
      "movq        %%xmm0,(%1)                   \n"
485
0
      "movq        %%xmm1,0x8(%1)                \n"
486
0
      "movq        %%xmm2,0x10(%1)               \n"
487
0
      "lea         0x18(%1),%1                   \n"
488
0
      "sub         $0x8,%2                       \n"
489
0
      "jg          1b                            \n"
490
0
      : "+r"(src_raw),                  // %0
491
0
        "+r"(dst_rgb24),                // %1
492
0
        "+r"(width)                     // %2
493
0
      : "m"(kShuffleMaskRAWToRGB24_0),  // %3
494
0
        "m"(kShuffleMaskRAWToRGB24_1),  // %4
495
0
        "m"(kShuffleMaskRAWToRGB24_2)   // %5
496
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
497
0
}
498
499
#ifdef HAS_RGB565TOARGBROW_AVX2
500
0
void RGB565ToARGBRow_AVX2(const uint8_t* src, uint8_t* dst, int width) {
501
0
  asm volatile(
502
0
      "mov         $0x1080108,%%eax              \n"
503
0
      "vmovd       %%eax,%%xmm5                  \n"
504
0
      "vpbroadcastd %%xmm5,%%ymm5                \n"
505
0
      "mov         $0x20802080,%%eax             \n"
506
0
      "vmovd       %%eax,%%xmm6                  \n"
507
0
      "vpbroadcastd %%xmm6,%%ymm6                \n"
508
0
      "vpcmpeqb    %%ymm3,%%ymm3,%%ymm3          \n"
509
0
      "vpsllw      $0xb,%%ymm3,%%ymm3            \n"
510
0
      "vpcmpeqb    %%ymm4,%%ymm4,%%ymm4          \n"
511
0
      "vpsllw      $10,%%ymm4,%%ymm4             \n"
512
0
      "vpsrlw      $5,%%ymm4,%%ymm4              \n"
513
0
      "vpcmpeqb    %%ymm7,%%ymm7,%%ymm7          \n"
514
0
      "vpsllw      $0x8,%%ymm7,%%ymm7            \n"
515
0
      "sub         %0,%1                         \n"
516
0
      "sub         %0,%1                         \n"
517
518
0
      LABELALIGN
519
0
      "1:          \n"
520
0
      "vmovdqu     (%0),%%ymm0                   \n"
521
0
      "vpand       %%ymm3,%%ymm0,%%ymm1          \n"
522
0
      "vpsllw      $0xb,%%ymm0,%%ymm2            \n"
523
0
      "vpmulhuw    %%ymm5,%%ymm1,%%ymm1          \n"
524
0
      "vpmulhuw    %%ymm5,%%ymm2,%%ymm2          \n"
525
0
      "vpsllw      $0x8,%%ymm1,%%ymm1            \n"
526
0
      "vpor        %%ymm2,%%ymm1,%%ymm1          \n"
527
0
      "vpand       %%ymm4,%%ymm0,%%ymm0          \n"
528
0
      "vpmulhuw    %%ymm6,%%ymm0,%%ymm0          \n"
529
0
      "vpor        %%ymm7,%%ymm0,%%ymm0          \n"
530
0
      "vpunpcklbw  %%ymm0,%%ymm1,%%ymm2          \n"
531
0
      "vpunpckhbw  %%ymm0,%%ymm1,%%ymm1          \n"
532
0
      "vperm2i128  $0x20,%%ymm1,%%ymm2,%%ymm0    \n"
533
0
      "vperm2i128  $0x31,%%ymm1,%%ymm2,%%ymm1    \n"
534
0
      "vmovdqu     %%ymm0,(%1,%0,2)              \n"
535
0
      "vmovdqu     %%ymm1,0x20(%1,%0,2)          \n"
536
0
      "lea         0x20(%0),%0                   \n"
537
0
      "sub         $0x10,%2                      \n"
538
0
      "jg          1b                            \n"
539
0
      "vzeroupper  \n"
540
0
      : "+r"(src),   // %0
541
0
        "+r"(dst),   // %1
542
0
        "+r"(width)  // %2
543
0
      :
544
0
      : "memory", "cc", "eax", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5",
545
0
        "xmm6", "xmm7");
546
0
}
547
#endif
548
549
#ifdef HAS_ARGB1555TOARGBROW_AVX2
550
0
void ARGB1555ToARGBRow_AVX2(const uint8_t* src, uint8_t* dst, int width) {
551
0
  asm volatile(
552
0
      "mov         $0x1080108,%%eax              \n"
553
0
      "vmovd       %%eax,%%xmm5                  \n"
554
0
      "vpbroadcastd %%xmm5,%%ymm5                \n"
555
0
      "mov         $0x42004200,%%eax             \n"
556
0
      "vmovd       %%eax,%%xmm6                  \n"
557
0
      "vpbroadcastd %%xmm6,%%ymm6                \n"
558
0
      "vpcmpeqb    %%ymm3,%%ymm3,%%ymm3          \n"
559
0
      "vpsllw      $0xb,%%ymm3,%%ymm3            \n"
560
0
      "vpsrlw      $0x6,%%ymm3,%%ymm4            \n"
561
0
      "vpcmpeqb    %%ymm7,%%ymm7,%%ymm7          \n"
562
0
      "vpsllw      $0x8,%%ymm7,%%ymm7            \n"
563
0
      "sub         %0,%1                         \n"
564
0
      "sub         %0,%1                         \n"
565
566
0
      LABELALIGN
567
0
      "1:          \n"
568
0
      "vmovdqu     (%0),%%ymm0                   \n"
569
0
      "vpsllw      $0x1,%%ymm0,%%ymm1            \n"
570
0
      "vpsllw      $0xb,%%ymm0,%%ymm2            \n"
571
0
      "vpand       %%ymm3,%%ymm1,%%ymm1          \n"
572
0
      "vpmulhuw    %%ymm5,%%ymm2,%%ymm2          \n"
573
0
      "vpmulhuw    %%ymm5,%%ymm1,%%ymm1          \n"
574
0
      "vpsllw      $0x8,%%ymm1,%%ymm1            \n"
575
0
      "vpor        %%ymm2,%%ymm1,%%ymm1          \n"
576
0
      "vpsraw      $0x8,%%ymm0,%%ymm2            \n"
577
0
      "vpand       %%ymm4,%%ymm0,%%ymm0          \n"
578
0
      "vpmulhuw    %%ymm6,%%ymm0,%%ymm0          \n"
579
0
      "vpand       %%ymm7,%%ymm2,%%ymm2          \n"
580
0
      "vpor        %%ymm2,%%ymm0,%%ymm0          \n"
581
0
      "vpunpcklbw  %%ymm0,%%ymm1,%%ymm2          \n"
582
0
      "vpunpckhbw  %%ymm0,%%ymm1,%%ymm1          \n"
583
0
      "vperm2i128  $0x20,%%ymm1,%%ymm2,%%ymm0    \n"
584
0
      "vperm2i128  $0x31,%%ymm1,%%ymm2,%%ymm1    \n"
585
0
      "vmovdqu     %%ymm0,(%1,%0,2)              \n"
586
0
      "vmovdqu     %%ymm1,0x20(%1,%0,2)          \n"
587
0
      "lea         0x20(%0),%0                   \n"
588
0
      "sub         $0x10,%2                      \n"
589
0
      "jg          1b                            \n"
590
0
      "vzeroupper  \n"
591
0
      : "+r"(src),   // %0
592
0
        "+r"(dst),   // %1
593
0
        "+r"(width)  // %2
594
0
      :
595
0
      : "memory", "cc", "eax", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5",
596
0
        "xmm6", "xmm7");
597
0
}
598
#endif
599
600
#ifdef HAS_ARGB4444TOARGBROW_AVX2
601
0
void ARGB4444ToARGBRow_AVX2(const uint8_t* src, uint8_t* dst, int width) {
602
0
  asm volatile(
603
0
      "mov         $0x0f0f0f0f,%%eax             \n"
604
0
      "vmovd       %%eax,%%xmm4                  \n"
605
0
      "vpbroadcastd %%xmm4,%%ymm4                \n"
606
0
      "vpslld      $0x4,%%ymm4,%%ymm5            \n"
607
0
      "sub         %0,%1                         \n"
608
0
      "sub         %0,%1                         \n"
609
610
0
      LABELALIGN
611
0
      "1:          \n"
612
0
      "vmovdqu     (%0),%%ymm0                   \n"
613
0
      "vpand       %%ymm5,%%ymm0,%%ymm2          \n"
614
0
      "vpand       %%ymm4,%%ymm0,%%ymm0          \n"
615
0
      "vpsllw      $0x4,%%ymm0,%%ymm1            \n"
616
0
      "vpsrlw      $0x4,%%ymm2,%%ymm3            \n"
617
0
      "vpor        %%ymm1,%%ymm0,%%ymm0          \n"
618
0
      "vpor        %%ymm3,%%ymm2,%%ymm2          \n"
619
0
      "vpunpckhbw  %%ymm2,%%ymm0,%%ymm1          \n"
620
0
      "vpunpcklbw  %%ymm2,%%ymm0,%%ymm0          \n"
621
0
      "vperm2i128  $0x20,%%ymm1,%%ymm0,%%ymm2    \n"
622
0
      "vperm2i128  $0x31,%%ymm1,%%ymm0,%%ymm1    \n"
623
0
      "vmovdqu     %%ymm2,(%1,%0,2)              \n"
624
0
      "vmovdqu     %%ymm1,0x20(%1,%0,2)          \n"
625
0
      "lea         0x20(%0),%0                   \n"
626
0
      "sub         $0x10,%2                      \n"
627
0
      "jg          1b                            \n"
628
0
      "vzeroupper  \n"
629
0
      : "+r"(src),   // %0
630
0
        "+r"(dst),   // %1
631
0
        "+r"(width)  // %2
632
0
      :
633
0
      : "memory", "cc", "eax", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
634
0
}
635
#endif
636
637
0
void ARGBToRGB24Row_SSSE3(const uint8_t* src, uint8_t* dst, int width) {
638
0
  asm volatile("movdqa      %3,%%xmm6                     \n"
639
640
0
               LABELALIGN
641
0
               "1:          \n"
642
0
               "movdqu      (%0),%%xmm0                   \n"
643
0
               "movdqu      0x10(%0),%%xmm1               \n"
644
0
               "movdqu      0x20(%0),%%xmm2               \n"
645
0
               "movdqu      0x30(%0),%%xmm3               \n"
646
0
               "lea         0x40(%0),%0                   \n"
647
0
               "pshufb      %%xmm6,%%xmm0                 \n"
648
0
               "pshufb      %%xmm6,%%xmm1                 \n"
649
0
               "pshufb      %%xmm6,%%xmm2                 \n"
650
0
               "pshufb      %%xmm6,%%xmm3                 \n"
651
0
               "movdqa      %%xmm1,%%xmm4                 \n"
652
0
               "psrldq      $0x4,%%xmm1                   \n"
653
0
               "pslldq      $0xc,%%xmm4                   \n"
654
0
               "movdqa      %%xmm2,%%xmm5                 \n"
655
0
               "por         %%xmm4,%%xmm0                 \n"
656
0
               "pslldq      $0x8,%%xmm5                   \n"
657
0
               "movdqu      %%xmm0,(%1)                   \n"
658
0
               "por         %%xmm5,%%xmm1                 \n"
659
0
               "psrldq      $0x8,%%xmm2                   \n"
660
0
               "pslldq      $0x4,%%xmm3                   \n"
661
0
               "por         %%xmm3,%%xmm2                 \n"
662
0
               "movdqu      %%xmm1,0x10(%1)               \n"
663
0
               "movdqu      %%xmm2,0x20(%1)               \n"
664
0
               "lea         0x30(%1),%1                   \n"
665
0
               "sub         $0x10,%2                      \n"
666
0
               "jg          1b                            \n"
667
0
               : "+r"(src),                    // %0
668
0
                 "+r"(dst),                    // %1
669
0
                 "+r"(width)                   // %2
670
0
               : "m"(kShuffleMaskARGBToRGB24)  // %3
671
0
               : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5",
672
0
                 "xmm6");
673
0
}
674
675
0
void ARGBToRAWRow_SSSE3(const uint8_t* src, uint8_t* dst, int width) {
676
0
  asm volatile("movdqa      %3,%%xmm6                     \n"
677
678
0
               LABELALIGN
679
0
               "1:          \n"
680
0
               "movdqu      (%0),%%xmm0                   \n"
681
0
               "movdqu      0x10(%0),%%xmm1               \n"
682
0
               "movdqu      0x20(%0),%%xmm2               \n"
683
0
               "movdqu      0x30(%0),%%xmm3               \n"
684
0
               "lea         0x40(%0),%0                   \n"
685
0
               "pshufb      %%xmm6,%%xmm0                 \n"
686
0
               "pshufb      %%xmm6,%%xmm1                 \n"
687
0
               "pshufb      %%xmm6,%%xmm2                 \n"
688
0
               "pshufb      %%xmm6,%%xmm3                 \n"
689
0
               "movdqa      %%xmm1,%%xmm4                 \n"
690
0
               "psrldq      $0x4,%%xmm1                   \n"
691
0
               "pslldq      $0xc,%%xmm4                   \n"
692
0
               "movdqa      %%xmm2,%%xmm5                 \n"
693
0
               "por         %%xmm4,%%xmm0                 \n"
694
0
               "pslldq      $0x8,%%xmm5                   \n"
695
0
               "movdqu      %%xmm0,(%1)                   \n"
696
0
               "por         %%xmm5,%%xmm1                 \n"
697
0
               "psrldq      $0x8,%%xmm2                   \n"
698
0
               "pslldq      $0x4,%%xmm3                   \n"
699
0
               "por         %%xmm3,%%xmm2                 \n"
700
0
               "movdqu      %%xmm1,0x10(%1)               \n"
701
0
               "movdqu      %%xmm2,0x20(%1)               \n"
702
0
               "lea         0x30(%1),%1                   \n"
703
0
               "sub         $0x10,%2                      \n"
704
0
               "jg          1b                            \n"
705
0
               : "+r"(src),                  // %0
706
0
                 "+r"(dst),                  // %1
707
0
                 "+r"(width)                 // %2
708
0
               : "m"(kShuffleMaskARGBToRAW)  // %3
709
0
               : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5",
710
0
                 "xmm6");
711
0
}
712
713
#ifdef HAS_ARGBTORGB24ROW_AVX2
714
// vpermd for 12+12 to 24
715
static const lvec32 kPermdRGB24_AVX = {0, 1, 2, 4, 5, 6, 3, 7};
716
717
10.3k
void ARGBToRGB24Row_AVX2(const uint8_t* src, uint8_t* dst, int width) {
718
10.3k
  asm volatile(
719
10.3k
      "vbroadcasti128 %3,%%ymm6                  \n"
720
10.3k
      "vmovdqa     %4,%%ymm7                     \n"
721
722
10.3k
      LABELALIGN
723
10.3k
      "1:          \n"
724
10.3k
      "vmovdqu     (%0),%%ymm0                   \n"
725
10.3k
      "vmovdqu     0x20(%0),%%ymm1               \n"
726
10.3k
      "vmovdqu     0x40(%0),%%ymm2               \n"
727
10.3k
      "vmovdqu     0x60(%0),%%ymm3               \n"
728
10.3k
      "lea         0x80(%0),%0                   \n"
729
10.3k
      "vpshufb     %%ymm6,%%ymm0,%%ymm0          \n"  // xxx0yyy0
730
10.3k
      "vpshufb     %%ymm6,%%ymm1,%%ymm1          \n"
731
10.3k
      "vpshufb     %%ymm6,%%ymm2,%%ymm2          \n"
732
10.3k
      "vpshufb     %%ymm6,%%ymm3,%%ymm3          \n"
733
10.3k
      "vpermd      %%ymm0,%%ymm7,%%ymm0          \n"  // pack to 24 bytes
734
10.3k
      "vpermd      %%ymm1,%%ymm7,%%ymm1          \n"
735
10.3k
      "vpermd      %%ymm2,%%ymm7,%%ymm2          \n"
736
10.3k
      "vpermd      %%ymm3,%%ymm7,%%ymm3          \n"
737
10.3k
      "vpermq      $0x3f,%%ymm1,%%ymm4           \n"  // combine 24 + 8
738
10.3k
      "vpor        %%ymm4,%%ymm0,%%ymm0          \n"
739
10.3k
      "vmovdqu     %%ymm0,(%1)                   \n"
740
10.3k
      "vpermq      $0xf9,%%ymm1,%%ymm1           \n"  // combine 16 + 16
741
10.3k
      "vpermq      $0x4f,%%ymm2,%%ymm4           \n"
742
10.3k
      "vpor        %%ymm4,%%ymm1,%%ymm1          \n"
743
10.3k
      "vmovdqu     %%ymm1,0x20(%1)               \n"
744
10.3k
      "vpermq      $0xfe,%%ymm2,%%ymm2           \n"  // combine 8 + 24
745
10.3k
      "vpermq      $0x93,%%ymm3,%%ymm3           \n"
746
10.3k
      "vpor        %%ymm3,%%ymm2,%%ymm2          \n"
747
10.3k
      "vmovdqu     %%ymm2,0x40(%1)               \n"
748
10.3k
      "lea         0x60(%1),%1                   \n"
749
10.3k
      "sub         $0x20,%2                      \n"
750
10.3k
      "jg          1b                            \n"
751
10.3k
      "vzeroupper  \n"
752
10.3k
      : "+r"(src),                     // %0
753
10.3k
        "+r"(dst),                     // %1
754
10.3k
        "+r"(width)                    // %2
755
10.3k
      : "m"(kShuffleMaskARGBToRGB24),  // %3
756
10.3k
        "m"(kPermdRGB24_AVX)           // %4
757
10.3k
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
758
10.3k
        "xmm7");
759
10.3k
}
760
#endif
761
762
#ifdef HAS_ARGBTORGB24ROW_AVX512VBMI
763
// Shuffle table for converting ARGBToRGB24
764
static const ulvec8 kPermARGBToRGB24_0 = {
765
    0u,  1u,  2u,  4u,  5u,  6u,  8u,  9u,  10u, 12u, 13u,
766
    14u, 16u, 17u, 18u, 20u, 21u, 22u, 24u, 25u, 26u, 28u,
767
    29u, 30u, 32u, 33u, 34u, 36u, 37u, 38u, 40u, 41u};
768
static const ulvec8 kPermARGBToRGB24_1 = {
769
    10u, 12u, 13u, 14u, 16u, 17u, 18u, 20u, 21u, 22u, 24u,
770
    25u, 26u, 28u, 29u, 30u, 32u, 33u, 34u, 36u, 37u, 38u,
771
    40u, 41u, 42u, 44u, 45u, 46u, 48u, 49u, 50u, 52u};
772
static const ulvec8 kPermARGBToRGB24_2 = {
773
    21u, 22u, 24u, 25u, 26u, 28u, 29u, 30u, 32u, 33u, 34u,
774
    36u, 37u, 38u, 40u, 41u, 42u, 44u, 45u, 46u, 48u, 49u,
775
    50u, 52u, 53u, 54u, 56u, 57u, 58u, 60u, 61u, 62u};
776
777
0
void ARGBToRGB24Row_AVX512VBMI(const uint8_t* src, uint8_t* dst, int width) {
778
0
  asm volatile(
779
0
      "vmovdqa     %3,%%ymm5                     \n"
780
0
      "vmovdqa     %4,%%ymm6                     \n"
781
0
      "vmovdqa     %5,%%ymm7                     \n"
782
783
0
      LABELALIGN
784
0
      "1:          \n"
785
0
      "vmovdqu     (%0),%%ymm0                   \n"
786
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
787
0
      "vmovdqu     0x40(%0),%%ymm2               \n"
788
0
      "vmovdqu     0x60(%0),%%ymm3               \n"
789
0
      "lea         0x80(%0),%0                   \n"
790
0
      "vpermt2b    %%ymm1,%%ymm5,%%ymm0          \n"
791
0
      "vpermt2b    %%ymm2,%%ymm6,%%ymm1          \n"
792
0
      "vpermt2b    %%ymm3,%%ymm7,%%ymm2          \n"
793
0
      "vmovdqu     %%ymm0,(%1)                   \n"
794
0
      "vmovdqu     %%ymm1,0x20(%1)               \n"
795
0
      "vmovdqu     %%ymm2,0x40(%1)               \n"
796
0
      "lea         0x60(%1),%1                   \n"
797
0
      "sub         $0x20,%2                      \n"
798
0
      "jg          1b                            \n"
799
0
      "vzeroupper  \n"
800
0
      : "+r"(src),                // %0
801
0
        "+r"(dst),                // %1
802
0
        "+r"(width)               // %2
803
0
      : "m"(kPermARGBToRGB24_0),  // %3
804
0
        "m"(kPermARGBToRGB24_1),  // %4
805
0
        "m"(kPermARGBToRGB24_2)   // %5
806
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5", "xmm6", "xmm7");
807
0
}
808
#endif
809
810
#ifdef HAS_ARGBTORAWROW_AVX2
811
0
void ARGBToRAWRow_AVX2(const uint8_t* src, uint8_t* dst, int width) {
812
0
  asm volatile(
813
0
      "vbroadcasti128 %3,%%ymm6                  \n"
814
0
      "vmovdqa     %4,%%ymm7                     \n"
815
816
0
      LABELALIGN
817
0
      "1:          \n"
818
0
      "vmovdqu     (%0),%%ymm0                   \n"
819
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
820
0
      "vmovdqu     0x40(%0),%%ymm2               \n"
821
0
      "vmovdqu     0x60(%0),%%ymm3               \n"
822
0
      "lea         0x80(%0),%0                   \n"
823
0
      "vpshufb     %%ymm6,%%ymm0,%%ymm0          \n"  // xxx0yyy0
824
0
      "vpshufb     %%ymm6,%%ymm1,%%ymm1          \n"
825
0
      "vpshufb     %%ymm6,%%ymm2,%%ymm2          \n"
826
0
      "vpshufb     %%ymm6,%%ymm3,%%ymm3          \n"
827
0
      "vpermd      %%ymm0,%%ymm7,%%ymm0          \n"  // pack to 24 bytes
828
0
      "vpermd      %%ymm1,%%ymm7,%%ymm1          \n"
829
0
      "vpermd      %%ymm2,%%ymm7,%%ymm2          \n"
830
0
      "vpermd      %%ymm3,%%ymm7,%%ymm3          \n"
831
0
      "vpermq      $0x3f,%%ymm1,%%ymm4           \n"  // combine 24 + 8
832
0
      "vpor        %%ymm4,%%ymm0,%%ymm0          \n"
833
0
      "vmovdqu     %%ymm0,(%1)                   \n"
834
0
      "vpermq      $0xf9,%%ymm1,%%ymm1           \n"  // combine 16 + 16
835
0
      "vpermq      $0x4f,%%ymm2,%%ymm4           \n"
836
0
      "vpor        %%ymm4,%%ymm1,%%ymm1          \n"
837
0
      "vmovdqu     %%ymm1,0x20(%1)               \n"
838
0
      "vpermq      $0xfe,%%ymm2,%%ymm2           \n"  // combine 8 + 24
839
0
      "vpermq      $0x93,%%ymm3,%%ymm3           \n"
840
0
      "vpor        %%ymm3,%%ymm2,%%ymm2          \n"
841
0
      "vmovdqu     %%ymm2,0x40(%1)               \n"
842
0
      "lea         0x60(%1),%1                   \n"
843
0
      "sub         $0x20,%2                      \n"
844
0
      "jg          1b                            \n"
845
0
      "vzeroupper  \n"
846
0
      : "+r"(src),                   // %0
847
0
        "+r"(dst),                   // %1
848
0
        "+r"(width)                  // %2
849
0
      : "m"(kShuffleMaskARGBToRAW),  // %3
850
0
        "m"(kPermdRGB24_AVX)         // %4
851
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
852
0
        "xmm7");
853
0
}
854
#endif
855
856
#ifdef HAS_ARGBTORGB565DITHERROW_AVX2
857
void ARGBToRGB565DitherRow_AVX2(const uint8_t* src,
858
                                uint8_t* dst,
859
                                uint32_t dither4,
860
0
                                int width) {
861
0
  asm volatile(
862
0
      "vbroadcastss %3,%%xmm6                    \n"
863
0
      "vpunpcklbw  %%xmm6,%%xmm6,%%xmm6          \n"
864
0
      "vpermq      $0xd8,%%ymm6,%%ymm6           \n"
865
0
      "vpunpcklwd  %%ymm6,%%ymm6,%%ymm6          \n"
866
0
      "vpcmpeqb    %%ymm3,%%ymm3,%%ymm3          \n"
867
0
      "vpsrld      $0x1b,%%ymm3,%%ymm3           \n"
868
0
      "vpcmpeqb    %%ymm4,%%ymm4,%%ymm4          \n"
869
0
      "vpsrld      $0x1a,%%ymm4,%%ymm4           \n"
870
0
      "vpslld      $0x5,%%ymm4,%%ymm4            \n"
871
0
      "vpslld      $0xb,%%ymm3,%%ymm5            \n"
872
873
0
      LABELALIGN
874
0
      "1:          \n"
875
0
      "vmovdqu     (%0),%%ymm0                   \n"
876
0
      "vpaddusb    %%ymm6,%%ymm0,%%ymm0          \n"
877
0
      "vpsrld      $0x5,%%ymm0,%%ymm2            \n"
878
0
      "vpsrld      $0x3,%%ymm0,%%ymm1            \n"
879
0
      "vpsrld      $0x8,%%ymm0,%%ymm0            \n"
880
0
      "vpand       %%ymm4,%%ymm2,%%ymm2          \n"
881
0
      "vpand       %%ymm3,%%ymm1,%%ymm1          \n"
882
0
      "vpand       %%ymm5,%%ymm0,%%ymm0          \n"
883
0
      "vpor        %%ymm2,%%ymm1,%%ymm1          \n"
884
0
      "vpor        %%ymm1,%%ymm0,%%ymm0          \n"
885
0
      "vpackusdw   %%ymm0,%%ymm0,%%ymm0          \n"
886
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
887
0
      "lea         0x20(%0),%0                   \n"
888
0
      "vmovdqu     %%xmm0,(%1)                   \n"
889
0
      "lea         0x10(%1),%1                   \n"
890
0
      "sub         $0x8,%2                       \n"
891
0
      "jg          1b                            \n"
892
0
      "vzeroupper  \n"
893
0
      : "+r"(src),    // %0
894
0
        "+r"(dst),    // %1
895
0
        "+r"(width)   // %2
896
0
      : "m"(dither4)  // %3
897
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
898
0
        "xmm7");
899
0
}
900
#endif  // HAS_ARGBTORGB565DITHERROW_AVX2
901
902
#endif  // HAS_RGB24TOARGBROW_SSSE3
903
904
/*
905
906
ARGBToAR30Row:
907
908
Red Blue
909
With the 8 bit value in the upper bits of a short, vpmulhuw by (1024+4) will
910
produce a 10 bit value in the low 10 bits of each 16 bit value. This is whats
911
wanted for the blue channel. The red needs to be shifted 4 left, so multiply by
912
(1024+4)*16 for red.
913
914
Alpha Green
915
Alpha and Green are already in the high bits so vpand can zero out the other
916
bits, keeping just 2 upper bits of alpha and 8 bit green. The same multiplier
917
could be used for Green - (1024+4) putting the 10 bit green in the lsb.  Alpha
918
would be a simple multiplier to shift it into position.  It wants a gap of 10
919
above the green.  Green is 10 bits, so there are 6 bits in the low short.  4
920
more are needed, so a multiplier of 4 gets the 2 bits into the upper 16 bits,
921
and then a shift of 4 is a multiply of 16, so (4*16) = 64.  Then shift the
922
result left 10 to position the A and G channels.
923
*/
924
925
// Shuffle table for converting RAW to RGB24.  Last 8.
926
static const uvec8 kShuffleRB30 = {128u, 0u, 128u, 2u,  128u, 4u,  128u, 6u,
927
                                   128u, 8u, 128u, 10u, 128u, 12u, 128u, 14u};
928
929
static const uvec8 kShuffleBR30 = {128u, 2u,  128u, 0u, 128u, 6u,  128u, 4u,
930
                                   128u, 10u, 128u, 8u, 128u, 14u, 128u, 12u};
931
932
static const uint32_t kMulRB10 = 1028 * 16 * 65536 + 1028;
933
static const uint32_t kMaskRB10 = 0x3ff003ff;
934
static const uint32_t kMaskAG10 = 0xc000ff00;
935
static const uint32_t kMulAG10 = 64 * 65536 + 1028;
936
937
0
void ARGBToAR30Row_SSSE3(const uint8_t* src, uint8_t* dst, int width) {
938
0
  asm volatile(
939
0
      "movdqa      %3,%%xmm2                     \n"  // shuffler for RB
940
0
      "movd        %4,%%xmm3                     \n"  // multipler for RB
941
0
      "movd        %5,%%xmm4                     \n"  // mask for R10 B10
942
0
      "movd        %6,%%xmm5                     \n"  // mask for AG
943
0
      "movd        %7,%%xmm6                     \n"  // multipler for AG
944
0
      "pshufd      $0x0,%%xmm3,%%xmm3            \n"
945
0
      "pshufd      $0x0,%%xmm4,%%xmm4            \n"
946
0
      "pshufd      $0x0,%%xmm5,%%xmm5            \n"
947
0
      "pshufd      $0x0,%%xmm6,%%xmm6            \n"
948
0
      "sub         %0,%1                         \n"
949
950
0
      "1:          \n"
951
0
      "movdqu      (%0),%%xmm0                   \n"  // fetch 4 ARGB pixels
952
0
      "movdqa      %%xmm0,%%xmm1                 \n"
953
0
      "pshufb      %%xmm2,%%xmm1                 \n"  // R0B0
954
0
      "pand        %%xmm5,%%xmm0                 \n"  // A0G0
955
0
      "pmulhuw     %%xmm3,%%xmm1                 \n"  // X2 R16 X4  B10
956
0
      "pmulhuw     %%xmm6,%%xmm0                 \n"  // X10 A2 X10 G10
957
0
      "pand        %%xmm4,%%xmm1                 \n"  // X2 R10 X10 B10
958
0
      "pslld       $10,%%xmm0                    \n"  // A2 x10 G10 x10
959
0
      "por         %%xmm1,%%xmm0                 \n"  // A2 R10 G10 B10
960
0
      "movdqu      %%xmm0,(%1,%0)                \n"  // store 4 AR30 pixels
961
0
      "add         $0x10,%0                      \n"
962
0
      "sub         $0x4,%2                       \n"
963
0
      "jg          1b                            \n"
964
965
0
      : "+r"(src),          // %0
966
0
        "+r"(dst),          // %1
967
0
        "+r"(width)         // %2
968
0
      : "m"(kShuffleRB30),  // %3
969
0
        "m"(kMulRB10),      // %4
970
0
        "m"(kMaskRB10),     // %5
971
0
        "m"(kMaskAG10),     // %6
972
0
        "m"(kMulAG10)       // %7
973
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
974
0
}
975
976
0
void ABGRToAR30Row_SSSE3(const uint8_t* src, uint8_t* dst, int width) {
977
0
  asm volatile(
978
0
      "movdqa      %3,%%xmm2                     \n"  // shuffler for RB
979
0
      "movd        %4,%%xmm3                     \n"  // multipler for RB
980
0
      "movd        %5,%%xmm4                     \n"  // mask for R10 B10
981
0
      "movd        %6,%%xmm5                     \n"  // mask for AG
982
0
      "movd        %7,%%xmm6                     \n"  // multipler for AG
983
0
      "pshufd      $0x0,%%xmm3,%%xmm3            \n"
984
0
      "pshufd      $0x0,%%xmm4,%%xmm4            \n"
985
0
      "pshufd      $0x0,%%xmm5,%%xmm5            \n"
986
0
      "pshufd      $0x0,%%xmm6,%%xmm6            \n"
987
0
      "sub         %0,%1                         \n"
988
989
0
      "1:          \n"
990
0
      "movdqu      (%0),%%xmm0                   \n"  // fetch 4 ABGR pixels
991
0
      "movdqa      %%xmm0,%%xmm1                 \n"
992
0
      "pshufb      %%xmm2,%%xmm1                 \n"  // R0B0
993
0
      "pand        %%xmm5,%%xmm0                 \n"  // A0G0
994
0
      "pmulhuw     %%xmm3,%%xmm1                 \n"  // X2 R16 X4  B10
995
0
      "pmulhuw     %%xmm6,%%xmm0                 \n"  // X10 A2 X10 G10
996
0
      "pand        %%xmm4,%%xmm1                 \n"  // X2 R10 X10 B10
997
0
      "pslld       $10,%%xmm0                    \n"  // A2 x10 G10 x10
998
0
      "por         %%xmm1,%%xmm0                 \n"  // A2 R10 G10 B10
999
0
      "movdqu      %%xmm0,(%1,%0)                \n"  // store 4 AR30 pixels
1000
0
      "add         $0x10,%0                      \n"
1001
0
      "sub         $0x4,%2                       \n"
1002
0
      "jg          1b                            \n"
1003
1004
0
      : "+r"(src),          // %0
1005
0
        "+r"(dst),          // %1
1006
0
        "+r"(width)         // %2
1007
0
      : "m"(kShuffleBR30),  // %3  reversed shuffler
1008
0
        "m"(kMulRB10),      // %4
1009
0
        "m"(kMaskRB10),     // %5
1010
0
        "m"(kMaskAG10),     // %6
1011
0
        "m"(kMulAG10)       // %7
1012
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
1013
0
}
1014
1015
#ifdef HAS_ARGBTOAR30ROW_AVX2
1016
0
void ARGBToAR30Row_AVX2(const uint8_t* src, uint8_t* dst, int width) {
1017
0
  asm volatile(
1018
0
      "vbroadcasti128 %3,%%ymm2                  \n"  // shuffler for RB
1019
0
      "vbroadcastss %4,%%ymm3                    \n"  // multipler for RB
1020
0
      "vbroadcastss %5,%%ymm4                    \n"  // mask for R10 B10
1021
0
      "vbroadcastss %6,%%ymm5                    \n"  // mask for AG
1022
0
      "vbroadcastss %7,%%ymm6                    \n"  // multipler for AG
1023
0
      "sub         %0,%1                         \n"
1024
1025
0
      "1:          \n"
1026
0
      "vmovdqu     (%0),%%ymm0                   \n"  // fetch 8 ARGB pixels
1027
0
      "vpshufb     %%ymm2,%%ymm0,%%ymm1          \n"  // R0B0
1028
0
      "vpand       %%ymm5,%%ymm0,%%ymm0          \n"  // A0G0
1029
0
      "vpmulhuw    %%ymm3,%%ymm1,%%ymm1          \n"  // X2 R16 X4  B10
1030
0
      "vpmulhuw    %%ymm6,%%ymm0,%%ymm0          \n"  // X10 A2 X10 G10
1031
0
      "vpand       %%ymm4,%%ymm1,%%ymm1          \n"  // X2 R10 X10 B10
1032
0
      "vpslld      $10,%%ymm0,%%ymm0             \n"  // A2 x10 G10 x10
1033
0
      "vpor        %%ymm1,%%ymm0,%%ymm0          \n"  // A2 R10 G10 B10
1034
0
      "vmovdqu     %%ymm0,(%1,%0)                \n"  // store 8 AR30 pixels
1035
0
      "add         $0x20,%0                      \n"
1036
0
      "sub         $0x8,%2                       \n"
1037
0
      "jg          1b                            \n"
1038
0
      "vzeroupper  \n"
1039
1040
0
      : "+r"(src),          // %0
1041
0
        "+r"(dst),          // %1
1042
0
        "+r"(width)         // %2
1043
0
      : "m"(kShuffleRB30),  // %3
1044
0
        "m"(kMulRB10),      // %4
1045
0
        "m"(kMaskRB10),     // %5
1046
0
        "m"(kMaskAG10),     // %6
1047
0
        "m"(kMulAG10)       // %7
1048
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
1049
0
}
1050
#endif
1051
1052
#ifdef HAS_ABGRTOAR30ROW_AVX2
1053
0
void ABGRToAR30Row_AVX2(const uint8_t* src, uint8_t* dst, int width) {
1054
0
  asm volatile(
1055
0
      "vbroadcasti128 %3,%%ymm2                  \n"  // shuffler for RB
1056
0
      "vbroadcastss %4,%%ymm3                    \n"  // multipler for RB
1057
0
      "vbroadcastss %5,%%ymm4                    \n"  // mask for R10 B10
1058
0
      "vbroadcastss %6,%%ymm5                    \n"  // mask for AG
1059
0
      "vbroadcastss %7,%%ymm6                    \n"  // multipler for AG
1060
0
      "sub         %0,%1                         \n"
1061
1062
0
      "1:          \n"
1063
0
      "vmovdqu     (%0),%%ymm0                   \n"  // fetch 8 ABGR pixels
1064
0
      "vpshufb     %%ymm2,%%ymm0,%%ymm1          \n"  // R0B0
1065
0
      "vpand       %%ymm5,%%ymm0,%%ymm0          \n"  // A0G0
1066
0
      "vpmulhuw    %%ymm3,%%ymm1,%%ymm1          \n"  // X2 R16 X4  B10
1067
0
      "vpmulhuw    %%ymm6,%%ymm0,%%ymm0          \n"  // X10 A2 X10 G10
1068
0
      "vpand       %%ymm4,%%ymm1,%%ymm1          \n"  // X2 R10 X10 B10
1069
0
      "vpslld      $10,%%ymm0,%%ymm0             \n"  // A2 x10 G10 x10
1070
0
      "vpor        %%ymm1,%%ymm0,%%ymm0          \n"  // A2 R10 G10 B10
1071
0
      "vmovdqu     %%ymm0,(%1,%0)                \n"  // store 8 AR30 pixels
1072
0
      "add         $0x20,%0                      \n"
1073
0
      "sub         $0x8,%2                       \n"
1074
0
      "jg          1b                            \n"
1075
0
      "vzeroupper  \n"
1076
1077
0
      : "+r"(src),          // %0
1078
0
        "+r"(dst),          // %1
1079
0
        "+r"(width)         // %2
1080
0
      : "m"(kShuffleBR30),  // %3  reversed shuffler
1081
0
        "m"(kMulRB10),      // %4
1082
0
        "m"(kMaskRB10),     // %5
1083
0
        "m"(kMaskAG10),     // %6
1084
0
        "m"(kMulAG10)       // %7
1085
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
1086
0
}
1087
#endif
1088
1089
static const uvec8 kShuffleARGBToABGR = {2,  1, 0, 3,  6,  5,  4,  7,
1090
                                         10, 9, 8, 11, 14, 13, 12, 15};
1091
1092
static const uvec8 kShuffleARGBToAB64Lo = {2, 2, 1, 1, 0, 0, 3, 3,
1093
                                           6, 6, 5, 5, 4, 4, 7, 7};
1094
static const uvec8 kShuffleARGBToAB64Hi = {10, 10, 9,  9,  8,  8,  11, 11,
1095
                                           14, 14, 13, 13, 12, 12, 15, 15};
1096
1097
void ARGBToAR64Row_SSSE3(const uint8_t* src_argb,
1098
                         uint16_t* dst_ar64,
1099
0
                         int width) {
1100
0
  asm volatile(
1101
0
      "1:          \n"
1102
0
      "movdqu      (%0),%%xmm0                   \n"
1103
0
      "movdqa      %%xmm0,%%xmm1                 \n"
1104
0
      "punpcklbw   %%xmm0,%%xmm0                 \n"
1105
0
      "punpckhbw   %%xmm1,%%xmm1                 \n"
1106
0
      "movdqu      %%xmm0,(%1)                   \n"
1107
0
      "movdqu      %%xmm1,0x10(%1)               \n"
1108
0
      "lea         0x10(%0),%0                   \n"
1109
0
      "lea         0x20(%1),%1                   \n"
1110
0
      "sub         $0x4,%2                       \n"
1111
0
      "jg          1b                            \n"
1112
0
      : "+r"(src_argb),  // %0
1113
0
        "+r"(dst_ar64),  // %1
1114
0
        "+r"(width)      // %2
1115
0
        ::"memory",
1116
0
        "cc", "xmm0", "xmm1");
1117
0
}
1118
1119
void ARGBToAB64Row_SSSE3(const uint8_t* src_argb,
1120
                         uint16_t* dst_ab64,
1121
0
                         int width) {
1122
0
  asm volatile(
1123
0
      "movdqa      %3,%%xmm2                     \n"
1124
0
      "movdqa      %4,%%xmm3                     \n" LABELALIGN
1125
0
      "1:          \n"
1126
0
      "movdqu      (%0),%%xmm0                   \n"
1127
0
      "movdqa      %%xmm0,%%xmm1                 \n"
1128
0
      "pshufb      %%xmm2,%%xmm0                 \n"
1129
0
      "pshufb      %%xmm3,%%xmm1                 \n"
1130
0
      "movdqu      %%xmm0,(%1)                   \n"
1131
0
      "movdqu      %%xmm1,0x10(%1)               \n"
1132
0
      "lea         0x10(%0),%0                   \n"
1133
0
      "lea         0x20(%1),%1                   \n"
1134
0
      "sub         $0x4,%2                       \n"
1135
0
      "jg          1b                            \n"
1136
0
      : "+r"(src_argb),             // %0
1137
0
        "+r"(dst_ab64),             // %1
1138
0
        "+r"(width)                 // %2
1139
0
      : "m"(kShuffleARGBToAB64Lo),  // %3
1140
0
        "m"(kShuffleARGBToAB64Hi)   // %4
1141
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
1142
0
}
1143
1144
void AR64ToARGBRow_SSSE3(const uint16_t* src_ar64,
1145
                         uint8_t* dst_argb,
1146
0
                         int width) {
1147
0
  asm volatile(
1148
0
      "1:          \n"
1149
0
      "movdqu      (%0),%%xmm0                   \n"
1150
0
      "movdqu      0x10(%0),%%xmm1               \n"
1151
0
      "psrlw       $8,%%xmm0                     \n"
1152
0
      "psrlw       $8,%%xmm1                     \n"
1153
0
      "packuswb    %%xmm1,%%xmm0                 \n"
1154
0
      "movdqu      %%xmm0,(%1)                   \n"
1155
0
      "lea         0x20(%0),%0                   \n"
1156
0
      "lea         0x10(%1),%1                   \n"
1157
0
      "sub         $0x4,%2                       \n"
1158
0
      "jg          1b                            \n"
1159
0
      : "+r"(src_ar64),  // %0
1160
0
        "+r"(dst_argb),  // %1
1161
0
        "+r"(width)      // %2
1162
0
        ::"memory",
1163
0
        "cc", "xmm0", "xmm1");
1164
0
}
1165
1166
void AB64ToARGBRow_SSSE3(const uint16_t* src_ab64,
1167
                         uint8_t* dst_argb,
1168
0
                         int width) {
1169
0
  asm volatile("movdqa      %3,%%xmm2                     \n"
1170
1171
0
               LABELALIGN
1172
0
               "1:          \n"
1173
0
               "movdqu      (%0),%%xmm0                   \n"
1174
0
               "movdqu      0x10(%0),%%xmm1               \n"
1175
0
               "psrlw       $8,%%xmm0                     \n"
1176
0
               "psrlw       $8,%%xmm1                     \n"
1177
0
               "packuswb    %%xmm1,%%xmm0                 \n"
1178
0
               "pshufb      %%xmm2,%%xmm0                 \n"
1179
0
               "movdqu      %%xmm0,(%1)                   \n"
1180
0
               "lea         0x20(%0),%0                   \n"
1181
0
               "lea         0x10(%1),%1                   \n"
1182
0
               "sub         $0x4,%2                       \n"
1183
0
               "jg          1b                            \n"
1184
0
               : "+r"(src_ab64),          // %0
1185
0
                 "+r"(dst_argb),          // %1
1186
0
                 "+r"(width)              // %2
1187
0
               : "m"(kShuffleARGBToABGR)  // %3
1188
0
               : "memory", "cc", "xmm0", "xmm1", "xmm2");
1189
0
}
1190
1191
#ifdef HAS_ARGBTOAR64ROW_AVX2
1192
void ARGBToAR64Row_AVX2(const uint8_t* src_argb,
1193
                        uint16_t* dst_ar64,
1194
0
                        int width) {
1195
0
  asm volatile(
1196
0
      "1:          \n"
1197
0
      "vmovdqu     (%0),%%ymm0                   \n"
1198
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
1199
0
      "vpunpckhbw  %%ymm0,%%ymm0,%%ymm1          \n"
1200
0
      "vpunpcklbw  %%ymm0,%%ymm0,%%ymm0          \n"
1201
0
      "vmovdqu     %%ymm0,(%1)                   \n"
1202
0
      "vmovdqu     %%ymm1,0x20(%1)               \n"
1203
0
      "lea         0x20(%0),%0                   \n"
1204
0
      "lea         0x40(%1),%1                   \n"
1205
0
      "sub         $0x8,%2                       \n"
1206
0
      "jg          1b                            \n"
1207
0
      "vzeroupper  \n"
1208
0
      : "+r"(src_argb),  // %0
1209
0
        "+r"(dst_ar64),  // %1
1210
0
        "+r"(width)      // %2
1211
0
        ::"memory",
1212
0
        "cc", "xmm0", "xmm1");
1213
0
}
1214
#endif
1215
1216
#ifdef HAS_ARGBTOAB64ROW_AVX2
1217
void ARGBToAB64Row_AVX2(const uint8_t* src_argb,
1218
                        uint16_t* dst_ab64,
1219
0
                        int width) {
1220
0
  asm volatile(
1221
0
      "vbroadcasti128 %3,%%ymm2                  \n"
1222
0
      "vbroadcasti128 %4,%%ymm3                  \n" LABELALIGN
1223
0
      "1:          \n"
1224
0
      "vmovdqu     (%0),%%ymm0                   \n"
1225
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
1226
0
      "vpshufb     %%ymm3,%%ymm0,%%ymm1          \n"
1227
0
      "vpshufb     %%ymm2,%%ymm0,%%ymm0          \n"
1228
0
      "vmovdqu     %%ymm0,(%1)                   \n"
1229
0
      "vmovdqu     %%ymm1,0x20(%1)               \n"
1230
0
      "lea         0x20(%0),%0                   \n"
1231
0
      "lea         0x40(%1),%1                   \n"
1232
0
      "sub         $0x8,%2                       \n"
1233
0
      "jg          1b                            \n"
1234
0
      "vzeroupper  \n"
1235
0
      : "+r"(src_argb),             // %0
1236
0
        "+r"(dst_ab64),             // %1
1237
0
        "+r"(width)                 // %2
1238
0
      : "m"(kShuffleARGBToAB64Lo),  // %3
1239
0
        "m"(kShuffleARGBToAB64Hi)   // %3
1240
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
1241
0
}
1242
#endif
1243
1244
#ifdef HAS_AR64TOARGBROW_AVX2
1245
void AR64ToARGBRow_AVX2(const uint16_t* src_ar64,
1246
                        uint8_t* dst_argb,
1247
0
                        int width) {
1248
0
  asm volatile(
1249
0
      "1:          \n"
1250
0
      "vmovdqu     (%0),%%ymm0                   \n"
1251
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
1252
0
      "vpsrlw      $8,%%ymm0,%%ymm0              \n"
1253
0
      "vpsrlw      $8,%%ymm1,%%ymm1              \n"
1254
0
      "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"
1255
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
1256
0
      "vmovdqu     %%ymm0,(%1)                   \n"
1257
0
      "lea         0x40(%0),%0                   \n"
1258
0
      "lea         0x20(%1),%1                   \n"
1259
0
      "sub         $0x8,%2                       \n"
1260
0
      "jg          1b                            \n"
1261
0
      "vzeroupper  \n"
1262
0
      : "+r"(src_ar64),  // %0
1263
0
        "+r"(dst_argb),  // %1
1264
0
        "+r"(width)      // %2
1265
0
        ::"memory",
1266
0
        "cc", "xmm0", "xmm1");
1267
0
}
1268
#endif
1269
1270
#ifdef HAS_AB64TOARGBROW_AVX2
1271
void AB64ToARGBRow_AVX2(const uint16_t* src_ab64,
1272
                        uint8_t* dst_argb,
1273
0
                        int width) {
1274
0
  asm volatile("vbroadcasti128 %3,%%ymm2                  \n" LABELALIGN
1275
0
               "1:          \n"
1276
0
               "vmovdqu     (%0),%%ymm0                   \n"
1277
0
               "vmovdqu     0x20(%0),%%ymm1               \n"
1278
0
               "vpsrlw      $8,%%ymm0,%%ymm0              \n"
1279
0
               "vpsrlw      $8,%%ymm1,%%ymm1              \n"
1280
0
               "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"
1281
0
               "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
1282
0
               "vpshufb     %%ymm2,%%ymm0,%%ymm0          \n"
1283
0
               "vmovdqu     %%ymm0,(%1)                   \n"
1284
0
               "lea         0x40(%0),%0                   \n"
1285
0
               "lea         0x20(%1),%1                   \n"
1286
0
               "sub         $0x8,%2                       \n"
1287
0
               "jg          1b                            \n"
1288
0
               "vzeroupper  \n"
1289
0
               : "+r"(src_ab64),          // %0
1290
0
                 "+r"(dst_argb),          // %1
1291
0
                 "+r"(width)              // %2
1292
0
               : "m"(kShuffleARGBToABGR)  // %3
1293
0
               : "memory", "cc", "xmm0", "xmm1", "xmm2");
1294
0
}
1295
#endif
1296
1297
// clang-format off
1298
1299
// TODO(mraptis): Consider passing R, G, B multipliers as parameter.
1300
// round parameter is register containing value to add before shift.
1301
#define RGBTOY(round)                            \
1302
  "1:                                        \n" \
1303
  "movdqu    (%0),%%xmm0                     \n" \
1304
  "movdqu    0x10(%0),%%xmm1                 \n" \
1305
  "movdqu    0x20(%0),%%xmm2                 \n" \
1306
  "movdqu    0x30(%0),%%xmm3                 \n" \
1307
  "psubb     %%xmm5,%%xmm0                   \n" \
1308
  "psubb     %%xmm5,%%xmm1                   \n" \
1309
  "psubb     %%xmm5,%%xmm2                   \n" \
1310
  "psubb     %%xmm5,%%xmm3                   \n" \
1311
  "movdqu    %%xmm4,%%xmm6                   \n" \
1312
  "pmaddubsw %%xmm0,%%xmm6                   \n" \
1313
  "movdqu    %%xmm4,%%xmm0                   \n" \
1314
  "pmaddubsw %%xmm1,%%xmm0                   \n" \
1315
  "movdqu    %%xmm4,%%xmm1                   \n" \
1316
  "pmaddubsw %%xmm2,%%xmm1                   \n" \
1317
  "movdqu    %%xmm4,%%xmm2                   \n" \
1318
  "pmaddubsw %%xmm3,%%xmm2                   \n" \
1319
  "lea       0x40(%0),%0                     \n" \
1320
  "phaddw    %%xmm0,%%xmm6                   \n" \
1321
  "phaddw    %%xmm2,%%xmm1                   \n" \
1322
  "prefetcht0 1280(%0)                       \n" \
1323
  "paddw     %%" #round ",%%xmm6             \n" \
1324
  "paddw     %%" #round ",%%xmm1             \n" \
1325
  "psrlw     $0x8,%%xmm6                     \n" \
1326
  "psrlw     $0x8,%%xmm1                     \n" \
1327
  "packuswb  %%xmm1,%%xmm6                   \n" \
1328
  "movdqu    %%xmm6,(%1)                     \n" \
1329
  "lea       0x10(%1),%1                     \n" \
1330
  "sub       $0x10,%2                        \n" \
1331
  "jg        1b                              \n"
1332
1333
#define RGBTOY_AVX2(round)                                       \
1334
  "1:                                        \n"                 \
1335
  "vmovdqu    (%0),%%ymm0                    \n"                 \
1336
  "vmovdqu    0x20(%0),%%ymm1                \n"                 \
1337
  "vmovdqu    0x40(%0),%%ymm2                \n"                 \
1338
  "vmovdqu    0x60(%0),%%ymm3                \n"                 \
1339
  "vpsubb     %%ymm5, %%ymm0, %%ymm0         \n"                 \
1340
  "vpsubb     %%ymm5, %%ymm1, %%ymm1         \n"                 \
1341
  "vpsubb     %%ymm5, %%ymm2, %%ymm2         \n"                 \
1342
  "vpsubb     %%ymm5, %%ymm3, %%ymm3         \n"                 \
1343
  "vpmaddubsw %%ymm0,%%ymm4,%%ymm0           \n"                 \
1344
  "vpmaddubsw %%ymm1,%%ymm4,%%ymm1           \n"                 \
1345
  "vpmaddubsw %%ymm2,%%ymm4,%%ymm2           \n"                 \
1346
  "vpmaddubsw %%ymm3,%%ymm4,%%ymm3           \n"                 \
1347
  "lea       0x80(%0),%0                     \n"                 \
1348
  "vphaddw    %%ymm1,%%ymm0,%%ymm0           \n" /* mutates. */  \
1349
  "vphaddw    %%ymm3,%%ymm2,%%ymm2           \n"                 \
1350
  "prefetcht0 1280(%0)                       \n"                 \
1351
  "vpaddw     %%" #round ",%%ymm0,%%ymm0     \n" /* Add 16 */    \
1352
  "vpaddw     %%" #round ",%%ymm2,%%ymm2     \n"                 \
1353
  "vpsrlw     $0x8,%%ymm0,%%ymm0             \n"                 \
1354
  "vpsrlw     $0x8,%%ymm2,%%ymm2             \n"                 \
1355
  "vpackuswb  %%ymm2,%%ymm0,%%ymm0           \n" /* mutates. */  \
1356
  "vpermd     %%ymm0,%%ymm6,%%ymm0           \n" /* unmutate. */ \
1357
  "vmovdqu    %%ymm0,(%1)                    \n"                 \
1358
  "lea       0x20(%1),%1                     \n"                 \
1359
  "sub       $0x20,%2                        \n"                 \
1360
  "jg        1b                              \n"
1361
1362
// clang-format on
1363
1364
#ifdef HAS_ARGBTOYROW_SSSE3
1365
// Convert 16 ARGB pixels (64 bytes) to 16 Y values.
1366
1367
0
void ARGBToYRow_SSSE3(const uint8_t* src_argb, uint8_t* dst_y, int width) {
1368
0
  ARGBToYMatrixRow_SSSE3(src_argb, dst_y, width, &kArgbI601Constants);
1369
0
}
1370
#endif  // HAS_ARGBTOYROW_SSSE3
1371
1372
#ifdef HAS_ARGBTOYJROW_SSSE3
1373
// Convert 16 ARGB pixels (64 bytes) to 16 YJ values.
1374
// Same as ARGBToYRow but different coefficients, no add 16.
1375
0
void ARGBToYJRow_SSSE3(const uint8_t* src_argb, uint8_t* dst_y, int width) {
1376
0
  ARGBToYMatrixRow_SSSE3(src_argb, dst_y, width, &kArgbJPEGConstants);
1377
0
}
1378
#endif  // HAS_ARGBTOYJROW_SSSE3
1379
1380
#ifdef HAS_ABGRTOYJROW_SSSE3
1381
// Convert 16 ABGR pixels (64 bytes) to 16 YJ values.
1382
// Same as ABGRToYRow but different coefficients, no add 16.
1383
0
void ABGRToYJRow_SSSE3(const uint8_t* src_abgr, uint8_t* dst_y, int width) {
1384
0
  ARGBToYMatrixRow_SSSE3(src_abgr, dst_y, width, &kAbgrJPEGConstants);
1385
0
}
1386
#endif  // HAS_ABGRTOYJROW_SSSE3
1387
1388
#ifdef HAS_RGBATOYJROW_SSSE3
1389
// Convert 16 RGBA pixels (64 bytes) to 16 YJ values.
1390
// Same as ARGBToYRow but different coefficients, no add 16.
1391
0
void RGBAToYJRow_SSSE3(const uint8_t* src_rgba, uint8_t* dst_y, int width) {
1392
0
  ARGBToYMatrixRow_SSSE3(src_rgba, dst_y, width, &kRgbaJPEGConstants);
1393
0
}
1394
#endif  // HAS_RGBATOYJROW_SSSE3
1395
1396
#if defined(HAS_ARGBTOYROW_AVX2) || defined(HAS_ABGRTOYROW_AVX2) || \
1397
    defined(HAS_ARGBEXTRACTALPHAROW_AVX2)
1398
// vpermd for vphaddw + vpackuswb vpermd.
1399
#endif
1400
1401
#ifdef HAS_ARGBTOYROW_AVX2
1402
1403
// Convert 32 ARGB pixels (128 bytes) to 32 Y values.
1404
#ifdef HAS_ARGBTOYROW_AVX2
1405
0
void ARGBToYRow_AVX2(const uint8_t* src_argb, uint8_t* dst_y, int width) {
1406
0
  ARGBToYMatrixRow_AVX2(src_argb, dst_y, width, &kArgbI601Constants);
1407
0
}
1408
#endif
1409
#endif  // HAS_ARGBTOYROW_AVX2
1410
1411
#ifdef HAS_ABGRTOYROW_AVX2
1412
// Convert 32 ABGR pixels (128 bytes) to 32 Y values.
1413
#ifdef HAS_ARGBTOYROW_AVX2
1414
0
void ABGRToYRow_AVX2(const uint8_t* src_abgr, uint8_t* dst_y, int width) {
1415
0
  ARGBToYMatrixRow_AVX2(src_abgr, dst_y, width, &kAbgrI601Constants);
1416
0
}
1417
#endif
1418
#endif  // HAS_ABGRTOYROW_AVX2
1419
1420
#ifdef HAS_ARGBTOYJROW_AVX2
1421
// Convert 32 ARGB pixels (128 bytes) to 32 Y values.
1422
#ifdef HAS_ARGBTOYROW_AVX2
1423
0
void ARGBToYJRow_AVX2(const uint8_t* src_argb, uint8_t* dst_y, int width) {
1424
0
  ARGBToYMatrixRow_AVX2(src_argb, dst_y, width, &kArgbJPEGConstants);
1425
0
}
1426
#endif
1427
1428
#endif  // HAS_ARGBTOYJROW_AVX2
1429
1430
#ifdef HAS_ABGRTOYJROW_AVX2
1431
// Convert 32 ABGR pixels (128 bytes) to 32 Y values.
1432
#ifdef HAS_ARGBTOYROW_AVX2
1433
0
void ABGRToYJRow_AVX2(const uint8_t* src_abgr, uint8_t* dst_y, int width) {
1434
0
  ARGBToYMatrixRow_AVX2(src_abgr, dst_y, width, &kAbgrJPEGConstants);
1435
0
}
1436
#endif
1437
#endif  // HAS_ABGRTOYJROW_AVX2
1438
1439
#ifdef HAS_RGBATOYJROW_AVX2
1440
// Convert 32 ARGB pixels (128 bytes) to 32 Y values.
1441
#ifdef HAS_ARGBTOYROW_AVX2
1442
0
void RGBAToYJRow_AVX2(const uint8_t* src_rgba, uint8_t* dst_y, int width) {
1443
0
  ARGBToYMatrixRow_AVX2(src_rgba, dst_y, width, &kRgbaJPEGConstants);
1444
0
}
1445
#endif
1446
#endif  // HAS_RGBATOYJROW_AVX2
1447
1448
#if defined(HAS_ARGBTOYROW_AVX2) || defined(HAS_ARGBTOUV444ROW_AVX2) || \
1449
    defined(HAS_ARGBEXTRACTALPHAROW_AVX2)
1450
// vpermd for vphaddw + vpackuswb vpermd.
1451
static const lvec32 kPermdARGBToY_AVX = {0, 4, 1, 5, 2, 6, 3, 7};
1452
#endif
1453
1454
#ifdef HAS_ARGBTOYROW_SSSE3
1455
void ARGBToYMatrixRow_SSSE3(const uint8_t* src_argb,
1456
                            uint8_t* dst_y,
1457
                            int width,
1458
0
                            const struct ArgbConstants* c) {
1459
0
  asm volatile(
1460
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
1461
0
      "psllw       $15,%%xmm5                    \n"
1462
0
      "packsswb    %%xmm5,%%xmm5                 \n"
1463
0
      "movdqa      0(%3),%%xmm4                  \n"
1464
0
      "movdqa      0x60(%3),%%xmm7               \n"
1465
0
      "movdqa      %%xmm4,%%xmm6                 \n"
1466
0
      "pmaddubsw   %%xmm5,%%xmm6                 \n"
1467
0
      "phaddw      %%xmm6,%%xmm6                 \n"
1468
0
      "psubw       %%xmm6,%%xmm7                 \n" LABELALIGN "" RGBTOY(xmm7)
1469
0
      : "+r"(src_argb),  // %0
1470
0
        "+r"(dst_y),     // %1
1471
0
        "+r"(width)      // %2
1472
0
      : "r"(c)           // %3
1473
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
1474
0
        "xmm7");
1475
0
}
1476
#endif
1477
1478
#ifdef HAS_ARGBTOYROW_AVX2
1479
void ARGBToYMatrixRow_AVX2(const uint8_t* src_argb,
1480
                           uint8_t* dst_y,
1481
                           int width,
1482
0
                           const struct ArgbConstants* c) {
1483
0
  asm volatile(
1484
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
1485
0
      "vpsllw      $15,%%ymm5,%%ymm5             \n"
1486
0
      "vpacksswb   %%ymm5,%%ymm5,%%ymm5          \n"
1487
0
      "vbroadcasti128 0(%3),%%ymm4               \n"
1488
0
      "vbroadcasti128 0x60(%3),%%ymm7            \n"
1489
0
      "vpmaddubsw  %%ymm5,%%ymm4,%%ymm6          \n"
1490
0
      "vphaddw     %%ymm6,%%ymm6,%%ymm6          \n"
1491
0
      "vpsubw      %%ymm6,%%ymm7,%%ymm7          \n"
1492
0
      "vmovdqa     %4,%%ymm6                     \n" LABELALIGN
1493
0
      "" RGBTOY_AVX2(ymm7) "vzeroupper  \n"
1494
0
      : "+r"(src_argb),         // %0
1495
0
        "+r"(dst_y),            // %1
1496
0
        "+r"(width)             // %2
1497
0
      : "r"(c),                 // %3
1498
0
        "m"(kPermdARGBToY_AVX)  // %4
1499
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
1500
0
        "xmm7");
1501
0
}
1502
#endif
1503
1504
#if defined(HAS_ARGBTOYROW_AVX512BW) || \
1505
    defined(HAS_ARGBTOUV444ROW_AVX512BW) || defined(HAS_ARGBTOUVROW_AVX512BW)
1506
static const uint32_t kPermdARGBToY_AVX512BW[16] = {0, 4, 8,  12, 1, 5, 9,  13,
1507
                                                    2, 6, 10, 14, 3, 7, 11, 15};
1508
#endif
1509
1510
#if defined(HAS_ARGBTOUVROW_AVX512BW) || defined(HAS_ARGBTOUVJROW_AVX512BW)
1511
static const uint32_t kPermdARGBToUV_AVX512BW[16] = {
1512
    0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15};
1513
#endif
1514
1515
#ifdef HAS_ARGBTOYROW_AVX512BW
1516
void ARGBToYMatrixRow_AVX512BW(const uint8_t* src_argb,
1517
                               uint8_t* dst_y,
1518
                               int width,
1519
0
                               const struct ArgbConstants* c) {
1520
0
  asm volatile(
1521
0
      "vpternlogd  $0xff,%%zmm16,%%zmm16,%%zmm16 \n"
1522
0
      "vpsllw      $15,%%zmm16,%%zmm5            \n"
1523
0
      "vpacksswb   %%zmm5,%%zmm5,%%zmm5          \n"
1524
0
      "vpsrlw      $15,%%zmm16,%%zmm16           \n"  // zmm16 = 1
1525
0
      "vbroadcasti64x4 0(%3),%%zmm4              \n"
1526
0
      "vbroadcasti64x4 0x60(%3),%%zmm7           \n"
1527
0
      "vpmaddubsw  %%zmm5,%%zmm4,%%zmm6          \n"
1528
0
      "vpmaddwd    %%zmm16,%%zmm6,%%zmm6         \n"
1529
0
      "vpackssdw   %%zmm6,%%zmm6,%%zmm6          \n"
1530
0
      "vpsubw      %%zmm6,%%zmm7,%%zmm7          \n"
1531
0
      "vmovups     %4,%%zmm6                     \n" LABELALIGN
1532
0
      "1:          \n"
1533
0
      "vmovups     (%0),%%zmm0                   \n"
1534
0
      "vmovups     0x40(%0),%%zmm1               \n"
1535
0
      "vmovups     0x80(%0),%%zmm2               \n"
1536
0
      "vmovups     0xc0(%0),%%zmm3               \n"
1537
0
      "vpsubb      %%zmm5,%%zmm0,%%zmm0          \n"
1538
0
      "vpsubb      %%zmm5,%%zmm1,%%zmm1          \n"
1539
0
      "vpsubb      %%zmm5,%%zmm2,%%zmm2          \n"
1540
0
      "vpsubb      %%zmm5,%%zmm3,%%zmm3          \n"
1541
0
      "vpmaddubsw  %%zmm0,%%zmm4,%%zmm0          \n"
1542
0
      "vpmaddubsw  %%zmm1,%%zmm4,%%zmm1          \n"
1543
0
      "vpmaddubsw  %%zmm2,%%zmm4,%%zmm2          \n"
1544
0
      "vpmaddubsw  %%zmm3,%%zmm4,%%zmm3          \n"
1545
0
      "lea         0x100(%0),%0                  \n"
1546
0
      "vpmaddwd    %%zmm16,%%zmm0,%%zmm0         \n"
1547
0
      "vpmaddwd    %%zmm16,%%zmm1,%%zmm1         \n"
1548
0
      "vpackssdw   %%zmm1,%%zmm0,%%zmm0          \n"
1549
0
      "vpmaddwd    %%zmm16,%%zmm2,%%zmm2         \n"
1550
0
      "vpmaddwd    %%zmm16,%%zmm3,%%zmm3         \n"
1551
0
      "vpackssdw   %%zmm3,%%zmm2,%%zmm2          \n"
1552
0
      "vpaddw      %%zmm7,%%zmm0,%%zmm0          \n"
1553
0
      "vpaddw      %%zmm7,%%zmm2,%%zmm2          \n"
1554
0
      "vpsrlw      $0x8,%%zmm0,%%zmm0            \n"
1555
0
      "vpsrlw      $0x8,%%zmm2,%%zmm2            \n"
1556
0
      "vpackuswb   %%zmm2,%%zmm0,%%zmm0          \n"
1557
0
      "vpermd      %%zmm0,%%zmm6,%%zmm0          \n"
1558
0
      "vmovups     %%zmm0,(%1)                   \n"
1559
0
      "lea         0x40(%1),%1                   \n"
1560
0
      "sub         $0x40,%2                      \n"
1561
0
      "jg          1b                            \n"
1562
0
      "vzeroupper  \n"
1563
0
      : "+r"(src_argb),              // %0
1564
0
        "+r"(dst_y),                 // %1
1565
0
        "+r"(width)                  // %2
1566
0
      : "r"(c),                      // %3
1567
0
        "m"(kPermdARGBToY_AVX512BW)  // %4
1568
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
1569
0
        "xmm7", "xmm16");
1570
0
}
1571
#endif
1572
1573
#ifdef HAS_ARGBTOUV444ROW_SSSE3
1574
void ARGBToUV444MatrixRow_SSSE3(const uint8_t* src_argb,
1575
                                uint8_t* dst_u,
1576
                                uint8_t* dst_v,
1577
                                int width,
1578
0
                                const struct ArgbConstants* c) {
1579
0
  asm volatile(
1580
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"  // 0x8000
1581
0
      "psllw       $15,%%xmm5                    \n"
1582
0
      "movdqa      0x20(%4),%%xmm3               \n"  // kRGBToU
1583
0
      "movdqa      0x40(%4),%%xmm4               \n"  // kRGBToV
1584
0
      "sub         %1,%2                         \n"
1585
1586
0
      LABELALIGN
1587
0
      "1:          \n"
1588
0
      "movdqu      (%0),%%xmm0                   \n"
1589
0
      "movdqu      0x10(%0),%%xmm1               \n"
1590
0
      "movdqu      0x20(%0),%%xmm2               \n"
1591
0
      "movdqu      0x30(%0),%%xmm6               \n"
1592
0
      "pmaddubsw   %%xmm3,%%xmm0                 \n"
1593
0
      "pmaddubsw   %%xmm3,%%xmm1                 \n"
1594
0
      "pmaddubsw   %%xmm3,%%xmm2                 \n"
1595
0
      "pmaddubsw   %%xmm3,%%xmm6                 \n"
1596
0
      "phaddw      %%xmm1,%%xmm0                 \n"
1597
0
      "phaddw      %%xmm6,%%xmm2                 \n"
1598
0
      "movdqa      %%xmm5,%%xmm1                 \n"
1599
0
      "movdqa      %%xmm5,%%xmm6                 \n"
1600
0
      "psubw       %%xmm0,%%xmm1                 \n"
1601
0
      "psubw       %%xmm2,%%xmm6                 \n"
1602
0
      "psrlw       $0x8,%%xmm1                   \n"
1603
0
      "psrlw       $0x8,%%xmm6                   \n"
1604
0
      "packuswb    %%xmm6,%%xmm1                 \n"
1605
0
      "movdqu      %%xmm1,(%1)                   \n"
1606
1607
0
      "movdqu      (%0),%%xmm0                   \n"
1608
0
      "movdqu      0x10(%0),%%xmm1               \n"
1609
0
      "movdqu      0x20(%0),%%xmm2               \n"
1610
0
      "movdqu      0x30(%0),%%xmm6               \n"
1611
0
      "pmaddubsw   %%xmm4,%%xmm0                 \n"
1612
0
      "pmaddubsw   %%xmm4,%%xmm1                 \n"
1613
0
      "pmaddubsw   %%xmm4,%%xmm2                 \n"
1614
0
      "pmaddubsw   %%xmm4,%%xmm6                 \n"
1615
0
      "phaddw      %%xmm1,%%xmm0                 \n"
1616
0
      "phaddw      %%xmm6,%%xmm2                 \n"
1617
0
      "movdqa      %%xmm5,%%xmm1                 \n"
1618
0
      "movdqa      %%xmm5,%%xmm6                 \n"
1619
0
      "psubw       %%xmm0,%%xmm1                 \n"
1620
0
      "psubw       %%xmm2,%%xmm6                 \n"
1621
0
      "psrlw       $0x8,%%xmm1                   \n"
1622
0
      "psrlw       $0x8,%%xmm6                   \n"
1623
0
      "packuswb    %%xmm6,%%xmm1                 \n"
1624
0
      "movdqu      %%xmm1,0x00(%1,%2,1)          \n"
1625
1626
0
      "lea         0x40(%0),%0                   \n"
1627
0
      "lea         0x10(%1),%1                   \n"
1628
0
      "subl        $0x10,%3                      \n"
1629
0
      "jg          1b                            \n"
1630
0
      : "+r"(src_argb),  // %0
1631
0
        "+r"(dst_u),     // %1
1632
0
        "+r"(dst_v),     // %2
1633
#if defined(__i386__)
1634
        "+m"(width)  // %3
1635
#else
1636
0
        "+rm"(width)  // %3
1637
0
#endif
1638
0
      : "r"(c)  // %4
1639
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
1640
0
}
1641
#endif  // HAS_ARGBTOUV444ROW_SSSE3
1642
1643
#ifdef HAS_ARGBTOUV444ROW_AVX2
1644
1645
void ARGBToUV444MatrixRow_AVX2(const uint8_t* src_argb,
1646
                               uint8_t* dst_u,
1647
                               uint8_t* dst_v,
1648
                               int width,
1649
0
                               const struct ArgbConstants* c) {
1650
0
  asm volatile(
1651
0
      "vmovdqa     0x20(%4),%%ymm3               \n"  // kRGBToU
1652
0
      "vmovdqa     0x40(%4),%%ymm4               \n"  // kRGBToV
1653
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"  // 0x8000
1654
0
      "vpsllw      $15,%%ymm5,%%ymm5             \n"
1655
0
      "vmovdqa     %5,%%ymm7                     \n"
1656
0
      "sub         %1,%2                         \n"
1657
1658
0
      LABELALIGN
1659
0
      "1:          \n"
1660
0
      "vmovdqu     (%0),%%ymm0                   \n"
1661
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
1662
0
      "vmovdqu     0x40(%0),%%ymm2               \n"
1663
0
      "vmovdqu     0x60(%0),%%ymm6               \n"
1664
0
      "vpmaddubsw  %%ymm3,%%ymm0,%%ymm0          \n"
1665
0
      "vpmaddubsw  %%ymm3,%%ymm1,%%ymm1          \n"
1666
0
      "vpmaddubsw  %%ymm3,%%ymm2,%%ymm2          \n"
1667
0
      "vpmaddubsw  %%ymm3,%%ymm6,%%ymm6          \n"
1668
0
      "vphaddw     %%ymm1,%%ymm0,%%ymm0          \n"  // mutates
1669
0
      "vphaddw     %%ymm6,%%ymm2,%%ymm2          \n"
1670
0
      "vpsubw      %%ymm0,%%ymm5,%%ymm0          \n"
1671
0
      "vpsubw      %%ymm2,%%ymm5,%%ymm2          \n"
1672
0
      "vpsrlw      $0x8,%%ymm0,%%ymm0            \n"
1673
0
      "vpsrlw      $0x8,%%ymm2,%%ymm2            \n"
1674
0
      "vpackuswb   %%ymm2,%%ymm0,%%ymm0          \n"  // mutates
1675
0
      "vpermd      %%ymm0,%%ymm7,%%ymm0          \n"  // unmutate.
1676
0
      "vmovdqu     %%ymm0,(%1)                   \n"
1677
1678
0
      "vmovdqu     (%0),%%ymm0                   \n"
1679
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
1680
0
      "vmovdqu     0x40(%0),%%ymm2               \n"
1681
0
      "vmovdqu     0x60(%0),%%ymm6               \n"
1682
0
      "vpmaddubsw  %%ymm4,%%ymm0,%%ymm0          \n"
1683
0
      "vpmaddubsw  %%ymm4,%%ymm1,%%ymm1          \n"
1684
0
      "vpmaddubsw  %%ymm4,%%ymm2,%%ymm2          \n"
1685
0
      "vpmaddubsw  %%ymm4,%%ymm6,%%ymm6          \n"
1686
0
      "vphaddw     %%ymm1,%%ymm0,%%ymm0          \n"  // mutates
1687
0
      "vphaddw     %%ymm6,%%ymm2,%%ymm2          \n"
1688
0
      "vpsubw      %%ymm0,%%ymm5,%%ymm0          \n"
1689
0
      "vpsubw      %%ymm2,%%ymm5,%%ymm2          \n"
1690
0
      "vpsrlw      $0x8,%%ymm0,%%ymm0            \n"
1691
0
      "vpsrlw      $0x8,%%ymm2,%%ymm2            \n"
1692
0
      "vpackuswb   %%ymm2,%%ymm0,%%ymm0          \n"  // mutates
1693
0
      "vpermd      %%ymm0,%%ymm7,%%ymm0          \n"  // unmutate.
1694
0
      "vmovdqu     %%ymm0,(%1,%2,1)              \n"
1695
0
      "lea         0x80(%0),%0                   \n"
1696
0
      "lea         0x20(%1),%1                   \n"
1697
0
      "subl        $0x20,%3                      \n"
1698
0
      "jg          1b                            \n"
1699
0
      "vzeroupper  \n"
1700
0
      : "+r"(src_argb),  // %0
1701
0
        "+r"(dst_u),     // %1
1702
0
        "+r"(dst_v),     // %2
1703
#if defined(__i386__)
1704
        "+m"(width)  // %3
1705
#else
1706
0
        "+rm"(width)  // %3
1707
0
#endif
1708
0
      : "r"(c),                 // %4
1709
0
        "m"(kPermdARGBToY_AVX)  // %5
1710
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
1711
0
        "xmm7");
1712
0
}
1713
#endif  // HAS_ARGBTOUV444ROW_AVX2
1714
1715
#ifdef HAS_ARGBTOUV444ROW_AVX512BW
1716
1717
void ARGBToUV444MatrixRow_AVX512BW(const uint8_t* src_argb,
1718
                                   uint8_t* dst_u,
1719
                                   uint8_t* dst_v,
1720
                                   int width,
1721
0
                                   const struct ArgbConstants* c) {
1722
0
  asm volatile(
1723
0
      "vbroadcasti64x4 0x20(%4),%%zmm3               \n"  // kRGBToU
1724
0
      "vbroadcasti64x4 0x40(%4),%%zmm4               \n"  // kRGBToV
1725
0
      "vpternlogd  $0xff,%%zmm16,%%zmm16,%%zmm16 \n"      // -1
1726
0
      "vpsllw      $15,%%zmm16,%%zmm5            \n"      // 0x8000
1727
0
      "vmovups     %5,%%zmm7                     \n"
1728
0
      "sub         %1,%2                         \n"
1729
1730
0
      LABELALIGN
1731
0
      "1:          \n"
1732
0
      "vmovups     (%0),%%zmm0                   \n"
1733
0
      "vmovups     0x40(%0),%%zmm1               \n"
1734
0
      "vmovups     0x80(%0),%%zmm2               \n"
1735
0
      "vmovups     0xc0(%0),%%zmm6               \n"
1736
0
      "vpmaddubsw  %%zmm3,%%zmm0,%%zmm0          \n"
1737
0
      "vpmaddubsw  %%zmm3,%%zmm1,%%zmm1          \n"
1738
0
      "vpmaddubsw  %%zmm3,%%zmm2,%%zmm2          \n"
1739
0
      "vpmaddubsw  %%zmm3,%%zmm6,%%zmm6          \n"
1740
0
      "vpmaddwd    %%zmm16,%%zmm0,%%zmm0         \n"
1741
0
      "vpmaddwd    %%zmm16,%%zmm1,%%zmm1         \n"
1742
0
      "vpmaddwd    %%zmm16,%%zmm2,%%zmm2         \n"
1743
0
      "vpmaddwd    %%zmm16,%%zmm6,%%zmm6         \n"
1744
0
      "vpackssdw   %%zmm1,%%zmm0,%%zmm0          \n"  // mutates
1745
0
      "vpackssdw   %%zmm6,%%zmm2,%%zmm2          \n"
1746
0
      "vpsubw      %%zmm5,%%zmm0,%%zmm0          \n"
1747
0
      "vpsubw      %%zmm5,%%zmm2,%%zmm2          \n"
1748
0
      "vpsrlw      $0x8,%%zmm0,%%zmm0            \n"
1749
0
      "vpsrlw      $0x8,%%zmm2,%%zmm2            \n"
1750
0
      "vpackuswb   %%zmm2,%%zmm0,%%zmm0          \n"  // mutates
1751
0
      "vpermd      %%zmm0,%%zmm7,%%zmm0          \n"  // unmutate.
1752
0
      "vmovups     %%zmm0,(%1)                   \n"
1753
1754
0
      "vmovups     (%0),%%zmm0                   \n"
1755
0
      "vmovups     0x40(%0),%%zmm1               \n"
1756
0
      "vmovups     0x80(%0),%%zmm2               \n"
1757
0
      "vmovups     0xc0(%0),%%zmm6               \n"
1758
0
      "vpmaddubsw  %%zmm4,%%zmm0,%%zmm0          \n"
1759
0
      "vpmaddubsw  %%zmm4,%%zmm1,%%zmm1          \n"
1760
0
      "vpmaddubsw  %%zmm4,%%zmm2,%%zmm2          \n"
1761
0
      "vpmaddubsw  %%zmm4,%%zmm6,%%zmm6          \n"
1762
0
      "vpmaddwd    %%zmm16,%%zmm0,%%zmm0         \n"
1763
0
      "vpmaddwd    %%zmm16,%%zmm1,%%zmm1         \n"
1764
0
      "vpmaddwd    %%zmm16,%%zmm2,%%zmm2         \n"
1765
0
      "vpmaddwd    %%zmm16,%%zmm6,%%zmm6         \n"
1766
0
      "vpackssdw   %%zmm1,%%zmm0,%%zmm0          \n"  // mutates
1767
0
      "vpackssdw   %%zmm6,%%zmm2,%%zmm2          \n"
1768
0
      "vpsubw      %%zmm5,%%zmm0,%%zmm0          \n"
1769
0
      "vpsubw      %%zmm5,%%zmm2,%%zmm2          \n"
1770
0
      "vpsrlw      $0x8,%%zmm0,%%zmm0            \n"
1771
0
      "vpsrlw      $0x8,%%zmm2,%%zmm2            \n"
1772
0
      "vpackuswb   %%zmm2,%%zmm0,%%zmm0          \n"  // mutates
1773
0
      "vpermd      %%zmm0,%%zmm7,%%zmm0          \n"  // unmutate.
1774
0
      "vmovups     %%zmm0,(%1,%2,1)              \n"
1775
0
      "lea         0x100(%0),%0                  \n"
1776
0
      "lea         0x40(%1),%1                   \n"
1777
0
      "subl        $0x40,%3                      \n"
1778
0
      "jg          1b                            \n"
1779
0
      "vzeroupper  \n"
1780
0
      : "+r"(src_argb),  // %0
1781
0
        "+r"(dst_u),     // %1
1782
0
        "+r"(dst_v),     // %2
1783
#if defined(__i386__)
1784
        "+m"(width)  // %3
1785
#else
1786
0
        "+rm"(width)  // %3
1787
0
#endif
1788
0
      : "r"(c),                      // %4
1789
0
        "m"(kPermdARGBToY_AVX512BW)  // %5
1790
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
1791
0
        "xmm7", "xmm16");
1792
0
}
1793
#endif  // HAS_ARGBTOUV444ROW_AVX512BW
1794
1795
#ifdef HAS_ARGBTOUVROW_SSSE3
1796
1797
// ARGBARGB to AARRGGBB shuffle
1798
static const lvec8 kShuffleAARRGGBB = {
1799
    0, 4, 1, 5, 2, 6, 3, 7, 8, 12, 9, 13, 10, 14, 11, 15,
1800
    0, 4, 1, 5, 2, 6, 3, 7, 8, 12, 9, 13, 10, 14, 11, 15,
1801
};
1802
1803
// 8x2 -> 4x1 ARGB pixels converted to 4 U and 4 V
1804
// ARGBToUV does rounding average of 4 ARGB pixels
1805
void ARGBToUVMatrixRow_SSSE3(const uint8_t* src_argb,
1806
                             int src_stride_argb,
1807
                             uint8_t* dst_u,
1808
                             uint8_t* dst_v,
1809
                             int width,
1810
0
                             const struct ArgbConstants* c) {
1811
0
  asm volatile(
1812
0
      "movdqa      0x20(%5),%%xmm4               \n"  // RGBToU
1813
0
      "movdqa      0x40(%5),%%xmm5               \n"  // RGBToV
1814
0
      "pcmpeqb     %%xmm6,%%xmm6                 \n"  // 0x0101
1815
0
      "pabsb       %%xmm6,%%xmm6                 \n"
1816
0
      "movdqa      %6,%%xmm7                     \n"  // kShuffleAARRGGBB
1817
0
      "sub         %1,%2                         \n"
1818
1819
0
      "1:          \n"
1820
0
      "movdqu      (%0),%%xmm0                   \n"  // Read 8x2 ARGB Pixels
1821
0
      "movdqu      0x10(%0),%%xmm1               \n"
1822
0
      "movdqu      0x00(%0,%4,1),%%xmm2          \n"
1823
0
      "movdqu      0x10(%0,%4,1),%%xmm3          \n"
1824
0
      "pshufb      %%xmm7,%%xmm0                 \n"  // aarrggbb
1825
0
      "pshufb      %%xmm7,%%xmm1                 \n"
1826
0
      "pshufb      %%xmm7,%%xmm2                 \n"
1827
0
      "pshufb      %%xmm7,%%xmm3                 \n"
1828
0
      "pmaddubsw   %%xmm6,%%xmm0                 \n"  // 8x2 -> 4x2
1829
0
      "pmaddubsw   %%xmm6,%%xmm1                 \n"
1830
0
      "pmaddubsw   %%xmm6,%%xmm2                 \n"
1831
0
      "pmaddubsw   %%xmm6,%%xmm3                 \n"
1832
0
      "paddw       %%xmm2,%%xmm0                 \n"  // 4x2 -> 4x1
1833
0
      "paddw       %%xmm3,%%xmm1                 \n"
1834
0
      "pxor        %%xmm2,%%xmm2                 \n"  // 0 for vpavgw
1835
0
      "psrlw       $1,%%xmm0                     \n"
1836
0
      "psrlw       $1,%%xmm1                     \n"
1837
0
      "pavgw       %%xmm2,%%xmm0                 \n"
1838
0
      "pavgw       %%xmm2,%%xmm1                 \n"
1839
0
      "packuswb    %%xmm1,%%xmm0                 \n"  // mutates
1840
1841
0
      "movdqa      %%xmm6,%%xmm2                 \n"
1842
0
      "psllw       $15,%%xmm2                    \n"  // 0x8000
1843
0
      "movdqa      %%xmm0,%%xmm1                 \n"
1844
0
      "pmaddubsw   %%xmm5,%%xmm1                 \n"  // 4 V
1845
0
      "pmaddubsw   %%xmm4,%%xmm0                 \n"  // 4 U
1846
0
      "phaddw      %%xmm1,%%xmm0                 \n"  // uuuuvvvv
1847
0
      "psubw       %%xmm0,%%xmm2                 \n"
1848
0
      "psrlw       $0x8,%%xmm2                   \n"
1849
0
      "packuswb    %%xmm2,%%xmm2                 \n"
1850
0
      "movd        %%xmm2,(%1)                   \n"  // Write 4 U's
1851
0
      "pshufd      $0x55,%%xmm2,%%xmm2           \n"  // Copy V to low 4 bytes
1852
0
      "movd        %%xmm2,0x00(%1,%2,1)          \n"  // Write 4 V's
1853
1854
0
      "lea         0x20(%0),%0                  \n"
1855
0
      "lea         0x4(%1),%1                   \n"
1856
0
      "subl        $0x8,%3                      \n"
1857
0
      "jg          1b                           \n"
1858
0
      : "+r"(src_argb),  // %0
1859
0
        "+r"(dst_u),     // %1
1860
0
        "+r"(dst_v),     // %2
1861
#if defined(__i386__)
1862
        "+m"(width)  // %3
1863
#else
1864
0
        "+rm"(width)  // %3
1865
0
#endif
1866
0
      : "r"((ptrdiff_t)(src_stride_argb)),  // %4
1867
0
        "r"(c),                             // %5
1868
0
        "m"(kShuffleAARRGGBB)               // %6
1869
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
1870
0
        "xmm7");
1871
0
}
1872
1873
#endif  // HAS_ARGBTOUVROW_SSSE3
1874
1875
#ifdef HAS_ARGBTOUVROW_AVX2
1876
1877
// 16x2 -> 8x1 ARGB pixels converted to 8 U and 8 V
1878
// ARGBToUV does rounding average of 4 ARGB pixels
1879
void ARGBToUVMatrixRow_AVX2(const uint8_t* src_argb,
1880
                            int src_stride_argb,
1881
                            uint8_t* dst_u,
1882
                            uint8_t* dst_v,
1883
                            int width,
1884
0
                            const struct ArgbConstants* c) {
1885
0
  asm volatile(
1886
0
      "vbroadcasti128 0x20(%5),%%ymm4           \n"   // RGBToU
1887
0
      "vbroadcasti128 0x40(%5),%%ymm5           \n"   // RGBToV
1888
0
      "vpcmpeqb    %%ymm6,%%ymm6,%%ymm6          \n"  // 0x0101
1889
0
      "vpabsb      %%ymm6,%%ymm6                 \n"
1890
0
      "vmovdqa     %6,%%ymm7                     \n"  // kShuffleAARRGGBB
1891
0
      "sub         %1,%2                         \n"
1892
1893
0
      "1:          \n"
1894
0
      "vmovdqu     (%0),%%ymm0                   \n"  // Read 16x2 ARGB Pixels
1895
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
1896
0
      "vmovdqu     0x00(%0,%4,1),%%ymm2          \n"
1897
0
      "vmovdqu     0x20(%0,%4,1),%%ymm3          \n"
1898
0
      "vpshufb     %%ymm7,%%ymm0,%%ymm0          \n"  // aarrggbb
1899
0
      "vpshufb     %%ymm7,%%ymm1,%%ymm1          \n"
1900
0
      "vpshufb     %%ymm7,%%ymm2,%%ymm2          \n"
1901
0
      "vpshufb     %%ymm7,%%ymm3,%%ymm3          \n"
1902
0
      "vpmaddubsw  %%ymm6,%%ymm0,%%ymm0          \n"  // 16x2 -> 8x2
1903
0
      "vpmaddubsw  %%ymm6,%%ymm1,%%ymm1          \n"
1904
0
      "vpmaddubsw  %%ymm6,%%ymm2,%%ymm2          \n"
1905
0
      "vpmaddubsw  %%ymm6,%%ymm3,%%ymm3          \n"
1906
0
      "vpaddw      %%ymm0,%%ymm2,%%ymm0          \n"  // 8x2 -> 8x1
1907
0
      "vpaddw      %%ymm1,%%ymm3,%%ymm1          \n"
1908
0
      "vpxor       %%ymm2,%%ymm2,%%ymm2          \n"  // 0 for vpavgw
1909
0
      "vpsrlw      $1,%%ymm0,%%ymm0              \n"
1910
0
      "vpsrlw      $1,%%ymm1,%%ymm1              \n"
1911
0
      "vpavgw      %%ymm2,%%ymm0,%%ymm0          \n"
1912
0
      "vpavgw      %%ymm2,%%ymm1,%%ymm1          \n"
1913
0
      "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"  // mutates
1914
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"  // 8 ARGB Pixels
1915
1916
0
      "vpsllw      $15,%%ymm6,%%ymm2             \n"  // 0x8000
1917
0
      "vpmaddubsw  %%ymm5,%%ymm0,%%ymm1          \n"  // 8 V
1918
0
      "vpmaddubsw  %%ymm4,%%ymm0,%%ymm0          \n"  // 8 U
1919
0
      "vphaddw     %%ymm1,%%ymm0,%%ymm0          \n"  // uuuuvvvv uuuuvvvv
1920
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"  // uuuuuuuu vvvvvvvv
1921
0
      "vpsubw      %%ymm0,%%ymm2,%%ymm0          \n"
1922
0
      "vpsrlw      $0x8,%%ymm0,%%ymm0            \n"
1923
0
      "vpackuswb   %%ymm0,%%ymm0,%%ymm0          \n"  // mutates 8U8u- 8V8v
1924
0
      "vmovq       %%xmm0,(%1)                   \n"  // Write 8 U's
1925
0
      "vextractf128 $0x1,%%ymm0,%%xmm0           \n"  // Copy V to low 8 bytes
1926
0
      "vmovq       %%xmm0,0x00(%1,%2,1)          \n"  // Write 8 V's
1927
1928
0
      "lea         0x40(%0),%0                   \n"
1929
0
      "lea         0x8(%1),%1                    \n"
1930
0
      "subl        $0x10,%3                      \n"
1931
0
      "jg          1b                            \n"
1932
0
      "vzeroupper  \n"
1933
0
      : "+r"(src_argb),  // %0
1934
0
        "+r"(dst_u),     // %1
1935
0
        "+r"(dst_v),     // %2
1936
#if defined(__i386__)
1937
        "+m"(width)  // %3
1938
#else
1939
0
        "+rm"(width)  // %3
1940
0
#endif
1941
0
      : "r"((ptrdiff_t)(src_stride_argb)),  // %4
1942
0
        "r"(c),                             // %5
1943
0
        "m"(kShuffleAARRGGBB)               // %6
1944
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
1945
0
        "xmm7");
1946
0
}
1947
#endif  // HAS_ARGBTOUVROW_AVX2
1948
1949
// RGB to BT601 coefficients
1950
// UB   0.875 coefficient = 112
1951
// UG -0.5781 coefficient = -74
1952
// UR -0.2969 coefficient = -38
1953
// VB -0.1406 coefficient = -18
1954
// VG -0.7344 coefficient = -94
1955
// VR   0.875 coefficient = 112
1956
1957
#ifdef HAS_ARGBTOUV444ROW_SSSE3
1958
void ARGBToUV444Row_SSSE3(const uint8_t* src_argb,
1959
                          uint8_t* dst_u,
1960
                          uint8_t* dst_v,
1961
0
                          int width) {
1962
0
  ARGBToUV444MatrixRow_SSSE3(src_argb, dst_u, dst_v, width,
1963
0
                             &kArgbI601Constants);
1964
0
}
1965
#endif  // HAS_ARGBTOUV444ROW_SSSE3
1966
1967
#ifdef HAS_ARGBTOYROW_AVX2
1968
0
void RGBAToYRow_AVX2(const uint8_t* src_rgba, uint8_t* dst_y, int width) {
1969
0
  ARGBToYMatrixRow_AVX2(src_rgba, dst_y, width, &kRgbaI601Constants);
1970
0
}
1971
#endif
1972
1973
#ifdef HAS_ARGBTOYROW_AVX2
1974
0
void BGRAToYRow_AVX2(const uint8_t* src_bgra, uint8_t* dst_y, int width) {
1975
0
  ARGBToYMatrixRow_AVX2(src_bgra, dst_y, width, &kBgraI601Constants);
1976
0
}
1977
#endif
1978
1979
#ifdef HAS_ARGBTOYROW_AVX512BW
1980
0
void ARGBToYRow_AVX512BW(const uint8_t* src_argb, uint8_t* dst_y, int width) {
1981
0
  ARGBToYMatrixRow_AVX512BW(src_argb, dst_y, width, &kArgbI601Constants);
1982
0
}
1983
#endif
1984
1985
#ifdef HAS_ARGBTOYROW_AVX512BW
1986
0
void ARGBToYJRow_AVX512BW(const uint8_t* src_argb, uint8_t* dst_y, int width) {
1987
0
  ARGBToYMatrixRow_AVX512BW(src_argb, dst_y, width, &kArgbJPEGConstants);
1988
0
}
1989
#endif
1990
1991
#ifdef HAS_ARGBTOYROW_AVX512BW
1992
0
void ABGRToYRow_AVX512BW(const uint8_t* src_abgr, uint8_t* dst_y, int width) {
1993
0
  ARGBToYMatrixRow_AVX512BW(src_abgr, dst_y, width, &kAbgrI601Constants);
1994
0
}
1995
#endif
1996
1997
#ifdef HAS_ARGBTOYROW_AVX512BW
1998
0
void ABGRToYJRow_AVX512BW(const uint8_t* src_abgr, uint8_t* dst_y, int width) {
1999
0
  ARGBToYMatrixRow_AVX512BW(src_abgr, dst_y, width, &kAbgrJPEGConstants);
2000
0
}
2001
#endif
2002
2003
#ifdef HAS_ARGBTOYROW_AVX512BW
2004
0
void RGBAToYRow_AVX512BW(const uint8_t* src_rgba, uint8_t* dst_y, int width) {
2005
0
  ARGBToYMatrixRow_AVX512BW(src_rgba, dst_y, width, &kRgbaI601Constants);
2006
0
}
2007
#endif
2008
2009
#ifdef HAS_ARGBTOYROW_AVX512BW
2010
0
void RGBAToYJRow_AVX512BW(const uint8_t* src_rgba, uint8_t* dst_y, int width) {
2011
0
  ARGBToYMatrixRow_AVX512BW(src_rgba, dst_y, width, &kRgbaJPEGConstants);
2012
0
}
2013
#endif
2014
2015
#ifdef HAS_ARGBTOYROW_AVX512BW
2016
0
void BGRAToYRow_AVX512BW(const uint8_t* src_bgra, uint8_t* dst_y, int width) {
2017
0
  ARGBToYMatrixRow_AVX512BW(src_bgra, dst_y, width, &kBgraI601Constants);
2018
0
}
2019
#endif
2020
2021
#ifdef HAS_ARGBTOUV444ROW_AVX2
2022
void ARGBToUV444Row_AVX2(const uint8_t* src_argb,
2023
                         uint8_t* dst_u,
2024
                         uint8_t* dst_v,
2025
0
                         int width) {
2026
0
  ARGBToUV444MatrixRow_AVX2(src_argb, dst_u, dst_v, width, &kArgbI601Constants);
2027
0
}
2028
#endif  // HAS_ARGBTOUV444ROW_AVX2
2029
2030
#ifdef HAS_ARGBTOUV444ROW_AVX512BW
2031
void ARGBToUV444Row_AVX512BW(const uint8_t* src_argb,
2032
                             uint8_t* dst_u,
2033
                             uint8_t* dst_v,
2034
0
                             int width) {
2035
0
  ARGBToUV444MatrixRow_AVX512BW(src_argb, dst_u, dst_v, width,
2036
0
                                &kArgbI601Constants);
2037
0
}
2038
#endif  // HAS_ARGBTOUV444ROW_AVX512BW
2039
2040
#ifdef HAS_ARGBTOUVROW_SSSE3
2041
void ARGBToUVRow_SSSE3(const uint8_t* src_argb,
2042
                       int src_stride_argb,
2043
                       uint8_t* dst_u,
2044
                       uint8_t* dst_v,
2045
0
                       int width) {
2046
0
  ARGBToUVMatrixRow_SSSE3(src_argb, src_stride_argb, dst_u, dst_v, width,
2047
0
                          &kArgbI601Constants);
2048
0
}
2049
2050
void ABGRToUVRow_SSSE3(const uint8_t* src_abgr,
2051
                       int src_stride_abgr,
2052
                       uint8_t* dst_u,
2053
                       uint8_t* dst_v,
2054
0
                       int width) {
2055
0
  ARGBToUVMatrixRow_SSSE3(src_abgr, src_stride_abgr, dst_u, dst_v, width,
2056
0
                          &kAbgrI601Constants);
2057
0
}
2058
2059
void BGRAToUVRow_SSSE3(const uint8_t* src_bgra,
2060
                       int src_stride_bgra,
2061
                       uint8_t* dst_u,
2062
                       uint8_t* dst_v,
2063
0
                       int width) {
2064
0
  ARGBToUVMatrixRow_SSSE3(src_bgra, src_stride_bgra, dst_u, dst_v, width,
2065
0
                          &kBgraI601Constants);
2066
0
}
2067
2068
void RGBAToUVRow_SSSE3(const uint8_t* src_rgba,
2069
                       int src_stride_rgba,
2070
                       uint8_t* dst_u,
2071
                       uint8_t* dst_v,
2072
0
                       int width) {
2073
0
  ARGBToUVMatrixRow_SSSE3(src_rgba, src_stride_rgba, dst_u, dst_v, width,
2074
0
                          &kRgbaI601Constants);
2075
0
}
2076
#endif  // HAS_ARGBTOUVROW_SSSE3
2077
2078
#ifdef HAS_ARGBTOUVROW_AVX2
2079
void ARGBToUVRow_AVX2(const uint8_t* src_argb,
2080
                      int src_stride_argb,
2081
                      uint8_t* dst_u,
2082
                      uint8_t* dst_v,
2083
0
                      int width) {
2084
0
  ARGBToUVMatrixRow_AVX2(src_argb, src_stride_argb, dst_u, dst_v, width,
2085
0
                         &kArgbI601Constants);
2086
0
}
2087
2088
void ABGRToUVRow_AVX2(const uint8_t* src_abgr,
2089
                      int src_stride_abgr,
2090
                      uint8_t* dst_u,
2091
                      uint8_t* dst_v,
2092
0
                      int width) {
2093
0
  ARGBToUVMatrixRow_AVX2(src_abgr, src_stride_abgr, dst_u, dst_v, width,
2094
0
                         &kAbgrI601Constants);
2095
0
}
2096
#endif  // HAS_ARGBTOUVROW_AVX2
2097
2098
#ifdef HAS_ARGBTOUVJ444ROW_SSSE3
2099
void ARGBToUVJ444Row_SSSE3(const uint8_t* src_argb,
2100
                           uint8_t* dst_u,
2101
                           uint8_t* dst_v,
2102
0
                           int width) {
2103
0
  ARGBToUV444MatrixRow_SSSE3(src_argb, dst_u, dst_v, width,
2104
0
                             &kArgbJPEGConstants);
2105
0
}
2106
#endif  // HAS_ARGBTOUVJ444ROW_SSSE3
2107
2108
#ifdef HAS_ARGBTOUVJ444ROW_AVX2
2109
void ARGBToUVJ444Row_AVX2(const uint8_t* src_argb,
2110
                          uint8_t* dst_u,
2111
                          uint8_t* dst_v,
2112
0
                          int width) {
2113
0
  ARGBToUV444MatrixRow_AVX2(src_argb, dst_u, dst_v, width, &kArgbJPEGConstants);
2114
0
}
2115
#endif  // HAS_ARGBTOUVJ444ROW_AVX2
2116
2117
#ifdef HAS_ARGBTOUVJ444ROW_AVX512BW
2118
void ARGBToUVJ444Row_AVX512BW(const uint8_t* src_argb,
2119
                              uint8_t* dst_u,
2120
                              uint8_t* dst_v,
2121
0
                              int width) {
2122
0
  ARGBToUV444MatrixRow_AVX512BW(src_argb, dst_u, dst_v, width,
2123
0
                                &kArgbJPEGConstants);
2124
0
}
2125
#endif  // HAS_ARGBTOUVJ444ROW_AVX512BW
2126
2127
#ifdef HAS_ARGBTOUVJROW_SSSE3
2128
void ARGBToUVJRow_SSSE3(const uint8_t* src_argb,
2129
                        int src_stride_argb,
2130
                        uint8_t* dst_u,
2131
                        uint8_t* dst_v,
2132
0
                        int width) {
2133
0
  ARGBToUVMatrixRow_SSSE3(src_argb, src_stride_argb, dst_u, dst_v, width,
2134
0
                          &kArgbJPEGConstants);
2135
0
}
2136
#endif  // HAS_ARGBTOUVJROW_SSSE3
2137
2138
#ifdef HAS_ABGRTOUVJROW_SSSE3
2139
void ABGRToUVJRow_SSSE3(const uint8_t* src_abgr,
2140
                        int src_stride_abgr,
2141
                        uint8_t* dst_u,
2142
                        uint8_t* dst_v,
2143
0
                        int width) {
2144
0
  ARGBToUVMatrixRow_SSSE3(src_abgr, src_stride_abgr, dst_u, dst_v, width,
2145
0
                          &kAbgrJPEGConstants);
2146
0
}
2147
#endif  // HAS_ABGRTOUVJROW_SSSE3
2148
2149
#ifdef HAS_ARGBTOUVJROW_AVX2
2150
void ARGBToUVJRow_AVX2(const uint8_t* src_argb,
2151
                       int src_stride_argb,
2152
                       uint8_t* dst_u,
2153
                       uint8_t* dst_v,
2154
0
                       int width) {
2155
0
  ARGBToUVMatrixRow_AVX2(src_argb, src_stride_argb, dst_u, dst_v, width,
2156
0
                         &kArgbJPEGConstants);
2157
0
}
2158
#endif  // HAS_ARGBTOUVJROW_AVX2
2159
2160
#ifdef HAS_ABGRTOUVJROW_AVX2
2161
void ABGRToUVJRow_AVX2(const uint8_t* src_abgr,
2162
                       int src_stride_abgr,
2163
                       uint8_t* dst_u,
2164
                       uint8_t* dst_v,
2165
0
                       int width) {
2166
0
  ARGBToUVMatrixRow_AVX2(src_abgr, src_stride_abgr, dst_u, dst_v, width,
2167
0
                         &kAbgrJPEGConstants);
2168
0
}
2169
#endif  // HAS_ABGRTOUVJROW_AVX2
2170
2171
#ifdef HAS_ARGBTOUVROW_AVX512BW
2172
2173
// 32x2 -> 16x1 ARGB pixels converted to 16 U and 16 V
2174
// ARGBToUV does rounding average of 4 ARGB pixels
2175
2176
void ARGBToUVMatrixRow_AVX512BW(const uint8_t* src_argb,
2177
                                int src_stride_argb,
2178
                                uint8_t* dst_u,
2179
                                uint8_t* dst_v,
2180
                                int width,
2181
0
                                const struct ArgbConstants* c) {
2182
0
  asm volatile(
2183
0
      "vbroadcasti64x4 0x20(%5),%%zmm4               \n"  // RGBToU
2184
0
      "vbroadcasti64x4 0x40(%5),%%zmm5               \n"  // RGBToV
2185
0
      "vpternlogd  $0xff,%%zmm16,%%zmm16,%%zmm16 \n"
2186
0
      "vpabsb      %%zmm16,%%zmm6                \n"      // 0x0101
2187
0
      "vpsllw      $15,%%zmm16,%%zmm17           \n"      // 0x8000
2188
0
      "vbroadcasti64x4 %6,%%zmm7                     \n"  // kShuffleAARRGGBB
2189
0
      "vmovups     %7,%%zmm18                    \n"  // kPermdARGBToY_AVX512BW
2190
0
      "vmovups     %8,%%zmm19                    \n"  // kPermdARGBToUV_AVX512BW
2191
0
      "sub         %1,%2                         \n"
2192
2193
0
      LABELALIGN
2194
0
      "1:          \n"
2195
0
      "vmovups     (%0),%%zmm0                   \n"  // Read 32x2 ARGB Pixels
2196
0
      "vmovups     0x40(%0),%%zmm1               \n"
2197
0
      "vmovups     0x00(%0,%4,1),%%zmm2          \n"
2198
0
      "vmovups     0x40(%0,%4,1),%%zmm3          \n"
2199
0
      "vpshufb     %%zmm7,%%zmm0,%%zmm0          \n"  // aarrggbb
2200
0
      "vpshufb     %%zmm7,%%zmm1,%%zmm1          \n"
2201
0
      "vpshufb     %%zmm7,%%zmm2,%%zmm2          \n"
2202
0
      "vpshufb     %%zmm7,%%zmm3,%%zmm3          \n"
2203
0
      "vpmaddubsw  %%zmm6,%%zmm0,%%zmm0          \n"  // 32x2 -> 16x2
2204
0
      "vpmaddubsw  %%zmm6,%%zmm1,%%zmm1          \n"
2205
0
      "vpmaddubsw  %%zmm6,%%zmm2,%%zmm2          \n"
2206
0
      "vpmaddubsw  %%zmm6,%%zmm3,%%zmm3          \n"
2207
0
      "vpaddw      %%zmm0,%%zmm2,%%zmm0          \n"  // 16x2 -> 16x1
2208
0
      "vpaddw      %%zmm1,%%zmm3,%%zmm1          \n"
2209
0
      "vpxorq      %%zmm2,%%zmm2,%%zmm2          \n"  // 0 for vpavgw
2210
0
      "vpsrlw      $1,%%zmm0,%%zmm0              \n"
2211
0
      "vpsrlw      $1,%%zmm1,%%zmm1              \n"
2212
0
      "vpavgw      %%zmm2,%%zmm0,%%zmm0          \n"
2213
0
      "vpavgw      %%zmm2,%%zmm1,%%zmm1          \n"
2214
0
      "vpackuswb   %%zmm1,%%zmm0,%%zmm0          \n"  // mutates
2215
0
      "vpermd      %%zmm0,%%zmm19,%%zmm0         \n"  // unscramble pixels
2216
2217
0
      "vpmaddubsw  %%zmm4,%%zmm0,%%zmm1          \n"  // 16 U
2218
0
      "vpmaddubsw  %%zmm5,%%zmm0,%%zmm0          \n"  // 16 V
2219
0
      "vpmaddwd    %%zmm16,%%zmm1,%%zmm1         \n"
2220
0
      "vpmaddwd    %%zmm16,%%zmm0,%%zmm0         \n"
2221
0
      "vpackssdw   %%zmm0,%%zmm1,%%zmm0          \n"  // mutates (U in lower, V
2222
                                                      // in upper)
2223
0
      "vpaddw      %%zmm17,%%zmm0,%%zmm0         \n"
2224
0
      "vpsrlw      $0x8,%%zmm0,%%zmm0            \n"
2225
0
      "vpackuswb   %%zmm0,%%zmm0,%%zmm0          \n"  // mutates
2226
0
      "vpermd      %%zmm0,%%zmm18,%%zmm0         \n"  // unmutate
2227
2228
0
      "vmovdqu     %%xmm0,(%1)                   \n"  // Write 16 U's
2229
0
      "vextracti32x4 $0x1,%%zmm0,%%xmm0          \n"
2230
0
      "vmovdqu     %%xmm0,0x00(%1,%2,1)          \n"  // Write 16 V's
2231
2232
0
      "lea         0x80(%0),%0                   \n"
2233
0
      "lea         0x10(%1),%1                   \n"
2234
0
      "subl        $0x20,%3                      \n"
2235
0
      "jg          1b                            \n"
2236
0
      "vzeroupper  \n"
2237
0
      : "+r"(src_argb),  // %0
2238
0
        "+r"(dst_u),     // %1
2239
0
        "+r"(dst_v),     // %2
2240
#if defined(__i386__)
2241
        "+m"(width)  // %3
2242
#else
2243
0
        "+rm"(width)  // %3
2244
0
#endif
2245
0
      : "r"((ptrdiff_t)(src_stride_argb)),  // %4
2246
0
        "r"(c),                             // %5
2247
0
        "m"(kShuffleAARRGGBB),              // %6
2248
0
        "m"(kPermdARGBToY_AVX512BW),        // %7
2249
0
        "m"(kPermdARGBToUV_AVX512BW)        // %8
2250
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
2251
0
        "xmm7", "xmm16", "xmm17", "xmm18", "xmm19");
2252
0
}
2253
2254
void ARGBToUVRow_AVX512BW(const uint8_t* src_argb,
2255
                          int src_stride_argb,
2256
                          uint8_t* dst_u,
2257
                          uint8_t* dst_v,
2258
0
                          int width) {
2259
0
  ARGBToUVMatrixRow_AVX512BW(src_argb, src_stride_argb, dst_u, dst_v, width,
2260
0
                             &kArgbI601Constants);
2261
0
}
2262
2263
void ABGRToUVRow_AVX512BW(const uint8_t* src_abgr,
2264
                          int src_stride_abgr,
2265
                          uint8_t* dst_u,
2266
                          uint8_t* dst_v,
2267
0
                          int width) {
2268
0
  ARGBToUVMatrixRow_AVX512BW(src_abgr, src_stride_abgr, dst_u, dst_v, width,
2269
0
                             &kAbgrI601Constants);
2270
0
}
2271
2272
#ifdef HAS_ARGBTOUVJROW_AVX512BW
2273
void ARGBToUVJRow_AVX512BW(const uint8_t* src_argb,
2274
                           int src_stride_argb,
2275
                           uint8_t* dst_u,
2276
                           uint8_t* dst_v,
2277
0
                           int width) {
2278
0
  ARGBToUVMatrixRow_AVX512BW(src_argb, src_stride_argb, dst_u, dst_v, width,
2279
0
                             &kArgbJPEGConstants);
2280
0
}
2281
#endif  // HAS_ARGBTOUVJROW_AVX512BW
2282
2283
#ifdef HAS_ABGRTOUVJROW_AVX512BW
2284
void ABGRToUVJRow_AVX512BW(const uint8_t* src_abgr,
2285
                           int src_stride_abgr,
2286
                           uint8_t* dst_u,
2287
                           uint8_t* dst_v,
2288
                           int width) {
2289
  ARGBToUVMatrixRow_AVX512BW(src_abgr, src_stride_abgr, dst_u, dst_v, width,
2290
                             &kAbgrJPEGConstants);
2291
}
2292
#endif  // HAS_ABGRTOUVJROW_AVX512BW
2293
#endif  // HAS_ARGBTOUVROW_AVX512BW
2294
2295
0
void BGRAToYRow_SSSE3(const uint8_t* src_bgra, uint8_t* dst_y, int width) {
2296
0
  ARGBToYMatrixRow_SSSE3(src_bgra, dst_y, width, &kBgraI601Constants);
2297
0
}
2298
2299
0
void ABGRToYRow_SSSE3(const uint8_t* src_abgr, uint8_t* dst_y, int width) {
2300
0
  ARGBToYMatrixRow_SSSE3(src_abgr, dst_y, width, &kAbgrI601Constants);
2301
0
}
2302
2303
0
void RGBAToYRow_SSSE3(const uint8_t* src_rgba, uint8_t* dst_y, int width) {
2304
0
  ARGBToYMatrixRow_SSSE3(src_rgba, dst_y, width, &kRgbaI601Constants);
2305
0
}
2306
2307
#if defined(HAS_I422TOARGBROW_SSSE3) || defined(HAS_I422TOARGBROW_AVX2)
2308
2309
// Read 8 UV from 444
2310
#define READYUV444                                                \
2311
  "movq       (%[u_buf]),%%xmm3                               \n" \
2312
  "movq       0x00(%[u_buf],%[v_buf],1),%%xmm1                \n" \
2313
  "lea        0x8(%[u_buf]),%[u_buf]                          \n" \
2314
  "punpcklbw  %%xmm1,%%xmm3                                   \n" \
2315
  "movq       (%[y_buf]),%%xmm4                               \n" \
2316
  "punpcklbw  %%xmm4,%%xmm4                                   \n" \
2317
  "lea        0x8(%[y_buf]),%[y_buf]                          \n"
2318
2319
// Read 4 UV from 422, upsample to 8 UV
2320
#define READYUV422                                                \
2321
  "movd       (%[u_buf]),%%xmm3                               \n" \
2322
  "movd       0x00(%[u_buf],%[v_buf],1),%%xmm1                \n" \
2323
  "lea        0x4(%[u_buf]),%[u_buf]                          \n" \
2324
  "punpcklbw  %%xmm1,%%xmm3                                   \n" \
2325
  "punpcklwd  %%xmm3,%%xmm3                                   \n" \
2326
  "movq       (%[y_buf]),%%xmm4                               \n" \
2327
  "punpcklbw  %%xmm4,%%xmm4                                   \n" \
2328
  "lea        0x8(%[y_buf]),%[y_buf]                          \n"
2329
2330
// Read 4 UV from 422 10 bit, upsample to 8 UV
2331
#define READYUV210                                                \
2332
  "movq       (%[u_buf]),%%xmm3                               \n" \
2333
  "movq       0x00(%[u_buf],%[v_buf],1),%%xmm1                \n" \
2334
  "lea        0x8(%[u_buf]),%[u_buf]                          \n" \
2335
  "punpcklwd  %%xmm1,%%xmm3                                   \n" \
2336
  "psraw      $2,%%xmm3                                       \n" \
2337
  "packuswb   %%xmm3,%%xmm3                                   \n" \
2338
  "punpcklwd  %%xmm3,%%xmm3                                   \n" \
2339
  "movdqu     (%[y_buf]),%%xmm4                               \n" \
2340
  "movdqa     %%xmm4,%%xmm2                                   \n" \
2341
  "psllw      $6,%%xmm4                                       \n" \
2342
  "psrlw      $4,%%xmm2                                       \n" \
2343
  "paddw      %%xmm2,%%xmm4                                   \n" \
2344
  "lea        0x10(%[y_buf]),%[y_buf]                         \n"
2345
2346
#define READYUVA210                                               \
2347
  "movq       (%[u_buf]),%%xmm3                               \n" \
2348
  "movq       0x00(%[u_buf],%[v_buf],1),%%xmm1                \n" \
2349
  "lea        0x8(%[u_buf]),%[u_buf]                          \n" \
2350
  "punpcklwd  %%xmm1,%%xmm3                                   \n" \
2351
  "psraw      $2,%%xmm3                                       \n" \
2352
  "packuswb   %%xmm3,%%xmm3                                   \n" \
2353
  "punpcklwd  %%xmm3,%%xmm3                                   \n" \
2354
  "movdqu     (%[y_buf]),%%xmm4                               \n" \
2355
  "movdqa     %%xmm4,%%xmm2                                   \n" \
2356
  "psllw      $6,%%xmm4                                       \n" \
2357
  "psrlw      $4,%%xmm2                                       \n" \
2358
  "paddw      %%xmm2,%%xmm4                                   \n" \
2359
  "lea        0x10(%[y_buf]),%[y_buf]                         \n" \
2360
  "movdqu     (%[a_buf]),%%xmm5                               \n" \
2361
  "psraw      $2,%%xmm5                                       \n" \
2362
  "packuswb   %%xmm5,%%xmm5                                   \n" \
2363
  "lea        0x10(%[a_buf]),%[a_buf]                         \n"
2364
2365
// Read 8 UV from 444 10 bit
2366
#define READYUV410                                                \
2367
  "movdqu     (%[u_buf]),%%xmm3                               \n" \
2368
  "movdqu     0x00(%[u_buf],%[v_buf],1),%%xmm2                \n" \
2369
  "lea        0x10(%[u_buf]),%[u_buf]                         \n" \
2370
  "psraw      $2,%%xmm3                                       \n" \
2371
  "psraw      $2,%%xmm2                                       \n" \
2372
  "movdqa     %%xmm3,%%xmm1                                   \n" \
2373
  "punpcklwd  %%xmm2,%%xmm3                                   \n" \
2374
  "punpckhwd  %%xmm2,%%xmm1                                   \n" \
2375
  "packuswb   %%xmm1,%%xmm3                                   \n" \
2376
  "movdqu     (%[y_buf]),%%xmm4                               \n" \
2377
  "movdqa     %%xmm4,%%xmm2                                   \n" \
2378
  "psllw      $6,%%xmm4                                       \n" \
2379
  "psrlw      $4,%%xmm2                                       \n" \
2380
  "paddw      %%xmm2,%%xmm4                                   \n" \
2381
  "lea        0x10(%[y_buf]),%[y_buf]                         \n"
2382
2383
// Read 8 UV from 444 10 bit.  With 8 Alpha.
2384
#define READYUVA410                                               \
2385
  "movdqu     (%[u_buf]),%%xmm3                               \n" \
2386
  "movdqu     0x00(%[u_buf],%[v_buf],1),%%xmm2                \n" \
2387
  "lea        0x10(%[u_buf]),%[u_buf]                         \n" \
2388
  "psraw      $2,%%xmm3                                       \n" \
2389
  "psraw      $2,%%xmm2                                       \n" \
2390
  "movdqa     %%xmm3,%%xmm1                                   \n" \
2391
  "punpcklwd  %%xmm2,%%xmm3                                   \n" \
2392
  "punpckhwd  %%xmm2,%%xmm1                                   \n" \
2393
  "packuswb   %%xmm1,%%xmm3                                   \n" \
2394
  "movdqu     (%[y_buf]),%%xmm4                               \n" \
2395
  "movdqa     %%xmm4,%%xmm2                                   \n" \
2396
  "psllw      $6,%%xmm4                                       \n" \
2397
  "psrlw      $4,%%xmm2                                       \n" \
2398
  "paddw      %%xmm2,%%xmm4                                   \n" \
2399
  "lea        0x10(%[y_buf]),%[y_buf]                         \n" \
2400
  "movdqu     (%[a_buf]),%%xmm5                               \n" \
2401
  "psraw      $2,%%xmm5                                       \n" \
2402
  "packuswb   %%xmm5,%%xmm5                                   \n" \
2403
  "lea        0x10(%[a_buf]),%[a_buf]                         \n"
2404
2405
// Read 4 UV from 422 12 bit, upsample to 8 UV
2406
#define READYUV212                                                \
2407
  "movq       (%[u_buf]),%%xmm3                               \n" \
2408
  "movq       0x00(%[u_buf],%[v_buf],1),%%xmm1                \n" \
2409
  "lea        0x8(%[u_buf]),%[u_buf]                          \n" \
2410
  "punpcklwd  %%xmm1,%%xmm3                                   \n" \
2411
  "psraw      $0x4,%%xmm3                                     \n" \
2412
  "packuswb   %%xmm3,%%xmm3                                   \n" \
2413
  "punpcklwd  %%xmm3,%%xmm3                                   \n" \
2414
  "movdqu     (%[y_buf]),%%xmm4                               \n" \
2415
  "movdqa     %%xmm4,%%xmm2                                   \n" \
2416
  "psllw      $4,%%xmm4                                       \n" \
2417
  "psrlw      $8,%%xmm2                                       \n" \
2418
  "paddw      %%xmm2,%%xmm4                                   \n" \
2419
  "lea        0x10(%[y_buf]),%[y_buf]                         \n"
2420
2421
// Read 4 UV from 422, upsample to 8 UV.  With 8 Alpha.
2422
#define READYUVA422                                               \
2423
  "movd       (%[u_buf]),%%xmm3                               \n" \
2424
  "movd       0x00(%[u_buf],%[v_buf],1),%%xmm1                \n" \
2425
  "lea        0x4(%[u_buf]),%[u_buf]                          \n" \
2426
  "punpcklbw  %%xmm1,%%xmm3                                   \n" \
2427
  "punpcklwd  %%xmm3,%%xmm3                                   \n" \
2428
  "movq       (%[y_buf]),%%xmm4                               \n" \
2429
  "punpcklbw  %%xmm4,%%xmm4                                   \n" \
2430
  "lea        0x8(%[y_buf]),%[y_buf]                          \n" \
2431
  "movq       (%[a_buf]),%%xmm5                               \n" \
2432
  "lea        0x8(%[a_buf]),%[a_buf]                          \n"
2433
2434
// Read 8 UV from 444.  With 8 Alpha.
2435
#define READYUVA444                                               \
2436
  "movq       (%[u_buf]),%%xmm3                               \n" \
2437
  "movq       0x00(%[u_buf],%[v_buf],1),%%xmm1                \n" \
2438
  "lea        0x8(%[u_buf]),%[u_buf]                          \n" \
2439
  "punpcklbw  %%xmm1,%%xmm3                                   \n" \
2440
  "movq       (%[y_buf]),%%xmm4                               \n" \
2441
  "punpcklbw  %%xmm4,%%xmm4                                   \n" \
2442
  "lea        0x8(%[y_buf]),%[y_buf]                          \n" \
2443
  "movq       (%[a_buf]),%%xmm5                               \n" \
2444
  "lea        0x8(%[a_buf]),%[a_buf]                          \n"
2445
2446
// Read 4 UV from NV12, upsample to 8 UV
2447
#define READNV12                                                  \
2448
  "movq       (%[uv_buf]),%%xmm3                              \n" \
2449
  "lea        0x8(%[uv_buf]),%[uv_buf]                        \n" \
2450
  "punpcklwd  %%xmm3,%%xmm3                                   \n" \
2451
  "movq       (%[y_buf]),%%xmm4                               \n" \
2452
  "punpcklbw  %%xmm4,%%xmm4                                   \n" \
2453
  "lea        0x8(%[y_buf]),%[y_buf]                          \n"
2454
2455
// Read 4 VU from NV21, upsample to 8 UV
2456
#define READNV21                                                  \
2457
  "movq       (%[vu_buf]),%%xmm3                              \n" \
2458
  "lea        0x8(%[vu_buf]),%[vu_buf]                        \n" \
2459
  "pshufb     %[kShuffleNV21], %%xmm3                         \n" \
2460
  "movq       (%[y_buf]),%%xmm4                               \n" \
2461
  "punpcklbw  %%xmm4,%%xmm4                                   \n" \
2462
  "lea        0x8(%[y_buf]),%[y_buf]                          \n"
2463
2464
// Read 4 YUY2 with 8 Y and upsample 4 UV to 8 UV.
2465
// xmm6 kShuffleYUY2Y,
2466
// xmm7 kShuffleYUY2UV
2467
#define READYUY2                                                  \
2468
  "movdqu     (%[yuy2_buf]),%%xmm4                            \n" \
2469
  "lea        0x10(%[yuy2_buf]),%[yuy2_buf]                   \n" \
2470
  "movdqa     %%xmm4,%%xmm3                                   \n" \
2471
  "pshufb     %%xmm6,%%xmm4                                   \n" \
2472
  "pshufb     %%xmm7,%%xmm3                                   \n"
2473
2474
// Read 4 UYVY with 8 Y and upsample 4 UV to 8 UV.
2475
// xmm6 kShuffleUYVYY,
2476
// xmm7 kShuffleUYVYUV
2477
#define READUYVY                                                  \
2478
  "movdqu     (%[uyvy_buf]),%%xmm4                            \n" \
2479
  "lea        0x10(%[uyvy_buf]),%[uyvy_buf]                   \n" \
2480
  "movdqa     %%xmm4,%%xmm3                                   \n" \
2481
  "pshufb     %%xmm6,%%xmm4                                   \n" \
2482
  "pshufb     %%xmm7,%%xmm3                                   \n"
2483
2484
// Read 4 UV from P210, upsample to 8 UV
2485
#define READP210                                                  \
2486
  "movdqu     (%[uv_buf]),%%xmm3                              \n" \
2487
  "lea        0x10(%[uv_buf]),%[uv_buf]                       \n" \
2488
  "psrlw      $0x8,%%xmm3                                     \n" \
2489
  "packuswb   %%xmm3,%%xmm3                                   \n" \
2490
  "punpcklwd  %%xmm3,%%xmm3                                   \n" \
2491
  "movdqu     (%[y_buf]),%%xmm4                               \n" \
2492
  "lea        0x10(%[y_buf]),%[y_buf]                         \n"
2493
2494
// Read 8 UV from P410
2495
#define READP410                                                  \
2496
  "movdqu     (%[uv_buf]),%%xmm3                              \n" \
2497
  "movdqu     0x10(%[uv_buf]),%%xmm1                          \n" \
2498
  "lea        0x20(%[uv_buf]),%[uv_buf]                       \n" \
2499
  "psrlw      $0x8,%%xmm3                                     \n" \
2500
  "psrlw      $0x8,%%xmm1                                     \n" \
2501
  "packuswb   %%xmm1,%%xmm3                                   \n" \
2502
  "movdqu     (%[y_buf]),%%xmm4                               \n" \
2503
  "lea        0x10(%[y_buf]),%[y_buf]                         \n"
2504
2505
#if defined(__x86_64__)
2506
#define YUVTORGB_SETUP(yuvconstants)                              \
2507
  "pcmpeqb    %%xmm13,%%xmm13                                 \n" \
2508
  "movdqa     (%[yuvconstants]),%%xmm8                        \n" \
2509
  "pxor       %%xmm12,%%xmm12                                 \n" \
2510
  "movdqa     32(%[yuvconstants]),%%xmm9                      \n" \
2511
  "psllw      $7,%%xmm13                                      \n" \
2512
  "movdqa     64(%[yuvconstants]),%%xmm10                     \n" \
2513
  "pshufb     %%xmm12,%%xmm13                                 \n" \
2514
  "movdqa     96(%[yuvconstants]),%%xmm11                     \n" \
2515
  "movdqa     128(%[yuvconstants]),%%xmm12                    \n"
2516
2517
// Convert 8 pixels: 8 UV and 8 Y
2518
#define YUVTORGB16(yuvconstants)                                  \
2519
  "psubb      %%xmm13,%%xmm3                                  \n" \
2520
  "pmulhuw    %%xmm11,%%xmm4                                  \n" \
2521
  "movdqa     %%xmm8,%%xmm0                                   \n" \
2522
  "movdqa     %%xmm9,%%xmm1                                   \n" \
2523
  "movdqa     %%xmm10,%%xmm2                                  \n" \
2524
  "paddw      %%xmm12,%%xmm4                                  \n" \
2525
  "pmaddubsw  %%xmm3,%%xmm0                                   \n" \
2526
  "pmaddubsw  %%xmm3,%%xmm1                                   \n" \
2527
  "pmaddubsw  %%xmm3,%%xmm2                                   \n" \
2528
  "paddsw     %%xmm4,%%xmm0                                   \n" \
2529
  "paddsw     %%xmm4,%%xmm2                                   \n" \
2530
  "psubsw     %%xmm1,%%xmm4                                   \n" \
2531
  "movdqa     %%xmm4,%%xmm1                                   \n"
2532
2533
#define YUVTORGB_REGS "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13",
2534
2535
#else
2536
#define YUVTORGB_SETUP(yuvconstants)
2537
2538
// Convert 8 pixels: 8 UV and 8 Y
2539
#define YUVTORGB16(yuvconstants)                                  \
2540
  "pcmpeqb    %%xmm0,%%xmm0                                   \n" \
2541
  "pxor       %%xmm1,%%xmm1                                   \n" \
2542
  "psllw      $7,%%xmm0                                       \n" \
2543
  "pshufb     %%xmm1,%%xmm0                                   \n" \
2544
  "psubb      %%xmm0,%%xmm3                                   \n" \
2545
  "pmulhuw    96(%[yuvconstants]),%%xmm4                      \n" \
2546
  "movdqa     (%[yuvconstants]),%%xmm0                        \n" \
2547
  "movdqa     32(%[yuvconstants]),%%xmm1                      \n" \
2548
  "movdqa     64(%[yuvconstants]),%%xmm2                      \n" \
2549
  "pmaddubsw  %%xmm3,%%xmm0                                   \n" \
2550
  "pmaddubsw  %%xmm3,%%xmm1                                   \n" \
2551
  "pmaddubsw  %%xmm3,%%xmm2                                   \n" \
2552
  "movdqa     128(%[yuvconstants]),%%xmm3                     \n" \
2553
  "paddw      %%xmm3,%%xmm4                                   \n" \
2554
  "paddsw     %%xmm4,%%xmm0                                   \n" \
2555
  "paddsw     %%xmm4,%%xmm2                                   \n" \
2556
  "psubsw     %%xmm1,%%xmm4                                   \n" \
2557
  "movdqa     %%xmm4,%%xmm1                                   \n"
2558
2559
#define YUVTORGB_REGS
2560
#endif
2561
2562
#define YUVTORGB(yuvconstants)                                    \
2563
  YUVTORGB16(yuvconstants)                                        \
2564
  "psraw      $0x6,%%xmm0                                     \n" \
2565
  "psraw      $0x6,%%xmm1                                     \n" \
2566
  "psraw      $0x6,%%xmm2                                     \n" \
2567
  "packuswb   %%xmm0,%%xmm0                                   \n" \
2568
  "packuswb   %%xmm1,%%xmm1                                   \n" \
2569
  "packuswb   %%xmm2,%%xmm2                                   \n"
2570
2571
// Store 8 ARGB values.
2572
#define STOREARGB                                                  \
2573
  "punpcklbw  %%xmm1,%%xmm0                                    \n" \
2574
  "punpcklbw  %%xmm5,%%xmm2                                    \n" \
2575
  "movdqa     %%xmm0,%%xmm1                                    \n" \
2576
  "punpcklwd  %%xmm2,%%xmm0                                    \n" \
2577
  "punpckhwd  %%xmm2,%%xmm1                                    \n" \
2578
  "movdqu     %%xmm0,(%[dst_argb])                             \n" \
2579
  "movdqu     %%xmm1,0x10(%[dst_argb])                         \n" \
2580
  "lea        0x20(%[dst_argb]), %[dst_argb]                   \n"
2581
2582
// Store 8 RGBA values.
2583
#define STORERGBA                                                  \
2584
  "pcmpeqb   %%xmm5,%%xmm5                                     \n" \
2585
  "punpcklbw %%xmm2,%%xmm1                                     \n" \
2586
  "punpcklbw %%xmm0,%%xmm5                                     \n" \
2587
  "movdqa    %%xmm5,%%xmm0                                     \n" \
2588
  "punpcklwd %%xmm1,%%xmm5                                     \n" \
2589
  "punpckhwd %%xmm1,%%xmm0                                     \n" \
2590
  "movdqu    %%xmm5,(%[dst_rgba])                              \n" \
2591
  "movdqu    %%xmm0,0x10(%[dst_rgba])                          \n" \
2592
  "lea       0x20(%[dst_rgba]),%[dst_rgba]                     \n"
2593
2594
// Store 8 RGB24 values.
2595
#define STORERGB24                                                      \
2596
  "punpcklbw   %%xmm1,%%xmm0                                        \n" \
2597
  "punpcklbw   %%xmm2,%%xmm2                                        \n" \
2598
  "movdqa      %%xmm0,%%xmm1                                        \n" \
2599
  "punpcklwd   %%xmm2,%%xmm0                                        \n" \
2600
  "punpckhwd   %%xmm2,%%xmm1                                        \n" \
2601
  "pshufb      %%xmm5,%%xmm0                                        \n" \
2602
  "pshufb      %%xmm6,%%xmm1                                        \n" \
2603
  "palignr     $0xc,%%xmm0,%%xmm1                                   \n" \
2604
  "movq        %%xmm0,(%[dst_rgb24])                                \n" \
2605
  "movdqu      %%xmm1,0x8(%[dst_rgb24])                             \n" \
2606
  "lea         0x18(%[dst_rgb24]),%[dst_rgb24]                      \n"
2607
2608
// Store 8 AR30 values.
2609
#define STOREAR30                                                  \
2610
  "psraw      $0x4,%%xmm0                                      \n" \
2611
  "psraw      $0x4,%%xmm1                                      \n" \
2612
  "psraw      $0x4,%%xmm2                                      \n" \
2613
  "pminsw     %%xmm7,%%xmm0                                    \n" \
2614
  "pminsw     %%xmm7,%%xmm1                                    \n" \
2615
  "pminsw     %%xmm7,%%xmm2                                    \n" \
2616
  "pmaxsw     %%xmm6,%%xmm0                                    \n" \
2617
  "pmaxsw     %%xmm6,%%xmm1                                    \n" \
2618
  "pmaxsw     %%xmm6,%%xmm2                                    \n" \
2619
  "psllw      $0x4,%%xmm2                                      \n" \
2620
  "movdqa     %%xmm0,%%xmm3                                    \n" \
2621
  "punpcklwd  %%xmm2,%%xmm0                                    \n" \
2622
  "punpckhwd  %%xmm2,%%xmm3                                    \n" \
2623
  "movdqa     %%xmm1,%%xmm2                                    \n" \
2624
  "punpcklwd  %%xmm5,%%xmm1                                    \n" \
2625
  "punpckhwd  %%xmm5,%%xmm2                                    \n" \
2626
  "pslld      $0xa,%%xmm1                                      \n" \
2627
  "pslld      $0xa,%%xmm2                                      \n" \
2628
  "por        %%xmm1,%%xmm0                                    \n" \
2629
  "por        %%xmm2,%%xmm3                                    \n" \
2630
  "movdqu     %%xmm0,(%[dst_ar30])                             \n" \
2631
  "movdqu     %%xmm3,0x10(%[dst_ar30])                         \n" \
2632
  "lea        0x20(%[dst_ar30]), %[dst_ar30]                   \n"
2633
2634
void OMITFP I444ToARGBRow_SSSE3(const uint8_t* y_buf,
2635
                                const uint8_t* u_buf,
2636
                                const uint8_t* v_buf,
2637
                                uint8_t* dst_argb,
2638
                                const struct YuvConstants* yuvconstants,
2639
0
                                int width) {
2640
0
  asm volatile (
2641
0
    YUVTORGB_SETUP(yuvconstants)
2642
0
      "sub         %[u_buf],%[v_buf]             \n"
2643
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
2644
2645
0
    LABELALIGN
2646
0
      "1:          \n"
2647
0
    READYUV444
2648
0
    YUVTORGB(yuvconstants)
2649
0
    STOREARGB
2650
0
      "sub         $0x8,%[width]                 \n"
2651
0
      "jg          1b                            \n"
2652
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
2653
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
2654
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
2655
0
    [dst_argb]"+r"(dst_argb),  // %[dst_argb]
2656
0
    [width]"+rm"(width)    // %[width]
2657
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
2658
0
  : "memory", "cc", YUVTORGB_REGS
2659
0
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"
2660
0
  );
2661
0
}
2662
2663
#ifdef HAS_I444ALPHATOARGBROW_SSSE3
2664
void OMITFP I444AlphaToARGBRow_SSSE3(const uint8_t* y_buf,
2665
                                     const uint8_t* u_buf,
2666
                                     const uint8_t* v_buf,
2667
                                     const uint8_t* a_buf,
2668
                                     uint8_t* dst_argb,
2669
                                     const struct YuvConstants* yuvconstants,
2670
0
                                     int width) {
2671
0
  asm volatile(YUVTORGB_SETUP(
2672
0
                   yuvconstants) "sub         %[u_buf],%[v_buf]             \n"
2673
2674
0
               LABELALIGN "1:          \n" READYUVA444 YUVTORGB(yuvconstants)
2675
0
                   STOREARGB
2676
0
               "subl        $0x8,%[width]                 \n"
2677
0
               "jg          1b                            \n"
2678
0
               : [y_buf] "+r"(y_buf),        // %[y_buf]
2679
0
                 [u_buf] "+r"(u_buf),        // %[u_buf]
2680
0
                 [v_buf] "+r"(v_buf),        // %[v_buf]
2681
0
                 [a_buf] "+r"(a_buf),        // %[a_buf]
2682
0
                 [dst_argb] "+r"(dst_argb),  // %[dst_argb]
2683
#if defined(__i386__)
2684
                 [width] "+m"(width)  // %[width]
2685
#else
2686
0
                 [width] "+rm"(width)  // %[width]
2687
0
#endif
2688
0
               : [yuvconstants] "r"(yuvconstants)  // %[yuvconstants]
2689
0
               : "memory", "cc", YUVTORGB_REGS "xmm0", "xmm1", "xmm2", "xmm3",
2690
0
                 "xmm4", "xmm5");
2691
0
}
2692
#endif  // HAS_I444ALPHATOARGBROW_SSSE3
2693
2694
void OMITFP I422ToRGB24Row_SSSE3(const uint8_t* y_buf,
2695
                                 const uint8_t* u_buf,
2696
                                 const uint8_t* v_buf,
2697
                                 uint8_t* dst_rgb24,
2698
                                 const struct YuvConstants* yuvconstants,
2699
0
                                 int width) {
2700
0
  asm volatile (
2701
0
    YUVTORGB_SETUP(yuvconstants)
2702
0
      "movdqa      %[kShuffleMaskARGBToRGB24_0],%%xmm5 \n"
2703
0
      "movdqa      %[kShuffleMaskARGBToRGB24],%%xmm6 \n"
2704
0
      "sub         %[u_buf],%[v_buf]             \n"
2705
2706
0
    LABELALIGN
2707
0
      "1:          \n"
2708
0
    READYUV422
2709
0
    YUVTORGB(yuvconstants)
2710
0
    STORERGB24
2711
0
      "subl        $0x8,%[width]                 \n"
2712
0
      "jg          1b                            \n"
2713
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
2714
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
2715
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
2716
0
    [dst_rgb24]"+r"(dst_rgb24),  // %[dst_rgb24]
2717
#if defined(__i386__)
2718
    [width]"+m"(width)     // %[width]
2719
#else
2720
0
    [width]"+rm"(width)    // %[width]
2721
0
#endif
2722
0
  : [yuvconstants]"r"(yuvconstants),  // %[yuvconstants]
2723
0
    [kShuffleMaskARGBToRGB24_0]"m"(kShuffleMaskARGBToRGB24_0),
2724
0
    [kShuffleMaskARGBToRGB24]"m"(kShuffleMaskARGBToRGB24)
2725
0
  : "memory", "cc", YUVTORGB_REGS
2726
0
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6"
2727
0
  );
2728
0
}
2729
2730
void OMITFP I444ToRGB24Row_SSSE3(const uint8_t* y_buf,
2731
                                 const uint8_t* u_buf,
2732
                                 const uint8_t* v_buf,
2733
                                 uint8_t* dst_rgb24,
2734
                                 const struct YuvConstants* yuvconstants,
2735
0
                                 int width) {
2736
0
  asm volatile (
2737
0
    YUVTORGB_SETUP(yuvconstants)
2738
0
      "movdqa      %[kShuffleMaskARGBToRGB24_0],%%xmm5 \n"
2739
0
      "movdqa      %[kShuffleMaskARGBToRGB24],%%xmm6 \n"
2740
0
      "sub         %[u_buf],%[v_buf]             \n"
2741
2742
0
    LABELALIGN
2743
0
      "1:          \n"
2744
0
    READYUV444
2745
0
    YUVTORGB(yuvconstants)
2746
0
    STORERGB24
2747
0
      "subl        $0x8,%[width]                 \n"
2748
0
      "jg          1b                            \n"
2749
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
2750
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
2751
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
2752
0
    [dst_rgb24]"+r"(dst_rgb24),  // %[dst_rgb24]
2753
#if defined(__i386__)
2754
    [width]"+m"(width)     // %[width]
2755
#else
2756
0
    [width]"+rm"(width)    // %[width]
2757
0
#endif
2758
0
  : [yuvconstants]"r"(yuvconstants),  // %[yuvconstants]
2759
0
    [kShuffleMaskARGBToRGB24_0]"m"(kShuffleMaskARGBToRGB24_0),
2760
0
    [kShuffleMaskARGBToRGB24]"m"(kShuffleMaskARGBToRGB24)
2761
0
  : "memory", "cc", YUVTORGB_REGS
2762
0
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6"
2763
0
  );
2764
0
}
2765
2766
void OMITFP I422ToARGBRow_SSSE3(const uint8_t* y_buf,
2767
                                const uint8_t* u_buf,
2768
                                const uint8_t* v_buf,
2769
                                uint8_t* dst_argb,
2770
                                const struct YuvConstants* yuvconstants,
2771
0
                                int width) {
2772
0
  asm volatile (
2773
0
    YUVTORGB_SETUP(yuvconstants)
2774
0
      "sub         %[u_buf],%[v_buf]             \n"
2775
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
2776
2777
0
    LABELALIGN
2778
0
      "1:          \n"
2779
0
    READYUV422
2780
0
    YUVTORGB(yuvconstants)
2781
0
    STOREARGB
2782
0
      "sub         $0x8,%[width]                 \n"
2783
0
      "jg          1b                            \n"
2784
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
2785
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
2786
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
2787
0
    [dst_argb]"+r"(dst_argb),  // %[dst_argb]
2788
0
    [width]"+rm"(width)    // %[width]
2789
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
2790
0
  : "memory", "cc", YUVTORGB_REGS
2791
0
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"
2792
0
  );
2793
0
}
2794
2795
void OMITFP I422ToAR30Row_SSSE3(const uint8_t* y_buf,
2796
                                const uint8_t* u_buf,
2797
                                const uint8_t* v_buf,
2798
                                uint8_t* dst_ar30,
2799
                                const struct YuvConstants* yuvconstants,
2800
0
                                int width) {
2801
0
  asm volatile (
2802
0
    YUVTORGB_SETUP(yuvconstants)
2803
0
      "sub         %[u_buf],%[v_buf]             \n"
2804
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"  // AR30 constants
2805
0
      "psrlw       $14,%%xmm5                    \n"
2806
0
      "psllw       $4,%%xmm5                     \n"  // 2 alpha bits
2807
0
      "pxor        %%xmm6,%%xmm6                 \n"  // 0 for min
2808
0
      "pcmpeqb     %%xmm7,%%xmm7                 \n"
2809
0
      "psrlw       $6,%%xmm7                     \n"  // 1023 for max
2810
2811
0
    LABELALIGN
2812
0
      "1:          \n"
2813
0
    READYUV422
2814
0
    YUVTORGB16(yuvconstants)
2815
0
    STOREAR30
2816
0
      "sub         $0x8,%[width]                 \n"
2817
0
      "jg          1b                            \n"
2818
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
2819
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
2820
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
2821
0
    [dst_ar30]"+r"(dst_ar30),  // %[dst_ar30]
2822
0
    [width]"+rm"(width)    // %[width]
2823
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
2824
0
  : "memory", "cc", YUVTORGB_REGS
2825
0
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
2826
0
  );
2827
0
}
2828
2829
// 10 bit YUV to ARGB
2830
void OMITFP I210ToARGBRow_SSSE3(const uint16_t* y_buf,
2831
                                const uint16_t* u_buf,
2832
                                const uint16_t* v_buf,
2833
                                uint8_t* dst_argb,
2834
                                const struct YuvConstants* yuvconstants,
2835
0
                                int width) {
2836
0
  asm volatile (
2837
0
    YUVTORGB_SETUP(yuvconstants)
2838
0
      "sub         %[u_buf],%[v_buf]             \n"
2839
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
2840
2841
0
    LABELALIGN
2842
0
      "1:          \n"
2843
0
    READYUV210
2844
0
    YUVTORGB(yuvconstants)
2845
0
    STOREARGB
2846
0
      "sub         $0x8,%[width]                 \n"
2847
0
      "jg          1b                            \n"
2848
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
2849
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
2850
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
2851
0
    [dst_argb]"+r"(dst_argb),  // %[dst_argb]
2852
0
    [width]"+rm"(width)    // %[width]
2853
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
2854
0
  : "memory", "cc", YUVTORGB_REGS
2855
0
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"
2856
0
  );
2857
0
}
2858
2859
// 12 bit YUV to ARGB
2860
void OMITFP I212ToARGBRow_SSSE3(const uint16_t* y_buf,
2861
                                const uint16_t* u_buf,
2862
                                const uint16_t* v_buf,
2863
                                uint8_t* dst_argb,
2864
                                const struct YuvConstants* yuvconstants,
2865
0
                                int width) {
2866
0
  asm volatile (
2867
0
    YUVTORGB_SETUP(yuvconstants)
2868
0
      "sub         %[u_buf],%[v_buf]             \n"
2869
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
2870
2871
0
    LABELALIGN
2872
0
      "1:          \n"
2873
0
    READYUV212
2874
0
    YUVTORGB(yuvconstants)
2875
0
    STOREARGB
2876
0
      "sub         $0x8,%[width]                 \n"
2877
0
      "jg          1b                            \n"
2878
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
2879
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
2880
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
2881
0
    [dst_argb]"+r"(dst_argb),  // %[dst_argb]
2882
0
    [width]"+rm"(width)    // %[width]
2883
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
2884
0
  : "memory", "cc", YUVTORGB_REGS
2885
0
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"
2886
0
  );
2887
0
}
2888
2889
// 10 bit YUV to AR30
2890
void OMITFP I210ToAR30Row_SSSE3(const uint16_t* y_buf,
2891
                                const uint16_t* u_buf,
2892
                                const uint16_t* v_buf,
2893
                                uint8_t* dst_ar30,
2894
                                const struct YuvConstants* yuvconstants,
2895
0
                                int width) {
2896
0
  asm volatile (
2897
0
    YUVTORGB_SETUP(yuvconstants)
2898
0
      "sub         %[u_buf],%[v_buf]             \n"
2899
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
2900
0
      "psrlw       $14,%%xmm5                    \n"
2901
0
      "psllw       $4,%%xmm5                     \n"  // 2 alpha bits
2902
0
      "pxor        %%xmm6,%%xmm6                 \n"  // 0 for min
2903
0
      "pcmpeqb     %%xmm7,%%xmm7                 \n"
2904
0
      "psrlw       $6,%%xmm7                     \n"  // 1023 for max
2905
2906
0
    LABELALIGN
2907
0
      "1:          \n"
2908
0
    READYUV210
2909
0
    YUVTORGB16(yuvconstants)
2910
0
    STOREAR30
2911
0
      "sub         $0x8,%[width]                 \n"
2912
0
      "jg          1b                            \n"
2913
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
2914
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
2915
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
2916
0
    [dst_ar30]"+r"(dst_ar30),  // %[dst_ar30]
2917
0
    [width]"+rm"(width)    // %[width]
2918
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
2919
0
  : "memory", "cc", YUVTORGB_REGS
2920
0
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
2921
0
  );
2922
0
}
2923
2924
// 12 bit YUV to AR30
2925
void OMITFP I212ToAR30Row_SSSE3(const uint16_t* y_buf,
2926
                                const uint16_t* u_buf,
2927
                                const uint16_t* v_buf,
2928
                                uint8_t* dst_ar30,
2929
                                const struct YuvConstants* yuvconstants,
2930
0
                                int width) {
2931
0
  asm volatile (
2932
0
    YUVTORGB_SETUP(yuvconstants)
2933
0
      "sub         %[u_buf],%[v_buf]             \n"
2934
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
2935
0
      "psrlw       $14,%%xmm5                    \n"
2936
0
      "psllw       $4,%%xmm5                     \n"  // 2 alpha bits
2937
0
      "pxor        %%xmm6,%%xmm6                 \n"  // 0 for min
2938
0
      "pcmpeqb     %%xmm7,%%xmm7                 \n"
2939
0
      "psrlw       $6,%%xmm7                     \n"  // 1023 for max
2940
2941
0
    LABELALIGN
2942
0
      "1:          \n"
2943
0
    READYUV212
2944
0
    YUVTORGB16(yuvconstants)
2945
0
    STOREAR30
2946
0
      "sub         $0x8,%[width]                 \n"
2947
0
      "jg          1b                            \n"
2948
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
2949
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
2950
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
2951
0
    [dst_ar30]"+r"(dst_ar30),  // %[dst_ar30]
2952
0
    [width]"+rm"(width)    // %[width]
2953
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
2954
0
  : "memory", "cc", YUVTORGB_REGS
2955
0
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
2956
0
  );
2957
0
}
2958
2959
// 10 bit YUV to ARGB
2960
void OMITFP I410ToARGBRow_SSSE3(const uint16_t* y_buf,
2961
                                const uint16_t* u_buf,
2962
                                const uint16_t* v_buf,
2963
                                uint8_t* dst_argb,
2964
                                const struct YuvConstants* yuvconstants,
2965
0
                                int width) {
2966
0
  asm volatile (
2967
0
    YUVTORGB_SETUP(yuvconstants)
2968
0
      "sub         %[u_buf],%[v_buf]             \n"
2969
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
2970
2971
0
    LABELALIGN
2972
0
      "1:          \n"
2973
0
    READYUV410
2974
0
    YUVTORGB(yuvconstants)
2975
0
    STOREARGB
2976
0
      "sub         $0x8,%[width]                 \n"
2977
0
      "jg          1b                            \n"
2978
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
2979
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
2980
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
2981
0
    [dst_argb]"+r"(dst_argb),  // %[dst_argb]
2982
0
    [width]"+rm"(width)    // %[width]
2983
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
2984
0
  : "memory", "cc", YUVTORGB_REGS "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"
2985
0
  );
2986
0
}
2987
2988
#ifdef HAS_I210ALPHATOARGBROW_SSSE3
2989
// 10 bit YUVA to ARGB
2990
void OMITFP I210AlphaToARGBRow_SSSE3(const uint16_t* y_buf,
2991
                                     const uint16_t* u_buf,
2992
                                     const uint16_t* v_buf,
2993
                                     const uint16_t* a_buf,
2994
                                     uint8_t* dst_argb,
2995
                                     const struct YuvConstants* yuvconstants,
2996
0
                                     int width) {
2997
0
  asm volatile(YUVTORGB_SETUP(
2998
0
                   yuvconstants) "sub         %[u_buf],%[v_buf]             \n"
2999
3000
0
               LABELALIGN "1:          \n" READYUVA210 YUVTORGB(yuvconstants)
3001
0
                   STOREARGB
3002
0
               "subl        $0x8,%[width]                 \n"
3003
0
               "jg          1b                            \n"
3004
0
               : [y_buf] "+r"(y_buf),  // %[y_buf]
3005
0
                 [u_buf] "+r"(u_buf),  // %[u_buf]
3006
0
                 [v_buf] "+r"(v_buf),  // %[v_buf]
3007
0
                 [a_buf] "+r"(a_buf),
3008
0
                 [dst_argb] "+r"(dst_argb),  // %[dst_argb]
3009
#if defined(__i386__)
3010
                 [width] "+m"(width)  // %[width]
3011
#else
3012
0
                 [width] "+rm"(width)  // %[width]
3013
0
#endif
3014
0
               : [yuvconstants] "r"(yuvconstants)  // %[yuvconstants]
3015
0
               : "memory", "cc", YUVTORGB_REGS "xmm0", "xmm1", "xmm2", "xmm3",
3016
0
                 "xmm4", "xmm5");
3017
0
}
3018
#endif
3019
3020
#ifdef HAS_I410ALPHATOARGBROW_SSSE3
3021
// 10 bit YUVA to ARGB
3022
void OMITFP I410AlphaToARGBRow_SSSE3(const uint16_t* y_buf,
3023
                                     const uint16_t* u_buf,
3024
                                     const uint16_t* v_buf,
3025
                                     const uint16_t* a_buf,
3026
                                     uint8_t* dst_argb,
3027
                                     const struct YuvConstants* yuvconstants,
3028
0
                                     int width) {
3029
0
  asm volatile(YUVTORGB_SETUP(
3030
0
                   yuvconstants) "sub         %[u_buf],%[v_buf]             \n"
3031
3032
0
               LABELALIGN "1:          \n" READYUVA410 YUVTORGB(yuvconstants)
3033
0
                   STOREARGB
3034
0
               "subl        $0x8,%[width]                 \n"
3035
0
               "jg          1b                            \n"
3036
0
               : [y_buf] "+r"(y_buf),  // %[y_buf]
3037
0
                 [u_buf] "+r"(u_buf),  // %[u_buf]
3038
0
                 [v_buf] "+r"(v_buf),  // %[v_buf]
3039
0
                 [a_buf] "+r"(a_buf),
3040
0
                 [dst_argb] "+r"(dst_argb),  // %[dst_argb]
3041
#if defined(__i386__)
3042
                 [width] "+m"(width)  // %[width]
3043
#else
3044
0
                 [width] "+rm"(width)  // %[width]
3045
0
#endif
3046
0
               : [yuvconstants] "r"(yuvconstants)  // %[yuvconstants]
3047
0
               : "memory", "cc", YUVTORGB_REGS "xmm0", "xmm1", "xmm2", "xmm3",
3048
0
                 "xmm4", "xmm5");
3049
0
}
3050
#endif
3051
3052
// 10 bit YUV to AR30
3053
void OMITFP I410ToAR30Row_SSSE3(const uint16_t* y_buf,
3054
                                const uint16_t* u_buf,
3055
                                const uint16_t* v_buf,
3056
                                uint8_t* dst_ar30,
3057
                                const struct YuvConstants* yuvconstants,
3058
0
                                int width) {
3059
0
  asm volatile (
3060
0
    YUVTORGB_SETUP(yuvconstants)
3061
0
      "sub         %[u_buf],%[v_buf]             \n"
3062
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
3063
0
      "psrlw       $14,%%xmm5                    \n"
3064
0
      "psllw       $4,%%xmm5                     \n"  // 2 alpha bits
3065
0
      "pxor        %%xmm6,%%xmm6                 \n"  // 0 for min
3066
0
      "pcmpeqb     %%xmm7,%%xmm7                 \n"
3067
0
      "psrlw       $6,%%xmm7                     \n"  // 1023 for max
3068
3069
0
    LABELALIGN
3070
0
      "1:          \n"
3071
0
    READYUV410
3072
0
    YUVTORGB16(yuvconstants)
3073
0
    STOREAR30
3074
0
      "sub         $0x8,%[width]                 \n"
3075
0
      "jg          1b                            \n"
3076
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
3077
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
3078
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
3079
0
    [dst_ar30]"+r"(dst_ar30),  // %[dst_ar30]
3080
0
    [width]"+rm"(width)    // %[width]
3081
0
  : [yuvconstants]"r"(yuvconstants)   // %[yuvconstants]
3082
0
  : "memory", "cc", YUVTORGB_REGS
3083
0
      "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
3084
0
  );
3085
0
}
3086
3087
#ifdef HAS_I422ALPHATOARGBROW_SSSE3
3088
void OMITFP I422AlphaToARGBRow_SSSE3(const uint8_t* y_buf,
3089
                                     const uint8_t* u_buf,
3090
                                     const uint8_t* v_buf,
3091
                                     const uint8_t* a_buf,
3092
                                     uint8_t* dst_argb,
3093
                                     const struct YuvConstants* yuvconstants,
3094
0
                                     int width) {
3095
0
  asm volatile(YUVTORGB_SETUP(
3096
0
                   yuvconstants) "sub         %[u_buf],%[v_buf]             \n"
3097
3098
0
               LABELALIGN "1:          \n" READYUVA422 YUVTORGB(yuvconstants)
3099
0
                   STOREARGB
3100
0
               "subl        $0x8,%[width]                 \n"
3101
0
               "jg          1b                            \n"
3102
0
               : [y_buf] "+r"(y_buf),        // %[y_buf]
3103
0
                 [u_buf] "+r"(u_buf),        // %[u_buf]
3104
0
                 [v_buf] "+r"(v_buf),        // %[v_buf]
3105
0
                 [a_buf] "+r"(a_buf),        // %[a_buf]
3106
0
                 [dst_argb] "+r"(dst_argb),  // %[dst_argb]
3107
#if defined(__i386__)
3108
                 [width] "+m"(width)  // %[width]
3109
#else
3110
0
                 [width] "+rm"(width)  // %[width]
3111
0
#endif
3112
0
               : [yuvconstants] "r"(yuvconstants)  // %[yuvconstants]
3113
0
               : "memory", "cc", YUVTORGB_REGS "xmm0", "xmm1", "xmm2", "xmm3",
3114
0
                 "xmm4", "xmm5");
3115
0
}
3116
#endif  // HAS_I422ALPHATOARGBROW_SSSE3
3117
3118
void OMITFP NV12ToARGBRow_SSSE3(const uint8_t* y_buf,
3119
                                const uint8_t* uv_buf,
3120
                                uint8_t* dst_argb,
3121
                                const struct YuvConstants* yuvconstants,
3122
0
                                int width) {
3123
0
  asm volatile(YUVTORGB_SETUP(
3124
0
                   yuvconstants) "pcmpeqb     %%xmm5,%%xmm5                 \n"
3125
3126
0
               LABELALIGN "1:          \n" READNV12 YUVTORGB(yuvconstants)
3127
0
                   STOREARGB
3128
0
               "sub         $0x8,%[width]                 \n"
3129
0
               "jg          1b                            \n"
3130
0
               : [y_buf] "+r"(y_buf),              // %[y_buf]
3131
0
                 [uv_buf] "+r"(uv_buf),            // %[uv_buf]
3132
0
                 [dst_argb] "+r"(dst_argb),        // %[dst_argb]
3133
0
                 [width] "+rm"(width)              // %[width]
3134
0
               : [yuvconstants] "r"(yuvconstants)  // %[yuvconstants]
3135
0
               : "memory", "cc", YUVTORGB_REGS "xmm0", "xmm1", "xmm2", "xmm3",
3136
0
                 "xmm4", "xmm5");
3137
0
}
3138
3139
void OMITFP NV21ToARGBRow_SSSE3(const uint8_t* y_buf,
3140
                                const uint8_t* vu_buf,
3141
                                uint8_t* dst_argb,
3142
                                const struct YuvConstants* yuvconstants,
3143
0
                                int width) {
3144
0
  asm volatile(YUVTORGB_SETUP(
3145
0
                   yuvconstants) "pcmpeqb     %%xmm5,%%xmm5                 \n"
3146
3147
0
               LABELALIGN "1:          \n" READNV21 YUVTORGB(yuvconstants)
3148
0
                   STOREARGB
3149
0
               "sub         $0x8,%[width]                 \n"
3150
0
               "jg          1b                            \n"
3151
0
               : [y_buf] "+r"(y_buf),               // %[y_buf]
3152
0
                 [vu_buf] "+r"(vu_buf),             // %[vu_buf]
3153
0
                 [dst_argb] "+r"(dst_argb),         // %[dst_argb]
3154
0
                 [width] "+rm"(width)               // %[width]
3155
0
               : [yuvconstants] "r"(yuvconstants),  // %[yuvconstants]
3156
0
                 [kShuffleNV21] "m"(kShuffleNV21)
3157
0
               : "memory", "cc", YUVTORGB_REGS "xmm0", "xmm1", "xmm2", "xmm3",
3158
0
                 "xmm4", "xmm5");
3159
0
}
3160
3161
void OMITFP YUY2ToARGBRow_SSSE3(const uint8_t* yuy2_buf,
3162
                                uint8_t* dst_argb,
3163
                                const struct YuvConstants* yuvconstants,
3164
0
                                int width) {
3165
0
  asm volatile(
3166
0
      "movdqa      %[kShuffleYUY2Y],%%xmm6       \n"
3167
0
      "movdqa      %[kShuffleYUY2UV],%%xmm7      \n" YUVTORGB_SETUP(
3168
0
          yuvconstants) "pcmpeqb     %%xmm5,%%xmm5                 \n"
3169
3170
0
      LABELALIGN "1:          \n" READYUY2 YUVTORGB(yuvconstants) STOREARGB
3171
0
      "sub         $0x8,%[width]                 \n"
3172
0
      "jg          1b                            \n"
3173
0
      : [yuy2_buf] "+r"(yuy2_buf),         // %[yuy2_buf]
3174
0
        [dst_argb] "+r"(dst_argb),         // %[dst_argb]
3175
0
        [width] "+rm"(width)               // %[width]
3176
0
      : [yuvconstants] "r"(yuvconstants),  // %[yuvconstants]
3177
0
        [kShuffleYUY2Y] "m"(kShuffleYUY2Y), [kShuffleYUY2UV] "m"(kShuffleYUY2UV)
3178
0
      : "memory", "cc", YUVTORGB_REGS "xmm0", "xmm1", "xmm2", "xmm3", "xmm4",
3179
0
        "xmm5", "xmm6", "xmm7");
3180
0
}
3181
3182
void OMITFP UYVYToARGBRow_SSSE3(const uint8_t* uyvy_buf,
3183
                                uint8_t* dst_argb,
3184
                                const struct YuvConstants* yuvconstants,
3185
0
                                int width) {
3186
0
  asm volatile(
3187
0
      "movdqa      %[kShuffleUYVYY],%%xmm6       \n"
3188
0
      "movdqa      %[kShuffleUYVYUV],%%xmm7      \n" YUVTORGB_SETUP(
3189
0
          yuvconstants) "pcmpeqb     %%xmm5,%%xmm5                 \n"
3190
3191
0
      LABELALIGN "1:          \n" READUYVY YUVTORGB(yuvconstants) STOREARGB
3192
0
      "sub         $0x8,%[width]                 \n"
3193
0
      "jg          1b                            \n"
3194
0
      : [uyvy_buf] "+r"(uyvy_buf),         // %[uyvy_buf]
3195
0
        [dst_argb] "+r"(dst_argb),         // %[dst_argb]
3196
0
        [width] "+rm"(width)               // %[width]
3197
0
      : [yuvconstants] "r"(yuvconstants),  // %[yuvconstants]
3198
0
        [kShuffleUYVYY] "m"(kShuffleUYVYY), [kShuffleUYVYUV] "m"(kShuffleUYVYUV)
3199
0
      : "memory", "cc", YUVTORGB_REGS "xmm0", "xmm1", "xmm2", "xmm3", "xmm4",
3200
0
        "xmm5");
3201
0
}
3202
3203
void OMITFP P210ToARGBRow_SSSE3(const uint16_t* y_buf,
3204
                                const uint16_t* uv_buf,
3205
                                uint8_t* dst_argb,
3206
                                const struct YuvConstants* yuvconstants,
3207
0
                                int width) {
3208
0
  asm volatile(YUVTORGB_SETUP(
3209
0
                   yuvconstants) "pcmpeqb     %%xmm5,%%xmm5                 \n"
3210
3211
0
               LABELALIGN "1:          \n" READP210 YUVTORGB(yuvconstants)
3212
0
                   STOREARGB
3213
0
               "sub         $0x8,%[width]                 \n"
3214
0
               "jg          1b                            \n"
3215
0
               : [y_buf] "+r"(y_buf),              // %[y_buf]
3216
0
                 [uv_buf] "+r"(uv_buf),            // %[u_buf]
3217
0
                 [dst_argb] "+r"(dst_argb),        // %[dst_argb]
3218
0
                 [width] "+rm"(width)              // %[width]
3219
0
               : [yuvconstants] "r"(yuvconstants)  // %[yuvconstants]
3220
0
               : "memory", "cc", YUVTORGB_REGS "xmm0", "xmm1", "xmm2", "xmm3",
3221
0
                 "xmm4", "xmm5");
3222
0
}
3223
3224
void OMITFP P410ToARGBRow_SSSE3(const uint16_t* y_buf,
3225
                                const uint16_t* uv_buf,
3226
                                uint8_t* dst_argb,
3227
                                const struct YuvConstants* yuvconstants,
3228
0
                                int width) {
3229
0
  asm volatile(YUVTORGB_SETUP(
3230
0
                   yuvconstants) "pcmpeqb     %%xmm5,%%xmm5                 \n"
3231
3232
0
               LABELALIGN "1:          \n" READP410 YUVTORGB(yuvconstants)
3233
0
                   STOREARGB
3234
0
               "sub         $0x8,%[width]                 \n"
3235
0
               "jg          1b                            \n"
3236
0
               : [y_buf] "+r"(y_buf),              // %[y_buf]
3237
0
                 [uv_buf] "+r"(uv_buf),            // %[u_buf]
3238
0
                 [dst_argb] "+r"(dst_argb),        // %[dst_argb]
3239
0
                 [width] "+rm"(width)              // %[width]
3240
0
               : [yuvconstants] "r"(yuvconstants)  // %[yuvconstants]
3241
0
               : "memory", "cc", YUVTORGB_REGS "xmm0", "xmm1", "xmm2", "xmm3",
3242
0
                 "xmm4", "xmm5");
3243
0
}
3244
3245
void OMITFP P210ToAR30Row_SSSE3(const uint16_t* y_buf,
3246
                                const uint16_t* uv_buf,
3247
                                uint8_t* dst_ar30,
3248
                                const struct YuvConstants* yuvconstants,
3249
0
                                int width) {
3250
0
  asm volatile (
3251
0
    YUVTORGB_SETUP(yuvconstants)
3252
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
3253
0
      "psrlw       $14,%%xmm5                    \n"
3254
0
      "psllw       $4,%%xmm5                     \n"  // 2 alpha bits
3255
0
      "pxor        %%xmm6,%%xmm6                 \n"  // 0 for min
3256
0
      "pcmpeqb     %%xmm7,%%xmm7                 \n"
3257
0
      "psrlw       $6,%%xmm7                     \n"  // 1023 for max
3258
3259
0
    LABELALIGN
3260
0
      "1:          \n"
3261
0
    READP210
3262
0
    YUVTORGB16(yuvconstants)
3263
0
    STOREAR30
3264
0
      "sub         $0x8,%[width]                 \n"
3265
0
      "jg          1b                            \n"
3266
0
  : [y_buf]"+r"(y_buf),              // %[y_buf]
3267
0
    [uv_buf]"+r"(uv_buf),            // %[uv_buf]
3268
0
    [dst_ar30]"+r"(dst_ar30),        // %[dst_ar30]
3269
0
    [width]"+rm"(width)              // %[width]
3270
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
3271
0
  : "memory", "cc", YUVTORGB_REGS
3272
0
      "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
3273
0
  );
3274
0
}
3275
3276
void OMITFP P410ToAR30Row_SSSE3(const uint16_t* y_buf,
3277
                                const uint16_t* uv_buf,
3278
                                uint8_t* dst_ar30,
3279
                                const struct YuvConstants* yuvconstants,
3280
0
                                int width) {
3281
0
  asm volatile (
3282
0
    YUVTORGB_SETUP(yuvconstants)
3283
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
3284
0
      "psrlw       $14,%%xmm5                    \n"
3285
0
      "psllw       $4,%%xmm5                     \n"  // 2 alpha bits
3286
0
      "pxor        %%xmm6,%%xmm6                 \n"  // 0 for min
3287
0
      "pcmpeqb     %%xmm7,%%xmm7                 \n"
3288
0
      "psrlw       $6,%%xmm7                     \n"  // 1023 for max
3289
3290
0
    LABELALIGN
3291
0
      "1:          \n"
3292
0
    READP410
3293
0
    YUVTORGB16(yuvconstants)
3294
0
    STOREAR30
3295
0
      "sub         $0x8,%[width]                 \n"
3296
0
      "jg          1b                            \n"
3297
0
  : [y_buf]"+r"(y_buf),              // %[y_buf]
3298
0
    [uv_buf]"+r"(uv_buf),            // %[uv_buf]
3299
0
    [dst_ar30]"+r"(dst_ar30),        // %[dst_ar30]
3300
0
    [width]"+rm"(width)              // %[width]
3301
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
3302
0
  : "memory", "cc", YUVTORGB_REGS
3303
0
      "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
3304
0
  );
3305
0
}
3306
3307
void OMITFP I422ToRGBARow_SSSE3(const uint8_t* y_buf,
3308
                                const uint8_t* u_buf,
3309
                                const uint8_t* v_buf,
3310
                                uint8_t* dst_rgba,
3311
                                const struct YuvConstants* yuvconstants,
3312
0
                                int width) {
3313
0
  asm volatile (
3314
0
    YUVTORGB_SETUP(yuvconstants)
3315
0
      "sub         %[u_buf],%[v_buf]             \n"
3316
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
3317
3318
0
    LABELALIGN
3319
0
      "1:          \n"
3320
0
    READYUV422
3321
0
    YUVTORGB(yuvconstants)
3322
0
    STORERGBA
3323
0
      "sub         $0x8,%[width]                 \n"
3324
0
      "jg          1b                            \n"
3325
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
3326
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
3327
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
3328
0
    [dst_rgba]"+r"(dst_rgba),  // %[dst_rgba]
3329
0
    [width]"+rm"(width)    // %[width]
3330
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
3331
0
  : "memory", "cc", YUVTORGB_REGS
3332
0
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"
3333
0
  );
3334
0
}
3335
3336
#endif  // HAS_I422TOARGBROW_SSSE3
3337
3338
// Read 16 UV from 444
3339
#define READYUV444_AVX2                                               \
3340
  "vmovdqu    (%[u_buf]),%%xmm3                                   \n" \
3341
  "vmovdqu    0x00(%[u_buf],%[v_buf],1),%%xmm1                    \n" \
3342
  "lea        0x10(%[u_buf]),%[u_buf]                             \n" \
3343
  "vpermq     $0xd8,%%ymm3,%%ymm3                                 \n" \
3344
  "vpermq     $0xd8,%%ymm1,%%ymm1                                 \n" \
3345
  "vpunpcklbw %%ymm1,%%ymm3,%%ymm3                                \n" \
3346
  "vmovdqu    (%[y_buf]),%%xmm4                                   \n" \
3347
  "vpermq     $0xd8,%%ymm4,%%ymm4                                 \n" \
3348
  "vpunpcklbw %%ymm4,%%ymm4,%%ymm4                                \n" \
3349
  "lea        0x10(%[y_buf]),%[y_buf]                             \n"
3350
3351
// Read 8 UV from 422, upsample to 16 UV.
3352
#define READYUV422_AVX2                                               \
3353
  "vmovq      (%[u_buf]),%%xmm3                                   \n" \
3354
  "vmovq      0x00(%[u_buf],%[v_buf],1),%%xmm1                    \n" \
3355
  "lea        0x8(%[u_buf]),%[u_buf]                              \n" \
3356
  "vpunpcklbw %%ymm1,%%ymm3,%%ymm3                                \n" \
3357
  "vpermq     $0xd8,%%ymm3,%%ymm3                                 \n" \
3358
  "vpunpcklwd %%ymm3,%%ymm3,%%ymm3                                \n" \
3359
  "vmovdqu    (%[y_buf]),%%xmm4                                   \n" \
3360
  "vpermq     $0xd8,%%ymm4,%%ymm4                                 \n" \
3361
  "vpunpcklbw %%ymm4,%%ymm4,%%ymm4                                \n" \
3362
  "lea        0x10(%[y_buf]),%[y_buf]                             \n"
3363
3364
#define READYUV422_AVX512BW                                           \
3365
  "vmovdqu    (%[u_buf]),%%xmm3                                   \n" \
3366
  "vmovdqu    0x00(%[u_buf],%[v_buf],1),%%xmm1                    \n" \
3367
  "vpermq     %%zmm3,%%zmm16,%%zmm3                               \n" \
3368
  "vpermq     %%zmm1,%%zmm16,%%zmm1                               \n" \
3369
  "lea        0x10(%[u_buf]),%[u_buf]                             \n" \
3370
  "vpunpcklbw %%zmm1,%%zmm3,%%zmm3                                \n" \
3371
  "vpermq     $0xd8,%%zmm3,%%zmm3                                 \n" \
3372
  "vpunpcklwd %%zmm3,%%zmm3,%%zmm3                                \n" \
3373
  "vmovdqu    (%[y_buf]),%%ymm4                                   \n" \
3374
  "vpermq     %%zmm4,%%zmm17,%%zmm4                               \n" \
3375
  "vpermq     $0xd8,%%zmm4,%%zmm4                                 \n" \
3376
  "vpunpcklbw %%zmm4,%%zmm4,%%zmm4                                \n" \
3377
  "lea        0x20(%[y_buf]),%[y_buf]                             \n"
3378
3379
// Read 8 UV from 210, upsample to 16 UV
3380
// TODO(fbarchard): Consider vpshufb to replace pack/unpack
3381
// TODO(fbarchard): Consider vunpcklpd to combine the 2 registers into 1.
3382
#define READYUV210_AVX2                                            \
3383
  "vmovdqu    (%[u_buf]),%%xmm3                                \n" \
3384
  "vmovdqu    0x00(%[u_buf],%[v_buf],1),%%xmm1                 \n" \
3385
  "lea        0x10(%[u_buf]),%[u_buf]                          \n" \
3386
  "vpermq     $0xd8,%%ymm3,%%ymm3                              \n" \
3387
  "vpermq     $0xd8,%%ymm1,%%ymm1                              \n" \
3388
  "vpunpcklwd %%ymm1,%%ymm3,%%ymm3                             \n" \
3389
  "vpsraw     $2,%%ymm3,%%ymm3                                 \n" \
3390
  "vpackuswb  %%ymm3,%%ymm3,%%ymm3                             \n" \
3391
  "vpunpcklwd %%ymm3,%%ymm3,%%ymm3                             \n" \
3392
  "vmovdqu    (%[y_buf]),%%ymm4                                \n" \
3393
  "vpsllw     $6,%%ymm4,%%ymm2                                 \n" \
3394
  "vpsrlw     $4,%%ymm4,%%ymm4                                 \n" \
3395
  "vpaddw     %%ymm2,%%ymm4,%%ymm4                             \n" \
3396
  "lea        0x20(%[y_buf]),%[y_buf]                          \n"
3397
3398
// Read 8 UV from 210, upsample to 16 UV. With 16 Alpha.
3399
#define READYUVA210_AVX2                                           \
3400
  "vmovdqu    (%[u_buf]),%%xmm3                                \n" \
3401
  "vmovdqu    0x00(%[u_buf],%[v_buf],1),%%xmm1                 \n" \
3402
  "lea        0x10(%[u_buf]),%[u_buf]                          \n" \
3403
  "vpermq     $0xd8,%%ymm3,%%ymm3                              \n" \
3404
  "vpermq     $0xd8,%%ymm1,%%ymm1                              \n" \
3405
  "vpunpcklwd %%ymm1,%%ymm3,%%ymm3                             \n" \
3406
  "vpsraw     $2,%%ymm3,%%ymm3                                 \n" \
3407
  "vpackuswb  %%ymm3,%%ymm3,%%ymm3                             \n" \
3408
  "vpunpcklwd %%ymm3,%%ymm3,%%ymm3                             \n" \
3409
  "vmovdqu    (%[y_buf]),%%ymm4                                \n" \
3410
  "vpsllw     $6,%%ymm4,%%ymm2                                 \n" \
3411
  "vpsrlw     $4,%%ymm4,%%ymm4                                 \n" \
3412
  "vpaddw     %%ymm2,%%ymm4,%%ymm4                             \n" \
3413
  "lea        0x20(%[y_buf]),%[y_buf]                          \n" \
3414
  "vmovdqu    (%[a_buf]),%%ymm5                                \n" \
3415
  "vpsraw     $2,%%ymm5,%%ymm5                                 \n" \
3416
  "vpackuswb  %%ymm5,%%ymm5,%%ymm5                             \n" \
3417
  "lea        0x20(%[a_buf]),%[a_buf]                          \n"
3418
3419
// Read 16 UV from 410
3420
#define READYUV410_AVX2                                            \
3421
  "vmovdqu    (%[u_buf]),%%ymm3                                \n" \
3422
  "vmovdqu    0x00(%[u_buf],%[v_buf],1),%%ymm2                 \n" \
3423
  "lea        0x20(%[u_buf]),%[u_buf]                          \n" \
3424
  "vpsraw     $2,%%ymm3,%%ymm3                                 \n" \
3425
  "vpsraw     $2,%%ymm2,%%ymm2                                 \n" \
3426
  "vpunpckhwd %%ymm2,%%ymm3,%%ymm1                             \n" \
3427
  "vpunpcklwd %%ymm2,%%ymm3,%%ymm3                             \n" \
3428
  "vpackuswb  %%ymm1,%%ymm3,%%ymm3                             \n" \
3429
  "vmovdqu    (%[y_buf]),%%ymm4                                \n" \
3430
  "vpsllw     $6,%%ymm4,%%ymm2                                 \n" \
3431
  "vpsrlw     $4,%%ymm4,%%ymm4                                 \n" \
3432
  "vpaddw     %%ymm2,%%ymm4,%%ymm4                             \n" \
3433
  "lea        0x20(%[y_buf]),%[y_buf]                          \n"
3434
3435
// Read 8 UV from 212 12 bit, upsample to 16 UV
3436
#define READYUV212_AVX2                                            \
3437
  "vmovdqu    (%[u_buf]),%%xmm3                                \n" \
3438
  "vmovdqu    0x00(%[u_buf],%[v_buf],1),%%xmm1                 \n" \
3439
  "lea        0x10(%[u_buf]),%[u_buf]                          \n" \
3440
  "vpermq     $0xd8,%%ymm3,%%ymm3                              \n" \
3441
  "vpermq     $0xd8,%%ymm1,%%ymm1                              \n" \
3442
  "vpunpcklwd %%ymm1,%%ymm3,%%ymm3                             \n" \
3443
  "vpsraw     $0x4,%%ymm3,%%ymm3                               \n" \
3444
  "vpackuswb  %%ymm3,%%ymm3,%%ymm3                             \n" \
3445
  "vpunpcklwd %%ymm3,%%ymm3,%%ymm3                             \n" \
3446
  "vmovdqu    (%[y_buf]),%%ymm4                                \n" \
3447
  "vpsllw     $4,%%ymm4,%%ymm2                                 \n" \
3448
  "vpsrlw     $8,%%ymm4,%%ymm4                                 \n" \
3449
  "vpaddw     %%ymm2,%%ymm4,%%ymm4                             \n" \
3450
  "lea        0x20(%[y_buf]),%[y_buf]                          \n"
3451
3452
// Read 16 UV from 410. With 16 Alpha.
3453
#define READYUVA410_AVX2                                           \
3454
  "vmovdqu    (%[u_buf]),%%ymm3                                \n" \
3455
  "vmovdqu    0x00(%[u_buf],%[v_buf],1),%%ymm2                 \n" \
3456
  "lea        0x20(%[u_buf]),%[u_buf]                          \n" \
3457
  "vpsraw     $2,%%ymm3,%%ymm3                                 \n" \
3458
  "vpsraw     $2,%%ymm2,%%ymm2                                 \n" \
3459
  "vpunpckhwd %%ymm2,%%ymm3,%%ymm1                             \n" \
3460
  "vpunpcklwd %%ymm2,%%ymm3,%%ymm3                             \n" \
3461
  "vpackuswb  %%ymm1,%%ymm3,%%ymm3                             \n" \
3462
  "vmovdqu    (%[y_buf]),%%ymm4                                \n" \
3463
  "vpsllw     $6,%%ymm4,%%ymm2                                 \n" \
3464
  "vpsrlw     $4,%%ymm4,%%ymm4                                 \n" \
3465
  "vpaddw     %%ymm2,%%ymm4,%%ymm4                             \n" \
3466
  "lea        0x20(%[y_buf]),%[y_buf]                          \n" \
3467
  "vmovdqu    (%[a_buf]),%%ymm5                                \n" \
3468
  "vpsraw     $2,%%ymm5,%%ymm5                                 \n" \
3469
  "vpackuswb  %%ymm5,%%ymm5,%%ymm5                             \n" \
3470
  "lea        0x20(%[a_buf]),%[a_buf]                          \n"
3471
3472
// Read 16 UV from 444.  With 16 Alpha.
3473
#define READYUVA444_AVX2                                              \
3474
  "vmovdqu    (%[u_buf]),%%xmm3                                   \n" \
3475
  "vmovdqu    0x00(%[u_buf],%[v_buf],1),%%xmm1                    \n" \
3476
  "lea        0x10(%[u_buf]),%[u_buf]                             \n" \
3477
  "vpermq     $0xd8,%%ymm3,%%ymm3                                 \n" \
3478
  "vpermq     $0xd8,%%ymm1,%%ymm1                                 \n" \
3479
  "vpunpcklbw %%ymm1,%%ymm3,%%ymm3                                \n" \
3480
  "vmovdqu    (%[y_buf]),%%xmm4                                   \n" \
3481
  "vpermq     $0xd8,%%ymm4,%%ymm4                                 \n" \
3482
  "vpunpcklbw %%ymm4,%%ymm4,%%ymm4                                \n" \
3483
  "lea        0x10(%[y_buf]),%[y_buf]                             \n" \
3484
  "vmovdqu    (%[a_buf]),%%xmm5                                   \n" \
3485
  "vpermq     $0xd8,%%ymm5,%%ymm5                                 \n" \
3486
  "lea        0x10(%[a_buf]),%[a_buf]                             \n"
3487
3488
// Read 8 UV from 422, upsample to 16 UV.  With 16 Alpha.
3489
#define READYUVA422_AVX2                                              \
3490
  "vmovq      (%[u_buf]),%%xmm3                                   \n" \
3491
  "vmovq      0x00(%[u_buf],%[v_buf],1),%%xmm1                    \n" \
3492
  "lea        0x8(%[u_buf]),%[u_buf]                              \n" \
3493
  "vpunpcklbw %%ymm1,%%ymm3,%%ymm3                                \n" \
3494
  "vpermq     $0xd8,%%ymm3,%%ymm3                                 \n" \
3495
  "vpunpcklwd %%ymm3,%%ymm3,%%ymm3                                \n" \
3496
  "vmovdqu    (%[y_buf]),%%xmm4                                   \n" \
3497
  "vpermq     $0xd8,%%ymm4,%%ymm4                                 \n" \
3498
  "vpunpcklbw %%ymm4,%%ymm4,%%ymm4                                \n" \
3499
  "lea        0x10(%[y_buf]),%[y_buf]                             \n" \
3500
  "vmovdqu    (%[a_buf]),%%xmm5                                   \n" \
3501
  "vpermq     $0xd8,%%ymm5,%%ymm5                                 \n" \
3502
  "lea        0x10(%[a_buf]),%[a_buf]                             \n"
3503
3504
// Read 8 UV from NV12, upsample to 16 UV.
3505
#define READNV12_AVX2                                                 \
3506
  "vmovdqu    (%[uv_buf]),%%xmm3                                  \n" \
3507
  "lea        0x10(%[uv_buf]),%[uv_buf]                           \n" \
3508
  "vpermq     $0xd8,%%ymm3,%%ymm3                                 \n" \
3509
  "vpunpcklwd %%ymm3,%%ymm3,%%ymm3                                \n" \
3510
  "vmovdqu    (%[y_buf]),%%xmm4                                   \n" \
3511
  "vpermq     $0xd8,%%ymm4,%%ymm4                                 \n" \
3512
  "vpunpcklbw %%ymm4,%%ymm4,%%ymm4                                \n" \
3513
  "lea        0x10(%[y_buf]),%[y_buf]                             \n"
3514
3515
// Read 8 VU from NV21, upsample to 16 UV.
3516
#define READNV21_AVX2                                                 \
3517
  "vmovdqu    (%[vu_buf]),%%xmm3                                  \n" \
3518
  "lea        0x10(%[vu_buf]),%[vu_buf]                           \n" \
3519
  "vpermq     $0xd8,%%ymm3,%%ymm3                                 \n" \
3520
  "vpshufb     %[kShuffleNV21], %%ymm3, %%ymm3                    \n" \
3521
  "vmovdqu    (%[y_buf]),%%xmm4                                   \n" \
3522
  "vpermq     $0xd8,%%ymm4,%%ymm4                                 \n" \
3523
  "vpunpcklbw %%ymm4,%%ymm4,%%ymm4                                \n" \
3524
  "lea        0x10(%[y_buf]),%[y_buf]                             \n"
3525
3526
// Read 4 UV from P210, upsample to 8 UV
3527
#define READP210_AVX2                                                 \
3528
  "vmovdqu    (%[uv_buf]),%%ymm3                                  \n" \
3529
  "lea        0x20(%[uv_buf]),%[uv_buf]                           \n" \
3530
  "vpsrlw     $0x8,%%ymm3,%%ymm3                                  \n" \
3531
  "vpackuswb  %%ymm3,%%ymm3,%%ymm3                                \n" \
3532
  "vpunpcklwd %%ymm3,%%ymm3,%%ymm3                                \n" \
3533
  "vmovdqu    (%[y_buf]),%%ymm4                                   \n" \
3534
  "lea        0x20(%[y_buf]),%[y_buf]                             \n"
3535
3536
// Read 8 UV from P410
3537
#define READP410_AVX2                                                 \
3538
  "vmovdqu    (%[uv_buf]),%%ymm3                                  \n" \
3539
  "vmovdqu    0x20(%[uv_buf]),%%ymm1                              \n" \
3540
  "lea        0x40(%[uv_buf]),%[uv_buf]                           \n" \
3541
  "vpsrlw     $0x8,%%ymm3,%%ymm3                                  \n" \
3542
  "vpsrlw     $0x8,%%ymm1,%%ymm1                                  \n" \
3543
  "vpackuswb  %%ymm1,%%ymm3,%%ymm3                                \n" \
3544
  "vpermq     $0xd8,%%ymm3,%%ymm3                                 \n" \
3545
  "vmovdqu    (%[y_buf]),%%ymm4                                   \n" \
3546
  "lea        0x20(%[y_buf]),%[y_buf]                             \n"
3547
3548
// Read 8 YUY2 with 16 Y and upsample 8 UV to 16 UV.
3549
// ymm6 kShuffleYUY2Y,
3550
// ymm7 kShuffleYUY2UV
3551
#define READYUY2_AVX2                                                 \
3552
  "vmovdqu    (%[yuy2_buf]),%%ymm1                                \n" \
3553
  "vpshufb    %%ymm6,%%ymm1,%%ymm4                                \n" \
3554
  "vpshufb    %%ymm7,%%ymm1,%%ymm3                                \n" \
3555
  "lea        0x20(%[yuy2_buf]),%[yuy2_buf]                       \n"
3556
3557
// Read 8 UYVY with 16 Y and upsample 8 UV to 16 UV.
3558
// ymm6 kShuffleUYVYY,
3559
// ymm7 kShuffleUYVYUV
3560
#define READUYVY_AVX2                                                 \
3561
  "vmovdqu    (%[uyvy_buf]),%%ymm1                                \n" \
3562
  "vpshufb    %%ymm6,%%ymm1,%%ymm4                                \n" \
3563
  "vpshufb    %%ymm7,%%ymm1,%%ymm3                                \n" \
3564
  "lea        0x20(%[uyvy_buf]),%[uyvy_buf]                       \n"
3565
3566
#if defined(__x86_64__)
3567
#define YUVTORGB_SETUP_AVX2(yuvconstants)                             \
3568
  "vpcmpeqb    %%ymm13,%%ymm13,%%ymm13                            \n" \
3569
  "vmovdqa     (%[yuvconstants]),%%ymm8                           \n" \
3570
  "vpabsb      %%ymm13,%%ymm13                                    \n" \
3571
  "vmovdqa     32(%[yuvconstants]),%%ymm9                         \n" \
3572
  "vpsllw      $7,%%ymm13,%%ymm13                                 \n" \
3573
  "vmovdqa     64(%[yuvconstants]),%%ymm10                        \n" \
3574
  "vmovdqa     96(%[yuvconstants]),%%ymm11                        \n" \
3575
  "vmovdqa     128(%[yuvconstants]),%%ymm12                       \n"
3576
3577
#define YUVTORGB_SETUP_AVX512BW(yuvconstants)                         \
3578
  "vpternlogd $0xff,%%zmm13,%%zmm13,%%zmm13                       \n" \
3579
  "vpbroadcastq (%[yuvconstants]),%%zmm8                          \n" \
3580
  "vpabsb     %%zmm13,%%zmm13                                     \n" \
3581
  "vpsllw     $7,%%zmm13,%%zmm13                                  \n" \
3582
  "vpbroadcastq 32(%[yuvconstants]),%%zmm9                        \n" \
3583
  "vpbroadcastq 64(%[yuvconstants]),%%zmm10                       \n" \
3584
  "vpbroadcastq 96(%[yuvconstants]),%%zmm11                       \n" \
3585
  "vpbroadcastq 128(%[yuvconstants]),%%zmm12                      \n" \
3586
  "vmovups    (%[quadsplitperm]),%%zmm16                          \n" \
3587
  "vmovups    (%[dquadsplitperm]),%%zmm17                         \n" \
3588
  "vmovups    (%[unperm]),%%zmm18                                 \n"
3589
3590
#define YUVTORGB16_AVX2(yuvconstants)                                 \
3591
  "vpsubb      %%ymm13,%%ymm3,%%ymm3                              \n" \
3592
  "vpmulhuw    %%ymm11,%%ymm4,%%ymm4                              \n" \
3593
  "vpmaddubsw  %%ymm3,%%ymm8,%%ymm0                               \n" \
3594
  "vpmaddubsw  %%ymm3,%%ymm9,%%ymm1                               \n" \
3595
  "vpmaddubsw  %%ymm3,%%ymm10,%%ymm2                              \n" \
3596
  "vpaddw      %%ymm4,%%ymm12,%%ymm4                              \n" \
3597
  "vpaddsw     %%ymm4,%%ymm0,%%ymm0                               \n" \
3598
  "vpsubsw     %%ymm1,%%ymm4,%%ymm1                               \n" \
3599
  "vpaddsw     %%ymm4,%%ymm2,%%ymm2                               \n"
3600
3601
#define YUVTORGB16_AVX512BW(yuvconstants)                             \
3602
  "vpsubb      %%zmm13,%%zmm3,%%zmm3                              \n" \
3603
  "vpmulhuw    %%zmm11,%%zmm4,%%zmm4                              \n" \
3604
  "vpmaddubsw  %%zmm3,%%zmm8,%%zmm0                               \n" \
3605
  "vpmaddubsw  %%zmm3,%%zmm9,%%zmm1                               \n" \
3606
  "vpmaddubsw  %%zmm3,%%zmm10,%%zmm2                              \n" \
3607
  "vpaddw      %%zmm4,%%zmm12,%%zmm4                              \n" \
3608
  "vpaddsw     %%zmm4,%%zmm0,%%zmm0                               \n" \
3609
  "vpsubsw     %%zmm1,%%zmm4,%%zmm1                               \n" \
3610
  "vpaddsw     %%zmm4,%%zmm2,%%zmm2                               \n"
3611
3612
#define YUVTORGB_REGS_AVX2 "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13",
3613
#define YUVTORGB_REGS_AVX512BW \
3614
  "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm16", "xmm17", "xmm18",
3615
3616
#else  // Convert 16 pixels: 16 UV and 16 Y.
3617
3618
#define YUVTORGB_SETUP_AVX2(yuvconstants)
3619
#define YUVTORGB16_AVX2(yuvconstants)                                 \
3620
  "vpcmpeqb    %%xmm0,%%xmm0,%%xmm0                               \n" \
3621
  "vpsllw      $7,%%xmm0,%%xmm0                                   \n" \
3622
  "vpbroadcastb %%xmm0,%%ymm0                                     \n" \
3623
  "vpsubb      %%ymm0,%%ymm3,%%ymm3                               \n" \
3624
  "vpmulhuw    96(%[yuvconstants]),%%ymm4,%%ymm4                  \n" \
3625
  "vmovdqa     (%[yuvconstants]),%%ymm0                           \n" \
3626
  "vmovdqa     32(%[yuvconstants]),%%ymm1                         \n" \
3627
  "vmovdqa     64(%[yuvconstants]),%%ymm2                         \n" \
3628
  "vpmaddubsw  %%ymm3,%%ymm0,%%ymm0                               \n" \
3629
  "vpmaddubsw  %%ymm3,%%ymm1,%%ymm1                               \n" \
3630
  "vpmaddubsw  %%ymm3,%%ymm2,%%ymm2                               \n" \
3631
  "vmovdqa     128(%[yuvconstants]),%%ymm3                        \n" \
3632
  "vpaddw      %%ymm4,%%ymm3,%%ymm4                               \n" \
3633
  "vpaddsw     %%ymm4,%%ymm0,%%ymm0                               \n" \
3634
  "vpsubsw     %%ymm1,%%ymm4,%%ymm1                               \n" \
3635
  "vpaddsw     %%ymm4,%%ymm2,%%ymm2                               \n"
3636
3637
#define YUVTORGB_REGS_AVX2
3638
#endif
3639
3640
#define YUVTORGB_AVX2(yuvconstants)                                   \
3641
  YUVTORGB16_AVX2(yuvconstants)                                       \
3642
  "vpsraw      $0x6,%%ymm0,%%ymm0                                 \n" \
3643
  "vpsraw      $0x6,%%ymm1,%%ymm1                                 \n" \
3644
  "vpsraw      $0x6,%%ymm2,%%ymm2                                 \n" \
3645
  "vpackuswb   %%ymm0,%%ymm0,%%ymm0                               \n" \
3646
  "vpackuswb   %%ymm1,%%ymm1,%%ymm1                               \n" \
3647
  "vpackuswb   %%ymm2,%%ymm2,%%ymm2                               \n"
3648
3649
#define YUVTORGB_AVX512BW(yuvconstants)                               \
3650
  YUVTORGB16_AVX512BW(yuvconstants)                                   \
3651
  "vpsraw     $0x6,%%zmm0,%%zmm0                                  \n" \
3652
  "vpsraw     $0x6,%%zmm1,%%zmm1                                  \n" \
3653
  "vpsraw     $0x6,%%zmm2,%%zmm2                                  \n" \
3654
  "vpackuswb  %%zmm0,%%zmm0,%%zmm0                                \n" \
3655
  "vpackuswb  %%zmm1,%%zmm1,%%zmm1                                \n" \
3656
  "vpackuswb  %%zmm2,%%zmm2,%%zmm2                                \n"
3657
3658
// Store 16 ARGB values.
3659
#define STOREARGB_AVX2                                                \
3660
  "vpunpcklbw %%ymm1,%%ymm0,%%ymm0                                \n" \
3661
  "vpermq     $0xd8,%%ymm0,%%ymm0                                 \n" \
3662
  "vpunpcklbw %%ymm5,%%ymm2,%%ymm2                                \n" \
3663
  "vpermq     $0xd8,%%ymm2,%%ymm2                                 \n" \
3664
  "vpunpcklwd %%ymm2,%%ymm0,%%ymm1                                \n" \
3665
  "vpunpckhwd %%ymm2,%%ymm0,%%ymm0                                \n" \
3666
  "vmovdqu    %%ymm1,(%[dst_argb])                                \n" \
3667
  "vmovdqu    %%ymm0,0x20(%[dst_argb])                            \n" \
3668
  "lea        0x40(%[dst_argb]), %[dst_argb]                      \n"
3669
3670
// Store 32 ARGB values.
3671
#define STOREARGB_AVX512BW                                            \
3672
  "vpunpcklbw %%zmm1,%%zmm0,%%zmm0                                \n" \
3673
  "vpermq     %%zmm0,%%zmm18,%%zmm0                               \n" \
3674
  "vpunpcklbw %%zmm5,%%zmm2,%%zmm2                                \n" \
3675
  "vpermq     %%zmm2,%%zmm18,%%zmm2                               \n" \
3676
  "vpunpcklwd %%zmm2,%%zmm0,%%zmm1                                \n" \
3677
  "vpunpckhwd %%zmm2,%%zmm0,%%zmm0                                \n" \
3678
  "vmovups    %%zmm1,(%[dst_argb])                                \n" \
3679
  "vmovups    %%zmm0,0x40(%[dst_argb])                            \n" \
3680
  "lea        0x80(%[dst_argb]), %[dst_argb]                      \n"
3681
3682
// Store 16 AR30 values.
3683
#define STOREAR30_AVX2                                                \
3684
  "vpsraw     $0x4,%%ymm0,%%ymm0                                  \n" \
3685
  "vpsraw     $0x4,%%ymm1,%%ymm1                                  \n" \
3686
  "vpsraw     $0x4,%%ymm2,%%ymm2                                  \n" \
3687
  "vpminsw    %%ymm7,%%ymm0,%%ymm0                                \n" \
3688
  "vpminsw    %%ymm7,%%ymm1,%%ymm1                                \n" \
3689
  "vpminsw    %%ymm7,%%ymm2,%%ymm2                                \n" \
3690
  "vpmaxsw    %%ymm6,%%ymm0,%%ymm0                                \n" \
3691
  "vpmaxsw    %%ymm6,%%ymm1,%%ymm1                                \n" \
3692
  "vpmaxsw    %%ymm6,%%ymm2,%%ymm2                                \n" \
3693
  "vpsllw     $0x4,%%ymm2,%%ymm2                                  \n" \
3694
  "vpermq     $0xd8,%%ymm0,%%ymm0                                 \n" \
3695
  "vpermq     $0xd8,%%ymm1,%%ymm1                                 \n" \
3696
  "vpermq     $0xd8,%%ymm2,%%ymm2                                 \n" \
3697
  "vpunpckhwd %%ymm2,%%ymm0,%%ymm3                                \n" \
3698
  "vpunpcklwd %%ymm2,%%ymm0,%%ymm0                                \n" \
3699
  "vpunpckhwd %%ymm5,%%ymm1,%%ymm2                                \n" \
3700
  "vpunpcklwd %%ymm5,%%ymm1,%%ymm1                                \n" \
3701
  "vpslld     $0xa,%%ymm1,%%ymm1                                  \n" \
3702
  "vpslld     $0xa,%%ymm2,%%ymm2                                  \n" \
3703
  "vpor       %%ymm1,%%ymm0,%%ymm0                                \n" \
3704
  "vpor       %%ymm2,%%ymm3,%%ymm3                                \n" \
3705
  "vmovdqu    %%ymm0,(%[dst_ar30])                                \n" \
3706
  "vmovdqu    %%ymm3,0x20(%[dst_ar30])                            \n" \
3707
  "lea        0x40(%[dst_ar30]), %[dst_ar30]                      \n"
3708
3709
#ifdef HAS_I444TOARGBROW_AVX2
3710
// 16 pixels
3711
// 16 UV values with 16 Y producing 16 ARGB (64 bytes).
3712
void OMITFP I444ToARGBRow_AVX2(const uint8_t* y_buf,
3713
                               const uint8_t* u_buf,
3714
                               const uint8_t* v_buf,
3715
                               uint8_t* dst_argb,
3716
                               const struct YuvConstants* yuvconstants,
3717
17.4k
                               int width) {
3718
17.4k
  asm volatile (
3719
17.4k
    YUVTORGB_SETUP_AVX2(yuvconstants)
3720
17.4k
      "sub         %[u_buf],%[v_buf]             \n"
3721
17.4k
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
3722
3723
17.4k
    LABELALIGN
3724
17.4k
      "1:          \n"
3725
17.4k
    READYUV444_AVX2
3726
17.4k
    YUVTORGB_AVX2(yuvconstants)
3727
17.4k
    STOREARGB_AVX2
3728
17.4k
      "sub         $0x10,%[width]                \n"
3729
17.4k
      "jg          1b                            \n"
3730
17.4k
      "vzeroupper  \n"
3731
17.4k
  : [y_buf]"+r"(y_buf),    // %[y_buf]
3732
17.4k
    [u_buf]"+r"(u_buf),    // %[u_buf]
3733
17.4k
    [v_buf]"+r"(v_buf),    // %[v_buf]
3734
17.4k
    [dst_argb]"+r"(dst_argb),  // %[dst_argb]
3735
17.4k
    [width]"+rm"(width)    // %[width]
3736
17.4k
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
3737
17.4k
  : "memory", "cc", YUVTORGB_REGS_AVX2
3738
17.4k
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"
3739
17.4k
  );
3740
17.4k
}
3741
#endif  // HAS_I444TOARGBROW_AVX2
3742
3743
#if defined(HAS_I422TOARGBROW_AVX2)
3744
// 16 pixels
3745
// 8 UV values upsampled to 16 UV, mixed with 16 Y producing 16 ARGB (64 bytes).
3746
void OMITFP I422ToARGBRow_AVX2(const uint8_t* y_buf,
3747
                               const uint8_t* u_buf,
3748
                               const uint8_t* v_buf,
3749
                               uint8_t* dst_argb,
3750
                               const struct YuvConstants* yuvconstants,
3751
8.36k
                               int width) {
3752
8.36k
  asm volatile (
3753
8.36k
    YUVTORGB_SETUP_AVX2(yuvconstants)
3754
8.36k
      "sub         %[u_buf],%[v_buf]             \n"
3755
8.36k
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
3756
3757
8.36k
    LABELALIGN
3758
8.36k
      "1:          \n"
3759
8.36k
    READYUV422_AVX2
3760
8.36k
    YUVTORGB_AVX2(yuvconstants)
3761
8.36k
    STOREARGB_AVX2
3762
8.36k
      "sub         $0x10,%[width]                \n"
3763
8.36k
      "jg          1b                            \n"
3764
3765
8.36k
      "vzeroupper  \n"
3766
8.36k
  : [y_buf]"+r"(y_buf),    // %[y_buf]
3767
8.36k
    [u_buf]"+r"(u_buf),    // %[u_buf]
3768
8.36k
    [v_buf]"+r"(v_buf),    // %[v_buf]
3769
8.36k
    [dst_argb]"+r"(dst_argb),  // %[dst_argb]
3770
8.36k
    [width]"+rm"(width)    // %[width]
3771
8.36k
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
3772
8.36k
  : "memory", "cc", YUVTORGB_REGS_AVX2
3773
8.36k
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"
3774
8.36k
  );
3775
8.36k
}
3776
#endif  // HAS_I422TOARGBROW_AVX2
3777
3778
#if defined(HAS_I422TOARGBROW_AVX512BW)
3779
static const uint64_t kSplitQuadWords[8] = {0, 2, 2, 2, 1, 2, 2, 2};
3780
static const uint64_t kSplitDoubleQuadWords[8] = {0, 1, 4, 4, 2, 3, 4, 4};
3781
static const uint64_t kUnpermuteAVX512[8] = {0, 4, 1, 5, 2, 6, 3, 7};
3782
3783
// 32 pixels
3784
// 16 UV values upsampled to 32 UV, mixed with 32 Y producing 32 ARGB (128
3785
// bytes).
3786
void OMITFP I422ToARGBRow_AVX512BW(const uint8_t* y_buf,
3787
                                   const uint8_t* u_buf,
3788
                                   const uint8_t* v_buf,
3789
                                   uint8_t* dst_argb,
3790
                                   const struct YuvConstants* yuvconstants,
3791
0
                                   int width) {
3792
0
  asm volatile (
3793
0
    YUVTORGB_SETUP_AVX512BW(yuvconstants)
3794
0
      "sub         %[u_buf],%[v_buf]             \n"
3795
0
      "vpcmpeqb    %%xmm5,%%xmm5,%%xmm5          \n"
3796
0
      "vpbroadcastq %%xmm5,%%zmm5                \n"
3797
3798
0
    LABELALIGN
3799
0
      "1:          \n"
3800
0
    READYUV422_AVX512BW
3801
0
    YUVTORGB_AVX512BW(yuvconstants)
3802
0
    STOREARGB_AVX512BW
3803
0
      "sub         $0x20,%[width]                \n"
3804
0
      "jg          1b                            \n"
3805
3806
0
      "vzeroupper  \n"
3807
0
  : [y_buf]"+r"(y_buf),                         // %[y_buf]
3808
0
    [u_buf]"+r"(u_buf),                         // %[u_buf]
3809
0
    [v_buf]"+r"(v_buf),                         // %[v_buf]
3810
0
    [dst_argb]"+r"(dst_argb),                   // %[dst_argb]
3811
0
    [width]"+rm"(width)                         // %[width]
3812
0
  : [yuvconstants]"r"(yuvconstants),            // %[yuvconstants]
3813
0
    [quadsplitperm]"r"(kSplitQuadWords),        // %[quadsplitperm]
3814
0
    [dquadsplitperm]"r"(kSplitDoubleQuadWords), // %[dquadsplitperm]
3815
0
    [unperm]"r"(kUnpermuteAVX512)               // %[unperm]
3816
0
  : "memory", "cc", YUVTORGB_REGS_AVX512BW
3817
0
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"
3818
0
  );
3819
0
}
3820
#endif  // HAS_I422TOARGBROW_AVX512BW
3821
3822
#if defined(HAS_I422TOAR30ROW_AVX2)
3823
// 16 pixels
3824
// 8 UV values upsampled to 16 UV, mixed with 16 Y producing 16 AR30 (64 bytes).
3825
void OMITFP I422ToAR30Row_AVX2(const uint8_t* y_buf,
3826
                               const uint8_t* u_buf,
3827
                               const uint8_t* v_buf,
3828
                               uint8_t* dst_ar30,
3829
                               const struct YuvConstants* yuvconstants,
3830
0
                               int width) {
3831
0
  asm volatile (
3832
0
    YUVTORGB_SETUP_AVX2(yuvconstants)
3833
0
      "sub         %[u_buf],%[v_buf]             \n"
3834
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"  // AR30 constants
3835
0
      "vpsrlw      $14,%%ymm5,%%ymm5             \n"
3836
0
      "vpsllw      $4,%%ymm5,%%ymm5              \n"  // 2 alpha bits
3837
0
      "vpxor       %%ymm6,%%ymm6,%%ymm6          \n"  // 0 for min
3838
0
      "vpcmpeqb    %%ymm7,%%ymm7,%%ymm7          \n"  // 1023 for max
3839
0
      "vpsrlw      $6,%%ymm7,%%ymm7              \n"
3840
3841
0
    LABELALIGN
3842
0
      "1:          \n"
3843
0
    READYUV422_AVX2
3844
0
    YUVTORGB16_AVX2(yuvconstants)
3845
0
    STOREAR30_AVX2
3846
0
      "sub         $0x10,%[width]                \n"
3847
0
      "jg          1b                            \n"
3848
3849
0
      "vzeroupper  \n"
3850
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
3851
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
3852
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
3853
0
    [dst_ar30]"+r"(dst_ar30),  // %[dst_ar30]
3854
0
    [width]"+rm"(width)    // %[width]
3855
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
3856
0
  : "memory", "cc", YUVTORGB_REGS_AVX2
3857
0
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
3858
0
  );
3859
0
}
3860
#endif  // HAS_I422TOAR30ROW_AVX2
3861
3862
#if defined(HAS_I210TOARGBROW_AVX2)
3863
// 16 pixels
3864
// 8 UV values upsampled to 16 UV, mixed with 16 Y producing 16 ARGB (64 bytes).
3865
void OMITFP I210ToARGBRow_AVX2(const uint16_t* y_buf,
3866
                               const uint16_t* u_buf,
3867
                               const uint16_t* v_buf,
3868
                               uint8_t* dst_argb,
3869
                               const struct YuvConstants* yuvconstants,
3870
4.26k
                               int width) {
3871
4.26k
  asm volatile (
3872
4.26k
    YUVTORGB_SETUP_AVX2(yuvconstants)
3873
4.26k
      "sub         %[u_buf],%[v_buf]             \n"
3874
4.26k
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
3875
3876
4.26k
    LABELALIGN
3877
4.26k
      "1:          \n"
3878
4.26k
    READYUV210_AVX2
3879
4.26k
    YUVTORGB_AVX2(yuvconstants)
3880
4.26k
    STOREARGB_AVX2
3881
4.26k
      "sub         $0x10,%[width]                \n"
3882
4.26k
      "jg          1b                            \n"
3883
3884
4.26k
      "vzeroupper  \n"
3885
4.26k
  : [y_buf]"+r"(y_buf),    // %[y_buf]
3886
4.26k
    [u_buf]"+r"(u_buf),    // %[u_buf]
3887
4.26k
    [v_buf]"+r"(v_buf),    // %[v_buf]
3888
4.26k
    [dst_argb]"+r"(dst_argb),  // %[dst_argb]
3889
4.26k
    [width]"+rm"(width)    // %[width]
3890
4.26k
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
3891
4.26k
  : "memory", "cc", YUVTORGB_REGS_AVX2
3892
4.26k
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"
3893
4.26k
  );
3894
4.26k
}
3895
#endif  // HAS_I210TOARGBROW_AVX2
3896
3897
#if defined(HAS_I212TOARGBROW_AVX2)
3898
// 16 pixels
3899
// 8 UV values upsampled to 16 UV, mixed with 16 Y producing 16 ARGB (64 bytes).
3900
void OMITFP I212ToARGBRow_AVX2(const uint16_t* y_buf,
3901
                               const uint16_t* u_buf,
3902
                               const uint16_t* v_buf,
3903
                               uint8_t* dst_argb,
3904
                               const struct YuvConstants* yuvconstants,
3905
5.78k
                               int width) {
3906
5.78k
  asm volatile (
3907
5.78k
    YUVTORGB_SETUP_AVX2(yuvconstants)
3908
5.78k
      "sub         %[u_buf],%[v_buf]             \n"
3909
5.78k
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
3910
3911
5.78k
    LABELALIGN
3912
5.78k
      "1:          \n"
3913
5.78k
    READYUV212_AVX2
3914
5.78k
    YUVTORGB_AVX2(yuvconstants)
3915
5.78k
    STOREARGB_AVX2
3916
5.78k
      "sub         $0x10,%[width]                \n"
3917
5.78k
      "jg          1b                            \n"
3918
3919
5.78k
      "vzeroupper  \n"
3920
5.78k
  : [y_buf]"+r"(y_buf),    // %[y_buf]
3921
5.78k
    [u_buf]"+r"(u_buf),    // %[u_buf]
3922
5.78k
    [v_buf]"+r"(v_buf),    // %[v_buf]
3923
5.78k
    [dst_argb]"+r"(dst_argb),  // %[dst_argb]
3924
5.78k
    [width]"+rm"(width)    // %[width]
3925
5.78k
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
3926
5.78k
  : "memory", "cc", YUVTORGB_REGS_AVX2
3927
5.78k
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"
3928
5.78k
  );
3929
5.78k
}
3930
#endif  // HAS_I212TOARGBROW_AVX2
3931
3932
#if defined(HAS_I210TOAR30ROW_AVX2)
3933
// 16 pixels
3934
// 8 UV values upsampled to 16 UV, mixed with 16 Y producing 16 AR30 (64 bytes).
3935
void OMITFP I210ToAR30Row_AVX2(const uint16_t* y_buf,
3936
                               const uint16_t* u_buf,
3937
                               const uint16_t* v_buf,
3938
                               uint8_t* dst_ar30,
3939
                               const struct YuvConstants* yuvconstants,
3940
0
                               int width) {
3941
0
  asm volatile (
3942
0
    YUVTORGB_SETUP_AVX2(yuvconstants)
3943
0
      "sub         %[u_buf],%[v_buf]             \n"
3944
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"  // AR30 constants
3945
0
      "vpsrlw      $14,%%ymm5,%%ymm5             \n"
3946
0
      "vpsllw      $4,%%ymm5,%%ymm5              \n"  // 2 alpha bits
3947
0
      "vpxor       %%ymm6,%%ymm6,%%ymm6          \n"  // 0 for min
3948
0
      "vpcmpeqb    %%ymm7,%%ymm7,%%ymm7          \n"  // 1023 for max
3949
0
      "vpsrlw      $6,%%ymm7,%%ymm7              \n"
3950
3951
0
    LABELALIGN
3952
0
      "1:          \n"
3953
0
    READYUV210_AVX2
3954
0
    YUVTORGB16_AVX2(yuvconstants)
3955
0
    STOREAR30_AVX2
3956
0
      "sub         $0x10,%[width]                \n"
3957
0
      "jg          1b                            \n"
3958
3959
0
      "vzeroupper  \n"
3960
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
3961
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
3962
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
3963
0
    [dst_ar30]"+r"(dst_ar30),  // %[dst_ar30]
3964
0
    [width]"+rm"(width)    // %[width]
3965
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
3966
0
  : "memory", "cc", YUVTORGB_REGS_AVX2
3967
0
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
3968
0
  );
3969
0
}
3970
#endif  // HAS_I210TOAR30ROW_AVX2
3971
3972
#if defined(HAS_I212TOAR30ROW_AVX2)
3973
// 16 pixels
3974
// 8 UV values upsampled to 16 UV, mixed with 16 Y producing 16 AR30 (64 bytes).
3975
void OMITFP I212ToAR30Row_AVX2(const uint16_t* y_buf,
3976
                               const uint16_t* u_buf,
3977
                               const uint16_t* v_buf,
3978
                               uint8_t* dst_ar30,
3979
                               const struct YuvConstants* yuvconstants,
3980
0
                               int width) {
3981
0
  asm volatile (
3982
0
    YUVTORGB_SETUP_AVX2(yuvconstants)
3983
0
      "sub         %[u_buf],%[v_buf]             \n"
3984
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"  // AR30 constants
3985
0
      "vpsrlw      $14,%%ymm5,%%ymm5             \n"
3986
0
      "vpsllw      $4,%%ymm5,%%ymm5              \n"  // 2 alpha bits
3987
0
      "vpxor       %%ymm6,%%ymm6,%%ymm6          \n"  // 0 for min
3988
0
      "vpcmpeqb    %%ymm7,%%ymm7,%%ymm7          \n"  // 1023 for max
3989
0
      "vpsrlw      $6,%%ymm7,%%ymm7              \n"
3990
3991
0
    LABELALIGN
3992
0
      "1:          \n"
3993
0
    READYUV212_AVX2
3994
0
    YUVTORGB16_AVX2(yuvconstants)
3995
0
    STOREAR30_AVX2
3996
0
      "sub         $0x10,%[width]                \n"
3997
0
      "jg          1b                            \n"
3998
3999
0
      "vzeroupper  \n"
4000
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
4001
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
4002
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
4003
0
    [dst_ar30]"+r"(dst_ar30),  // %[dst_ar30]
4004
0
    [width]"+rm"(width)    // %[width]
4005
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
4006
0
  : "memory", "cc", YUVTORGB_REGS_AVX2
4007
0
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
4008
0
  );
4009
0
}
4010
#endif  // HAS_I212TOAR30ROW_AVX2
4011
4012
#if defined(HAS_I410TOARGBROW_AVX2)
4013
// 16 pixels
4014
// 16 UV values with 16 Y producing 16 ARGB (64 bytes).
4015
void OMITFP I410ToARGBRow_AVX2(const uint16_t* y_buf,
4016
                               const uint16_t* u_buf,
4017
                               const uint16_t* v_buf,
4018
                               uint8_t* dst_argb,
4019
                               const struct YuvConstants* yuvconstants,
4020
9.09k
                               int width) {
4021
9.09k
  asm volatile (
4022
9.09k
    YUVTORGB_SETUP_AVX2(yuvconstants)
4023
9.09k
      "sub         %[u_buf],%[v_buf]             \n"
4024
9.09k
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
4025
4026
9.09k
    LABELALIGN
4027
9.09k
      "1:          \n"
4028
9.09k
    READYUV410_AVX2
4029
9.09k
    YUVTORGB_AVX2(yuvconstants)
4030
9.09k
    STOREARGB_AVX2
4031
9.09k
      "sub         $0x10,%[width]                \n"
4032
9.09k
      "jg          1b                            \n"
4033
9.09k
      "vzeroupper  \n"
4034
4035
9.09k
  : [y_buf]"+r"(y_buf),    // %[y_buf]
4036
9.09k
    [u_buf]"+r"(u_buf),    // %[u_buf]
4037
9.09k
    [v_buf]"+r"(v_buf),    // %[v_buf]
4038
9.09k
    [dst_argb]"+r"(dst_argb),  // %[dst_argb]
4039
9.09k
    [width]"+rm"(width)    // %[width]
4040
9.09k
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
4041
9.09k
  : "memory", "cc", YUVTORGB_REGS_AVX2
4042
9.09k
      "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"
4043
9.09k
  );
4044
9.09k
}
4045
#endif  // HAS_I410TOARGBROW_AVX2
4046
4047
#if defined(HAS_I210ALPHATOARGBROW_AVX2)
4048
// 16 pixels
4049
// 8 UV, 16 Y and 16 A producing 16 ARGB (64 bytes).
4050
void OMITFP I210AlphaToARGBRow_AVX2(const uint16_t* y_buf,
4051
                                    const uint16_t* u_buf,
4052
                                    const uint16_t* v_buf,
4053
                                    const uint16_t* a_buf,
4054
                                    uint8_t* dst_argb,
4055
                                    const struct YuvConstants* yuvconstants,
4056
2.93k
                                    int width) {
4057
2.93k
  asm volatile(YUVTORGB_SETUP_AVX2(
4058
2.93k
                   yuvconstants) "sub         %[u_buf],%[v_buf]             \n"
4059
4060
2.93k
               LABELALIGN "1:          \n" READYUVA210_AVX2 YUVTORGB_AVX2(
4061
2.93k
                   yuvconstants) STOREARGB_AVX2
4062
2.93k
               "subl        $0x10,%[width]                \n"
4063
2.93k
               "jg          1b                            \n"
4064
2.93k
               "vzeroupper  \n"
4065
4066
2.93k
               : [y_buf] "+r"(y_buf),        // %[y_buf]
4067
2.93k
                 [u_buf] "+r"(u_buf),        // %[u_buf]
4068
2.93k
                 [v_buf] "+r"(v_buf),        // %[v_buf]
4069
2.93k
                 [a_buf] "+r"(a_buf),        // %[a_buf]
4070
2.93k
                 [dst_argb] "+r"(dst_argb),  // %[dst_argb]
4071
#if defined(__i386__)
4072
                 [width] "+m"(width)  // %[width]
4073
#else
4074
2.93k
                 [width] "+rm"(width)  // %[width]
4075
2.93k
#endif
4076
2.93k
               : [yuvconstants] "r"(yuvconstants)  // %[yuvconstants]
4077
2.93k
               : "memory", "cc", YUVTORGB_REGS_AVX2 "xmm0", "xmm1", "xmm2",
4078
2.93k
                 "xmm3", "xmm4", "xmm5");
4079
2.93k
}
4080
#endif  // HAS_I210TOARGBROW_AVX2
4081
4082
#if defined(HAS_I410ALPHATOARGBROW_AVX2)
4083
// 16 pixels
4084
// 16 UV, 16 Y and 16 A producing 16 ARGB (64 bytes).
4085
void OMITFP I410AlphaToARGBRow_AVX2(const uint16_t* y_buf,
4086
                                    const uint16_t* u_buf,
4087
                                    const uint16_t* v_buf,
4088
                                    const uint16_t* a_buf,
4089
                                    uint8_t* dst_argb,
4090
                                    const struct YuvConstants* yuvconstants,
4091
4.14k
                                    int width) {
4092
4.14k
  asm volatile(YUVTORGB_SETUP_AVX2(
4093
4.14k
                   yuvconstants) "sub         %[u_buf],%[v_buf]             \n"
4094
4095
4.14k
               LABELALIGN "1:          \n" READYUVA410_AVX2 YUVTORGB_AVX2(
4096
4.14k
                   yuvconstants) STOREARGB_AVX2
4097
4.14k
               "subl        $0x10,%[width]                \n"
4098
4.14k
               "jg          1b                            \n"
4099
4.14k
               "vzeroupper  \n"
4100
4101
4.14k
               : [y_buf] "+r"(y_buf),        // %[y_buf]
4102
4.14k
                 [u_buf] "+r"(u_buf),        // %[u_buf]
4103
4.14k
                 [v_buf] "+r"(v_buf),        // %[v_buf]
4104
4.14k
                 [a_buf] "+r"(a_buf),        // %[a_buf]
4105
4.14k
                 [dst_argb] "+r"(dst_argb),  // %[dst_argb]
4106
#if defined(__i386__)
4107
                 [width] "+m"(width)  // %[width]
4108
#else
4109
4.14k
                 [width] "+rm"(width)  // %[width]
4110
4.14k
#endif
4111
4.14k
               : [yuvconstants] "r"(yuvconstants)  // %[yuvconstants]
4112
4.14k
               : "memory", "cc", YUVTORGB_REGS_AVX2 "xmm0", "xmm1", "xmm2",
4113
4.14k
                 "xmm3", "xmm4", "xmm5");
4114
4.14k
}
4115
#endif  // HAS_I410TOARGBROW_AVX2
4116
4117
#if defined(HAS_I410TOAR30ROW_AVX2)
4118
// 16 pixels
4119
// 16 UV values with 16 Y producing 16 AR30 (64 bytes).
4120
void OMITFP I410ToAR30Row_AVX2(const uint16_t* y_buf,
4121
                               const uint16_t* u_buf,
4122
                               const uint16_t* v_buf,
4123
                               uint8_t* dst_ar30,
4124
                               const struct YuvConstants* yuvconstants,
4125
0
                               int width) {
4126
0
  asm volatile (
4127
0
    YUVTORGB_SETUP_AVX2(yuvconstants)
4128
0
      "sub         %[u_buf],%[v_buf]             \n"
4129
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"  // AR30 constants
4130
0
      "vpsrlw      $14,%%ymm5,%%ymm5             \n"
4131
0
      "vpsllw      $4,%%ymm5,%%ymm5              \n"  // 2 alpha bits
4132
0
      "vpxor       %%ymm6,%%ymm6,%%ymm6          \n"  // 0 for min
4133
0
      "vpcmpeqb    %%ymm7,%%ymm7,%%ymm7          \n"  // 1023 for max
4134
0
      "vpsrlw      $6,%%ymm7,%%ymm7              \n"
4135
4136
0
    LABELALIGN
4137
0
      "1:          \n"
4138
0
    READYUV410_AVX2
4139
0
    YUVTORGB16_AVX2(yuvconstants)
4140
0
    STOREAR30_AVX2
4141
0
      "sub         $0x10,%[width]                \n"
4142
0
      "jg          1b                            \n"
4143
4144
0
      "vzeroupper  \n"
4145
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
4146
0
    [u_buf]"+r"(u_buf),    // %[u_buf]
4147
0
    [v_buf]"+r"(v_buf),    // %[v_buf]
4148
0
    [dst_ar30]"+r"(dst_ar30),  // %[dst_ar30]
4149
0
    [width]"+rm"(width)    // %[width]
4150
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
4151
0
  : "memory", "cc", YUVTORGB_REGS_AVX2
4152
0
      "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
4153
0
  );
4154
0
}
4155
#endif  // HAS_I410TOAR30ROW_AVX2
4156
4157
#if defined(HAS_I444ALPHATOARGBROW_AVX2)
4158
// 16 pixels
4159
// 16 UV values with 16 Y and 16 A producing 16 ARGB.
4160
void OMITFP I444AlphaToARGBRow_AVX2(const uint8_t* y_buf,
4161
                                    const uint8_t* u_buf,
4162
                                    const uint8_t* v_buf,
4163
                                    const uint8_t* a_buf,
4164
                                    uint8_t* dst_argb,
4165
                                    const struct YuvConstants* yuvconstants,
4166
11.3k
                                    int width) {
4167
11.3k
  asm volatile(YUVTORGB_SETUP_AVX2(
4168
11.3k
                   yuvconstants) "sub         %[u_buf],%[v_buf]             \n"
4169
4170
11.3k
               LABELALIGN "1:          \n" READYUVA444_AVX2 YUVTORGB_AVX2(
4171
11.3k
                   yuvconstants) STOREARGB_AVX2
4172
11.3k
               "subl        $0x10,%[width]                \n"
4173
11.3k
               "jg          1b                            \n"
4174
11.3k
               "vzeroupper  \n"
4175
11.3k
               : [y_buf] "+r"(y_buf),        // %[y_buf]
4176
11.3k
                 [u_buf] "+r"(u_buf),        // %[u_buf]
4177
11.3k
                 [v_buf] "+r"(v_buf),        // %[v_buf]
4178
11.3k
                 [a_buf] "+r"(a_buf),        // %[a_buf]
4179
11.3k
                 [dst_argb] "+r"(dst_argb),  // %[dst_argb]
4180
#if defined(__i386__)
4181
                 [width] "+m"(width)  // %[width]
4182
#else
4183
11.3k
                 [width] "+rm"(width)  // %[width]
4184
11.3k
#endif
4185
11.3k
               : [yuvconstants] "r"(yuvconstants)  // %[yuvconstants]
4186
11.3k
               : "memory", "cc", YUVTORGB_REGS_AVX2 "xmm0", "xmm1", "xmm2",
4187
11.3k
                 "xmm3", "xmm4", "xmm5");
4188
11.3k
}
4189
#endif  // HAS_I444ALPHATOARGBROW_AVX2
4190
4191
#if defined(HAS_I422ALPHATOARGBROW_AVX2)
4192
// 16 pixels
4193
// 8 UV values upsampled to 16 UV, mixed with 16 Y and 16 A producing 16 ARGB.
4194
void OMITFP I422AlphaToARGBRow_AVX2(const uint8_t* y_buf,
4195
                                    const uint8_t* u_buf,
4196
                                    const uint8_t* v_buf,
4197
                                    const uint8_t* a_buf,
4198
                                    uint8_t* dst_argb,
4199
                                    const struct YuvConstants* yuvconstants,
4200
4.04k
                                    int width) {
4201
4.04k
  asm volatile(YUVTORGB_SETUP_AVX2(
4202
4.04k
                   yuvconstants) "sub         %[u_buf],%[v_buf]             \n"
4203
4204
4.04k
               LABELALIGN "1:          \n" READYUVA422_AVX2 YUVTORGB_AVX2(
4205
4.04k
                   yuvconstants) STOREARGB_AVX2
4206
4.04k
               "subl        $0x10,%[width]                \n"
4207
4.04k
               "jg          1b                            \n"
4208
4.04k
               "vzeroupper  \n"
4209
4.04k
               : [y_buf] "+r"(y_buf),        // %[y_buf]
4210
4.04k
                 [u_buf] "+r"(u_buf),        // %[u_buf]
4211
4.04k
                 [v_buf] "+r"(v_buf),        // %[v_buf]
4212
4.04k
                 [a_buf] "+r"(a_buf),        // %[a_buf]
4213
4.04k
                 [dst_argb] "+r"(dst_argb),  // %[dst_argb]
4214
#if defined(__i386__)
4215
                 [width] "+m"(width)  // %[width]
4216
#else
4217
4.04k
                 [width] "+rm"(width)  // %[width]
4218
4.04k
#endif
4219
4.04k
               : [yuvconstants] "r"(yuvconstants)  // %[yuvconstants]
4220
4.04k
               : "memory", "cc", YUVTORGB_REGS_AVX2 "xmm0", "xmm1", "xmm2",
4221
4.04k
                 "xmm3", "xmm4", "xmm5");
4222
4.04k
}
4223
#endif  // HAS_I422ALPHATOARGBROW_AVX2
4224
4225
#if defined(HAS_I422TORGBAROW_AVX2)
4226
// 16 pixels
4227
// 8 UV values upsampled to 16 UV, mixed with 16 Y producing 16 RGBA (64 bytes).
4228
void OMITFP I422ToRGBARow_AVX2(const uint8_t* y_buf,
4229
                               const uint8_t* u_buf,
4230
                               const uint8_t* v_buf,
4231
                               uint8_t* dst_argb,
4232
                               const struct YuvConstants* yuvconstants,
4233
3.91k
                               int width) {
4234
3.91k
  asm volatile (
4235
3.91k
    YUVTORGB_SETUP_AVX2(yuvconstants)
4236
3.91k
      "sub         %[u_buf],%[v_buf]             \n"
4237
3.91k
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
4238
4239
3.91k
    LABELALIGN
4240
3.91k
      "1:          \n"
4241
3.91k
    READYUV422_AVX2
4242
3.91k
    YUVTORGB_AVX2(yuvconstants)
4243
4244
    // Step 3: Weave into RGBA
4245
3.91k
    "vpunpcklbw %%ymm2,%%ymm1,%%ymm1           \n"
4246
3.91k
    "vpermq     $0xd8,%%ymm1,%%ymm1            \n"
4247
3.91k
    "vpunpcklbw %%ymm0,%%ymm5,%%ymm2           \n"
4248
3.91k
    "vpermq     $0xd8,%%ymm2,%%ymm2            \n"
4249
3.91k
    "vpunpcklwd %%ymm1,%%ymm2,%%ymm0           \n"
4250
3.91k
    "vpunpckhwd %%ymm1,%%ymm2,%%ymm1           \n"
4251
3.91k
    "vmovdqu    %%ymm0,(%[dst_argb])           \n"
4252
3.91k
    "vmovdqu    %%ymm1,0x20(%[dst_argb])       \n"
4253
3.91k
    "lea        0x40(%[dst_argb]),%[dst_argb]  \n"
4254
3.91k
    "sub        $0x10,%[width]                 \n"
4255
3.91k
    "jg         1b                             \n"
4256
3.91k
    "vzeroupper                                \n"
4257
3.91k
  : [y_buf]"+r"(y_buf),    // %[y_buf]
4258
3.91k
    [u_buf]"+r"(u_buf),    // %[u_buf]
4259
3.91k
    [v_buf]"+r"(v_buf),    // %[v_buf]
4260
3.91k
    [dst_argb]"+r"(dst_argb),  // %[dst_argb]
4261
3.91k
    [width]"+rm"(width)    // %[width]
4262
3.91k
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
4263
3.91k
  : "memory", "cc", YUVTORGB_REGS_AVX2
4264
3.91k
    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"
4265
3.91k
  );
4266
3.91k
}
4267
#endif  // HAS_I422TORGBAROW_AVX2
4268
4269
#if defined(HAS_NV12TOARGBROW_AVX2)
4270
// 16 pixels.
4271
// 8 UV values upsampled to 16 UV, mixed with 16 Y producing 16 ARGB (64 bytes).
4272
void OMITFP NV12ToARGBRow_AVX2(const uint8_t* y_buf,
4273
                               const uint8_t* uv_buf,
4274
                               uint8_t* dst_argb,
4275
                               const struct YuvConstants* yuvconstants,
4276
0
                               int width) {
4277
0
  asm volatile(YUVTORGB_SETUP_AVX2(
4278
0
                   yuvconstants) "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
4279
4280
0
               LABELALIGN "1:          \n" READNV12_AVX2 YUVTORGB_AVX2(
4281
0
                   yuvconstants) STOREARGB_AVX2
4282
0
               "sub         $0x10,%[width]                \n"
4283
0
               "jg          1b                            \n"
4284
0
               "vzeroupper  \n"
4285
0
               : [y_buf] "+r"(y_buf),              // %[y_buf]
4286
0
                 [uv_buf] "+r"(uv_buf),            // %[uv_buf]
4287
0
                 [dst_argb] "+r"(dst_argb),        // %[dst_argb]
4288
0
                 [width] "+rm"(width)              // %[width]
4289
0
               : [yuvconstants] "r"(yuvconstants)  // %[yuvconstants]
4290
0
               : "memory", "cc", YUVTORGB_REGS_AVX2 "xmm0", "xmm0", "xmm1",
4291
0
                 "xmm2", "xmm3", "xmm4", "xmm5");
4292
0
}
4293
#endif  // HAS_NV12TOARGBROW_AVX2
4294
4295
#if defined(HAS_NV21TOARGBROW_AVX2)
4296
// 16 pixels.
4297
// 8 VU values upsampled to 16 UV, mixed with 16 Y producing 16 ARGB (64 bytes).
4298
void OMITFP NV21ToARGBRow_AVX2(const uint8_t* y_buf,
4299
                               const uint8_t* vu_buf,
4300
                               uint8_t* dst_argb,
4301
                               const struct YuvConstants* yuvconstants,
4302
0
                               int width) {
4303
0
  asm volatile(YUVTORGB_SETUP_AVX2(
4304
0
                   yuvconstants) "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
4305
4306
0
               LABELALIGN "1:          \n" READNV21_AVX2 YUVTORGB_AVX2(
4307
0
                   yuvconstants) STOREARGB_AVX2
4308
0
               "sub         $0x10,%[width]                \n"
4309
0
               "jg          1b                            \n"
4310
0
               "vzeroupper  \n"
4311
0
               : [y_buf] "+r"(y_buf),               // %[y_buf]
4312
0
                 [vu_buf] "+r"(vu_buf),             // %[vu_buf]
4313
0
                 [dst_argb] "+r"(dst_argb),         // %[dst_argb]
4314
0
                 [width] "+rm"(width)               // %[width]
4315
0
               : [yuvconstants] "r"(yuvconstants),  // %[yuvconstants]
4316
0
                 [kShuffleNV21] "m"(kShuffleNV21)
4317
0
               : "memory", "cc", YUVTORGB_REGS_AVX2 "xmm0", "xmm0", "xmm1",
4318
0
                 "xmm2", "xmm3", "xmm4", "xmm5");
4319
0
}
4320
#endif  // HAS_NV21TOARGBROW_AVX2
4321
4322
#if defined(HAS_YUY2TOARGBROW_AVX2)
4323
// 16 pixels.
4324
// 8 YUY2 values with 16 Y and 8 UV producing 16 ARGB (64 bytes).
4325
void OMITFP YUY2ToARGBRow_AVX2(const uint8_t* yuy2_buf,
4326
                               uint8_t* dst_argb,
4327
                               const struct YuvConstants* yuvconstants,
4328
0
                               int width) {
4329
0
  asm volatile(
4330
0
      "vbroadcasti128 %[kShuffleYUY2Y],%%ymm6    \n"
4331
0
      "vbroadcasti128 %[kShuffleYUY2UV],%%ymm7   \n" YUVTORGB_SETUP_AVX2(
4332
0
          yuvconstants) "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
4333
4334
0
      LABELALIGN "1:          \n" READYUY2_AVX2 YUVTORGB_AVX2(yuvconstants)
4335
0
          STOREARGB_AVX2
4336
0
      "sub         $0x10,%[width]                \n"
4337
0
      "jg          1b                            \n"
4338
0
      "vzeroupper  \n"
4339
0
      : [yuy2_buf] "+r"(yuy2_buf),         // %[yuy2_buf]
4340
0
        [dst_argb] "+r"(dst_argb),         // %[dst_argb]
4341
0
        [width] "+rm"(width)               // %[width]
4342
0
      : [yuvconstants] "r"(yuvconstants),  // %[yuvconstants]
4343
0
        [kShuffleYUY2Y] "m"(kShuffleYUY2Y), [kShuffleYUY2UV] "m"(kShuffleYUY2UV)
4344
0
      : "memory", "cc", YUVTORGB_REGS_AVX2 "xmm0", "xmm0", "xmm1", "xmm2",
4345
0
        "xmm3", "xmm4", "xmm5", "xmm6", "xmm7");
4346
0
}
4347
#endif  // HAS_YUY2TOARGBROW_AVX2
4348
4349
#if defined(HAS_UYVYTOARGBROW_AVX2)
4350
// 16 pixels.
4351
// 8 UYVY values with 16 Y and 8 UV producing 16 ARGB (64 bytes).
4352
void OMITFP UYVYToARGBRow_AVX2(const uint8_t* uyvy_buf,
4353
                               uint8_t* dst_argb,
4354
                               const struct YuvConstants* yuvconstants,
4355
0
                               int width) {
4356
0
  asm volatile(
4357
0
      "vbroadcasti128 %[kShuffleUYVYY],%%ymm6    \n"
4358
0
      "vbroadcasti128 %[kShuffleUYVYUV],%%ymm7   \n" YUVTORGB_SETUP_AVX2(
4359
0
          yuvconstants) "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
4360
4361
0
      LABELALIGN "1:          \n" READUYVY_AVX2 YUVTORGB_AVX2(yuvconstants)
4362
0
          STOREARGB_AVX2
4363
0
      "sub         $0x10,%[width]                \n"
4364
0
      "jg          1b                            \n"
4365
0
      "vzeroupper  \n"
4366
0
      : [uyvy_buf] "+r"(uyvy_buf),         // %[uyvy_buf]
4367
0
        [dst_argb] "+r"(dst_argb),         // %[dst_argb]
4368
0
        [width] "+rm"(width)               // %[width]
4369
0
      : [yuvconstants] "r"(yuvconstants),  // %[yuvconstants]
4370
0
        [kShuffleUYVYY] "m"(kShuffleUYVYY), [kShuffleUYVYUV] "m"(kShuffleUYVYUV)
4371
0
      : "memory", "cc", YUVTORGB_REGS_AVX2 "xmm0", "xmm1", "xmm2", "xmm3",
4372
0
        "xmm4", "xmm5", "xmm6", "xmm7");
4373
0
}
4374
#endif  // HAS_UYVYTOARGBROW_AVX2
4375
4376
#if defined(HAS_P210TOARGBROW_AVX2)
4377
// 16 pixels.
4378
// 8 UV values upsampled to 16 UV, mixed with 16 Y producing 16 ARGB (64 bytes).
4379
void OMITFP P210ToARGBRow_AVX2(const uint16_t* y_buf,
4380
                               const uint16_t* uv_buf,
4381
                               uint8_t* dst_argb,
4382
                               const struct YuvConstants* yuvconstants,
4383
0
                               int width) {
4384
0
  asm volatile(YUVTORGB_SETUP_AVX2(
4385
0
                   yuvconstants) "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
4386
4387
0
               LABELALIGN "1:          \n" READP210_AVX2 YUVTORGB_AVX2(
4388
0
                   yuvconstants) STOREARGB_AVX2
4389
0
               "sub         $0x10,%[width]                \n"
4390
0
               "jg          1b                            \n"
4391
0
               "vzeroupper  \n"
4392
0
               : [y_buf] "+r"(y_buf),              // %[y_buf]
4393
0
                 [uv_buf] "+r"(uv_buf),            // %[uv_buf]
4394
0
                 [dst_argb] "+r"(dst_argb),        // %[dst_argb]
4395
0
                 [width] "+rm"(width)              // %[width]
4396
0
               : [yuvconstants] "r"(yuvconstants)  // %[yuvconstants]
4397
0
               : "memory", "cc", YUVTORGB_REGS_AVX2 "xmm0", "xmm0", "xmm1",
4398
0
                 "xmm2", "xmm3", "xmm4", "xmm5");
4399
0
}
4400
#endif  // HAS_P210TOARGBROW_AVX2
4401
4402
#if defined(HAS_P410TOARGBROW_AVX2)
4403
// 16 pixels.
4404
// 8 UV values upsampled to 16 UV, mixed with 16 Y producing 16 ARGB (64 bytes).
4405
void OMITFP P410ToARGBRow_AVX2(const uint16_t* y_buf,
4406
                               const uint16_t* uv_buf,
4407
                               uint8_t* dst_argb,
4408
                               const struct YuvConstants* yuvconstants,
4409
0
                               int width) {
4410
0
  asm volatile(YUVTORGB_SETUP_AVX2(
4411
0
                   yuvconstants) "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
4412
4413
0
               LABELALIGN "1:          \n" READP410_AVX2 YUVTORGB_AVX2(
4414
0
                   yuvconstants) STOREARGB_AVX2
4415
0
               "sub         $0x10,%[width]                \n"
4416
0
               "jg          1b                            \n"
4417
0
               "vzeroupper  \n"
4418
0
               : [y_buf] "+r"(y_buf),              // %[y_buf]
4419
0
                 [uv_buf] "+r"(uv_buf),            // %[uv_buf]
4420
0
                 [dst_argb] "+r"(dst_argb),        // %[dst_argb]
4421
0
                 [width] "+rm"(width)              // %[width]
4422
0
               : [yuvconstants] "r"(yuvconstants)  // %[yuvconstants]
4423
0
               : "memory", "cc", YUVTORGB_REGS_AVX2 "xmm0", "xmm0", "xmm1",
4424
0
                 "xmm2", "xmm3", "xmm4", "xmm5");
4425
0
}
4426
#endif  // HAS_P410TOARGBROW_AVX2
4427
4428
#if defined(HAS_P210TOAR30ROW_AVX2)
4429
// 16 pixels
4430
// 16 UV values with 16 Y producing 16 AR30 (64 bytes).
4431
void OMITFP P210ToAR30Row_AVX2(const uint16_t* y_buf,
4432
                               const uint16_t* uv_buf,
4433
                               uint8_t* dst_ar30,
4434
                               const struct YuvConstants* yuvconstants,
4435
0
                               int width) {
4436
0
  asm volatile (
4437
0
    YUVTORGB_SETUP_AVX2(yuvconstants)
4438
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"  // AR30 constants
4439
0
      "vpsrlw      $14,%%ymm5,%%ymm5             \n"
4440
0
      "vpsllw      $4,%%ymm5,%%ymm5              \n"  // 2 alpha bits
4441
0
      "vpxor       %%ymm6,%%ymm6,%%ymm6          \n"  // 0 for min
4442
0
      "vpcmpeqb    %%ymm7,%%ymm7,%%ymm7          \n"  // 1023 for max
4443
0
      "vpsrlw      $6,%%ymm7,%%ymm7              \n"
4444
4445
0
    LABELALIGN
4446
0
      "1:          \n"
4447
0
    READP210_AVX2
4448
0
    YUVTORGB16_AVX2(yuvconstants)
4449
0
    STOREAR30_AVX2
4450
0
      "sub         $0x10,%[width]                \n"
4451
0
      "jg          1b                            \n"
4452
4453
0
      "vzeroupper  \n"
4454
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
4455
0
    [uv_buf]"+r"(uv_buf),    // %[uv_buf]
4456
0
    [dst_ar30]"+r"(dst_ar30),  // %[dst_ar30]
4457
0
    [width]"+rm"(width)    // %[width]
4458
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
4459
0
  : "memory", "cc", YUVTORGB_REGS_AVX2
4460
0
      "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
4461
0
  );
4462
0
}
4463
#endif  // HAS_P210TOAR30ROW_AVX2
4464
4465
#if defined(HAS_P410TOAR30ROW_AVX2)
4466
// 16 pixels
4467
// 16 UV values with 16 Y producing 16 AR30 (64 bytes).
4468
void OMITFP P410ToAR30Row_AVX2(const uint16_t* y_buf,
4469
                               const uint16_t* uv_buf,
4470
                               uint8_t* dst_ar30,
4471
                               const struct YuvConstants* yuvconstants,
4472
0
                               int width) {
4473
0
  asm volatile (
4474
0
    YUVTORGB_SETUP_AVX2(yuvconstants)
4475
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"  // AR30 constants
4476
0
      "vpsrlw      $14,%%ymm5,%%ymm5             \n"
4477
0
      "vpsllw      $4,%%ymm5,%%ymm5              \n"  // 2 alpha bits
4478
0
      "vpxor       %%ymm6,%%ymm6,%%ymm6          \n"  // 0 for min
4479
0
      "vpcmpeqb    %%ymm7,%%ymm7,%%ymm7          \n"  // 1023 for max
4480
0
      "vpsrlw      $6,%%ymm7,%%ymm7              \n"
4481
4482
0
    LABELALIGN
4483
0
      "1:          \n"
4484
0
    READP410_AVX2
4485
0
    YUVTORGB16_AVX2(yuvconstants)
4486
0
    STOREAR30_AVX2
4487
0
      "sub         $0x10,%[width]                \n"
4488
0
      "jg          1b                            \n"
4489
4490
0
      "vzeroupper  \n"
4491
0
  : [y_buf]"+r"(y_buf),    // %[y_buf]
4492
0
    [uv_buf]"+r"(uv_buf),    // %[uv_buf]
4493
0
    [dst_ar30]"+r"(dst_ar30),  // %[dst_ar30]
4494
0
    [width]"+rm"(width)    // %[width]
4495
0
  : [yuvconstants]"r"(yuvconstants)  // %[yuvconstants]
4496
0
  : "memory", "cc", YUVTORGB_REGS_AVX2
4497
0
      "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
4498
0
  );
4499
0
}
4500
#endif  // HAS_P410TOAR30ROW_AVX2
4501
4502
#ifdef HAS_I400TOARGBROW_SSE2
4503
void I400ToARGBRow_SSE2(const uint8_t* y_buf,
4504
                        uint8_t* dst_argb,
4505
                        const struct YuvConstants* yuvconstants,
4506
0
                        int width) {
4507
0
  asm volatile(
4508
0
      "movdqa      96(%3),%%xmm2                 \n"  // yg = 18997 = 1.164
4509
0
      "movdqa      128(%3),%%xmm3                \n"  // ygb = 1160 = 1.164 * 16
4510
0
      "pcmpeqb     %%xmm4,%%xmm4                 \n"  // 0xff000000
4511
0
      "pslld       $0x18,%%xmm4                  \n"
4512
4513
0
      LABELALIGN
4514
0
      "1:          \n"
4515
      // Step 1: Scale Y contribution to 8 G values. G = (y - 16) * 1.164
4516
0
      "movq      (%0),%%xmm0                     \n"
4517
0
      "lea       0x8(%0),%0                      \n"
4518
0
      "punpcklbw %%xmm0,%%xmm0                   \n"
4519
0
      "pmulhuw   %%xmm2,%%xmm0                   \n"
4520
0
      "paddsw    %%xmm3,%%xmm0                   \n"
4521
0
      "psraw     $6, %%xmm0                      \n"
4522
0
      "packuswb  %%xmm0,%%xmm0                   \n"
4523
4524
      // Step 2: Weave into ARGB
4525
0
      "punpcklbw %%xmm0,%%xmm0                   \n"
4526
0
      "movdqa    %%xmm0,%%xmm1                   \n"
4527
0
      "punpcklwd %%xmm0,%%xmm0                   \n"
4528
0
      "punpckhwd %%xmm1,%%xmm1                   \n"
4529
0
      "por       %%xmm4,%%xmm0                   \n"
4530
0
      "por       %%xmm4,%%xmm1                   \n"
4531
0
      "movdqu    %%xmm0,(%1)                     \n"
4532
0
      "movdqu    %%xmm1,0x10(%1)                 \n"
4533
0
      "lea       0x20(%1),%1                     \n"
4534
4535
0
      "sub       $0x8,%2                         \n"
4536
0
      "jg        1b                              \n"
4537
0
      : "+r"(y_buf),       // %0
4538
0
        "+r"(dst_argb),    // %1
4539
0
        "+rm"(width)       // %2
4540
0
      : "r"(yuvconstants)  // %3
4541
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4");
4542
0
}
4543
#endif  // HAS_I400TOARGBROW_SSE2
4544
4545
#ifdef HAS_I400TOARGBROW_AVX2
4546
// 16 pixels of Y converted to 16 pixels of ARGB (64 bytes).
4547
// note: vpunpcklbw mutates and vpackuswb unmutates.
4548
void I400ToARGBRow_AVX2(const uint8_t* y_buf,
4549
                        uint8_t* dst_argb,
4550
                        const struct YuvConstants* yuvconstants,
4551
439
                        int width) {
4552
439
  asm volatile(
4553
439
      "vmovdqa     96(%3),%%ymm2                 \n"  // yg = 18997 = 1.164
4554
439
      "vmovdqa     128(%3),%%ymm3                \n"  // ygb = -1160 = 1.164*16
4555
439
      "vpcmpeqb    %%ymm4,%%ymm4,%%ymm4          \n"  // 0xff000000
4556
439
      "vpslld      $0x18,%%ymm4,%%ymm4           \n"
4557
4558
439
      LABELALIGN
4559
439
      "1:          \n"
4560
      // Step 1: Scale Y contribution to 16 G values. G = (y - 16) * 1.164
4561
439
      "vmovdqu    (%0),%%xmm0                    \n"
4562
439
      "lea        0x10(%0),%0                    \n"
4563
439
      "vpermq     $0xd8,%%ymm0,%%ymm0            \n"
4564
439
      "vpunpcklbw %%ymm0,%%ymm0,%%ymm0           \n"
4565
439
      "vpmulhuw   %%ymm2,%%ymm0,%%ymm0           \n"
4566
439
      "vpaddsw    %%ymm3,%%ymm0,%%ymm0           \n"
4567
439
      "vpsraw     $0x6,%%ymm0,%%ymm0             \n"
4568
439
      "vpackuswb  %%ymm0,%%ymm0,%%ymm0           \n"
4569
439
      "vpunpcklbw %%ymm0,%%ymm0,%%ymm1           \n"
4570
439
      "vpermq     $0xd8,%%ymm1,%%ymm1            \n"
4571
439
      "vpunpcklwd %%ymm1,%%ymm1,%%ymm0           \n"
4572
439
      "vpunpckhwd %%ymm1,%%ymm1,%%ymm1           \n"
4573
439
      "vpor       %%ymm4,%%ymm0,%%ymm0           \n"
4574
439
      "vpor       %%ymm4,%%ymm1,%%ymm1           \n"
4575
439
      "vmovdqu    %%ymm0,(%1)                    \n"
4576
439
      "vmovdqu    %%ymm1,0x20(%1)                \n"
4577
439
      "lea        0x40(%1),%1                     \n"
4578
439
      "sub        $0x10,%2                       \n"
4579
439
      "jg        1b                              \n"
4580
439
      "vzeroupper                                \n"
4581
439
      : "+r"(y_buf),       // %0
4582
439
        "+r"(dst_argb),    // %1
4583
439
        "+rm"(width)       // %2
4584
439
      : "r"(yuvconstants)  // %3
4585
439
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4");
4586
439
}
4587
#endif  // HAS_I400TOARGBROW_AVX2
4588
4589
#ifdef HAS_MIRRORROW_SSSE3
4590
// Shuffle table for reversing the bytes.
4591
static const uvec8 kShuffleMirror = {15u, 14u, 13u, 12u, 11u, 10u, 9u, 8u,
4592
                                     7u,  6u,  5u,  4u,  3u,  2u,  1u, 0u};
4593
4594
0
void MirrorRow_SSSE3(const uint8_t* src, uint8_t* dst, int width) {
4595
0
  ptrdiff_t temp_width = (ptrdiff_t)(width);
4596
0
  asm volatile("movdqa      %3,%%xmm5                     \n"
4597
4598
0
               LABELALIGN
4599
0
               "1:          \n"
4600
0
               "movdqu      -0x10(%0,%2,1),%%xmm0         \n"
4601
0
               "pshufb      %%xmm5,%%xmm0                 \n"
4602
0
               "movdqu      %%xmm0,(%1)                   \n"
4603
0
               "lea         0x10(%1),%1                   \n"
4604
0
               "sub         $0x10,%2                      \n"
4605
0
               "jg          1b                            \n"
4606
0
               : "+r"(src),           // %0
4607
0
                 "+r"(dst),           // %1
4608
0
                 "+r"(temp_width)     // %2
4609
0
               : "m"(kShuffleMirror)  // %3
4610
0
               : "memory", "cc", "xmm0", "xmm5");
4611
0
}
4612
#endif  // HAS_MIRRORROW_SSSE3
4613
4614
#ifdef HAS_MIRRORROW_AVX512BW
4615
0
void MirrorRow_AVX512BW(const uint8_t* src, uint8_t* dst, int width) {
4616
0
  ptrdiff_t temp_width = (ptrdiff_t)(width);
4617
0
  asm volatile("vbroadcasti32x4 %3,%%zmm5                 \n"
4618
4619
0
               LABELALIGN
4620
0
               "1:          \n"
4621
0
               "vmovdqu8    -0x40(%0,%2,1),%%zmm0         \n"
4622
0
               "vpshufb     %%zmm5,%%zmm0,%%zmm0          \n"
4623
0
               "vshufi64x2  $0x1b,%%zmm0,%%zmm0,%%zmm0    \n"
4624
0
               "vmovdqu8    %%zmm0,(%1)                   \n"
4625
0
               "lea         0x40(%1),%1                   \n"
4626
0
               "sub         $0x40,%2                      \n"
4627
0
               "jg          1b                            \n"
4628
0
               "vzeroupper  \n"
4629
0
               : "+r"(src),           // %0
4630
0
                 "+r"(dst),           // %1
4631
0
                 "+r"(temp_width)     // %2
4632
0
               : "m"(kShuffleMirror)  // %3
4633
0
               : "memory", "cc", "zmm0", "zmm5");
4634
0
}
4635
#endif  // HAS_MIRRORROW_AVX512BW
4636
4637
#ifdef HAS_MIRRORROW_AVX2
4638
0
void MirrorRow_AVX2(const uint8_t* src, uint8_t* dst, int width) {
4639
0
  ptrdiff_t temp_width = (ptrdiff_t)(width);
4640
0
  asm volatile("vbroadcasti128 %3,%%ymm5                  \n"
4641
4642
0
               LABELALIGN
4643
0
               "1:          \n"
4644
0
               "vmovdqu     -0x20(%0,%2,1),%%ymm0         \n"
4645
0
               "vpshufb     %%ymm5,%%ymm0,%%ymm0          \n"
4646
0
               "vpermq      $0x4e,%%ymm0,%%ymm0           \n"
4647
0
               "vmovdqu     %%ymm0,(%1)                   \n"
4648
0
               "lea         0x20(%1),%1                   \n"
4649
0
               "sub         $0x20,%2                      \n"
4650
0
               "jg          1b                            \n"
4651
0
               "vzeroupper  \n"
4652
0
               : "+r"(src),           // %0
4653
0
                 "+r"(dst),           // %1
4654
0
                 "+r"(temp_width)     // %2
4655
0
               : "m"(kShuffleMirror)  // %3
4656
0
               : "memory", "cc", "xmm0", "xmm5");
4657
0
}
4658
#endif  // HAS_MIRRORROW_AVX2
4659
4660
#if defined(HAS_MIRRORSPLITUVROW_AVX2) || defined(HAS_MIRRORSPLITUVROW_AVX512BW)
4661
// Shuffle table for reversing the bytes of UV channels.
4662
static const uvec8 kShuffleMirrorSplitUV = {14u, 12u, 10u, 8u, 6u, 4u, 2u, 0u,
4663
                                            15u, 13u, 11u, 9u, 7u, 5u, 3u, 1u};
4664
#endif
4665
4666
#ifdef HAS_MIRRORSPLITUVROW_AVX512BW
4667
static const uint64_t kMirrorSplitUVPermute[8] = {6, 4, 2, 0, 7, 5, 3, 1};
4668
4669
void MirrorSplitUVRow_AVX512BW(const uint8_t* src,
4670
                               uint8_t* dst_u,
4671
                               uint8_t* dst_v,
4672
0
                               int width) {
4673
0
  ptrdiff_t temp_width = (ptrdiff_t)(width);
4674
0
  asm volatile(
4675
0
      "vbroadcasti32x4 %4,%%zmm1                 \n"
4676
0
      "lea         -0x40(%0,%3,2),%0             \n"
4677
0
      "sub         %1,%2                         \n"
4678
0
      "vmovdqu64   %5,%%zmm3                     \n"
4679
4680
0
      LABELALIGN
4681
0
      "1:          \n"
4682
0
      "vmovdqu8    (%0),%%zmm0                   \n"
4683
0
      "lea         -0x40(%0),%0                  \n"
4684
0
      "vpshufb     %%zmm1,%%zmm0,%%zmm0          \n"
4685
0
      "vpermq      %%zmm0,%%zmm3,%%zmm0          \n"
4686
0
      "vextracti64x4 $0x1,%%zmm0,%%ymm2          \n"
4687
0
      "vmovdqu     %%ymm0,(%1)                   \n"
4688
0
      "vmovdqu     %%ymm2,0x00(%1,%2,1)          \n"
4689
0
      "lea         0x20(%1),%1                   \n"
4690
0
      "sub         $0x20,%3                      \n"
4691
0
      "jg          1b                            \n"
4692
0
      "vzeroupper  \n"
4693
0
      : "+r"(src),                   // %0
4694
0
        "+r"(dst_u),                 // %1
4695
0
        "+r"(dst_v),                 // %2
4696
0
        "+r"(temp_width)             // %3
4697
0
      : "m"(kShuffleMirrorSplitUV),  // %4
4698
0
        "m"(kMirrorSplitUVPermute)   // %5
4699
0
      : "memory", "cc", "zmm0", "zmm1", "zmm2", "zmm3");
4700
0
}
4701
#endif  // HAS_MIRRORSPLITUVROW_AVX512BW
4702
4703
#ifdef HAS_MIRRORSPLITUVROW_AVX2
4704
void MirrorSplitUVRow_AVX2(const uint8_t* src,
4705
                           uint8_t* dst_u,
4706
                           uint8_t* dst_v,
4707
0
                           int width) {
4708
0
  ptrdiff_t temp_width = (ptrdiff_t)(width);
4709
0
  asm volatile(
4710
0
      "vbroadcasti128 %4,%%ymm1                  \n"
4711
0
      "lea         -0x20(%0,%3,2),%0             \n"
4712
0
      "sub         %1,%2                         \n"
4713
4714
0
      LABELALIGN
4715
0
      "1:          \n"
4716
0
      "vmovdqu     (%0),%%ymm0                   \n"
4717
0
      "lea         -0x20(%0),%0                  \n"
4718
0
      "vpshufb     %%ymm1,%%ymm0,%%ymm0          \n"
4719
0
      "vpermq      $0x72,%%ymm0,%%ymm0           \n"
4720
0
      "vextracti128 $0x1,%%ymm0,%%xmm2           \n"
4721
0
      "vmovdqu     %%xmm0,(%1)                   \n"
4722
0
      "vmovdqu     %%xmm2,0x00(%1,%2,1)          \n"
4723
0
      "lea         0x10(%1),%1                   \n"
4724
0
      "sub         $0x10,%3                      \n"
4725
0
      "jg          1b                            \n"
4726
0
      "vzeroupper  \n"
4727
0
      : "+r"(src),                  // %0
4728
0
        "+r"(dst_u),                // %1
4729
0
        "+r"(dst_v),                // %2
4730
0
        "+r"(temp_width)            // %3
4731
0
      : "m"(kShuffleMirrorSplitUV)  // %4
4732
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
4733
0
}
4734
#endif  // HAS_MIRRORSPLITUVROW_AVX2
4735
4736
#ifdef HAS_MIRRORUVROW_SSSE3
4737
// Shuffle table for reversing the UV.
4738
static const uvec8 kShuffleMirrorUV = {14u, 15u, 12u, 13u, 10u, 11u, 8u, 9u,
4739
                                       6u,  7u,  4u,  5u,  2u,  3u,  0u, 1u};
4740
4741
0
void MirrorUVRow_SSSE3(const uint8_t* src_uv, uint8_t* dst_uv, int width) {
4742
0
  ptrdiff_t temp_width = (ptrdiff_t)(width);
4743
0
  asm volatile("movdqa      %3,%%xmm5                     \n"
4744
4745
0
               LABELALIGN
4746
0
               "1:          \n"
4747
0
               "movdqu      -0x10(%0,%2,2),%%xmm0         \n"
4748
0
               "pshufb      %%xmm5,%%xmm0                 \n"
4749
0
               "movdqu      %%xmm0,(%1)                   \n"
4750
0
               "lea         0x10(%1),%1                   \n"
4751
0
               "sub         $0x8,%2                       \n"
4752
0
               "jg          1b                            \n"
4753
0
               : "+r"(src_uv),          // %0
4754
0
                 "+r"(dst_uv),          // %1
4755
0
                 "+r"(temp_width)       // %2
4756
0
               : "m"(kShuffleMirrorUV)  // %3
4757
0
               : "memory", "cc", "xmm0", "xmm5");
4758
0
}
4759
#endif  // HAS_MIRRORUVROW_SSSE3
4760
4761
#ifdef HAS_MIRRORUVROW_AVX2
4762
0
void MirrorUVRow_AVX2(const uint8_t* src_uv, uint8_t* dst_uv, int width) {
4763
0
  ptrdiff_t temp_width = (ptrdiff_t)(width);
4764
0
  asm volatile("vbroadcasti128 %3,%%ymm5                  \n"
4765
4766
0
               LABELALIGN
4767
0
               "1:          \n"
4768
0
               "vmovdqu     -0x20(%0,%2,2),%%ymm0         \n"
4769
0
               "vpshufb     %%ymm5,%%ymm0,%%ymm0          \n"
4770
0
               "vpermq      $0x4e,%%ymm0,%%ymm0           \n"
4771
0
               "vmovdqu     %%ymm0,(%1)                   \n"
4772
0
               "lea         0x20(%1),%1                   \n"
4773
0
               "sub         $0x10,%2                      \n"
4774
0
               "jg          1b                            \n"
4775
0
               "vzeroupper  \n"
4776
0
               : "+r"(src_uv),          // %0
4777
0
                 "+r"(dst_uv),          // %1
4778
0
                 "+r"(temp_width)       // %2
4779
0
               : "m"(kShuffleMirrorUV)  // %3
4780
0
               : "memory", "cc", "xmm0", "xmm5");
4781
0
}
4782
#endif  // HAS_MIRRORUVROW_AVX2
4783
4784
#ifdef HAS_RGB24MIRRORROW_SSSE3
4785
4786
// Shuffle first 5 pixels to last 5 mirrored.  first byte zero
4787
static const uvec8 kShuffleMirrorRGB0 = {128u, 12u, 13u, 14u, 9u, 10u, 11u, 6u,
4788
                                         7u,   8u,  3u,  4u,  5u, 0u,  1u,  2u};
4789
4790
// Shuffle last 5 pixels to first 5 mirrored.  last byte zero
4791
static const uvec8 kShuffleMirrorRGB1 = {
4792
    13u, 14u, 15u, 10u, 11u, 12u, 7u, 8u, 9u, 4u, 5u, 6u, 1u, 2u, 3u, 128u};
4793
4794
// Shuffle 5 pixels at a time (15 bytes)
4795
void RGB24MirrorRow_SSSE3(const uint8_t* src_rgb24,
4796
                          uint8_t* dst_rgb24,
4797
                          int width) {
4798
  ptrdiff_t temp_width = (ptrdiff_t)(width);
4799
  src_rgb24 += width * 3 - 48;
4800
  asm volatile(
4801
      "movdqa      %3,%%xmm4                     \n"
4802
      "movdqa      %4,%%xmm5                     \n"
4803
4804
      LABELALIGN
4805
      "1:          \n"
4806
      "movdqu      (%0),%%xmm0                   \n"  // first 5
4807
      "movdqu      15(%0),%%xmm1                 \n"  // next 5
4808
      "movdqu      30(%0),%%xmm2                 \n"  // next 5
4809
      "movdqu      32(%0),%%xmm3                 \n"  // last 1 special
4810
      "pshufb      %%xmm4,%%xmm0                 \n"
4811
      "pshufb      %%xmm4,%%xmm1                 \n"
4812
      "pshufb      %%xmm4,%%xmm2                 \n"
4813
      "pshufb      %%xmm5,%%xmm3                 \n"
4814
      "lea         -0x30(%0),%0                  \n"
4815
      "movdqu      %%xmm0,32(%1)                 \n"  // last 5
4816
      "movdqu      %%xmm1,17(%1)                 \n"  // next 5
4817
      "movdqu      %%xmm2,2(%1)                  \n"  // next 5
4818
      "movlpd      %%xmm3,0(%1)                  \n"  // first 1
4819
      "lea         0x30(%1),%1                   \n"
4820
      "sub         $0x10,%2                      \n"
4821
      "jg          1b                            \n"
4822
      : "+r"(src_rgb24),          // %0
4823
        "+r"(dst_rgb24),          // %1
4824
        "+r"(temp_width)          // %2
4825
      : "m"(kShuffleMirrorRGB0),  // %3
4826
        "m"(kShuffleMirrorRGB1)   // %4
4827
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
4828
}
4829
#endif  // HAS_RGB24MIRRORROW_SSSE3
4830
4831
#ifdef HAS_RGB24MIRRORROW_AVX2
4832
// Shuffle first 10 pixels to last 10 mirrored.  first byte zero
4833
static const uvec8 kShuffleMirrorRGB0_AVX = {
4834
    128u, 12u, 13u, 14u, 9u, 10u, 11u, 6u, 7u, 8u, 3u, 4u, 5u, 0u, 1u, 2u};
4835
4836
// Shuffle last 2 pixels to first 2 mirrored.  last byte zero
4837
static const uvec8 kShuffleMirrorRGB1_AVX = {
4838
    13u, 14u, 15u, 10u, 11u, 12u, 7u, 8u, 9u, 4u, 5u, 6u, 1u, 2u, 3u, 128u};
4839
4840
void RGB24MirrorRow_AVX2(const uint8_t* src_rgb24,
4841
                         uint8_t* dst_rgb24,
4842
0
                         int width) {
4843
0
  ptrdiff_t temp_width = (ptrdiff_t)(width);
4844
0
  src_rgb24 += width * 3 - 96;
4845
0
  asm volatile(
4846
0
      "vbroadcasti128 %3,%%ymm4                  \n"
4847
0
      "vmovdqa     %4,%%xmm5                     \n"
4848
4849
0
      LABELALIGN
4850
0
      "1:          \n"
4851
0
      "vmovdqu     (%0),%%xmm0                   \n"  // first 10
4852
0
      "vinserti128 $1,15(%0),%%ymm0,%%ymm0       \n"
4853
0
      "vmovdqu     30(%0),%%xmm1                 \n"  // next 10
4854
0
      "vinserti128 $1,45(%0),%%ymm1,%%ymm1       \n"
4855
0
      "vmovdqu     60(%0),%%xmm2                 \n"  // next 10
4856
0
      "vinserti128 $1,75(%0),%%ymm2,%%ymm2       \n"
4857
0
      "vmovdqu     80(%0),%%xmm3                 \n"  // last 2 special
4858
0
      "vpshufb     %%ymm4,%%ymm0,%%ymm0          \n"
4859
0
      "vpshufb     %%ymm4,%%ymm1,%%ymm1          \n"
4860
0
      "vpshufb     %%ymm4,%%ymm2,%%ymm2          \n"
4861
0
      "vpshufb     %%xmm5,%%xmm3,%%xmm3          \n"
4862
0
      "lea         -0x60(%0),%0                  \n"
4863
0
      "vmovdqu     %%xmm0,80(%1)                 \n"
4864
0
      "vextracti128 $1,%%ymm0,65(%1)             \n"
4865
0
      "vmovdqu     %%xmm1,50(%1)                 \n"
4866
0
      "vextracti128 $1,%%ymm1,35(%1)             \n"
4867
0
      "vmovdqu     %%xmm2,20(%1)                 \n"
4868
0
      "vextracti128 $1,%%ymm2,5(%1)              \n"
4869
0
      "vmovq       %%xmm3,0(%1)                  \n"
4870
0
      "lea         0x60(%1),%1                   \n"
4871
0
      "sub         $0x20,%2                      \n"
4872
0
      "jg          1b                            \n"
4873
0
      "vzeroupper  \n"
4874
0
      : "+r"(src_rgb24),              // %0
4875
0
        "+r"(dst_rgb24),              // %1
4876
0
        "+r"(temp_width)              // %2
4877
0
      : "m"(kShuffleMirrorRGB0_AVX),  // %3
4878
0
        "m"(kShuffleMirrorRGB1_AVX)   // %4
4879
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
4880
0
}
4881
#endif  // HAS_RGB24MIRRORROW_AVX2
4882
4883
#ifdef HAS_ARGBMIRRORROW_SSE2
4884
4885
0
void ARGBMirrorRow_SSE2(const uint8_t* src, uint8_t* dst, int width) {
4886
0
  ptrdiff_t temp_width = (ptrdiff_t)(width);
4887
0
  asm volatile("lea         -0x10(%0,%2,4),%0             \n"
4888
4889
0
               LABELALIGN
4890
0
               "1:          \n"
4891
0
               "movdqu      (%0),%%xmm0                   \n"
4892
0
               "pshufd      $0x1b,%%xmm0,%%xmm0           \n"
4893
0
               "lea         -0x10(%0),%0                  \n"
4894
0
               "movdqu      %%xmm0,(%1)                   \n"
4895
0
               "lea         0x10(%1),%1                   \n"
4896
0
               "sub         $0x4,%2                       \n"
4897
0
               "jg          1b                            \n"
4898
0
               : "+r"(src),        // %0
4899
0
                 "+r"(dst),        // %1
4900
0
                 "+r"(temp_width)  // %2
4901
0
               :
4902
0
               : "memory", "cc", "xmm0");
4903
0
}
4904
#endif  // HAS_ARGBMIRRORROW_SSE2
4905
4906
#ifdef HAS_ARGBMIRRORROW_AVX2
4907
// Shuffle table for reversing the bytes.
4908
static const ulvec32 kARGBShuffleMirror_AVX2 = {7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u};
4909
0
void ARGBMirrorRow_AVX2(const uint8_t* src, uint8_t* dst, int width) {
4910
0
  ptrdiff_t temp_width = (ptrdiff_t)(width);
4911
0
  asm volatile("vmovdqu     %3,%%ymm5                     \n"
4912
4913
0
               LABELALIGN
4914
0
               "1:          \n"
4915
0
               "vpermd      -0x20(%0,%2,4),%%ymm5,%%ymm0  \n"
4916
0
               "vmovdqu     %%ymm0,(%1)                   \n"
4917
0
               "lea         0x20(%1),%1                   \n"
4918
0
               "sub         $0x8,%2                       \n"
4919
0
               "jg          1b                            \n"
4920
0
               "vzeroupper  \n"
4921
0
               : "+r"(src),                    // %0
4922
0
                 "+r"(dst),                    // %1
4923
0
                 "+r"(temp_width)              // %2
4924
0
               : "m"(kARGBShuffleMirror_AVX2)  // %3
4925
0
               : "memory", "cc", "xmm0", "xmm5");
4926
0
}
4927
#endif  // HAS_ARGBMIRRORROW_AVX2
4928
4929
#ifdef HAS_SPLITUVROW_AVX2
4930
void SplitUVRow_AVX2(const uint8_t* src_uv,
4931
                     uint8_t* dst_u,
4932
                     uint8_t* dst_v,
4933
0
                     int width) {
4934
0
  asm volatile(
4935
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
4936
0
      "vpsrlw      $0x8,%%ymm5,%%ymm5            \n"
4937
0
      "sub         %1,%2                         \n"
4938
4939
0
      LABELALIGN
4940
0
      "1:          \n"
4941
0
      "vmovdqu     (%0),%%ymm0                   \n"
4942
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
4943
0
      "lea         0x40(%0),%0                   \n"
4944
0
      "vpsrlw      $0x8,%%ymm0,%%ymm2            \n"
4945
0
      "vpsrlw      $0x8,%%ymm1,%%ymm3            \n"
4946
0
      "vpand       %%ymm5,%%ymm0,%%ymm0          \n"
4947
0
      "vpand       %%ymm5,%%ymm1,%%ymm1          \n"
4948
0
      "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"
4949
0
      "vpackuswb   %%ymm3,%%ymm2,%%ymm2          \n"
4950
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
4951
0
      "vpermq      $0xd8,%%ymm2,%%ymm2           \n"
4952
0
      "vmovdqu     %%ymm0,(%1)                   \n"
4953
0
      "vmovdqu     %%ymm2,0x00(%1,%2,1)          \n"
4954
0
      "lea         0x20(%1),%1                   \n"
4955
0
      "sub         $0x20,%3                      \n"
4956
0
      "jg          1b                            \n"
4957
0
      "vzeroupper  \n"
4958
0
      : "+r"(src_uv),  // %0
4959
0
        "+r"(dst_u),   // %1
4960
0
        "+r"(dst_v),   // %2
4961
0
        "+r"(width)    // %3
4962
0
      :
4963
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5");
4964
0
}
4965
#endif  // HAS_SPLITUVROW_AVX2
4966
4967
#ifdef HAS_SPLITUVROW_AVX512BW
4968
static const uint64_t kSplitUVPermute[8] = {0, 2, 4, 6, 1, 3, 5, 7};
4969
4970
void SplitUVRow_AVX512BW(const uint8_t* src_uv,
4971
                         uint8_t* dst_u,
4972
                         uint8_t* dst_v,
4973
0
                         int width) {
4974
0
  asm volatile(
4975
0
      "vpternlogd  $0xff,%%zmm5,%%zmm5,%%zmm5    \n"
4976
0
      "vpsrlw      $0x8,%%zmm5,%%zmm5            \n"
4977
0
      "vmovdqu64   %4,%%zmm4                     \n"
4978
0
      "sub         %1,%2                         \n"
4979
4980
0
      LABELALIGN
4981
0
      "1:          \n"
4982
0
      "vmovdqu8    (%0),%%zmm0                   \n"
4983
0
      "vmovdqu8    0x40(%0),%%zmm1               \n"
4984
0
      "lea         0x80(%0),%0                   \n"
4985
0
      "vpsrlw      $0x8,%%zmm0,%%zmm2            \n"
4986
0
      "vpsrlw      $0x8,%%zmm1,%%zmm3            \n"
4987
0
      "vpandd      %%zmm5,%%zmm0,%%zmm0          \n"
4988
0
      "vpandd      %%zmm5,%%zmm1,%%zmm1          \n"
4989
0
      "vpackuswb   %%zmm1,%%zmm0,%%zmm0          \n"
4990
0
      "vpackuswb   %%zmm3,%%zmm2,%%zmm2          \n"
4991
0
      "vpermq      %%zmm0,%%zmm4,%%zmm0          \n"
4992
0
      "vpermq      %%zmm2,%%zmm4,%%zmm2          \n"
4993
0
      "vmovdqu8    %%zmm0,(%1)                   \n"
4994
0
      "vmovdqu8    %%zmm2,0x00(%1,%2,1)          \n"
4995
0
      "lea         0x40(%1),%1                   \n"
4996
0
      "sub         $0x40,%3                      \n"
4997
0
      "jg          1b                            \n"
4998
0
      "vzeroupper  \n"
4999
0
      : "+r"(src_uv),         // %0
5000
0
        "+r"(dst_u),          // %1
5001
0
        "+r"(dst_v),          // %2
5002
0
        "+r"(width)           // %3
5003
0
      : "m"(kSplitUVPermute)  // %4
5004
0
      : "memory", "cc", "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5");
5005
0
}
5006
#endif  // HAS_SPLITUVROW_AVX512BW
5007
5008
#ifdef HAS_SPLITUVROW_SSE2
5009
void SplitUVRow_SSE2(const uint8_t* src_uv,
5010
                     uint8_t* dst_u,
5011
                     uint8_t* dst_v,
5012
0
                     int width) {
5013
0
  asm volatile(
5014
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
5015
0
      "psrlw       $0x8,%%xmm5                   \n"
5016
0
      "sub         %1,%2                         \n"
5017
5018
0
      LABELALIGN
5019
0
      "1:          \n"
5020
0
      "movdqu      (%0),%%xmm0                   \n"
5021
0
      "movdqu      0x10(%0),%%xmm1               \n"
5022
0
      "lea         0x20(%0),%0                   \n"
5023
0
      "movdqa      %%xmm0,%%xmm2                 \n"
5024
0
      "movdqa      %%xmm1,%%xmm3                 \n"
5025
0
      "pand        %%xmm5,%%xmm0                 \n"
5026
0
      "pand        %%xmm5,%%xmm1                 \n"
5027
0
      "packuswb    %%xmm1,%%xmm0                 \n"
5028
0
      "psrlw       $0x8,%%xmm2                   \n"
5029
0
      "psrlw       $0x8,%%xmm3                   \n"
5030
0
      "packuswb    %%xmm3,%%xmm2                 \n"
5031
0
      "movdqu      %%xmm0,(%1)                   \n"
5032
0
      "movdqu      %%xmm2,0x00(%1,%2,1)          \n"
5033
0
      "lea         0x10(%1),%1                   \n"
5034
0
      "sub         $0x10,%3                      \n"
5035
0
      "jg          1b                            \n"
5036
0
      : "+r"(src_uv),  // %0
5037
0
        "+r"(dst_u),   // %1
5038
0
        "+r"(dst_v),   // %2
5039
0
        "+r"(width)    // %3
5040
0
      :
5041
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5");
5042
0
}
5043
#endif  // HAS_SPLITUVROW_SSE2
5044
5045
#ifdef HAS_DETILEROW_SSE2
5046
void DetileRow_SSE2(const uint8_t* src,
5047
                    ptrdiff_t src_tile_stride,
5048
                    uint8_t* dst,
5049
0
                    int width) {
5050
0
  asm volatile(
5051
0
      "1:          \n"
5052
0
      "movdqu      (%0),%%xmm0                   \n"
5053
0
      "sub         $0x10,%2                      \n"
5054
0
      "lea         (%0,%3),%0                    \n"
5055
0
      "movdqu      %%xmm0,(%1)                   \n"
5056
0
      "lea         0x10(%1),%1                   \n"
5057
0
      "jg          1b                            \n"
5058
0
      : "+r"(src),            // %0
5059
0
        "+r"(dst),            // %1
5060
0
        "+r"(width)           // %2
5061
0
      : "r"(src_tile_stride)  // %3
5062
0
      : "cc", "memory", "xmm0");
5063
0
}
5064
#endif  // HAS_DETILEROW_SSE2
5065
5066
#ifdef HAS_DETILEROW_16_SSE2
5067
void DetileRow_16_SSE2(const uint16_t* src,
5068
                       ptrdiff_t src_tile_stride,
5069
                       uint16_t* dst,
5070
0
                       int width) {
5071
0
  asm volatile(
5072
0
      "1:          \n"
5073
0
      "movdqu      (%0),%%xmm0                   \n"
5074
0
      "movdqu      0x10(%0),%%xmm1               \n"
5075
0
      "lea         (%0,%3,2),%0                  \n"
5076
0
      "movdqu      %%xmm0,(%1)                   \n"
5077
0
      "movdqu      %%xmm1,0x10(%1)               \n"
5078
0
      "lea         0x20(%1),%1                   \n"
5079
0
      "sub         $0x10,%2                      \n"
5080
0
      "jg          1b                            \n"
5081
0
      : "+r"(src),            // %0
5082
0
        "+r"(dst),            // %1
5083
0
        "+r"(width)           // %2
5084
0
      : "r"(src_tile_stride)  // %3
5085
0
      : "cc", "memory", "xmm0", "xmm1");
5086
0
}
5087
#endif  // HAS_DETILEROW_SSE2
5088
5089
#ifdef HAS_DETILEROW_16_AVX
5090
void DetileRow_16_AVX(const uint16_t* src,
5091
                      ptrdiff_t src_tile_stride,
5092
                      uint16_t* dst,
5093
0
                      int width) {
5094
0
  asm volatile(
5095
0
      "1:          \n"
5096
0
      "vmovdqu     (%0),%%ymm0                   \n"
5097
0
      "lea         (%0,%3,2),%0                  \n"
5098
0
      "vmovdqu     %%ymm0,(%1)                   \n"
5099
0
      "lea         0x20(%1),%1                   \n"
5100
0
      "sub         $0x10,%2                      \n"
5101
0
      "jg          1b                            \n"
5102
0
      "vzeroupper  \n"
5103
0
      : "+r"(src),            // %0
5104
0
        "+r"(dst),            // %1
5105
0
        "+r"(width)           // %2
5106
0
      : "r"(src_tile_stride)  // %3
5107
0
      : "cc", "memory", "xmm0");
5108
0
}
5109
#endif  // HAS_DETILEROW_AVX
5110
5111
#ifdef HAS_DETILETOYUY2_SSE2
5112
// Read 16 Y, 8 UV, and write 8 YUYV.
5113
void DetileToYUY2_SSE2(const uint8_t* src_y,
5114
                       ptrdiff_t src_y_tile_stride,
5115
                       const uint8_t* src_uv,
5116
                       ptrdiff_t src_uv_tile_stride,
5117
                       uint8_t* dst_yuy2,
5118
0
                       int width) {
5119
0
  asm volatile(
5120
0
      "1:          \n"
5121
0
      "movdqu      (%0),%%xmm0                   \n"  // Load 16 Y
5122
0
      "sub         $0x10,%3                      \n"
5123
0
      "lea         (%0,%4),%0                    \n"
5124
0
      "movdqu      (%1),%%xmm1                   \n"  // Load 8 UV
5125
0
      "lea         (%1,%5),%1                    \n"
5126
0
      "movdqu      %%xmm0,%%xmm2                 \n"
5127
0
      "punpcklbw   %%xmm1,%%xmm0                 \n"
5128
0
      "punpckhbw   %%xmm1,%%xmm2                 \n"
5129
0
      "movdqu      %%xmm0,(%2)                   \n"
5130
0
      "movdqu      %%xmm2,0x10(%2)               \n"
5131
0
      "lea         0x20(%2),%2                   \n"
5132
0
      "jg          1b                            \n"
5133
0
      : "+r"(src_y),                            // %0
5134
0
        "+r"(src_uv),                           // %1
5135
0
        "+r"(dst_yuy2),                         // %2
5136
0
        "+r"(width)                             // %3
5137
0
      : "r"(src_y_tile_stride),                 // %4
5138
0
        "r"(src_uv_tile_stride)                 // %5
5139
0
      : "cc", "memory", "xmm0", "xmm1", "xmm2"  // Clobber list
5140
0
  );
5141
0
}
5142
#endif
5143
5144
#ifdef HAS_DETILESPLITUVROW_SSSE3
5145
// TODO(greenjustin): Look into generating these constants instead of loading
5146
// them since this can cause branch mispredicts for fPIC code on 32-bit
5147
// machines.
5148
static const uvec8 kDeinterlaceUV = {0, 2, 4, 6, 8, 10, 12, 14,
5149
                                     1, 3, 5, 7, 9, 11, 13, 15};
5150
5151
// TODO(greenjustin): Research alternatives to pshufb, since pshufb can be very
5152
// slow on older SSE2 processors.
5153
void DetileSplitUVRow_SSSE3(const uint8_t* src_uv,
5154
                            ptrdiff_t src_tile_stride,
5155
                            uint8_t* dst_u,
5156
                            uint8_t* dst_v,
5157
0
                            int width) {
5158
0
  asm volatile(
5159
0
      "movdqu      %4,%%xmm1                     \n"
5160
0
      "1:          \n"
5161
0
      "movdqu      (%0),%%xmm0                   \n"
5162
0
      "lea         (%0, %5),%0                   \n"
5163
0
      "pshufb      %%xmm1,%%xmm0                 \n"
5164
0
      "movq        %%xmm0,(%1)                   \n"
5165
0
      "lea         0x8(%1),%1                    \n"
5166
0
      "movhps      %%xmm0,(%2)                   \n"
5167
0
      "lea         0x8(%2),%2                    \n"
5168
0
      "sub         $0x10,%3                      \n"
5169
0
      "jg          1b                            \n"
5170
0
      : "+r"(src_uv),         // %0
5171
0
        "+r"(dst_u),          // %1
5172
0
        "+r"(dst_v),          // %2
5173
0
        "+r"(width)           // %3
5174
0
      : "m"(kDeinterlaceUV),  // %4
5175
0
        "r"(src_tile_stride)  // %5
5176
0
      : "cc", "memory", "xmm0", "xmm1");
5177
0
}
5178
#endif  // HAS_DETILESPLITUVROW_SSSE3
5179
5180
#ifdef HAS_MERGEUVROW_AVX512BW
5181
void MergeUVRow_AVX512BW(const uint8_t* src_u,
5182
                         const uint8_t* src_v,
5183
                         uint8_t* dst_uv,
5184
0
                         int width) {
5185
0
  asm volatile("sub         %0,%1                         \n"
5186
5187
0
               LABELALIGN
5188
0
               "1:          \n"
5189
0
               "vpmovzxbw   (%0),%%zmm0                   \n"
5190
0
               "vpmovzxbw   0x00(%0,%1,1),%%zmm1          \n"
5191
0
               "lea         0x20(%0),%0                   \n"
5192
0
               "vpsllw      $0x8,%%zmm1,%%zmm1            \n"
5193
0
               "vporq       %%zmm0,%%zmm1,%%zmm2          \n"
5194
0
               "vmovdqu64   %%zmm2,(%2)                   \n"
5195
0
               "lea         0x40(%2),%2                   \n"
5196
0
               "sub         $0x20,%3                      \n"
5197
0
               "jg          1b                            \n"
5198
0
               "vzeroupper  \n"
5199
0
               : "+r"(src_u),   // %0
5200
0
                 "+r"(src_v),   // %1
5201
0
                 "+r"(dst_uv),  // %2
5202
0
                 "+r"(width)    // %3
5203
0
               :
5204
0
               : "memory", "cc", "xmm0", "xmm1", "xmm2");
5205
0
}
5206
#endif  // HAS_MERGEUVROW_AVX512BW
5207
5208
#ifdef HAS_MERGEUVROW_AVX2
5209
void MergeUVRow_AVX2(const uint8_t* src_u,
5210
                     const uint8_t* src_v,
5211
                     uint8_t* dst_uv,
5212
0
                     int width) {
5213
0
  asm volatile("sub         %0,%1                         \n"
5214
5215
0
               LABELALIGN
5216
0
               "1:          \n"
5217
0
               "vpmovzxbw   (%0),%%ymm0                   \n"
5218
0
               "vpmovzxbw   0x00(%0,%1,1),%%ymm1          \n"
5219
0
               "lea         0x10(%0),%0                   \n"
5220
0
               "vpsllw      $0x8,%%ymm1,%%ymm1            \n"
5221
0
               "vpor        %%ymm0,%%ymm1,%%ymm2          \n"
5222
0
               "vmovdqu     %%ymm2,(%2)                   \n"
5223
0
               "lea         0x20(%2),%2                   \n"
5224
0
               "sub         $0x10,%3                      \n"
5225
0
               "jg          1b                            \n"
5226
0
               "vzeroupper  \n"
5227
0
               : "+r"(src_u),   // %0
5228
0
                 "+r"(src_v),   // %1
5229
0
                 "+r"(dst_uv),  // %2
5230
0
                 "+r"(width)    // %3
5231
0
               :
5232
0
               : "memory", "cc", "xmm0", "xmm1", "xmm2");
5233
0
}
5234
#endif  // HAS_MERGEUVROW_AVX2
5235
5236
#ifdef HAS_MERGEUVROW_SSE2
5237
void MergeUVRow_SSE2(const uint8_t* src_u,
5238
                     const uint8_t* src_v,
5239
                     uint8_t* dst_uv,
5240
0
                     int width) {
5241
0
  asm volatile("sub         %0,%1                         \n"
5242
5243
0
               LABELALIGN
5244
0
               "1:          \n"
5245
0
               "movdqu      (%0),%%xmm0                   \n"
5246
0
               "movdqu      0x00(%0,%1,1),%%xmm1          \n"
5247
0
               "lea         0x10(%0),%0                   \n"
5248
0
               "movdqa      %%xmm0,%%xmm2                 \n"
5249
0
               "punpcklbw   %%xmm1,%%xmm0                 \n"
5250
0
               "punpckhbw   %%xmm1,%%xmm2                 \n"
5251
0
               "movdqu      %%xmm0,(%2)                   \n"
5252
0
               "movdqu      %%xmm2,0x10(%2)               \n"
5253
0
               "lea         0x20(%2),%2                   \n"
5254
0
               "sub         $0x10,%3                      \n"
5255
0
               "jg          1b                            \n"
5256
0
               : "+r"(src_u),   // %0
5257
0
                 "+r"(src_v),   // %1
5258
0
                 "+r"(dst_uv),  // %2
5259
0
                 "+r"(width)    // %3
5260
0
               :
5261
0
               : "memory", "cc", "xmm0", "xmm1", "xmm2");
5262
0
}
5263
#endif  // HAS_MERGEUVROW_SSE2
5264
5265
#ifdef HAS_MERGEUVROW_16_AVX2
5266
void MergeUVRow_16_AVX2(const uint16_t* src_u,
5267
                        const uint16_t* src_v,
5268
                        uint16_t* dst_uv,
5269
                        int depth,
5270
0
                        int width) {
5271
0
  asm volatile(
5272
0
      "vmovd       %4,%%xmm3                     \n"
5273
0
      "vmovd       %5,%%xmm4                     \n"
5274
5275
0
      "sub         %0,%1                         \n"
5276
      // 8 pixels per loop.
5277
5278
0
      LABELALIGN
5279
0
      "1:          \n"
5280
0
      "vpmovzxwd   (%0),%%ymm0                   \n"
5281
0
      "vpmovzxwd   0x00(%0,%1,1),%%ymm1          \n"
5282
0
      "lea         0x10(%0),%0                   \n"
5283
0
      "vpsllw      %%xmm3,%%ymm0,%%ymm0          \n"
5284
0
      "vpslld      %%xmm4,%%ymm1,%%ymm1          \n"
5285
0
      "vpor        %%ymm0,%%ymm1,%%ymm2          \n"
5286
0
      "vmovdqu     %%ymm2,(%2)                   \n"
5287
0
      "lea         0x20(%2),%2                   \n"
5288
0
      "sub         $0x8,%3                       \n"
5289
0
      "jg          1b                            \n"
5290
0
      "vzeroupper  \n"
5291
0
      : "+r"(src_u),      // %0
5292
0
        "+r"(src_v),      // %1
5293
0
        "+r"(dst_uv),     // %2
5294
0
        "+r"(width)       // %3
5295
0
      : "r"(16 - depth),  // %4
5296
0
        "r"(32 - depth)   // %5
5297
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4");
5298
0
}
5299
#endif  // HAS_MERGEUVROW_AVX2
5300
5301
#ifdef HAS_SPLITUVROW_16_AVX2
5302
const uvec8 kSplitUVShuffle16 = {0, 1, 4, 5, 8,  9,  12, 13,
5303
                                 2, 3, 6, 7, 10, 11, 14, 15};
5304
void SplitUVRow_16_AVX2(const uint16_t* src_uv,
5305
                        uint16_t* dst_u,
5306
                        uint16_t* dst_v,
5307
                        int depth,
5308
0
                        int width) {
5309
0
  depth = 16 - depth;
5310
0
  asm volatile(
5311
0
      "vmovd       %4,%%xmm3                     \n"
5312
0
      "vbroadcasti128 %5,%%ymm4                  \n"
5313
0
      "sub         %1,%2                         \n"
5314
5315
      // 16 pixels per loop.
5316
0
      LABELALIGN
5317
0
      "1:          \n"
5318
0
      "vmovdqu     (%0),%%ymm0                   \n"
5319
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
5320
0
      "add         $0x40,%0                      \n"
5321
5322
0
      "vpsrlw      %%xmm3,%%ymm0,%%ymm0          \n"
5323
0
      "vpsrlw      %%xmm3,%%ymm1,%%ymm1          \n"
5324
0
      "vpshufb     %%ymm4,%%ymm0,%%ymm0          \n"
5325
0
      "vpshufb     %%ymm4,%%ymm1,%%ymm1          \n"
5326
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
5327
0
      "vpermq      $0xd8,%%ymm1,%%ymm1           \n"
5328
0
      "vextractf128 $0x0,%%ymm0,(%1)             \n"
5329
0
      "vextractf128 $0x0,%%ymm1,0x10(%1)         \n"
5330
0
      "vextractf128 $0x1,%%ymm0,(%1,%2)          \n"
5331
0
      "vextractf128 $0x1,%%ymm1,0x10(%1,%2)      \n"
5332
0
      "add         $0x20,%1                      \n"
5333
0
      "sub         $0x10,%3                      \n"
5334
0
      "jg          1b                            \n"
5335
0
      "vzeroupper  \n"
5336
0
      : "+r"(src_uv),           // %0
5337
0
        "+r"(dst_u),            // %1
5338
0
        "+r"(dst_v),            // %2
5339
0
        "+r"(width)             // %3
5340
0
      : "r"(depth),             // %4
5341
0
        "m"(kSplitUVShuffle16)  // %5
5342
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4");
5343
0
}
5344
#endif  // HAS_SPLITUVROW_16_AVX2
5345
5346
// Use scale to convert lsb formats to msb, depending how many bits there are:
5347
// 128 = 9 bits
5348
// 64 = 10 bits
5349
// 16 = 12 bits
5350
// 1 = 16 bits
5351
#ifdef HAS_MULTIPLYROW_16_AVX2
5352
void MultiplyRow_16_AVX2(const uint16_t* src_y,
5353
                         uint16_t* dst_y,
5354
                         int scale,
5355
0
                         int width) {
5356
0
  asm volatile(
5357
0
      "vmovd       %3,%%xmm3                     \n"
5358
0
      "vpbroadcastw %%xmm3,%%ymm3                \n"
5359
0
      "sub         %0,%1                         \n"
5360
5361
      // 32 pixels per loop.
5362
0
      LABELALIGN
5363
0
      "1:          \n"
5364
0
      "vmovdqu     (%0),%%ymm0                   \n"
5365
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
5366
0
      "vpmullw     %%ymm3,%%ymm0,%%ymm0          \n"
5367
0
      "vpmullw     %%ymm3,%%ymm1,%%ymm1          \n"
5368
0
      "vmovdqu     %%ymm0,(%0,%1)                \n"
5369
0
      "vmovdqu     %%ymm1,0x20(%0,%1)            \n"
5370
0
      "add         $0x40,%0                      \n"
5371
0
      "sub         $0x20,%2                      \n"
5372
0
      "jg          1b                            \n"
5373
0
      "vzeroupper  \n"
5374
0
      : "+r"(src_y),  // %0
5375
0
        "+r"(dst_y),  // %1
5376
0
        "+r"(width)   // %2
5377
0
      : "r"(scale)    // %3
5378
0
      : "memory", "cc", "xmm0", "xmm1", "xmm3");
5379
0
}
5380
#endif  // HAS_MULTIPLYROW_16_AVX2
5381
5382
// Use scale to convert msb formats to lsb, depending how many bits there are:
5383
// 512 = 9 bits
5384
// 1024 = 10 bits
5385
// 4096 = 12 bits
5386
// 65536 = 16 bits
5387
#ifdef HAS_DIVIDEROW_16_AVX2
5388
void DivideRow_16_AVX2(const uint16_t* src_y,
5389
                       uint16_t* dst_y,
5390
                       int scale,
5391
0
                       int width) {
5392
0
  asm volatile(
5393
0
      "vmovd       %3,%%xmm3                     \n"
5394
0
      "vpbroadcastw %%xmm3,%%ymm3                \n"
5395
0
      "sub         %0,%1                         \n"
5396
5397
      // 32 pixels per loop.
5398
0
      LABELALIGN
5399
0
      "1:          \n"
5400
0
      "vmovdqu     (%0),%%ymm0                   \n"
5401
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
5402
0
      "vpmulhuw    %%ymm3,%%ymm0,%%ymm0          \n"
5403
0
      "vpmulhuw    %%ymm3,%%ymm1,%%ymm1          \n"
5404
0
      "vmovdqu     %%ymm0,(%0,%1)                \n"
5405
0
      "vmovdqu     %%ymm1,0x20(%0,%1)            \n"
5406
0
      "add         $0x40,%0                      \n"
5407
0
      "sub         $0x20,%2                      \n"
5408
0
      "jg          1b                            \n"
5409
0
      "vzeroupper  \n"
5410
0
      : "+r"(src_y),  // %0
5411
0
        "+r"(dst_y),  // %1
5412
0
        "+r"(width),  // %2
5413
0
        "+r"(scale)   // %3
5414
0
      :
5415
0
      : "memory", "cc", "xmm0", "xmm1", "xmm3");
5416
0
}
5417
#endif  // HAS_MULTIPLYROW_16_AVX2
5418
5419
// Use scale to convert lsb formats to msb, depending how many bits there are:
5420
// 32768 = 9 bits
5421
// 16384 = 10 bits
5422
// 4096 = 12 bits
5423
// 256 = 16 bits
5424
void Convert16To8Row_SSSE3(const uint16_t* src_y,
5425
                           uint8_t* dst_y,
5426
                           int scale,
5427
0
                           int width) {
5428
0
  asm volatile(
5429
0
      "movd        %3,%%xmm2                     \n"
5430
0
      "punpcklwd   %%xmm2,%%xmm2                 \n"
5431
0
      "pshufd      $0x0,%%xmm2,%%xmm2            \n"
5432
5433
      // 32 pixels per loop.
5434
0
      LABELALIGN
5435
0
      "1:          \n"
5436
0
      "movdqu      (%0),%%xmm0                   \n"
5437
0
      "movdqu      0x10(%0),%%xmm1               \n"
5438
0
      "add         $0x20,%0                      \n"
5439
0
      "pmulhuw     %%xmm2,%%xmm0                 \n"
5440
0
      "pmulhuw     %%xmm2,%%xmm1                 \n"
5441
0
      "packuswb    %%xmm1,%%xmm0                 \n"
5442
0
      "movdqu      %%xmm0,(%1)                   \n"
5443
0
      "add         $0x10,%1                      \n"
5444
0
      "sub         $0x10,%2                      \n"
5445
0
      "jg          1b                            \n"
5446
0
      : "+r"(src_y),  // %0
5447
0
        "+r"(dst_y),  // %1
5448
0
        "+r"(width)   // %2
5449
0
      : "r"(scale)    // %3
5450
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
5451
0
}
5452
5453
#ifdef HAS_CONVERT16TO8ROW_AVX2
5454
void Convert16To8Row_AVX2(const uint16_t* src_y,
5455
                          uint8_t* dst_y,
5456
                          int scale,
5457
724
                          int width) {
5458
724
  asm volatile(
5459
724
      "vmovd       %3,%%xmm2                     \n"
5460
724
      "vpbroadcastw %%xmm2,%%ymm2                \n"
5461
5462
      // 32 pixels per loop.
5463
724
      LABELALIGN
5464
724
      "1:          \n"
5465
724
      "vmovdqu     (%0),%%ymm0                   \n"
5466
724
      "vmovdqu     0x20(%0),%%ymm1               \n"
5467
724
      "add         $0x40,%0                      \n"
5468
724
      "vpmulhuw    %%ymm2,%%ymm0,%%ymm0          \n"
5469
724
      "vpmulhuw    %%ymm2,%%ymm1,%%ymm1          \n"
5470
724
      "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"  // mutates
5471
724
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
5472
724
      "vmovdqu     %%ymm0,(%1)                   \n"
5473
724
      "add         $0x20,%1                      \n"
5474
724
      "sub         $0x20,%2                      \n"
5475
724
      "jg          1b                            \n"
5476
724
      "vzeroupper  \n"
5477
724
      : "+r"(src_y),  // %0
5478
724
        "+r"(dst_y),  // %1
5479
724
        "+r"(width)   // %2
5480
724
      : "r"(scale)    // %3
5481
724
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
5482
724
}
5483
#endif  // HAS_CONVERT16TO8ROW_AVX2
5484
5485
#ifdef HAS_CONVERT16TO8ROW_AVX512BW
5486
void Convert16To8Row_AVX512BW(const uint16_t* src_y,
5487
                              uint8_t* dst_y,
5488
                              int scale,
5489
0
                              int width) {
5490
0
  asm volatile("vpbroadcastw %3,%%zmm2                    \n"
5491
5492
               // 64 pixels per loop.
5493
0
               LABELALIGN
5494
0
               "1:          \n"
5495
0
               "vmovups     (%0),%%zmm0                   \n"
5496
0
               "vmovups     0x40(%0),%%zmm1               \n"
5497
0
               "add         $0x80,%0                      \n"
5498
0
               "vpmulhuw    %%zmm2,%%zmm0,%%zmm0          \n"
5499
0
               "vpmulhuw    %%zmm2,%%zmm1,%%zmm1          \n"
5500
0
               "vpmovuswb   %%zmm0,%%ymm0                 \n"
5501
0
               "vpmovuswb   %%zmm1,%%ymm1                 \n"
5502
0
               "vmovups     %%ymm0,(%1)                   \n"
5503
0
               "vmovups     %%ymm1,0x20(%1)               \n"
5504
0
               "add         $0x40,%1                      \n"
5505
0
               "sub         $0x40,%2                      \n"
5506
0
               "jg          1b                            \n"
5507
0
               "vzeroupper  \n"
5508
0
               : "+r"(src_y),  // %0
5509
0
                 "+r"(dst_y),  // %1
5510
0
                 "+r"(width)   // %2
5511
0
               : "r"(scale)    // %3
5512
0
               : "memory", "cc", "xmm0", "xmm1", "xmm2");
5513
0
}
5514
#endif  // HAS_CONVERT16TO8ROW_AVX2
5515
5516
// Use scale to convert to lsb formats depending how many bits there are:
5517
// 512 = 9 bits
5518
// 1024 = 10 bits
5519
// 4096 = 12 bits
5520
void Convert8To16Row_SSE2(const uint8_t* src_y,
5521
                          uint16_t* dst_y,
5522
                          int scale,
5523
0
                          int width) {
5524
0
  asm volatile(
5525
0
      "movd        %3,%%xmm2                     \n"
5526
0
      "punpcklwd   %%xmm2,%%xmm2                 \n"
5527
0
      "pshufd      $0x0,%%xmm2,%%xmm2            \n"
5528
5529
      // 32 pixels per loop.
5530
0
      LABELALIGN
5531
0
      "1:          \n"
5532
0
      "movdqu      (%0),%%xmm0                   \n"
5533
0
      "movdqa      %%xmm0,%%xmm1                 \n"
5534
0
      "punpcklbw   %%xmm0,%%xmm0                 \n"
5535
0
      "punpckhbw   %%xmm1,%%xmm1                 \n"
5536
0
      "add         $0x10,%0                      \n"
5537
0
      "pmulhuw     %%xmm2,%%xmm0                 \n"
5538
0
      "pmulhuw     %%xmm2,%%xmm1                 \n"
5539
0
      "movdqu      %%xmm0,(%1)                   \n"
5540
0
      "movdqu      %%xmm1,0x10(%1)               \n"
5541
0
      "add         $0x20,%1                      \n"
5542
0
      "sub         $0x10,%2                      \n"
5543
0
      "jg          1b                            \n"
5544
0
      : "+r"(src_y),  // %0
5545
0
        "+r"(dst_y),  // %1
5546
0
        "+r"(width)   // %2
5547
0
      : "r"(scale)    // %3
5548
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
5549
0
}
5550
5551
#ifdef HAS_CONVERT8TO16ROW_AVX2
5552
void Convert8To16Row_AVX2(const uint8_t* src_y,
5553
                          uint16_t* dst_y,
5554
                          int scale,
5555
0
                          int width) {
5556
0
  const int shift = __builtin_clz(scale) - 15;
5557
0
  asm volatile("vmovd       %3,%%xmm2                     \n"
5558
5559
               // 32 pixels per loop.
5560
0
               LABELALIGN
5561
0
               "1:          \n"
5562
0
               "vmovdqu     (%0),%%ymm0                   \n"
5563
0
               "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
5564
0
               "add         $0x20,%0                      \n"
5565
0
               "vpunpckhbw  %%ymm0,%%ymm0,%%ymm1          \n"
5566
0
               "vpunpcklbw  %%ymm0,%%ymm0,%%ymm0          \n"
5567
0
               "vpsrlw      %%xmm2,%%ymm0,%%ymm0          \n"
5568
0
               "vpsrlw      %%xmm2,%%ymm1,%%ymm1          \n"
5569
0
               "vmovdqu     %%ymm0,(%1)                   \n"
5570
0
               "vmovdqu     %%ymm1,0x20(%1)               \n"
5571
0
               "add         $0x40,%1                      \n"
5572
0
               "sub         $0x20,%2                      \n"
5573
0
               "jg          1b                            \n"
5574
0
               "vzeroupper  \n"
5575
0
               : "+r"(src_y),  // %0
5576
0
                 "+r"(dst_y),  // %1
5577
0
                 "+r"(width)   // %2
5578
0
               : "r"(shift)    // %3
5579
0
               : "memory", "cc", "xmm0", "xmm1", "xmm2");
5580
0
}
5581
#endif  // HAS_CONVERT8TO16ROW_AVX2
5582
5583
#ifdef HAS_SPLITRGBROW_SSSE3
5584
// Shuffle table for converting RGB to Planar.
5585
static const uvec8 kSplitRGBShuffle[9] = {
5586
    {0u, 3u, 6u, 9u, 12u, 15u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u,
5587
     128u, 128u},
5588
    {128u, 128u, 128u, 128u, 128u, 128u, 2u, 5u, 8u, 11u, 14u, 128u, 128u, 128u,
5589
     128u, 128u},
5590
    {128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 1u, 4u,
5591
     7u, 10u, 13u},
5592
    {1u, 4u, 7u, 10u, 13u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u,
5593
     128u, 128u},
5594
    {128u, 128u, 128u, 128u, 128u, 0u, 3u, 6u, 9u, 12u, 15u, 128u, 128u, 128u,
5595
     128u, 128u},
5596
    {128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 2u, 5u,
5597
     8u, 11u, 14u},
5598
    {2u, 5u, 8u, 11u, 14u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u,
5599
     128u, 128u},
5600
    {128u, 128u, 128u, 128u, 128u, 1u, 4u, 7u, 10u, 13u, 128u, 128u, 128u, 128u,
5601
     128u, 128u},
5602
    {128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, 0u, 3u, 6u, 9u,
5603
     12u, 15u}};
5604
5605
void SplitRGBRow_SSSE3(const uint8_t* src_rgb,
5606
                       uint8_t* dst_r,
5607
                       uint8_t* dst_g,
5608
                       uint8_t* dst_b,
5609
0
                       int width) {
5610
0
  asm volatile(
5611
0
      "1:          \n"
5612
0
      "movdqu      (%0),%%xmm0                   \n"
5613
0
      "movdqu      0x10(%0),%%xmm1               \n"
5614
0
      "movdqu      0x20(%0),%%xmm2               \n"
5615
0
      "pshufb      0(%5), %%xmm0                 \n"
5616
0
      "pshufb      16(%5), %%xmm1                \n"
5617
0
      "pshufb      32(%5), %%xmm2                \n"
5618
0
      "por         %%xmm1,%%xmm0                 \n"
5619
0
      "por         %%xmm2,%%xmm0                 \n"
5620
0
      "movdqu      %%xmm0,(%1)                   \n"
5621
0
      "lea         0x10(%1),%1                   \n"
5622
5623
0
      "movdqu      (%0),%%xmm0                   \n"
5624
0
      "movdqu      0x10(%0),%%xmm1               \n"
5625
0
      "movdqu      0x20(%0),%%xmm2               \n"
5626
0
      "pshufb      48(%5),%%xmm0                 \n"
5627
0
      "pshufb      64(%5),%%xmm1                 \n"
5628
0
      "pshufb      80(%5), %%xmm2                \n"
5629
0
      "por         %%xmm1,%%xmm0                 \n"
5630
0
      "por         %%xmm2,%%xmm0                 \n"
5631
0
      "movdqu      %%xmm0,(%2)                   \n"
5632
0
      "lea         0x10(%2),%2                   \n"
5633
5634
0
      "movdqu      (%0),%%xmm0                   \n"
5635
0
      "movdqu      0x10(%0),%%xmm1               \n"
5636
0
      "movdqu      0x20(%0),%%xmm2               \n"
5637
0
      "pshufb      96(%5), %%xmm0                \n"
5638
0
      "pshufb      112(%5), %%xmm1               \n"
5639
0
      "pshufb      128(%5), %%xmm2               \n"
5640
0
      "por         %%xmm1,%%xmm0                 \n"
5641
0
      "por         %%xmm2,%%xmm0                 \n"
5642
0
      "movdqu      %%xmm0,(%3)                   \n"
5643
0
      "lea         0x10(%3),%3                   \n"
5644
0
      "lea         0x30(%0),%0                   \n"
5645
0
      "sub         $0x10,%4                      \n"
5646
0
      "jg          1b                            \n"
5647
0
      : "+r"(src_rgb),             // %0
5648
0
        "+r"(dst_r),               // %1
5649
0
        "+r"(dst_g),               // %2
5650
0
        "+r"(dst_b),               // %3
5651
0
        "+r"(width)                // %4
5652
0
      : "r"(&kSplitRGBShuffle[0])  // %5
5653
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
5654
0
}
5655
#endif  // HAS_SPLITRGBROW_SSSE3
5656
5657
#ifdef HAS_SPLITRGBROW_SSE41
5658
// Shuffle table for converting RGB to Planar, SSE4.1. Note: these are used for
5659
// the AVX2 implementation as well.
5660
static const uvec8 kSplitRGBShuffleSSE41[5] = {
5661
    {0u, 3u, 6u, 9u, 12u, 15u, 2u, 5u, 8u, 11u, 14u, 1u, 4u, 7u, 10u, 13u},
5662
    {1u, 4u, 7u, 10u, 13u, 0u, 3u, 6u, 9u, 12u, 15u, 2u, 5u, 8u, 11u, 14u},
5663
    {2u, 5u, 8u, 11u, 14u, 1u, 4u, 7u, 10u, 13u, 0u, 3u, 6u, 9u, 12u, 15u},
5664
    {0u, 128u, 0u, 0u, 128u, 0u, 0u, 128u, 0u, 0u, 128u, 0u, 0u, 128u, 0u, 0u},
5665
    {0u, 0u, 128u, 0u, 0u, 128u, 0u, 0u, 128u, 0u, 0u, 128u, 0u, 0u, 128u, 0u},
5666
};
5667
5668
void SplitRGBRow_SSE41(const uint8_t* src_rgb,
5669
                       uint8_t* dst_r,
5670
                       uint8_t* dst_g,
5671
                       uint8_t* dst_b,
5672
0
                       int width) {
5673
0
  asm volatile(
5674
0
      "movdqa      48(%5), %%xmm0                \n"
5675
0
      "1:          \n"
5676
0
      "movdqu      (%0),%%xmm1                   \n"
5677
0
      "movdqu      0x10(%0),%%xmm2               \n"
5678
0
      "movdqu      0x20(%0),%%xmm3               \n"
5679
0
      "lea         0x30(%0),%0                   \n"
5680
0
      "movdqa      %%xmm1, %%xmm4                \n"
5681
0
      "pblendvb    %%xmm3, %%xmm1                \n"
5682
0
      "pblendvb    %%xmm2, %%xmm3                \n"
5683
0
      "pblendvb    %%xmm4, %%xmm2                \n"
5684
0
      "palignr     $0xF, %%xmm0, %%xmm0          \n"
5685
0
      "pblendvb    %%xmm2, %%xmm1                \n"
5686
0
      "pblendvb    %%xmm3, %%xmm2                \n"
5687
0
      "pblendvb    %%xmm4, %%xmm3                \n"
5688
0
      "palignr     $0x1, %%xmm0, %%xmm0          \n"
5689
0
      "pshufb      0(%5), %%xmm1                 \n"
5690
0
      "pshufb      16(%5), %%xmm2                \n"
5691
0
      "pshufb      32(%5), %%xmm3                \n"
5692
0
      "movdqu      %%xmm1,(%1)                   \n"
5693
0
      "lea         0x10(%1),%1                   \n"
5694
0
      "movdqu      %%xmm2,(%2)                   \n"
5695
0
      "lea         0x10(%2),%2                   \n"
5696
0
      "movdqu      %%xmm3,(%3)                   \n"
5697
0
      "lea         0x10(%3),%3                   \n"
5698
0
      "sub         $0x10,%4                      \n"
5699
0
      "jg          1b                            \n"
5700
0
      : "+r"(src_rgb),                  // %0
5701
0
        "+r"(dst_r),                    // %1
5702
0
        "+r"(dst_g),                    // %2
5703
0
        "+r"(dst_b),                    // %3
5704
0
        "+r"(width)                     // %4
5705
0
      : "r"(&kSplitRGBShuffleSSE41[0])  // %5
5706
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4");
5707
0
}
5708
#endif  // HAS_SPLITRGBROW_SSE41
5709
5710
#ifdef HAS_SPLITRGBROW_AVX2
5711
void SplitRGBRow_AVX2(const uint8_t* src_rgb,
5712
                      uint8_t* dst_r,
5713
                      uint8_t* dst_g,
5714
                      uint8_t* dst_b,
5715
0
                      int width) {
5716
0
  asm volatile(
5717
0
      "vbroadcasti128 48(%5), %%ymm0             \n"
5718
0
      "vbroadcasti128 64(%5), %%ymm7             \n"
5719
0
#if defined(__x86_64__)
5720
0
      "vbroadcasti128 0(%5), %%ymm8              \n"
5721
0
      "vbroadcasti128 16(%5), %%ymm9             \n"
5722
0
      "vbroadcasti128 32(%5), %%ymm10            \n"
5723
0
#endif
5724
0
      "1:          \n"
5725
0
      "vmovdqu     (%0),%%ymm4                   \n"
5726
0
      "vmovdqu     0x20(%0),%%ymm5               \n"
5727
0
      "vmovdqu     0x40(%0),%%ymm6               \n"
5728
0
      "lea         0x60(%0),%0                   \n"
5729
0
      "vpblendd    $240, %%ymm5, %%ymm4, %%ymm1  \n"
5730
0
      "vperm2i128  $33, %%ymm6, %%ymm4, %%ymm2   \n"
5731
0
      "vpblendd    $240, %%ymm6, %%ymm5, %%ymm3  \n"
5732
0
      "vpblendvb   %%ymm0, %%ymm3, %%ymm1, %%ymm4 \n"
5733
0
      "vpblendvb   %%ymm0, %%ymm1, %%ymm2, %%ymm5 \n"
5734
0
      "vpblendvb   %%ymm0, %%ymm2, %%ymm3, %%ymm6 \n"
5735
0
      "vpblendvb   %%ymm7, %%ymm5, %%ymm4, %%ymm1 \n"
5736
0
      "vpblendvb   %%ymm7, %%ymm6, %%ymm5, %%ymm2 \n"
5737
0
      "vpblendvb   %%ymm7, %%ymm4, %%ymm6, %%ymm3 \n"
5738
0
#if defined(__x86_64__)
5739
0
      "vpshufb     %%ymm8, %%ymm1, %%ymm1        \n"
5740
0
      "vpshufb     %%ymm9, %%ymm2, %%ymm2        \n"
5741
0
      "vpshufb     %%ymm10, %%ymm3, %%ymm3       \n"
5742
#else
5743
      "vbroadcasti128 0(%5), %%ymm4              \n"
5744
      "vbroadcasti128 16(%5), %%ymm5             \n"
5745
      "vbroadcasti128 32(%5), %%ymm6             \n"
5746
      "vpshufb     %%ymm4, %%ymm1, %%ymm1        \n"
5747
      "vpshufb     %%ymm5, %%ymm2, %%ymm2        \n"
5748
      "vpshufb     %%ymm6, %%ymm3, %%ymm3        \n"
5749
#endif
5750
0
      "vmovdqu     %%ymm1,(%1)                   \n"
5751
0
      "lea         0x20(%1),%1                   \n"
5752
0
      "vmovdqu     %%ymm2,(%2)                   \n"
5753
0
      "lea         0x20(%2),%2                   \n"
5754
0
      "vmovdqu     %%ymm3,(%3)                   \n"
5755
0
      "lea         0x20(%3),%3                   \n"
5756
0
      "sub         $0x20,%4                      \n"
5757
0
      "jg          1b                            \n"
5758
0
      : "+r"(src_rgb),                  // %0
5759
0
        "+r"(dst_r),                    // %1
5760
0
        "+r"(dst_g),                    // %2
5761
0
        "+r"(dst_b),                    // %3
5762
0
        "+r"(width)                     // %4
5763
0
      : "r"(&kSplitRGBShuffleSSE41[0])  // %5
5764
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
5765
0
        "xmm7"
5766
0
#if defined(__x86_64__)
5767
0
        ,
5768
0
        "xmm8", "xmm9", "xmm10"
5769
0
#endif
5770
0
  );
5771
0
}
5772
#endif  // HAS_SPLITRGBROW_AVX2
5773
5774
#ifdef HAS_MERGERGBROW_SSSE3
5775
// Shuffle table for converting Planar to RGB.
5776
static const uvec8 kMergeRGBShuffle[9] = {
5777
    {0u, 128u, 128u, 1u, 128u, 128u, 2u, 128u, 128u, 3u, 128u, 128u, 4u, 128u,
5778
     128u, 5u},
5779
    {128u, 0u, 128u, 128u, 1u, 128u, 128u, 2u, 128u, 128u, 3u, 128u, 128u, 4u,
5780
     128u, 128u},
5781
    {128u, 128u, 0u, 128u, 128u, 1u, 128u, 128u, 2u, 128u, 128u, 3u, 128u, 128u,
5782
     4u, 128u},
5783
    {128u, 128u, 6u, 128u, 128u, 7u, 128u, 128u, 8u, 128u, 128u, 9u, 128u, 128u,
5784
     10u, 128u},
5785
    {5u, 128u, 128u, 6u, 128u, 128u, 7u, 128u, 128u, 8u, 128u, 128u, 9u, 128u,
5786
     128u, 10u},
5787
    {128u, 5u, 128u, 128u, 6u, 128u, 128u, 7u, 128u, 128u, 8u, 128u, 128u, 9u,
5788
     128u, 128u},
5789
    {128u, 11u, 128u, 128u, 12u, 128u, 128u, 13u, 128u, 128u, 14u, 128u, 128u,
5790
     15u, 128u, 128u},
5791
    {128u, 128u, 11u, 128u, 128u, 12u, 128u, 128u, 13u, 128u, 128u, 14u, 128u,
5792
     128u, 15u, 128u},
5793
    {10u, 128u, 128u, 11u, 128u, 128u, 12u, 128u, 128u, 13u, 128u, 128u, 14u,
5794
     128u, 128u, 15u}};
5795
5796
void MergeRGBRow_SSSE3(const uint8_t* src_r,
5797
                       const uint8_t* src_g,
5798
                       const uint8_t* src_b,
5799
                       uint8_t* dst_rgb,
5800
0
                       int width) {
5801
0
  asm volatile(
5802
0
      "1:          \n"
5803
0
      "movdqu      (%0),%%xmm0                   \n"
5804
0
      "movdqu      (%1),%%xmm1                   \n"
5805
0
      "movdqu      (%2),%%xmm2                   \n"
5806
0
      "pshufb      (%5), %%xmm0                  \n"
5807
0
      "pshufb      16(%5), %%xmm1                \n"
5808
0
      "pshufb      32(%5), %%xmm2                \n"
5809
0
      "por         %%xmm1,%%xmm0                 \n"
5810
0
      "por         %%xmm2,%%xmm0                 \n"
5811
0
      "movdqu      %%xmm0,(%3)                   \n"
5812
5813
0
      "movdqu      (%0),%%xmm0                   \n"
5814
0
      "movdqu      (%1),%%xmm1                   \n"
5815
0
      "movdqu      (%2),%%xmm2                   \n"
5816
0
      "pshufb      48(%5), %%xmm0                \n"
5817
0
      "pshufb      64(%5), %%xmm1                \n"
5818
0
      "pshufb      80(%5), %%xmm2                \n"
5819
0
      "por         %%xmm1,%%xmm0                 \n"
5820
0
      "por         %%xmm2,%%xmm0                 \n"
5821
0
      "movdqu      %%xmm0,16(%3)                 \n"
5822
5823
0
      "movdqu      (%0),%%xmm0                   \n"
5824
0
      "movdqu      (%1),%%xmm1                   \n"
5825
0
      "movdqu      (%2),%%xmm2                   \n"
5826
0
      "pshufb      96(%5), %%xmm0                \n"
5827
0
      "pshufb      112(%5), %%xmm1               \n"
5828
0
      "pshufb      128(%5), %%xmm2               \n"
5829
0
      "por         %%xmm1,%%xmm0                 \n"
5830
0
      "por         %%xmm2,%%xmm0                 \n"
5831
0
      "movdqu      %%xmm0,32(%3)                 \n"
5832
5833
0
      "lea         0x10(%0),%0                   \n"
5834
0
      "lea         0x10(%1),%1                   \n"
5835
0
      "lea         0x10(%2),%2                   \n"
5836
0
      "lea         0x30(%3),%3                   \n"
5837
0
      "sub         $0x10,%4                      \n"
5838
0
      "jg          1b                            \n"
5839
0
      : "+r"(src_r),               // %0
5840
0
        "+r"(src_g),               // %1
5841
0
        "+r"(src_b),               // %2
5842
0
        "+r"(dst_rgb),             // %3
5843
0
        "+r"(width)                // %4
5844
0
      : "r"(&kMergeRGBShuffle[0])  // %5
5845
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
5846
0
}
5847
#endif  // HAS_MERGERGBROW_SSSE3
5848
5849
#ifdef HAS_MERGEARGBROW_SSE2
5850
void MergeARGBRow_SSE2(const uint8_t* src_r,
5851
                       const uint8_t* src_g,
5852
                       const uint8_t* src_b,
5853
                       const uint8_t* src_a,
5854
                       uint8_t* dst_argb,
5855
0
                       int width) {
5856
0
  asm volatile(
5857
0
      "sub         %0,%1                         \n"
5858
0
      "sub         %0,%2                         \n"
5859
0
      "sub         %0,%3                         \n"
5860
5861
0
      LABELALIGN
5862
0
      "1:          \n"
5863
5864
0
      "movq        (%0,%2),%%xmm0                \n"  // B
5865
0
      "movq        (%0),%%xmm1                   \n"  // R
5866
0
      "movq        (%0,%1),%%xmm2                \n"  // G
5867
0
      "punpcklbw   %%xmm1,%%xmm0                 \n"  // BR
5868
0
      "movq        (%0,%3),%%xmm1                \n"  // A
5869
0
      "punpcklbw   %%xmm1,%%xmm2                 \n"  // GA
5870
0
      "movdqa      %%xmm0,%%xmm1                 \n"  // BR
5871
0
      "punpckhbw   %%xmm2,%%xmm1                 \n"  // BGRA (hi)
5872
0
      "punpcklbw   %%xmm2,%%xmm0                 \n"  // BGRA (lo)
5873
0
      "movdqu      %%xmm0,(%4)                   \n"
5874
0
      "movdqu      %%xmm1,16(%4)                 \n"
5875
5876
0
      "lea         8(%0),%0                      \n"
5877
0
      "lea         32(%4),%4                     \n"
5878
0
      "sub         $0x8,%5                       \n"
5879
0
      "jg          1b                            \n"
5880
0
      : "+r"(src_r),     // %0
5881
0
        "+r"(src_g),     // %1
5882
0
        "+r"(src_b),     // %2
5883
0
        "+r"(src_a),     // %3
5884
0
        "+r"(dst_argb),  // %4
5885
0
        "+r"(width)      // %5
5886
0
      :
5887
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
5888
0
}
5889
#endif
5890
5891
#ifdef HAS_MERGEXRGBROW_SSE2
5892
void MergeXRGBRow_SSE2(const uint8_t* src_r,
5893
                       const uint8_t* src_g,
5894
                       const uint8_t* src_b,
5895
                       uint8_t* dst_argb,
5896
0
                       int width) {
5897
0
  asm volatile(
5898
0
      "1:          \n"
5899
5900
0
      "movq        (%2),%%xmm0                   \n"  // B
5901
0
      "movq        (%0),%%xmm1                   \n"  // R
5902
0
      "movq        (%1),%%xmm2                   \n"  // G
5903
0
      "punpcklbw   %%xmm1,%%xmm0                 \n"  // BR
5904
0
      "pcmpeqd     %%xmm1,%%xmm1                 \n"  // A(255)
5905
0
      "punpcklbw   %%xmm1,%%xmm2                 \n"  // GA
5906
0
      "movdqa      %%xmm0,%%xmm1                 \n"  // BR
5907
0
      "punpckhbw   %%xmm2,%%xmm1                 \n"  // BGRA (hi)
5908
0
      "punpcklbw   %%xmm2,%%xmm0                 \n"  // BGRA (lo)
5909
0
      "movdqu      %%xmm0,(%3)                   \n"
5910
0
      "movdqu      %%xmm1,16(%3)                 \n"
5911
5912
0
      "lea         8(%0),%0                      \n"
5913
0
      "lea         8(%1),%1                      \n"
5914
0
      "lea         8(%2),%2                      \n"
5915
0
      "lea         32(%3),%3                     \n"
5916
0
      "sub         $0x8,%4                       \n"
5917
0
      "jg          1b                            \n"
5918
0
      : "+r"(src_r),     // %0
5919
0
        "+r"(src_g),     // %1
5920
0
        "+r"(src_b),     // %2
5921
0
        "+r"(dst_argb),  // %3
5922
0
        "+r"(width)      // %4
5923
0
      :
5924
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
5925
0
}
5926
#endif  // HAS_MERGEARGBROW_SSE2
5927
5928
#ifdef HAS_MERGEARGBROW_AVX2
5929
void MergeARGBRow_AVX2(const uint8_t* src_r,
5930
                       const uint8_t* src_g,
5931
                       const uint8_t* src_b,
5932
                       const uint8_t* src_a,
5933
                       uint8_t* dst_argb,
5934
0
                       int width) {
5935
0
  asm volatile(
5936
0
      "sub         %0,%1                         \n"
5937
0
      "sub         %0,%2                         \n"
5938
0
      "sub         %0,%3                         \n"
5939
5940
0
      LABELALIGN
5941
0
      "1:          \n"
5942
5943
0
      "vmovdqu     (%0,%2),%%xmm0                \n"  // B
5944
0
      "vmovdqu     (%0,%1),%%xmm1                \n"  // R
5945
0
      "vinserti128 $1,(%0),%%ymm0,%%ymm0         \n"  // G
5946
0
      "vinserti128 $1,(%0,%3),%%ymm1,%%ymm1      \n"  // A
5947
0
      "vpunpckhbw  %%ymm1,%%ymm0,%%ymm2          \n"
5948
0
      "vpunpcklbw  %%ymm1,%%ymm0,%%ymm0          \n"
5949
0
      "vperm2i128  $0x31,%%ymm2,%%ymm0,%%ymm1    \n"
5950
0
      "vperm2i128  $0x20,%%ymm2,%%ymm0,%%ymm0    \n"
5951
0
      "vpunpckhwd  %%ymm1,%%ymm0,%%ymm2          \n"
5952
0
      "vpunpcklwd  %%ymm1,%%ymm0,%%ymm0          \n"
5953
0
      "vperm2i128  $0x31,%%ymm2,%%ymm0,%%ymm1    \n"
5954
0
      "vperm2i128  $0x20,%%ymm2,%%ymm0,%%ymm0    \n"
5955
0
      "vmovdqu     %%ymm0,(%4)                   \n"  // First 8
5956
0
      "vmovdqu     %%ymm1,32(%4)                 \n"  // Next 8
5957
5958
0
      "lea         16(%0),%0                     \n"
5959
0
      "lea         64(%4),%4                     \n"
5960
0
      "sub         $0x10,%5                      \n"
5961
0
      "jg          1b                            \n"
5962
0
      "vzeroupper  \n"
5963
0
      : "+r"(src_r),     // %0
5964
0
        "+r"(src_g),     // %1
5965
0
        "+r"(src_b),     // %2
5966
0
        "+r"(src_a),     // %3
5967
0
        "+r"(dst_argb),  // %4
5968
0
        "+r"(width)      // %5
5969
0
      :
5970
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
5971
0
}
5972
#endif
5973
5974
#ifdef HAS_MERGEXRGBROW_AVX2
5975
void MergeXRGBRow_AVX2(const uint8_t* src_r,
5976
                       const uint8_t* src_g,
5977
                       const uint8_t* src_b,
5978
                       uint8_t* dst_argb,
5979
0
                       int width) {
5980
0
  asm volatile(
5981
0
      "1:          \n"
5982
5983
0
      "vmovdqu     (%2),%%xmm0                   \n"  // B
5984
0
      "vpcmpeqb    %%ymm1,%%ymm1,%%ymm1          \n"  // A(255)
5985
0
      "vinserti128 $0,(%1),%%ymm1,%%ymm1         \n"  // R
5986
0
      "vinserti128 $1,(%0),%%ymm0,%%ymm0         \n"  // G
5987
0
      "vpunpckhbw  %%ymm1,%%ymm0,%%ymm2          \n"
5988
0
      "vpunpcklbw  %%ymm1,%%ymm0,%%ymm0          \n"
5989
0
      "vperm2i128  $0x31,%%ymm2,%%ymm0,%%ymm1    \n"
5990
0
      "vperm2i128  $0x20,%%ymm2,%%ymm0,%%ymm0    \n"
5991
0
      "vpunpckhwd  %%ymm1,%%ymm0,%%ymm2          \n"
5992
0
      "vpunpcklwd  %%ymm1,%%ymm0,%%ymm0          \n"
5993
0
      "vperm2i128  $0x31,%%ymm2,%%ymm0,%%ymm1    \n"
5994
0
      "vperm2i128  $0x20,%%ymm2,%%ymm0,%%ymm0    \n"
5995
0
      "vmovdqu     %%ymm0,(%3)                   \n"  // First 8
5996
0
      "vmovdqu     %%ymm1,32(%3)                 \n"  // Next 8
5997
5998
0
      "lea         16(%0),%0                     \n"
5999
0
      "lea         16(%1),%1                     \n"
6000
0
      "lea         16(%2),%2                     \n"
6001
0
      "lea         64(%3),%3                     \n"
6002
0
      "sub         $0x10,%4                      \n"
6003
0
      "jg          1b                            \n"
6004
0
      "vzeroupper  \n"
6005
0
      : "+r"(src_r),     // %0
6006
0
        "+r"(src_g),     // %1
6007
0
        "+r"(src_b),     // %2
6008
0
        "+r"(dst_argb),  // %3
6009
0
        "+rm"(width)     // %4
6010
0
        ::"memory",
6011
0
        "cc", "xmm0", "xmm1", "xmm2");
6012
0
}
6013
#endif  // HAS_MERGEARGBROW_AVX2
6014
6015
#ifdef HAS_SPLITARGBROW_SSE2
6016
void SplitARGBRow_SSE2(const uint8_t* src_argb,
6017
                       uint8_t* dst_r,
6018
                       uint8_t* dst_g,
6019
                       uint8_t* dst_b,
6020
                       uint8_t* dst_a,
6021
0
                       int width) {
6022
0
  asm volatile(
6023
0
      "sub         %1,%2                         \n"
6024
0
      "sub         %1,%3                         \n"
6025
0
      "sub         %1,%4                         \n"
6026
6027
0
      LABELALIGN
6028
0
      "1:          \n"
6029
6030
0
      "movdqu      (%0),%%xmm0                   \n"  // 00-0F
6031
0
      "movdqu      16(%0),%%xmm1                 \n"  // 10-1F
6032
0
      "movdqa      %%xmm0,%%xmm2                 \n"
6033
0
      "punpcklqdq  %%xmm1,%%xmm0                 \n"  // 00-07 10-17
6034
0
      "punpckhqdq  %%xmm1,%%xmm2                 \n"  // 08-0F 18-1F
6035
0
      "movdqa      %%xmm0,%%xmm1                 \n"
6036
0
      "punpcklbw   %%xmm2,%%xmm0                 \n"  // 08192A3B4C5D6E7F (lo)
6037
0
      "punpckhbw   %%xmm2,%%xmm1                 \n"  // 08192A3B4C5D6E7F (hi)
6038
0
      "movdqa      %%xmm0,%%xmm2                 \n"
6039
0
      "punpcklqdq  %%xmm1,%%xmm0                 \n"  // 08192A3B08192A3B
6040
0
      "punpckhqdq  %%xmm1,%%xmm2                 \n"  // 4C5D6E7F4C5D6E7F
6041
0
      "movdqa      %%xmm0,%%xmm1                 \n"
6042
0
      "punpcklbw   %%xmm2,%%xmm0                 \n"  // 048C159D26AE37BF (lo)
6043
0
      "punpckhbw   %%xmm2,%%xmm1                 \n"  // 048C159D26AE37BF (hi)
6044
0
      "movdqa      %%xmm0,%%xmm2                 \n"
6045
0
      "punpckldq   %%xmm1,%%xmm0                 \n"  // 048C048C159D159D (BG)
6046
0
      "punpckhdq   %%xmm1,%%xmm2                 \n"  // 26AE26AE37BF37BF (RA)
6047
0
      "movlps      %%xmm0,(%1,%3)                \n"  // B
6048
0
      "movhps      %%xmm0,(%1,%2)                \n"  // G
6049
0
      "movlps      %%xmm2,(%1)                   \n"  // R
6050
0
      "movhps      %%xmm2,(%1,%4)                \n"  // A
6051
6052
0
      "lea         32(%0),%0                     \n"
6053
0
      "lea         8(%1),%1                      \n"
6054
0
      "sub         $0x8,%5                       \n"
6055
0
      "jg          1b                            \n"
6056
0
      : "+r"(src_argb),  // %0
6057
0
        "+r"(dst_r),     // %1
6058
0
        "+r"(dst_g),     // %2
6059
0
        "+r"(dst_b),     // %3
6060
0
        "+r"(dst_a),     // %4
6061
0
        "+rm"(width)     // %5
6062
0
      :
6063
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
6064
0
}
6065
#endif
6066
6067
#ifdef HAS_SPLITXRGBROW_SSE2
6068
void SplitXRGBRow_SSE2(const uint8_t* src_argb,
6069
                       uint8_t* dst_r,
6070
                       uint8_t* dst_g,
6071
                       uint8_t* dst_b,
6072
0
                       int width) {
6073
0
  asm volatile(
6074
0
      "1:          \n"
6075
6076
0
      "movdqu      (%0),%%xmm0                   \n"  // 00-0F
6077
0
      "movdqu      16(%0),%%xmm1                 \n"  // 10-1F
6078
0
      "movdqa      %%xmm0,%%xmm2                 \n"
6079
0
      "punpcklqdq  %%xmm1,%%xmm0                 \n"  // 00-07 10-17
6080
0
      "punpckhqdq  %%xmm1,%%xmm2                 \n"  // 08-0F 18-1F
6081
0
      "movdqa      %%xmm0,%%xmm1                 \n"
6082
0
      "punpcklbw   %%xmm2,%%xmm0                 \n"  // 08192A3B4C5D6E7F (lo)
6083
0
      "punpckhbw   %%xmm2,%%xmm1                 \n"  // 08192A3B4C5D6E7F (hi)
6084
0
      "movdqa      %%xmm0,%%xmm2                 \n"
6085
0
      "punpcklqdq  %%xmm1,%%xmm0                 \n"  // 08192A3B08192A3B
6086
0
      "punpckhqdq  %%xmm1,%%xmm2                 \n"  // 4C5D6E7F4C5D6E7F
6087
0
      "movdqa      %%xmm0,%%xmm1                 \n"
6088
0
      "punpcklbw   %%xmm2,%%xmm0                 \n"  // 048C159D26AE37BF (lo)
6089
0
      "punpckhbw   %%xmm2,%%xmm1                 \n"  // 048C159D26AE37BF (hi)
6090
0
      "movdqa      %%xmm0,%%xmm2                 \n"
6091
0
      "punpckldq   %%xmm1,%%xmm0                 \n"  // 048C048C159D159D (BG)
6092
0
      "punpckhdq   %%xmm1,%%xmm2                 \n"  // 26AE26AE37BF37BF (RA)
6093
0
      "movlps      %%xmm0,(%3)                   \n"  // B
6094
0
      "movhps      %%xmm0,(%2)                   \n"  // G
6095
0
      "movlps      %%xmm2,(%1)                   \n"  // R
6096
6097
0
      "lea         32(%0),%0                     \n"
6098
0
      "lea         8(%1),%1                      \n"
6099
0
      "lea         8(%2),%2                      \n"
6100
0
      "lea         8(%3),%3                      \n"
6101
0
      "sub         $0x8,%4                       \n"
6102
0
      "jg          1b                            \n"
6103
0
      : "+r"(src_argb),  // %0
6104
0
        "+r"(dst_r),     // %1
6105
0
        "+r"(dst_g),     // %2
6106
0
        "+r"(dst_b),     // %3
6107
0
        "+rm"(width)     // %4
6108
0
      :
6109
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
6110
0
}
6111
#endif
6112
6113
static const uvec8 kShuffleMaskARGBSplit = {0, 4, 8,  12, 1, 5, 9,  13,
6114
                                            2, 6, 10, 14, 3, 7, 11, 15};
6115
#ifdef HAS_SPLITARGBROW_SSSE3
6116
void SplitARGBRow_SSSE3(const uint8_t* src_argb,
6117
                        uint8_t* dst_r,
6118
                        uint8_t* dst_g,
6119
                        uint8_t* dst_b,
6120
                        uint8_t* dst_a,
6121
0
                        int width) {
6122
0
  asm volatile(
6123
0
      "movdqa      %6,%%xmm3                     \n"
6124
0
      "sub         %1,%2                         \n"
6125
0
      "sub         %1,%3                         \n"
6126
0
      "sub         %1,%4                         \n"
6127
6128
0
      LABELALIGN
6129
0
      "1:          \n"
6130
6131
0
      "movdqu      (%0),%%xmm0                   \n"  // 00-0F
6132
0
      "movdqu      16(%0),%%xmm1                 \n"  // 10-1F
6133
0
      "pshufb      %%xmm3,%%xmm0                 \n"  // 048C159D26AE37BF (lo)
6134
0
      "pshufb      %%xmm3,%%xmm1                 \n"  // 048C159D26AE37BF (hi)
6135
0
      "movdqa      %%xmm0,%%xmm2                 \n"
6136
0
      "punpckldq   %%xmm1,%%xmm0                 \n"  // 048C048C159D159D (BG)
6137
0
      "punpckhdq   %%xmm1,%%xmm2                 \n"  // 26AE26AE37BF37BF (RA)
6138
0
      "movlps      %%xmm0,(%1,%3)                \n"  // B
6139
0
      "movhps      %%xmm0,(%1,%2)                \n"  // G
6140
0
      "movlps      %%xmm2,(%1)                   \n"  // R
6141
0
      "movhps      %%xmm2,(%1,%4)                \n"  // A
6142
6143
0
      "lea         32(%0),%0                     \n"
6144
0
      "lea         8(%1),%1                      \n"
6145
0
      "subl        $0x8,%5                       \n"
6146
0
      "jg          1b                            \n"
6147
0
      : "+r"(src_argb),  // %0
6148
0
        "+r"(dst_r),     // %1
6149
0
        "+r"(dst_g),     // %2
6150
0
        "+r"(dst_b),     // %3
6151
0
        "+r"(dst_a),     // %4
6152
#if defined(__i386__)
6153
        "+m"(width)  // %5
6154
#else
6155
0
        "+rm"(width)  // %5
6156
0
#endif
6157
0
      : "m"(kShuffleMaskARGBSplit)  // %6
6158
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3");
6159
0
}
6160
#endif
6161
6162
#ifdef HAS_SPLITXRGBROW_SSSE3
6163
void SplitXRGBRow_SSSE3(const uint8_t* src_argb,
6164
                        uint8_t* dst_r,
6165
                        uint8_t* dst_g,
6166
                        uint8_t* dst_b,
6167
0
                        int width) {
6168
0
  asm volatile(
6169
0
      "movdqa      %5,%%xmm3                     \n"
6170
6171
0
      LABELALIGN
6172
0
      "1:          \n"
6173
6174
0
      "movdqu      (%0),%%xmm0                   \n"  // 00-0F
6175
0
      "movdqu      16(%0),%%xmm1                 \n"  // 10-1F
6176
0
      "pshufb      %%xmm3,%%xmm0                 \n"  // 048C159D26AE37BF (lo)
6177
0
      "pshufb      %%xmm3,%%xmm1                 \n"  // 048C159D26AE37BF (hi)
6178
0
      "movdqa      %%xmm0,%%xmm2                 \n"
6179
0
      "punpckldq   %%xmm1,%%xmm0                 \n"  // 048C048C159D159D (BG)
6180
0
      "punpckhdq   %%xmm1,%%xmm2                 \n"  // 26AE26AE37BF37BF (RA)
6181
0
      "movlps      %%xmm0,(%3)                   \n"  // B
6182
0
      "movhps      %%xmm0,(%2)                   \n"  // G
6183
0
      "movlps      %%xmm2,(%1)                   \n"  // R
6184
6185
0
      "lea         32(%0),%0                     \n"
6186
0
      "lea         8(%1),%1                      \n"
6187
0
      "lea         8(%2),%2                      \n"
6188
0
      "lea         8(%3),%3                      \n"
6189
0
      "sub         $0x8,%4                       \n"
6190
0
      "jg          1b                            \n"
6191
0
      : "+r"(src_argb),             // %0
6192
0
        "+r"(dst_r),                // %1
6193
0
        "+r"(dst_g),                // %2
6194
0
        "+r"(dst_b),                // %3
6195
0
        "+r"(width)                 // %4
6196
0
      : "m"(kShuffleMaskARGBSplit)  // %5
6197
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3");
6198
0
}
6199
#endif
6200
6201
#ifdef HAS_SPLITARGBROW_AVX2
6202
static const ulvec32 kShuffleMaskARGBPermute = {0, 4, 1, 5, 2, 6, 3, 7};
6203
void SplitARGBRow_AVX2(const uint8_t* src_argb,
6204
                       uint8_t* dst_r,
6205
                       uint8_t* dst_g,
6206
                       uint8_t* dst_b,
6207
                       uint8_t* dst_a,
6208
0
                       int width) {
6209
0
  asm volatile(
6210
0
      "sub         %1,%2                         \n"
6211
0
      "sub         %1,%3                         \n"
6212
0
      "sub         %1,%4                         \n"
6213
0
      "vmovdqa     %7,%%ymm3                     \n"
6214
0
      "vbroadcasti128 %6,%%ymm4                  \n"
6215
6216
0
      LABELALIGN
6217
0
      "1:          \n"
6218
6219
0
      "vmovdqu     (%0),%%xmm0                   \n"  // 00-0F
6220
0
      "vmovdqu     16(%0),%%xmm1                 \n"  // 10-1F
6221
0
      "vinserti128 $1,32(%0),%%ymm0,%%ymm0       \n"  // 00-0F 20-2F
6222
0
      "vinserti128 $1,48(%0),%%ymm1,%%ymm1       \n"  // 10-1F 30-3F
6223
0
      "vpshufb     %%ymm4,%%ymm0,%%ymm0          \n"
6224
0
      "vpshufb     %%ymm4,%%ymm1,%%ymm1          \n"
6225
0
      "vpermd      %%ymm0,%%ymm3,%%ymm0          \n"
6226
0
      "vpermd      %%ymm1,%%ymm3,%%ymm1          \n"
6227
0
      "vpunpckhdq  %%ymm1,%%ymm0,%%ymm2          \n"  // GA
6228
0
      "vpunpckldq  %%ymm1,%%ymm0,%%ymm0          \n"  // BR
6229
0
      "vmovdqu     %%xmm0,(%1,%3)                \n"  // B
6230
0
      "vextracti128 $1,%%ymm0,(%1)               \n"  // R
6231
0
      "vmovdqu     %%xmm2,(%1,%2)                \n"  // G
6232
0
      "vextracti128 $1,%%ymm2,(%1,%4)            \n"  // A
6233
0
      "lea         64(%0),%0                     \n"
6234
0
      "lea         16(%1),%1                     \n"
6235
0
      "subl        $0x10,%5                      \n"
6236
0
      "jg          1b                            \n"
6237
0
      "vzeroupper  \n"
6238
0
      : "+r"(src_argb),  // %0
6239
0
        "+r"(dst_r),     // %1
6240
0
        "+r"(dst_g),     // %2
6241
0
        "+r"(dst_b),     // %3
6242
0
        "+r"(dst_a),     // %4
6243
#if defined(__i386__)
6244
        "+m"(width)  // %5
6245
#else
6246
0
        "+rm"(width)  // %5
6247
0
#endif
6248
0
      : "m"(kShuffleMaskARGBSplit),   // %6
6249
0
        "m"(kShuffleMaskARGBPermute)  // %7
6250
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4");
6251
0
}
6252
#endif
6253
6254
#ifdef HAS_SPLITXRGBROW_AVX2
6255
void SplitXRGBRow_AVX2(const uint8_t* src_argb,
6256
                       uint8_t* dst_r,
6257
                       uint8_t* dst_g,
6258
                       uint8_t* dst_b,
6259
0
                       int width) {
6260
0
  asm volatile(
6261
0
      "vmovdqa     %6,%%ymm3                     \n"
6262
0
      "vbroadcasti128 %5,%%ymm4                  \n"
6263
6264
0
      LABELALIGN
6265
0
      "1:          \n"
6266
6267
0
      "vmovdqu     (%0),%%xmm0                   \n"  // 00-0F
6268
0
      "vmovdqu     16(%0),%%xmm1                 \n"  // 10-1F
6269
0
      "vinserti128 $1,32(%0),%%ymm0,%%ymm0       \n"  // 00-0F 20-2F
6270
0
      "vinserti128 $1,48(%0),%%ymm1,%%ymm1       \n"  // 10-1F 30-3F
6271
0
      "vpshufb     %%ymm4,%%ymm0,%%ymm0          \n"
6272
0
      "vpshufb     %%ymm4,%%ymm1,%%ymm1          \n"
6273
0
      "vpermd      %%ymm0,%%ymm3,%%ymm0          \n"
6274
0
      "vpermd      %%ymm1,%%ymm3,%%ymm1          \n"
6275
0
      "vpunpckhdq  %%ymm1,%%ymm0,%%ymm2          \n"  // GA
6276
0
      "vpunpckldq  %%ymm1,%%ymm0,%%ymm0          \n"  // BR
6277
0
      "vmovdqu     %%xmm0,(%3)                   \n"  // B
6278
0
      "vextracti128 $1,%%ymm0,(%1)               \n"  // R
6279
0
      "vmovdqu     %%xmm2,(%2)                   \n"  // G
6280
6281
0
      "lea         64(%0),%0                     \n"
6282
0
      "lea         16(%1),%1                     \n"
6283
0
      "lea         16(%2),%2                     \n"
6284
0
      "lea         16(%3),%3                     \n"
6285
0
      "sub         $0x10,%4                      \n"
6286
0
      "jg          1b                            \n"
6287
0
      "vzeroupper  \n"
6288
0
      : "+r"(src_argb),               // %0
6289
0
        "+r"(dst_r),                  // %1
6290
0
        "+r"(dst_g),                  // %2
6291
0
        "+r"(dst_b),                  // %3
6292
0
        "+r"(width)                   // %4
6293
0
      : "m"(kShuffleMaskARGBSplit),   // %5
6294
0
        "m"(kShuffleMaskARGBPermute)  // %6
6295
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4");
6296
0
}
6297
#endif
6298
6299
#ifdef HAS_MERGEXR30ROW_AVX2
6300
void MergeXR30Row_AVX2(const uint16_t* src_r,
6301
                       const uint16_t* src_g,
6302
                       const uint16_t* src_b,
6303
                       uint8_t* dst_ar30,
6304
                       int depth,
6305
0
                       int width) {
6306
0
  int shift = depth - 10;
6307
0
  asm volatile(
6308
0
      "sub         %0,%1                         \n"
6309
0
      "sub         %0,%2                         \n"
6310
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"  // AR30 constants
6311
0
      "vpsrlw      $14,%%ymm5,%%ymm5             \n"
6312
0
      "vpsllw      $4,%%ymm5,%%ymm5              \n"  // 2 alpha bits
6313
0
      "vpcmpeqb    %%ymm6,%%ymm6,%%ymm6          \n"
6314
0
      "vpsrlw      $6,%%ymm6,%%ymm6              \n"
6315
0
      "vmovd       %5,%%xmm4                     \n"
6316
6317
0
      LABELALIGN
6318
0
      "1:          \n"
6319
0
      "vmovdqu     (%0),%%ymm0                   \n"
6320
0
      "vmovdqu     (%0,%1),%%ymm1                \n"
6321
0
      "vmovdqu     (%0,%2),%%ymm2                \n"
6322
0
      "vpsrlw      %%xmm4,%%ymm0,%%ymm0          \n"
6323
0
      "vpsrlw      %%xmm4,%%ymm1,%%ymm1          \n"
6324
0
      "vpsrlw      %%xmm4,%%ymm2,%%ymm2          \n"
6325
0
      "vpminuw     %%ymm0,%%ymm6,%%ymm0          \n"
6326
0
      "vpminuw     %%ymm1,%%ymm6,%%ymm1          \n"
6327
0
      "vpminuw     %%ymm2,%%ymm6,%%ymm2          \n"
6328
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
6329
0
      "vpermq      $0xd8,%%ymm1,%%ymm1           \n"
6330
0
      "vpermq      $0xd8,%%ymm2,%%ymm2           \n"
6331
0
      "vpsllw      $0x4,%%ymm0,%%ymm0            \n"  // Shift R to target bit
6332
0
      "vpunpckhwd  %%ymm0,%%ymm2,%%ymm3          \n"  // RB
6333
0
      "vpunpcklwd  %%ymm0,%%ymm2,%%ymm0          \n"
6334
0
      "vpunpckhwd  %%ymm5,%%ymm1,%%ymm2          \n"  // AG
6335
0
      "vpunpcklwd  %%ymm5,%%ymm1,%%ymm1          \n"
6336
0
      "vpslld      $0xa,%%ymm1,%%ymm1            \n"  // Shift AG to target bit
6337
0
      "vpslld      $0xa,%%ymm2,%%ymm2            \n"
6338
0
      "vpor        %%ymm1,%%ymm0,%%ymm0          \n"  // Combine
6339
0
      "vpor        %%ymm2,%%ymm3,%%ymm3          \n"
6340
0
      "vmovdqu     %%ymm0,(%3)                   \n"
6341
0
      "vmovdqu     %%ymm3,0x20(%3)               \n"
6342
0
      "lea         0x20(%0),%0                   \n"
6343
0
      "lea         0x40(%3),%3                   \n"
6344
0
      "sub         $0x10,%4                      \n"
6345
0
      "jg          1b                            \n"
6346
0
      "vzeroupper  \n"
6347
0
      : "+r"(src_r),     // %0
6348
0
        "+r"(src_g),     // %1
6349
0
        "+r"(src_b),     // %2
6350
0
        "+r"(dst_ar30),  // %3
6351
0
        "+r"(width)      // %4
6352
#if defined(__i386__)
6353
      : "m"(shift)  // %5
6354
#else
6355
0
      : "rm"(shift)  // %5
6356
0
#endif
6357
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
6358
0
}
6359
#endif
6360
6361
#ifdef HAS_MERGEAR64ROW_AVX2
6362
static const lvec32 MergeAR64Permute = {0, 4, 2, 6, 1, 5, 3, 7};
6363
void MergeAR64Row_AVX2(const uint16_t* src_r,
6364
                       const uint16_t* src_g,
6365
                       const uint16_t* src_b,
6366
                       const uint16_t* src_a,
6367
                       uint16_t* dst_ar64,
6368
                       int depth,
6369
0
                       int width) {
6370
0
  int shift = 16 - depth;
6371
0
  int mask = (1 << depth) - 1;
6372
0
  mask = (mask << 16) + mask;
6373
0
  asm volatile(
6374
0
      "sub         %0,%1                         \n"
6375
0
      "sub         %0,%2                         \n"
6376
0
      "sub         %0,%3                         \n"
6377
0
      "vmovdqa     %8,%%ymm5                     \n"
6378
0
      "vmovd       %6,%%xmm6                     \n"
6379
0
      "vbroadcastss %7,%%ymm7                    \n"
6380
6381
0
      LABELALIGN
6382
0
      "1:          \n"
6383
0
      "vmovdqu     (%0),%%ymm0                   \n"  // R
6384
0
      "vmovdqu     (%0,%1),%%ymm1                \n"  // G
6385
0
      "vmovdqu     (%0,%2),%%ymm2                \n"  // B
6386
0
      "vmovdqu     (%0,%3),%%ymm3                \n"  // A
6387
0
      "vpminuw     %%ymm0,%%ymm7,%%ymm0          \n"
6388
0
      "vpminuw     %%ymm1,%%ymm7,%%ymm1          \n"
6389
0
      "vpminuw     %%ymm2,%%ymm7,%%ymm2          \n"
6390
0
      "vpminuw     %%ymm3,%%ymm7,%%ymm3          \n"
6391
0
      "vpsllw      %%xmm6,%%ymm0,%%ymm0          \n"
6392
0
      "vpsllw      %%xmm6,%%ymm1,%%ymm1          \n"
6393
0
      "vpsllw      %%xmm6,%%ymm2,%%ymm2          \n"
6394
0
      "vpsllw      %%xmm6,%%ymm3,%%ymm3          \n"
6395
0
      "vpermd      %%ymm0,%%ymm5,%%ymm0          \n"
6396
0
      "vpermd      %%ymm1,%%ymm5,%%ymm1          \n"
6397
0
      "vpermd      %%ymm2,%%ymm5,%%ymm2          \n"
6398
0
      "vpermd      %%ymm3,%%ymm5,%%ymm3          \n"
6399
0
      "vpunpcklwd  %%ymm1,%%ymm2,%%ymm4          \n"  // BG(low)
6400
0
      "vpunpckhwd  %%ymm1,%%ymm2,%%ymm1          \n"  // BG(hi)
6401
0
      "vpunpcklwd  %%ymm3,%%ymm0,%%ymm2          \n"  // RA(low)
6402
0
      "vpunpckhwd  %%ymm3,%%ymm0,%%ymm0          \n"  // RA(hi)
6403
0
      "vpunpckldq  %%ymm2,%%ymm4,%%ymm3          \n"  // BGRA(1)
6404
0
      "vpunpckhdq  %%ymm2,%%ymm4,%%ymm4          \n"  // BGRA(3)
6405
0
      "vpunpckldq  %%ymm0,%%ymm1,%%ymm2          \n"  // BGRA(2)
6406
0
      "vpunpckhdq  %%ymm0,%%ymm1,%%ymm1          \n"  // BGRA(4)
6407
0
      "vmovdqu     %%ymm3,(%4)                   \n"
6408
0
      "vmovdqu     %%ymm2,0x20(%4)               \n"
6409
0
      "vmovdqu     %%ymm4,0x40(%4)               \n"
6410
0
      "vmovdqu     %%ymm1,0x60(%4)               \n"
6411
0
      "lea         0x20(%0),%0                   \n"
6412
0
      "lea         0x80(%4),%4                   \n"
6413
0
      "subl        $0x10,%5                      \n"
6414
0
      "jg          1b                            \n"
6415
0
      "vzeroupper  \n"
6416
0
      : "+r"(src_r),     // %0
6417
0
        "+r"(src_g),     // %1
6418
0
        "+r"(src_b),     // %2
6419
0
        "+r"(src_a),     // %3
6420
0
        "+r"(dst_ar64),  // %4
6421
#if defined(__i386__)
6422
        "+m"(width)  // %5
6423
#else
6424
0
        "+rm"(width)  // %5
6425
0
#endif
6426
0
      : "m"(shift),            // %6
6427
0
        "m"(mask),             // %7
6428
0
        "m"(MergeAR64Permute)  // %8
6429
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
6430
0
        "xmm7");
6431
0
}
6432
#endif
6433
6434
#ifdef HAS_MERGEXR64ROW_AVX2
6435
void MergeXR64Row_AVX2(const uint16_t* src_r,
6436
                       const uint16_t* src_g,
6437
                       const uint16_t* src_b,
6438
                       uint16_t* dst_ar64,
6439
                       int depth,
6440
0
                       int width) {
6441
0
  int shift = 16 - depth;
6442
0
  int mask = (1 << depth) - 1;
6443
0
  mask = (mask << 16) + mask;
6444
0
  asm volatile(
6445
0
      "sub         %0,%1                         \n"
6446
0
      "sub         %0,%2                         \n"
6447
0
      "vmovdqa     %7,%%ymm5                     \n"
6448
0
      "vmovd       %5,%%xmm6                     \n"
6449
0
      "vbroadcastss %6,%%ymm7                    \n"
6450
6451
0
      LABELALIGN
6452
0
      "1:          \n"
6453
0
      "vmovdqu     (%0),%%ymm0                   \n"  // R
6454
0
      "vmovdqu     (%0,%1),%%ymm1                \n"  // G
6455
0
      "vmovdqu     (%0,%2),%%ymm2                \n"  // B
6456
0
      "vpminuw     %%ymm0,%%ymm7,%%ymm0          \n"
6457
0
      "vpminuw     %%ymm1,%%ymm7,%%ymm1          \n"
6458
0
      "vpminuw     %%ymm2,%%ymm7,%%ymm2          \n"
6459
0
      "vpsllw      %%xmm6,%%ymm0,%%ymm0          \n"
6460
0
      "vpsllw      %%xmm6,%%ymm1,%%ymm1          \n"
6461
0
      "vpsllw      %%xmm6,%%ymm2,%%ymm2          \n"
6462
0
      "vpermd      %%ymm0,%%ymm5,%%ymm0          \n"
6463
0
      "vpermd      %%ymm1,%%ymm5,%%ymm1          \n"
6464
0
      "vpermd      %%ymm2,%%ymm5,%%ymm2          \n"
6465
0
      "vpcmpeqb    %%ymm3,%%ymm3,%%ymm3          \n"  // A (0xffff)
6466
0
      "vpunpcklwd  %%ymm1,%%ymm2,%%ymm4          \n"  // BG(low)
6467
0
      "vpunpckhwd  %%ymm1,%%ymm2,%%ymm1          \n"  // BG(hi)
6468
0
      "vpunpcklwd  %%ymm3,%%ymm0,%%ymm2          \n"  // RA(low)
6469
0
      "vpunpckhwd  %%ymm3,%%ymm0,%%ymm0          \n"  // RA(hi)
6470
0
      "vpunpckldq  %%ymm2,%%ymm4,%%ymm3          \n"  // BGRA(1)
6471
0
      "vpunpckhdq  %%ymm2,%%ymm4,%%ymm4          \n"  // BGRA(3)
6472
0
      "vpunpckldq  %%ymm0,%%ymm1,%%ymm2          \n"  // BGRA(2)
6473
0
      "vpunpckhdq  %%ymm0,%%ymm1,%%ymm1          \n"  // BGRA(4)
6474
0
      "vmovdqu     %%ymm3,(%3)                   \n"
6475
0
      "vmovdqu     %%ymm2,0x20(%3)               \n"
6476
0
      "vmovdqu     %%ymm4,0x40(%3)               \n"
6477
0
      "vmovdqu     %%ymm1,0x60(%3)               \n"
6478
0
      "lea         0x20(%0),%0                   \n"
6479
0
      "lea         0x80(%3),%3                   \n"
6480
0
      "subl        $0x10,%4                      \n"
6481
0
      "jg          1b                            \n"
6482
0
      "vzeroupper  \n"
6483
0
      : "+r"(src_r),           // %0
6484
0
        "+r"(src_g),           // %1
6485
0
        "+r"(src_b),           // %2
6486
0
        "+r"(dst_ar64),        // %3
6487
0
        "+r"(width)            // %4
6488
0
      : "m"(shift),            // %5
6489
0
        "m"(mask),             // %6
6490
0
        "m"(MergeAR64Permute)  // %7
6491
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
6492
0
        "xmm7");
6493
0
}
6494
#endif
6495
6496
#ifdef HAS_MERGEARGB16TO8ROW_AVX2
6497
static const uvec8 MergeARGB16To8Shuffle = {0, 8,  1, 9,  2, 10, 3, 11,
6498
                                            4, 12, 5, 13, 6, 14, 7, 15};
6499
void MergeARGB16To8Row_AVX2(const uint16_t* src_r,
6500
                            const uint16_t* src_g,
6501
                            const uint16_t* src_b,
6502
                            const uint16_t* src_a,
6503
                            uint8_t* dst_argb,
6504
                            int depth,
6505
0
                            int width) {
6506
0
  int shift = depth - 8;
6507
0
  asm volatile(
6508
0
      "sub         %0,%1                         \n"
6509
0
      "sub         %0,%2                         \n"
6510
0
      "sub         %0,%3                         \n"
6511
0
      "vbroadcasti128 %7,%%ymm5                  \n"
6512
0
      "vmovd       %6,%%xmm6                     \n"
6513
6514
0
      LABELALIGN
6515
0
      "1:          \n"
6516
0
      "vmovdqu     (%0),%%ymm0                   \n"  // R
6517
0
      "vmovdqu     (%0,%1),%%ymm1                \n"  // G
6518
0
      "vmovdqu     (%0,%2),%%ymm2                \n"  // B
6519
0
      "vmovdqu     (%0,%3),%%ymm3                \n"  // A
6520
0
      "vpsrlw      %%xmm6,%%ymm0,%%ymm0          \n"
6521
0
      "vpsrlw      %%xmm6,%%ymm1,%%ymm1          \n"
6522
0
      "vpsrlw      %%xmm6,%%ymm2,%%ymm2          \n"
6523
0
      "vpsrlw      %%xmm6,%%ymm3,%%ymm3          \n"
6524
0
      "vpackuswb   %%ymm1,%%ymm2,%%ymm1          \n"  // BG (planar)
6525
0
      "vpackuswb   %%ymm3,%%ymm0,%%ymm0          \n"  // RA (planar)
6526
0
      "vpshufb     %%ymm5,%%ymm1,%%ymm1          \n"  // BG (interleave)
6527
0
      "vpshufb     %%ymm5,%%ymm0,%%ymm0          \n"  // RA (interleave)
6528
0
      "vpermq      $0xd8,%%ymm1,%%ymm1           \n"
6529
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
6530
0
      "vpunpcklwd  %%ymm0,%%ymm1,%%ymm2          \n"  // BGRA (low)
6531
0
      "vpunpckhwd  %%ymm0,%%ymm1,%%ymm0          \n"  // BGRA (hi)
6532
0
      "vmovdqu     %%ymm2,(%4)                   \n"
6533
0
      "vmovdqu     %%ymm0,0x20(%4)               \n"
6534
0
      "lea         0x20(%0),%0                   \n"
6535
0
      "lea         0x40(%4),%4                   \n"
6536
0
      "subl        $0x10,%5                      \n"
6537
0
      "jg          1b                            \n"
6538
0
      "vzeroupper  \n"
6539
0
      : "+r"(src_r),     // %0
6540
0
        "+r"(src_g),     // %1
6541
0
        "+r"(src_b),     // %2
6542
0
        "+r"(src_a),     // %3
6543
0
        "+r"(dst_argb),  // %4
6544
#if defined(__i386__)
6545
        "+m"(width)  // %5
6546
#else
6547
0
        "+rm"(width)  // %5
6548
0
#endif
6549
0
      : "m"(shift),                 // %6
6550
0
        "m"(MergeARGB16To8Shuffle)  // %7
6551
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
6552
0
}
6553
#endif
6554
6555
#ifdef HAS_MERGEXRGB16TO8ROW_AVX2
6556
void MergeXRGB16To8Row_AVX2(const uint16_t* src_r,
6557
                            const uint16_t* src_g,
6558
                            const uint16_t* src_b,
6559
                            uint8_t* dst_argb,
6560
                            int depth,
6561
0
                            int width) {
6562
0
  int shift = depth - 8;
6563
0
  asm volatile(
6564
0
      "sub         %0,%1                         \n"
6565
0
      "sub         %0,%2                         \n"
6566
0
      "vbroadcasti128 %6,%%ymm5                  \n"
6567
0
      "vmovd       %5,%%xmm6                     \n"
6568
0
      "vpcmpeqb    %%ymm3,%%ymm3,%%ymm3          \n"
6569
0
      "vpsrlw      $8,%%ymm3,%%ymm3              \n"  // A (0xff)
6570
6571
0
      LABELALIGN
6572
0
      "1:          \n"
6573
0
      "vmovdqu     (%0),%%ymm0                   \n"  // R
6574
0
      "vmovdqu     (%0,%1),%%ymm1                \n"  // G
6575
0
      "vmovdqu     (%0,%2),%%ymm2                \n"  // B
6576
0
      "vpsrlw      %%xmm6,%%ymm0,%%ymm0          \n"
6577
0
      "vpsrlw      %%xmm6,%%ymm1,%%ymm1          \n"
6578
0
      "vpsrlw      %%xmm6,%%ymm2,%%ymm2          \n"
6579
0
      "vpackuswb   %%ymm1,%%ymm2,%%ymm1          \n"  // BG (planar)
6580
0
      "vpackuswb   %%ymm3,%%ymm0,%%ymm0          \n"  // RA (planar)
6581
0
      "vpshufb     %%ymm5,%%ymm1,%%ymm1          \n"  // BG (interleave)
6582
0
      "vpshufb     %%ymm5,%%ymm0,%%ymm0          \n"  // RA (interleave)
6583
0
      "vpermq      $0xd8,%%ymm1,%%ymm1           \n"
6584
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
6585
0
      "vpunpcklwd  %%ymm0,%%ymm1,%%ymm2          \n"  // BGRA (low)
6586
0
      "vpunpckhwd  %%ymm0,%%ymm1,%%ymm0          \n"  // BGRA (hi)
6587
0
      "vmovdqu     %%ymm2,(%3)                   \n"
6588
0
      "vmovdqu     %%ymm0,0x20(%3)               \n"
6589
0
      "lea         0x20(%0),%0                   \n"
6590
0
      "lea         0x40(%3),%3                   \n"
6591
0
      "subl        $0x10,%4                      \n"
6592
0
      "jg          1b                            \n"
6593
0
      "vzeroupper  \n"
6594
0
      : "+r"(src_r),                // %0
6595
0
        "+r"(src_g),                // %1
6596
0
        "+r"(src_b),                // %2
6597
0
        "+r"(dst_argb),             // %3
6598
0
        "+r"(width)                 // %4
6599
0
      : "m"(shift),                 // %5
6600
0
        "m"(MergeARGB16To8Shuffle)  // %6
6601
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
6602
0
}
6603
#endif
6604
6605
#ifdef HAS_COPYROW_SSE2
6606
0
void CopyRow_SSE2(const uint8_t* src, uint8_t* dst, int width) {
6607
0
  asm volatile(
6608
0
      "test        $0xf,%0                       \n"
6609
0
      "jne         2f                            \n"
6610
0
      "test        $0xf,%1                       \n"
6611
0
      "jne         2f                            \n"
6612
6613
0
      LABELALIGN
6614
0
      "1:          \n"
6615
0
      "movdqa      (%0),%%xmm0                   \n"
6616
0
      "movdqa      0x10(%0),%%xmm1               \n"
6617
0
      "lea         0x20(%0),%0                   \n"
6618
0
      "movdqa      %%xmm0,(%1)                   \n"
6619
0
      "movdqa      %%xmm1,0x10(%1)               \n"
6620
0
      "lea         0x20(%1),%1                   \n"
6621
0
      "sub         $0x20,%2                      \n"
6622
0
      "jg          1b                            \n"
6623
0
      "jmp         9f                            \n"
6624
6625
0
      LABELALIGN
6626
0
      "2:          \n"
6627
0
      "movdqu      (%0),%%xmm0                   \n"
6628
0
      "movdqu      0x10(%0),%%xmm1               \n"
6629
0
      "lea         0x20(%0),%0                   \n"
6630
0
      "movdqu      %%xmm0,(%1)                   \n"
6631
0
      "movdqu      %%xmm1,0x10(%1)               \n"
6632
0
      "lea         0x20(%1),%1                   \n"
6633
0
      "sub         $0x20,%2                      \n"
6634
0
      "jg          2b                            \n"
6635
6636
0
      LABELALIGN "9:          \n"
6637
0
      : "+r"(src),   // %0
6638
0
        "+r"(dst),   // %1
6639
0
        "+r"(width)  // %2
6640
0
      :
6641
0
      : "memory", "cc", "xmm0", "xmm1");
6642
0
}
6643
#endif  // HAS_COPYROW_SSE2
6644
6645
#ifdef HAS_COPYROW_AVX
6646
0
void CopyRow_AVX(const uint8_t* src, uint8_t* dst, int width) {
6647
0
  asm volatile(
6648
0
      "1:          \n"
6649
0
      "vmovdqu     (%0),%%ymm0                   \n"
6650
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
6651
0
      "lea         0x40(%0),%0                   \n"
6652
0
      "vmovdqu     %%ymm0,(%1)                   \n"
6653
0
      "vmovdqu     %%ymm1,0x20(%1)               \n"
6654
0
      "lea         0x40(%1),%1                   \n"
6655
0
      "sub         $0x40,%2                      \n"
6656
0
      "jg          1b                            \n"
6657
0
      "vzeroupper  \n"
6658
0
      : "+r"(src),   // %0
6659
0
        "+r"(dst),   // %1
6660
0
        "+r"(width)  // %2
6661
0
      :
6662
0
      : "memory", "cc", "xmm0", "xmm1");
6663
0
}
6664
#endif  // HAS_COPYROW_AVX
6665
6666
#ifdef HAS_COPYROW_AVX512BW
6667
0
void CopyRow_AVX512BW(const uint8_t* src, uint8_t* dst, int width) {
6668
0
  asm volatile(
6669
0
      "1:          \n"
6670
0
      "vmovups     (%0),%%zmm0                   \n"
6671
0
      "vmovups     0x40(%0),%%zmm1               \n"
6672
0
      "lea         0x80(%0),%0                   \n"
6673
0
      "vmovups     %%zmm0,(%1)                   \n"
6674
0
      "vmovups     %%zmm1,0x40(%1)               \n"
6675
0
      "lea         0x80(%1),%1                   \n"
6676
0
      "sub         $0x80,%2                      \n"
6677
0
      "jg          1b                            \n"
6678
0
      "vzeroupper  \n"
6679
0
      : "+r"(src),   // %0
6680
0
        "+r"(dst),   // %1
6681
0
        "+r"(width)  // %2
6682
0
      :
6683
0
      : "memory", "cc", "xmm0", "xmm1");
6684
0
}
6685
#endif  // HAS_COPYROW_AVX512
6686
6687
#ifdef HAS_COPYROW_ERMS
6688
// Multiple of 1.
6689
22.6k
void CopyRow_ERMS(const uint8_t* src, uint8_t* dst, int width) {
6690
22.6k
  size_t width_tmp = (size_t)(width);
6691
22.6k
  asm volatile("rep         movsb                         \n"
6692
22.6k
               : "+S"(src),       // %0
6693
22.6k
                 "+D"(dst),       // %1
6694
22.6k
                 "+c"(width_tmp)  // %2
6695
22.6k
               :
6696
22.6k
               : "memory", "cc");
6697
22.6k
}
6698
#endif  // HAS_COPYROW_ERMS
6699
6700
#ifdef HAS_ARGBCOPYALPHAROW_SSE2
6701
// width in pixels
6702
0
void ARGBCopyAlphaRow_SSE2(const uint8_t* src, uint8_t* dst, int width) {
6703
0
  asm volatile(
6704
0
      "pcmpeqb     %%xmm0,%%xmm0                 \n"
6705
0
      "pslld       $0x18,%%xmm0                  \n"
6706
0
      "pcmpeqb     %%xmm1,%%xmm1                 \n"
6707
0
      "psrld       $0x8,%%xmm1                   \n"
6708
6709
0
      LABELALIGN
6710
0
      "1:          \n"
6711
0
      "movdqu      (%0),%%xmm2                   \n"
6712
0
      "movdqu      0x10(%0),%%xmm3               \n"
6713
0
      "lea         0x20(%0),%0                   \n"
6714
0
      "movdqu      (%1),%%xmm4                   \n"
6715
0
      "movdqu      0x10(%1),%%xmm5               \n"
6716
0
      "pand        %%xmm0,%%xmm2                 \n"
6717
0
      "pand        %%xmm0,%%xmm3                 \n"
6718
0
      "pand        %%xmm1,%%xmm4                 \n"
6719
0
      "pand        %%xmm1,%%xmm5                 \n"
6720
0
      "por         %%xmm4,%%xmm2                 \n"
6721
0
      "por         %%xmm5,%%xmm3                 \n"
6722
0
      "movdqu      %%xmm2,(%1)                   \n"
6723
0
      "movdqu      %%xmm3,0x10(%1)               \n"
6724
0
      "lea         0x20(%1),%1                   \n"
6725
0
      "sub         $0x8,%2                       \n"
6726
0
      "jg          1b                            \n"
6727
0
      : "+r"(src),   // %0
6728
0
        "+r"(dst),   // %1
6729
0
        "+r"(width)  // %2
6730
0
      :
6731
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
6732
0
}
6733
#endif  // HAS_ARGBCOPYALPHAROW_SSE2
6734
6735
#ifdef HAS_ARGBCOPYALPHAROW_AVX2
6736
// width in pixels
6737
0
void ARGBCopyAlphaRow_AVX2(const uint8_t* src, uint8_t* dst, int width) {
6738
0
  asm volatile(
6739
0
      "vpcmpeqb    %%ymm0,%%ymm0,%%ymm0          \n"
6740
0
      "vpsrld      $0x8,%%ymm0,%%ymm0            \n"
6741
6742
0
      LABELALIGN
6743
0
      "1:          \n"
6744
0
      "vmovdqu     (%0),%%ymm1                   \n"
6745
0
      "vmovdqu     0x20(%0),%%ymm2               \n"
6746
0
      "lea         0x40(%0),%0                   \n"
6747
0
      "vpblendvb   %%ymm0,(%1),%%ymm1,%%ymm1     \n"
6748
0
      "vpblendvb   %%ymm0,0x20(%1),%%ymm2,%%ymm2 \n"
6749
0
      "vmovdqu     %%ymm1,(%1)                   \n"
6750
0
      "vmovdqu     %%ymm2,0x20(%1)               \n"
6751
0
      "lea         0x40(%1),%1                   \n"
6752
0
      "sub         $0x10,%2                      \n"
6753
0
      "jg          1b                            \n"
6754
0
      "vzeroupper  \n"
6755
0
      : "+r"(src),   // %0
6756
0
        "+r"(dst),   // %1
6757
0
        "+r"(width)  // %2
6758
0
      :
6759
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
6760
0
}
6761
#endif  // HAS_ARGBCOPYALPHAROW_AVX2
6762
6763
#ifdef HAS_ARGBEXTRACTALPHAROW_SSE2
6764
// width in pixels
6765
void ARGBExtractAlphaRow_SSE2(const uint8_t* src_argb,
6766
                              uint8_t* dst_a,
6767
0
                              int width) {
6768
0
  asm volatile(
6769
0
      "1:          \n"
6770
0
      "movdqu      (%0), %%xmm0                  \n"
6771
0
      "movdqu      0x10(%0), %%xmm1              \n"
6772
0
      "lea         0x20(%0), %0                  \n"
6773
0
      "psrld       $0x18, %%xmm0                 \n"
6774
0
      "psrld       $0x18, %%xmm1                 \n"
6775
0
      "packssdw    %%xmm1, %%xmm0                \n"
6776
0
      "packuswb    %%xmm0, %%xmm0                \n"
6777
0
      "movq        %%xmm0,(%1)                   \n"
6778
0
      "lea         0x8(%1), %1                   \n"
6779
0
      "sub         $0x8, %2                      \n"
6780
0
      "jg          1b                            \n"
6781
0
      : "+r"(src_argb),  // %0
6782
0
        "+r"(dst_a),     // %1
6783
0
        "+rm"(width)     // %2
6784
0
      :
6785
0
      : "memory", "cc", "xmm0", "xmm1");
6786
0
}
6787
#endif  // HAS_ARGBEXTRACTALPHAROW_SSE2
6788
6789
#ifdef HAS_ARGBEXTRACTALPHAROW_AVX2
6790
static const uvec8 kShuffleAlphaShort_AVX2 = {
6791
    3u,  128u, 128u, 128u, 7u,  128u, 128u, 128u,
6792
    11u, 128u, 128u, 128u, 15u, 128u, 128u, 128u};
6793
6794
void ARGBExtractAlphaRow_AVX2(const uint8_t* src_argb,
6795
                              uint8_t* dst_a,
6796
0
                              int width) {
6797
0
  asm volatile(
6798
0
      "vmovdqa     %3,%%ymm4                     \n"
6799
0
      "vbroadcasti128 %4,%%ymm5                  \n"
6800
6801
0
      LABELALIGN
6802
0
      "1:          \n"
6803
0
      "vmovdqu     (%0), %%ymm0                  \n"
6804
0
      "vmovdqu     0x20(%0), %%ymm1              \n"
6805
0
      "vpshufb     %%ymm5,%%ymm0,%%ymm0          \n"  // vpsrld $0x18, %%ymm0
6806
0
      "vpshufb     %%ymm5,%%ymm1,%%ymm1          \n"
6807
0
      "vmovdqu     0x40(%0), %%ymm2              \n"
6808
0
      "vmovdqu     0x60(%0), %%ymm3              \n"
6809
0
      "lea         0x80(%0), %0                  \n"
6810
0
      "vpackssdw   %%ymm1, %%ymm0, %%ymm0        \n"  // mutates
6811
0
      "vpshufb     %%ymm5,%%ymm2,%%ymm2          \n"
6812
0
      "vpshufb     %%ymm5,%%ymm3,%%ymm3          \n"
6813
0
      "vpackssdw   %%ymm3, %%ymm2, %%ymm2        \n"  // mutates
6814
0
      "vpackuswb   %%ymm2,%%ymm0,%%ymm0          \n"  // mutates.
6815
0
      "vpermd      %%ymm0,%%ymm4,%%ymm0          \n"  // unmutate.
6816
0
      "vmovdqu     %%ymm0,(%1)                   \n"
6817
0
      "lea         0x20(%1),%1                   \n"
6818
0
      "sub         $0x20, %2                     \n"
6819
0
      "jg          1b                            \n"
6820
0
      "vzeroupper  \n"
6821
0
      : "+r"(src_argb),               // %0
6822
0
        "+r"(dst_a),                  // %1
6823
0
        "+rm"(width)                  // %2
6824
0
      : "m"(kPermdARGBToY_AVX),       // %3
6825
0
        "m"(kShuffleAlphaShort_AVX2)  // %4
6826
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
6827
0
}
6828
#endif  // HAS_ARGBEXTRACTALPHAROW_AVX2
6829
6830
#ifdef HAS_ARGBCOPYYTOALPHAROW_SSE2
6831
// width in pixels
6832
0
void ARGBCopyYToAlphaRow_SSE2(const uint8_t* src, uint8_t* dst, int width) {
6833
0
  asm volatile(
6834
0
      "pcmpeqb     %%xmm0,%%xmm0                 \n"
6835
0
      "pslld       $0x18,%%xmm0                  \n"
6836
0
      "pcmpeqb     %%xmm1,%%xmm1                 \n"
6837
0
      "psrld       $0x8,%%xmm1                   \n"
6838
6839
0
      LABELALIGN
6840
0
      "1:          \n"
6841
0
      "movq        (%0),%%xmm2                   \n"
6842
0
      "lea         0x8(%0),%0                    \n"
6843
0
      "punpcklbw   %%xmm2,%%xmm2                 \n"
6844
0
      "punpckhwd   %%xmm2,%%xmm3                 \n"
6845
0
      "punpcklwd   %%xmm2,%%xmm2                 \n"
6846
0
      "movdqu      (%1),%%xmm4                   \n"
6847
0
      "movdqu      0x10(%1),%%xmm5               \n"
6848
0
      "pand        %%xmm0,%%xmm2                 \n"
6849
0
      "pand        %%xmm0,%%xmm3                 \n"
6850
0
      "pand        %%xmm1,%%xmm4                 \n"
6851
0
      "pand        %%xmm1,%%xmm5                 \n"
6852
0
      "por         %%xmm4,%%xmm2                 \n"
6853
0
      "por         %%xmm5,%%xmm3                 \n"
6854
0
      "movdqu      %%xmm2,(%1)                   \n"
6855
0
      "movdqu      %%xmm3,0x10(%1)               \n"
6856
0
      "lea         0x20(%1),%1                   \n"
6857
0
      "sub         $0x8,%2                       \n"
6858
0
      "jg          1b                            \n"
6859
0
      : "+r"(src),   // %0
6860
0
        "+r"(dst),   // %1
6861
0
        "+r"(width)  // %2
6862
0
      :
6863
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
6864
0
}
6865
#endif  // HAS_ARGBCOPYYTOALPHAROW_SSE2
6866
6867
#ifdef HAS_ARGBCOPYYTOALPHAROW_AVX2
6868
// width in pixels
6869
0
void ARGBCopyYToAlphaRow_AVX2(const uint8_t* src, uint8_t* dst, int width) {
6870
0
  asm volatile(
6871
0
      "vpcmpeqb    %%ymm0,%%ymm0,%%ymm0          \n"
6872
0
      "vpsrld      $0x8,%%ymm0,%%ymm0            \n"
6873
6874
0
      LABELALIGN
6875
0
      "1:          \n"
6876
0
      "vpmovzxbd   (%0),%%ymm1                   \n"
6877
0
      "vpmovzxbd   0x8(%0),%%ymm2                \n"
6878
0
      "lea         0x10(%0),%0                   \n"
6879
0
      "vpslld      $0x18,%%ymm1,%%ymm1           \n"
6880
0
      "vpslld      $0x18,%%ymm2,%%ymm2           \n"
6881
0
      "vpblendvb   %%ymm0,(%1),%%ymm1,%%ymm1     \n"
6882
0
      "vpblendvb   %%ymm0,0x20(%1),%%ymm2,%%ymm2 \n"
6883
0
      "vmovdqu     %%ymm1,(%1)                   \n"
6884
0
      "vmovdqu     %%ymm2,0x20(%1)               \n"
6885
0
      "lea         0x40(%1),%1                   \n"
6886
0
      "sub         $0x10,%2                      \n"
6887
0
      "jg          1b                            \n"
6888
0
      "vzeroupper  \n"
6889
0
      : "+r"(src),   // %0
6890
0
        "+r"(dst),   // %1
6891
0
        "+r"(width)  // %2
6892
0
      :
6893
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
6894
0
}
6895
#endif  // HAS_ARGBCOPYYTOALPHAROW_AVX2
6896
6897
#ifdef HAS_SETROW_X86
6898
0
void SetRow_X86(uint8_t* dst, uint8_t v8, int width) {
6899
0
  size_t width_tmp = (size_t)(width >> 2);
6900
0
  const uint32_t v32 = v8 * 0x01010101u;  // Duplicate byte to all bytes.
6901
0
  asm volatile("rep         stosl                         \n"
6902
0
               : "+D"(dst),       // %0
6903
0
                 "+c"(width_tmp)  // %1
6904
0
               : "a"(v32)         // %2
6905
0
               : "memory", "cc");
6906
0
}
6907
6908
0
void SetRow_ERMS(uint8_t* dst, uint8_t v8, int width) {
6909
0
  size_t width_tmp = (size_t)(width);
6910
0
  asm volatile("rep         stosb                         \n"
6911
0
               : "+D"(dst),       // %0
6912
0
                 "+c"(width_tmp)  // %1
6913
0
               : "a"(v8)          // %2
6914
0
               : "memory", "cc");
6915
0
}
6916
6917
0
void ARGBSetRow_X86(uint8_t* dst_argb, uint32_t v32, int width) {
6918
0
  size_t width_tmp = (size_t)(width);
6919
0
  asm volatile("rep         stosl                         \n"
6920
0
               : "+D"(dst_argb),  // %0
6921
0
                 "+c"(width_tmp)  // %1
6922
0
               : "a"(v32)         // %2
6923
0
               : "memory", "cc");
6924
0
}
6925
#endif  // HAS_SETROW_X86
6926
6927
#ifdef HAS_YUY2TOYROW_SSE2
6928
0
void YUY2ToYRow_SSE2(const uint8_t* src_yuy2, uint8_t* dst_y, int width) {
6929
0
  asm volatile(
6930
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
6931
0
      "psrlw       $0x8,%%xmm5                   \n"
6932
6933
0
      LABELALIGN
6934
0
      "1:          \n"
6935
0
      "movdqu      (%0),%%xmm0                   \n"
6936
0
      "movdqu      0x10(%0),%%xmm1               \n"
6937
0
      "lea         0x20(%0),%0                   \n"
6938
0
      "pand        %%xmm5,%%xmm0                 \n"
6939
0
      "pand        %%xmm5,%%xmm1                 \n"
6940
0
      "packuswb    %%xmm1,%%xmm0                 \n"
6941
0
      "movdqu      %%xmm0,(%1)                   \n"
6942
0
      "lea         0x10(%1),%1                   \n"
6943
0
      "sub         $0x10,%2                      \n"
6944
0
      "jg          1b                            \n"
6945
0
      : "+r"(src_yuy2),  // %0
6946
0
        "+r"(dst_y),     // %1
6947
0
        "+r"(width)      // %2
6948
0
      :
6949
0
      : "memory", "cc", "xmm0", "xmm1", "xmm5");
6950
0
}
6951
6952
void YUY2ToNVUVRow_SSE2(const uint8_t* src_yuy2,
6953
                        int stride_yuy2,
6954
                        uint8_t* dst_uv,
6955
0
                        int width) {
6956
0
  asm volatile(
6957
0
      "1:          \n"
6958
0
      "movdqu      (%0),%%xmm0                   \n"
6959
0
      "movdqu      0x10(%0),%%xmm1               \n"
6960
0
      "movdqu      0x00(%0,%3,1),%%xmm2          \n"
6961
0
      "movdqu      0x10(%0,%3,1),%%xmm3          \n"
6962
0
      "lea         0x20(%0),%0                   \n"
6963
0
      "pavgb       %%xmm2,%%xmm0                 \n"
6964
0
      "pavgb       %%xmm3,%%xmm1                 \n"
6965
0
      "psrlw       $0x8,%%xmm0                   \n"
6966
0
      "psrlw       $0x8,%%xmm1                   \n"
6967
0
      "packuswb    %%xmm1,%%xmm0                 \n"
6968
0
      "movdqu      %%xmm0,(%1)                   \n"
6969
0
      "lea         0x10(%1),%1                   \n"
6970
0
      "sub         $0x10,%2                      \n"
6971
0
      "jg          1b                            \n"
6972
0
      : "+r"(src_yuy2),                // %0
6973
0
        "+r"(dst_uv),                  // %1
6974
0
        "+r"(width)                    // %2
6975
0
      : "r"((ptrdiff_t)(stride_yuy2))  // %3
6976
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3");
6977
0
}
6978
6979
void YUY2ToUVRow_SSE2(const uint8_t* src_yuy2,
6980
                      int stride_yuy2,
6981
                      uint8_t* dst_u,
6982
                      uint8_t* dst_v,
6983
0
                      int width) {
6984
0
  asm volatile(
6985
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
6986
0
      "psrlw       $0x8,%%xmm5                   \n"
6987
0
      "sub         %1,%2                         \n"
6988
6989
0
      LABELALIGN
6990
0
      "1:          \n"
6991
0
      "movdqu      (%0),%%xmm0                   \n"
6992
0
      "movdqu      0x10(%0),%%xmm1               \n"
6993
0
      "movdqu      0x00(%0,%4,1),%%xmm2          \n"
6994
0
      "movdqu      0x10(%0,%4,1),%%xmm3          \n"
6995
0
      "lea         0x20(%0),%0                   \n"
6996
0
      "pavgb       %%xmm2,%%xmm0                 \n"
6997
0
      "pavgb       %%xmm3,%%xmm1                 \n"
6998
0
      "psrlw       $0x8,%%xmm0                   \n"
6999
0
      "psrlw       $0x8,%%xmm1                   \n"
7000
0
      "packuswb    %%xmm1,%%xmm0                 \n"
7001
0
      "movdqa      %%xmm0,%%xmm1                 \n"
7002
0
      "pand        %%xmm5,%%xmm0                 \n"
7003
0
      "packuswb    %%xmm0,%%xmm0                 \n"
7004
0
      "psrlw       $0x8,%%xmm1                   \n"
7005
0
      "packuswb    %%xmm1,%%xmm1                 \n"
7006
0
      "movq        %%xmm0,(%1)                   \n"
7007
0
      "movq        %%xmm1,0x00(%1,%2,1)          \n"
7008
0
      "lea         0x8(%1),%1                    \n"
7009
0
      "sub         $0x10,%3                      \n"
7010
0
      "jg          1b                            \n"
7011
0
      : "+r"(src_yuy2),                // %0
7012
0
        "+r"(dst_u),                   // %1
7013
0
        "+r"(dst_v),                   // %2
7014
0
        "+r"(width)                    // %3
7015
0
      : "r"((ptrdiff_t)(stride_yuy2))  // %4
7016
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5");
7017
0
}
7018
7019
void YUY2ToUV422Row_SSE2(const uint8_t* src_yuy2,
7020
                         uint8_t* dst_u,
7021
                         uint8_t* dst_v,
7022
0
                         int width) {
7023
0
  asm volatile(
7024
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
7025
0
      "psrlw       $0x8,%%xmm5                   \n"
7026
0
      "sub         %1,%2                         \n"
7027
7028
0
      LABELALIGN
7029
0
      "1:          \n"
7030
0
      "movdqu      (%0),%%xmm0                   \n"
7031
0
      "movdqu      0x10(%0),%%xmm1               \n"
7032
0
      "lea         0x20(%0),%0                   \n"
7033
0
      "psrlw       $0x8,%%xmm0                   \n"
7034
0
      "psrlw       $0x8,%%xmm1                   \n"
7035
0
      "packuswb    %%xmm1,%%xmm0                 \n"
7036
0
      "movdqa      %%xmm0,%%xmm1                 \n"
7037
0
      "pand        %%xmm5,%%xmm0                 \n"
7038
0
      "packuswb    %%xmm0,%%xmm0                 \n"
7039
0
      "psrlw       $0x8,%%xmm1                   \n"
7040
0
      "packuswb    %%xmm1,%%xmm1                 \n"
7041
0
      "movq        %%xmm0,(%1)                   \n"
7042
0
      "movq        %%xmm1,0x00(%1,%2,1)          \n"
7043
0
      "lea         0x8(%1),%1                    \n"
7044
0
      "sub         $0x10,%3                      \n"
7045
0
      "jg          1b                            \n"
7046
0
      : "+r"(src_yuy2),  // %0
7047
0
        "+r"(dst_u),     // %1
7048
0
        "+r"(dst_v),     // %2
7049
0
        "+r"(width)      // %3
7050
0
      :
7051
0
      : "memory", "cc", "xmm0", "xmm1", "xmm5");
7052
0
}
7053
7054
0
void UYVYToYRow_SSE2(const uint8_t* src_uyvy, uint8_t* dst_y, int width) {
7055
0
  asm volatile(
7056
0
      "1:          \n"
7057
0
      "movdqu      (%0),%%xmm0                   \n"
7058
0
      "movdqu      0x10(%0),%%xmm1               \n"
7059
0
      "lea         0x20(%0),%0                   \n"
7060
0
      "psrlw       $0x8,%%xmm0                   \n"
7061
0
      "psrlw       $0x8,%%xmm1                   \n"
7062
0
      "packuswb    %%xmm1,%%xmm0                 \n"
7063
0
      "movdqu      %%xmm0,(%1)                   \n"
7064
0
      "lea         0x10(%1),%1                   \n"
7065
0
      "sub         $0x10,%2                      \n"
7066
0
      "jg          1b                            \n"
7067
0
      : "+r"(src_uyvy),  // %0
7068
0
        "+r"(dst_y),     // %1
7069
0
        "+r"(width)      // %2
7070
0
      :
7071
0
      : "memory", "cc", "xmm0", "xmm1");
7072
0
}
7073
7074
void UYVYToUVRow_SSE2(const uint8_t* src_uyvy,
7075
                      int stride_uyvy,
7076
                      uint8_t* dst_u,
7077
                      uint8_t* dst_v,
7078
0
                      int width) {
7079
0
  asm volatile(
7080
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
7081
0
      "psrlw       $0x8,%%xmm5                   \n"
7082
0
      "sub         %1,%2                         \n"
7083
7084
0
      LABELALIGN
7085
0
      "1:          \n"
7086
0
      "movdqu      (%0),%%xmm0                   \n"
7087
0
      "movdqu      0x10(%0),%%xmm1               \n"
7088
0
      "movdqu      0x00(%0,%4,1),%%xmm2          \n"
7089
0
      "movdqu      0x10(%0,%4,1),%%xmm3          \n"
7090
0
      "lea         0x20(%0),%0                   \n"
7091
0
      "pavgb       %%xmm2,%%xmm0                 \n"
7092
0
      "pavgb       %%xmm3,%%xmm1                 \n"
7093
0
      "pand        %%xmm5,%%xmm0                 \n"
7094
0
      "pand        %%xmm5,%%xmm1                 \n"
7095
0
      "packuswb    %%xmm1,%%xmm0                 \n"
7096
0
      "movdqa      %%xmm0,%%xmm1                 \n"
7097
0
      "pand        %%xmm5,%%xmm0                 \n"
7098
0
      "packuswb    %%xmm0,%%xmm0                 \n"
7099
0
      "psrlw       $0x8,%%xmm1                   \n"
7100
0
      "packuswb    %%xmm1,%%xmm1                 \n"
7101
0
      "movq        %%xmm0,(%1)                   \n"
7102
0
      "movq        %%xmm1,0x00(%1,%2,1)          \n"
7103
0
      "lea         0x8(%1),%1                    \n"
7104
0
      "sub         $0x10,%3                      \n"
7105
0
      "jg          1b                            \n"
7106
0
      : "+r"(src_uyvy),                // %0
7107
0
        "+r"(dst_u),                   // %1
7108
0
        "+r"(dst_v),                   // %2
7109
0
        "+r"(width)                    // %3
7110
0
      : "r"((ptrdiff_t)(stride_uyvy))  // %4
7111
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5");
7112
0
}
7113
7114
void UYVYToUV422Row_SSE2(const uint8_t* src_uyvy,
7115
                         uint8_t* dst_u,
7116
                         uint8_t* dst_v,
7117
0
                         int width) {
7118
0
  asm volatile(
7119
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
7120
0
      "psrlw       $0x8,%%xmm5                   \n"
7121
0
      "sub         %1,%2                         \n"
7122
7123
0
      LABELALIGN
7124
0
      "1:          \n"
7125
0
      "movdqu      (%0),%%xmm0                   \n"
7126
0
      "movdqu      0x10(%0),%%xmm1               \n"
7127
0
      "lea         0x20(%0),%0                   \n"
7128
0
      "pand        %%xmm5,%%xmm0                 \n"
7129
0
      "pand        %%xmm5,%%xmm1                 \n"
7130
0
      "packuswb    %%xmm1,%%xmm0                 \n"
7131
0
      "movdqa      %%xmm0,%%xmm1                 \n"
7132
0
      "pand        %%xmm5,%%xmm0                 \n"
7133
0
      "packuswb    %%xmm0,%%xmm0                 \n"
7134
0
      "psrlw       $0x8,%%xmm1                   \n"
7135
0
      "packuswb    %%xmm1,%%xmm1                 \n"
7136
0
      "movq        %%xmm0,(%1)                   \n"
7137
0
      "movq        %%xmm1,0x00(%1,%2,1)          \n"
7138
0
      "lea         0x8(%1),%1                    \n"
7139
0
      "sub         $0x10,%3                      \n"
7140
0
      "jg          1b                            \n"
7141
0
      : "+r"(src_uyvy),  // %0
7142
0
        "+r"(dst_u),     // %1
7143
0
        "+r"(dst_v),     // %2
7144
0
        "+r"(width)      // %3
7145
0
      :
7146
0
      : "memory", "cc", "xmm0", "xmm1", "xmm5");
7147
0
}
7148
#endif  // HAS_YUY2TOYROW_SSE2
7149
7150
#ifdef HAS_YUY2TOYROW_AVX2
7151
0
void YUY2ToYRow_AVX2(const uint8_t* src_yuy2, uint8_t* dst_y, int width) {
7152
0
  asm volatile(
7153
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
7154
0
      "vpsrlw      $0x8,%%ymm5,%%ymm5            \n"
7155
7156
0
      LABELALIGN
7157
0
      "1:          \n"
7158
0
      "vmovdqu     (%0),%%ymm0                   \n"
7159
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
7160
0
      "lea         0x40(%0),%0                   \n"
7161
0
      "vpand       %%ymm5,%%ymm0,%%ymm0          \n"
7162
0
      "vpand       %%ymm5,%%ymm1,%%ymm1          \n"
7163
0
      "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"
7164
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
7165
0
      "vmovdqu     %%ymm0,(%1)                   \n"
7166
0
      "lea         0x20(%1),%1                   \n"
7167
0
      "sub         $0x20,%2                      \n"
7168
0
      "jg          1b                            \n"
7169
0
      "vzeroupper  \n"
7170
0
      : "+r"(src_yuy2),  // %0
7171
0
        "+r"(dst_y),     // %1
7172
0
        "+r"(width)      // %2
7173
0
      :
7174
0
      : "memory", "cc", "xmm0", "xmm1", "xmm5");
7175
0
}
7176
7177
void YUY2ToNVUVRow_AVX2(const uint8_t* src_yuy2,
7178
                        int stride_yuy2,
7179
                        uint8_t* dst_uv,
7180
0
                        int width) {
7181
0
  asm volatile(
7182
0
      "1:          \n"
7183
0
      "vmovdqu     (%0),%%ymm0                   \n"
7184
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
7185
0
      "vpavgb      0x00(%0,%3,1),%%ymm0,%%ymm0   \n"
7186
0
      "vpavgb      0x20(%0,%3,1),%%ymm1,%%ymm1   \n"
7187
0
      "lea         0x40(%0),%0                   \n"
7188
0
      "vpsrlw      $0x8,%%ymm0,%%ymm0            \n"
7189
0
      "vpsrlw      $0x8,%%ymm1,%%ymm1            \n"
7190
0
      "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"
7191
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
7192
0
      "vmovdqu     %%ymm0,(%1)                   \n"
7193
0
      "lea         0x20(%1),%1                   \n"
7194
0
      "sub         $0x20,%2                      \n"
7195
0
      "jg          1b                            \n"
7196
0
      "vzeroupper  \n"
7197
0
      : "+r"(src_yuy2),                // %0
7198
0
        "+r"(dst_uv),                  // %1
7199
0
        "+r"(width)                    // %2
7200
0
      : "r"((ptrdiff_t)(stride_yuy2))  // %3
7201
0
      : "memory", "cc", "xmm0", "xmm1");
7202
0
}
7203
7204
void YUY2ToUVRow_AVX2(const uint8_t* src_yuy2,
7205
                      int stride_yuy2,
7206
                      uint8_t* dst_u,
7207
                      uint8_t* dst_v,
7208
0
                      int width) {
7209
0
  asm volatile(
7210
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
7211
0
      "vpsrlw      $0x8,%%ymm5,%%ymm5            \n"
7212
0
      "sub         %1,%2                         \n"
7213
7214
0
      LABELALIGN
7215
0
      "1:          \n"
7216
0
      "vmovdqu     (%0),%%ymm0                   \n"
7217
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
7218
0
      "vpavgb      0x00(%0,%4,1),%%ymm0,%%ymm0   \n"
7219
0
      "vpavgb      0x20(%0,%4,1),%%ymm1,%%ymm1   \n"
7220
0
      "lea         0x40(%0),%0                   \n"
7221
0
      "vpsrlw      $0x8,%%ymm0,%%ymm0            \n"
7222
0
      "vpsrlw      $0x8,%%ymm1,%%ymm1            \n"
7223
0
      "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"
7224
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
7225
0
      "vpand       %%ymm5,%%ymm0,%%ymm1          \n"
7226
0
      "vpsrlw      $0x8,%%ymm0,%%ymm0            \n"
7227
0
      "vpackuswb   %%ymm1,%%ymm1,%%ymm1          \n"
7228
0
      "vpackuswb   %%ymm0,%%ymm0,%%ymm0          \n"
7229
0
      "vpermq      $0xd8,%%ymm1,%%ymm1           \n"
7230
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
7231
0
      "vextractf128 $0x0,%%ymm1,(%1)             \n"
7232
0
      "vextractf128 $0x0,%%ymm0,0x00(%1,%2,1)    \n"
7233
0
      "lea         0x10(%1),%1                   \n"
7234
0
      "sub         $0x20,%3                      \n"
7235
0
      "jg          1b                            \n"
7236
0
      "vzeroupper  \n"
7237
0
      : "+r"(src_yuy2),                // %0
7238
0
        "+r"(dst_u),                   // %1
7239
0
        "+r"(dst_v),                   // %2
7240
0
        "+r"(width)                    // %3
7241
0
      : "r"((ptrdiff_t)(stride_yuy2))  // %4
7242
0
      : "memory", "cc", "xmm0", "xmm1", "xmm5");
7243
0
}
7244
7245
void YUY2ToUV422Row_AVX2(const uint8_t* src_yuy2,
7246
                         uint8_t* dst_u,
7247
                         uint8_t* dst_v,
7248
0
                         int width) {
7249
0
  asm volatile(
7250
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
7251
0
      "vpsrlw      $0x8,%%ymm5,%%ymm5            \n"
7252
0
      "sub         %1,%2                         \n"
7253
7254
0
      LABELALIGN
7255
0
      "1:          \n"
7256
0
      "vmovdqu     (%0),%%ymm0                   \n"
7257
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
7258
0
      "lea         0x40(%0),%0                   \n"
7259
0
      "vpsrlw      $0x8,%%ymm0,%%ymm0            \n"
7260
0
      "vpsrlw      $0x8,%%ymm1,%%ymm1            \n"
7261
0
      "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"
7262
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
7263
0
      "vpand       %%ymm5,%%ymm0,%%ymm1          \n"
7264
0
      "vpsrlw      $0x8,%%ymm0,%%ymm0            \n"
7265
0
      "vpackuswb   %%ymm1,%%ymm1,%%ymm1          \n"
7266
0
      "vpackuswb   %%ymm0,%%ymm0,%%ymm0          \n"
7267
0
      "vpermq      $0xd8,%%ymm1,%%ymm1           \n"
7268
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
7269
0
      "vextractf128 $0x0,%%ymm1,(%1)             \n"
7270
0
      "vextractf128 $0x0,%%ymm0,0x00(%1,%2,1)    \n"
7271
0
      "lea         0x10(%1),%1                   \n"
7272
0
      "sub         $0x20,%3                      \n"
7273
0
      "jg          1b                            \n"
7274
0
      "vzeroupper  \n"
7275
0
      : "+r"(src_yuy2),  // %0
7276
0
        "+r"(dst_u),     // %1
7277
0
        "+r"(dst_v),     // %2
7278
0
        "+r"(width)      // %3
7279
0
      :
7280
0
      : "memory", "cc", "xmm0", "xmm1", "xmm5");
7281
0
}
7282
7283
0
void UYVYToYRow_AVX2(const uint8_t* src_uyvy, uint8_t* dst_y, int width) {
7284
0
  asm volatile(
7285
0
      "1:          \n"
7286
0
      "vmovdqu     (%0),%%ymm0                   \n"
7287
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
7288
0
      "lea         0x40(%0),%0                   \n"
7289
0
      "vpsrlw      $0x8,%%ymm0,%%ymm0            \n"
7290
0
      "vpsrlw      $0x8,%%ymm1,%%ymm1            \n"
7291
0
      "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"
7292
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
7293
0
      "vmovdqu     %%ymm0,(%1)                   \n"
7294
0
      "lea         0x20(%1),%1                   \n"
7295
0
      "sub         $0x20,%2                      \n"
7296
0
      "jg          1b                            \n"
7297
0
      "vzeroupper  \n"
7298
0
      : "+r"(src_uyvy),  // %0
7299
0
        "+r"(dst_y),     // %1
7300
0
        "+r"(width)      // %2
7301
0
      :
7302
0
      : "memory", "cc", "xmm0", "xmm1", "xmm5");
7303
0
}
7304
void UYVYToUVRow_AVX2(const uint8_t* src_uyvy,
7305
                      int stride_uyvy,
7306
                      uint8_t* dst_u,
7307
                      uint8_t* dst_v,
7308
0
                      int width) {
7309
0
  asm volatile(
7310
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
7311
0
      "vpsrlw      $0x8,%%ymm5,%%ymm5            \n"
7312
0
      "sub         %1,%2                         \n"
7313
7314
0
      LABELALIGN
7315
0
      "1:          \n"
7316
0
      "vmovdqu     (%0),%%ymm0                   \n"
7317
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
7318
0
      "vpavgb      0x00(%0,%4,1),%%ymm0,%%ymm0   \n"
7319
0
      "vpavgb      0x20(%0,%4,1),%%ymm1,%%ymm1   \n"
7320
0
      "lea         0x40(%0),%0                   \n"
7321
0
      "vpand       %%ymm5,%%ymm0,%%ymm0          \n"
7322
0
      "vpand       %%ymm5,%%ymm1,%%ymm1          \n"
7323
0
      "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"
7324
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
7325
0
      "vpand       %%ymm5,%%ymm0,%%ymm1          \n"
7326
0
      "vpsrlw      $0x8,%%ymm0,%%ymm0            \n"
7327
0
      "vpackuswb   %%ymm1,%%ymm1,%%ymm1          \n"
7328
0
      "vpackuswb   %%ymm0,%%ymm0,%%ymm0          \n"
7329
0
      "vpermq      $0xd8,%%ymm1,%%ymm1           \n"
7330
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
7331
0
      "vextractf128 $0x0,%%ymm1,(%1)             \n"
7332
0
      "vextractf128 $0x0,%%ymm0,0x00(%1,%2,1)    \n"
7333
0
      "lea         0x10(%1),%1                   \n"
7334
0
      "sub         $0x20,%3                      \n"
7335
0
      "jg          1b                            \n"
7336
0
      "vzeroupper  \n"
7337
0
      : "+r"(src_uyvy),                // %0
7338
0
        "+r"(dst_u),                   // %1
7339
0
        "+r"(dst_v),                   // %2
7340
0
        "+r"(width)                    // %3
7341
0
      : "r"((ptrdiff_t)(stride_uyvy))  // %4
7342
0
      : "memory", "cc", "xmm0", "xmm1", "xmm5");
7343
0
}
7344
7345
void UYVYToUV422Row_AVX2(const uint8_t* src_uyvy,
7346
                         uint8_t* dst_u,
7347
                         uint8_t* dst_v,
7348
0
                         int width) {
7349
0
  asm volatile(
7350
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
7351
0
      "vpsrlw      $0x8,%%ymm5,%%ymm5            \n"
7352
0
      "sub         %1,%2                         \n"
7353
7354
0
      LABELALIGN
7355
0
      "1:          \n"
7356
0
      "vmovdqu     (%0),%%ymm0                   \n"
7357
0
      "vmovdqu     0x20(%0),%%ymm1               \n"
7358
0
      "lea         0x40(%0),%0                   \n"
7359
0
      "vpand       %%ymm5,%%ymm0,%%ymm0          \n"
7360
0
      "vpand       %%ymm5,%%ymm1,%%ymm1          \n"
7361
0
      "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"
7362
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
7363
0
      "vpand       %%ymm5,%%ymm0,%%ymm1          \n"
7364
0
      "vpsrlw      $0x8,%%ymm0,%%ymm0            \n"
7365
0
      "vpackuswb   %%ymm1,%%ymm1,%%ymm1          \n"
7366
0
      "vpackuswb   %%ymm0,%%ymm0,%%ymm0          \n"
7367
0
      "vpermq      $0xd8,%%ymm1,%%ymm1           \n"
7368
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
7369
0
      "vextractf128 $0x0,%%ymm1,(%1)             \n"
7370
0
      "vextractf128 $0x0,%%ymm0,0x00(%1,%2,1)    \n"
7371
0
      "lea         0x10(%1),%1                   \n"
7372
0
      "sub         $0x20,%3                      \n"
7373
0
      "jg          1b                            \n"
7374
0
      "vzeroupper  \n"
7375
0
      : "+r"(src_uyvy),  // %0
7376
0
        "+r"(dst_u),     // %1
7377
0
        "+r"(dst_v),     // %2
7378
0
        "+r"(width)      // %3
7379
0
      :
7380
0
      : "memory", "cc", "xmm0", "xmm1", "xmm5");
7381
0
}
7382
#endif  // HAS_YUY2TOYROW_AVX2
7383
7384
#ifdef HAS_ARGBBLENDROW_SSSE3
7385
// Shuffle table for isolating alpha.
7386
static const uvec8 kShuffleAlpha = {3u,  0x80, 3u,  0x80, 7u,  0x80, 7u,  0x80,
7387
                                    11u, 0x80, 11u, 0x80, 15u, 0x80, 15u, 0x80};
7388
7389
// Blend 8 pixels at a time
7390
void ARGBBlendRow_SSSE3(const uint8_t* src_argb,
7391
                        const uint8_t* src_argb1,
7392
                        uint8_t* dst_argb,
7393
0
                        int width) {
7394
0
  asm volatile(
7395
0
      "pcmpeqb     %%xmm7,%%xmm7                 \n"
7396
0
      "psrlw       $0xf,%%xmm7                   \n"
7397
0
      "pcmpeqb     %%xmm6,%%xmm6                 \n"
7398
0
      "psrlw       $0x8,%%xmm6                   \n"
7399
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
7400
0
      "psllw       $0x8,%%xmm5                   \n"
7401
0
      "pcmpeqb     %%xmm4,%%xmm4                 \n"
7402
0
      "pslld       $0x18,%%xmm4                  \n"
7403
0
      "sub         $0x4,%3                       \n"
7404
0
      "jl          49f                           \n"
7405
7406
      // 4 pixel loop.
7407
0
      LABELALIGN
7408
0
      "40:         \n"
7409
0
      "movdqu      (%0),%%xmm3                   \n"
7410
0
      "lea         0x10(%0),%0                   \n"
7411
0
      "movdqa      %%xmm3,%%xmm0                 \n"
7412
0
      "pxor        %%xmm4,%%xmm3                 \n"
7413
0
      "movdqu      (%1),%%xmm2                   \n"
7414
0
      "pshufb      %4,%%xmm3                     \n"
7415
0
      "pand        %%xmm6,%%xmm2                 \n"
7416
0
      "paddw       %%xmm7,%%xmm3                 \n"
7417
0
      "pmullw      %%xmm3,%%xmm2                 \n"
7418
0
      "movdqu      (%1),%%xmm1                   \n"
7419
0
      "lea         0x10(%1),%1                   \n"
7420
0
      "psrlw       $0x8,%%xmm1                   \n"
7421
0
      "por         %%xmm4,%%xmm0                 \n"
7422
0
      "pmullw      %%xmm3,%%xmm1                 \n"
7423
0
      "psrlw       $0x8,%%xmm2                   \n"
7424
0
      "paddusb     %%xmm2,%%xmm0                 \n"
7425
0
      "pand        %%xmm5,%%xmm1                 \n"
7426
0
      "paddusb     %%xmm1,%%xmm0                 \n"
7427
0
      "movdqu      %%xmm0,(%2)                   \n"
7428
0
      "lea         0x10(%2),%2                   \n"
7429
0
      "sub         $0x4,%3                       \n"
7430
0
      "jge         40b                           \n"
7431
7432
0
      "49:         \n"
7433
0
      "add         $0x3,%3                       \n"
7434
0
      "jl          99f                           \n"
7435
7436
      // 1 pixel loop.
7437
0
      "91:         \n"
7438
0
      "movd        (%0),%%xmm3                   \n"
7439
0
      "lea         0x4(%0),%0                    \n"
7440
0
      "movdqa      %%xmm3,%%xmm0                 \n"
7441
0
      "pxor        %%xmm4,%%xmm3                 \n"
7442
0
      "movd        (%1),%%xmm2                   \n"
7443
0
      "pshufb      %4,%%xmm3                     \n"
7444
0
      "pand        %%xmm6,%%xmm2                 \n"
7445
0
      "paddw       %%xmm7,%%xmm3                 \n"
7446
0
      "pmullw      %%xmm3,%%xmm2                 \n"
7447
0
      "movd        (%1),%%xmm1                   \n"
7448
0
      "lea         0x4(%1),%1                    \n"
7449
0
      "psrlw       $0x8,%%xmm1                   \n"
7450
0
      "por         %%xmm4,%%xmm0                 \n"
7451
0
      "pmullw      %%xmm3,%%xmm1                 \n"
7452
0
      "psrlw       $0x8,%%xmm2                   \n"
7453
0
      "paddusb     %%xmm2,%%xmm0                 \n"
7454
0
      "pand        %%xmm5,%%xmm1                 \n"
7455
0
      "paddusb     %%xmm1,%%xmm0                 \n"
7456
0
      "movd        %%xmm0,(%2)                   \n"
7457
0
      "lea         0x4(%2),%2                    \n"
7458
0
      "sub         $0x1,%3                       \n"
7459
0
      "jge         91b                           \n"
7460
0
      "99:         \n"
7461
0
      : "+r"(src_argb),     // %0
7462
0
        "+r"(src_argb1),    // %1
7463
0
        "+r"(dst_argb),     // %2
7464
0
        "+r"(width)         // %3
7465
0
      : "m"(kShuffleAlpha)  // %4
7466
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
7467
0
        "xmm7");
7468
0
}
7469
#endif  // HAS_ARGBBLENDROW_SSSE3
7470
7471
#ifdef HAS_BLENDPLANEROW_SSSE3
7472
// Blend 8 pixels at a time.
7473
// unsigned version of math
7474
// =((A2*C2)+(B2*(255-C2))+255)/256
7475
// signed version of math
7476
// =(((A2-128)*C2)+((B2-128)*(255-C2))+32768+127)/256
7477
void BlendPlaneRow_SSSE3(const uint8_t* src0,
7478
                         const uint8_t* src1,
7479
                         const uint8_t* alpha,
7480
                         uint8_t* dst,
7481
0
                         int width) {
7482
0
  asm volatile(
7483
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
7484
0
      "psllw       $0x8,%%xmm5                   \n"
7485
0
      "mov         $0x80808080,%%eax             \n"
7486
0
      "movd        %%eax,%%xmm6                  \n"
7487
0
      "pshufd      $0x0,%%xmm6,%%xmm6            \n"
7488
0
      "mov         $0x807f807f,%%eax             \n"
7489
0
      "movd        %%eax,%%xmm7                  \n"
7490
0
      "pshufd      $0x0,%%xmm7,%%xmm7            \n"
7491
0
      "sub         %2,%0                         \n"
7492
0
      "sub         %2,%1                         \n"
7493
0
      "sub         %2,%3                         \n"
7494
7495
      // 8 pixel loop.
7496
0
      LABELALIGN
7497
0
      "1:          \n"
7498
0
      "movq        (%2),%%xmm0                   \n"
7499
0
      "punpcklbw   %%xmm0,%%xmm0                 \n"
7500
0
      "pxor        %%xmm5,%%xmm0                 \n"
7501
0
      "movq        (%0,%2,1),%%xmm1              \n"
7502
0
      "movq        (%1,%2,1),%%xmm2              \n"
7503
0
      "punpcklbw   %%xmm2,%%xmm1                 \n"
7504
0
      "psubb       %%xmm6,%%xmm1                 \n"
7505
0
      "pmaddubsw   %%xmm1,%%xmm0                 \n"
7506
0
      "paddw       %%xmm7,%%xmm0                 \n"
7507
0
      "psrlw       $0x8,%%xmm0                   \n"
7508
0
      "packuswb    %%xmm0,%%xmm0                 \n"
7509
0
      "movq        %%xmm0,(%3,%2,1)              \n"
7510
0
      "lea         0x8(%2),%2                    \n"
7511
0
      "sub         $0x8,%4                       \n"
7512
0
      "jg          1b                            \n"
7513
0
      : "+r"(src0),   // %0
7514
0
        "+r"(src1),   // %1
7515
0
        "+r"(alpha),  // %2
7516
0
        "+r"(dst),    // %3
7517
0
        "+rm"(width)  // %4
7518
0
        ::"memory",
7519
0
        "cc", "eax", "xmm0", "xmm1", "xmm2", "xmm5", "xmm6", "xmm7");
7520
0
}
7521
#endif  // HAS_BLENDPLANEROW_SSSE3
7522
7523
#ifdef HAS_BLENDPLANEROW_AVX2
7524
// Blend 32 pixels at a time.
7525
// unsigned version of math
7526
// =((A2*C2)+(B2*(255-C2))+255)/256
7527
// signed version of math
7528
// =(((A2-128)*C2)+((B2-128)*(255-C2))+32768+127)/256
7529
void BlendPlaneRow_AVX2(const uint8_t* src0,
7530
                        const uint8_t* src1,
7531
                        const uint8_t* alpha,
7532
                        uint8_t* dst,
7533
0
                        int width) {
7534
0
  asm volatile(
7535
0
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
7536
0
      "vpsllw      $0x8,%%ymm5,%%ymm5            \n"
7537
0
      "mov         $0x80808080,%%eax             \n"
7538
0
      "vmovd       %%eax,%%xmm6                  \n"
7539
0
      "vbroadcastss %%xmm6,%%ymm6                \n"
7540
0
      "mov         $0x807f807f,%%eax             \n"
7541
0
      "vmovd       %%eax,%%xmm7                  \n"
7542
0
      "vbroadcastss %%xmm7,%%ymm7                \n"
7543
0
      "sub         %2,%0                         \n"
7544
0
      "sub         %2,%1                         \n"
7545
0
      "sub         %2,%3                         \n"
7546
7547
      // 32 pixel loop.
7548
0
      LABELALIGN
7549
0
      "1:          \n"
7550
0
      "vmovdqu     (%2),%%ymm0                   \n"
7551
0
      "vpunpckhbw  %%ymm0,%%ymm0,%%ymm3          \n"
7552
0
      "vpunpcklbw  %%ymm0,%%ymm0,%%ymm0          \n"
7553
0
      "vpxor       %%ymm5,%%ymm3,%%ymm3          \n"
7554
0
      "vpxor       %%ymm5,%%ymm0,%%ymm0          \n"
7555
0
      "vmovdqu     (%0,%2,1),%%ymm1              \n"
7556
0
      "vmovdqu     (%1,%2,1),%%ymm2              \n"
7557
0
      "vpunpckhbw  %%ymm2,%%ymm1,%%ymm4          \n"
7558
0
      "vpunpcklbw  %%ymm2,%%ymm1,%%ymm1          \n"
7559
0
      "vpsubb      %%ymm6,%%ymm4,%%ymm4          \n"
7560
0
      "vpsubb      %%ymm6,%%ymm1,%%ymm1          \n"
7561
0
      "vpmaddubsw  %%ymm4,%%ymm3,%%ymm3          \n"
7562
0
      "vpmaddubsw  %%ymm1,%%ymm0,%%ymm0          \n"
7563
0
      "vpaddw      %%ymm7,%%ymm3,%%ymm3          \n"
7564
0
      "vpaddw      %%ymm7,%%ymm0,%%ymm0          \n"
7565
0
      "vpsrlw      $0x8,%%ymm3,%%ymm3            \n"
7566
0
      "vpsrlw      $0x8,%%ymm0,%%ymm0            \n"
7567
0
      "vpackuswb   %%ymm3,%%ymm0,%%ymm0          \n"
7568
0
      "vmovdqu     %%ymm0,(%3,%2,1)              \n"
7569
0
      "lea         0x20(%2),%2                   \n"
7570
0
      "sub         $0x20,%4                      \n"
7571
0
      "jg          1b                            \n"
7572
0
      "vzeroupper  \n"
7573
0
      : "+r"(src0),   // %0
7574
0
        "+r"(src1),   // %1
7575
0
        "+r"(alpha),  // %2
7576
0
        "+r"(dst),    // %3
7577
0
        "+rm"(width)  // %4
7578
0
        ::"memory",
7579
0
        "cc", "eax", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
7580
0
        "xmm7");
7581
0
}
7582
#endif  // HAS_BLENDPLANEROW_AVX2
7583
7584
#ifdef HAS_ARGBATTENUATEROW_SSSE3
7585
// Shuffle table duplicating alpha.
7586
static const vec8 kAttenuateShuffle = {6,    -128, 6,    -128, 6,  -128,
7587
                                       -128, -128, 14,   -128, 14, -128,
7588
                                       14,   -128, -128, -128};
7589
7590
// Attenuate 4 pixels at a time.
7591
void ARGBAttenuateRow_SSSE3(const uint8_t* src_argb,
7592
                            uint8_t* dst_argb,
7593
0
                            int width) {
7594
0
  asm volatile(
7595
0
      "movdqa      %3,%%xmm4                     \n"
7596
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
7597
0
      "pslld       $0x18,%%xmm5                  \n"
7598
0
      "pxor        %%xmm6,%%xmm6                 \n"
7599
0
      "pcmpeqb     %%xmm7,%%xmm7                 \n"
7600
0
      "punpcklbw   %%xmm6,%%xmm7                 \n"
7601
0
      "sub         %0,%1                         \n"
7602
7603
      // 4 pixel loop.
7604
0
      LABELALIGN
7605
0
      "1:          \n"
7606
0
      "movdqu      (%0),%%xmm6                   \n"
7607
0
      "movdqa      %%xmm6,%%xmm0                 \n"
7608
0
      "movdqa      %%xmm6,%%xmm1                 \n"
7609
0
      "punpcklbw   %%xmm5,%%xmm0                 \n"
7610
0
      "punpckhbw   %%xmm5,%%xmm1                 \n"
7611
0
      "movdqa      %%xmm0,%%xmm2                 \n"
7612
0
      "movdqa      %%xmm1,%%xmm3                 \n"
7613
0
      "pshufb      %%xmm4,%%xmm2                 \n"  // a,a,a,0
7614
0
      "pshufb      %%xmm4,%%xmm3                 \n"
7615
0
      "pmullw      %%xmm2,%%xmm0                 \n"  // rgb * alpha
7616
0
      "pmullw      %%xmm3,%%xmm1                 \n"
7617
0
      "paddw       %%xmm7,%%xmm0                 \n"  // + 255
7618
0
      "paddw       %%xmm7,%%xmm1                 \n"
7619
0
      "psrlw       $0x8,%%xmm0                   \n"
7620
0
      "psrlw       $0x8,%%xmm1                   \n"
7621
0
      "packuswb    %%xmm1,%%xmm0                 \n"
7622
0
      "pand        %%xmm5,%%xmm6                 \n"
7623
0
      "por         %%xmm6,%%xmm0                 \n"
7624
0
      "movdqu      %%xmm0,(%0,%1)                \n"
7625
0
      "lea         0x10(%0),%0                   \n"
7626
0
      "sub         $0x4,%2                       \n"
7627
0
      "jg          1b                            \n"
7628
0
      : "+r"(src_argb),         // %0
7629
0
        "+r"(dst_argb),         // %1
7630
0
        "+r"(width)             // %2
7631
0
      : "m"(kAttenuateShuffle)  // %3
7632
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
7633
0
        "xmm7");
7634
0
}
7635
#endif  // HAS_ARGBATTENUATEROW_SSSE3
7636
7637
#ifdef HAS_ARGBATTENUATEROW_AVX2
7638
7639
// Shuffle table duplicating alpha.
7640
static const lvec8 kAttenuateShuffle_AVX2 = {
7641
    6,    -128, 6,    -128, 6,    -128, -128, -128, 14,   -128, 14,
7642
    -128, 14,   -128, -128, -128, 22,   -128, 22,   -128, 22,   -128,
7643
    -128, -128, 30,   -128, 30,   -128, 30,   -128, -128, -128};
7644
7645
// Attenuate 8 pixels at a time.
7646
void ARGBAttenuateRow_AVX2(const uint8_t* src_argb,
7647
                           uint8_t* dst_argb,
7648
913
                           int width) {
7649
913
  asm volatile(
7650
913
      "vmovdqa     %3,%%ymm4                     \n"
7651
913
      "vpcmpeqb    %%ymm5,%%ymm5,%%ymm5          \n"
7652
913
      "vpslld      $0x18,%%ymm5,%%ymm5           \n"
7653
913
      "vpxor       %%ymm6,%%ymm6,%%ymm6          \n"
7654
913
      "vpcmpeqb    %%ymm7,%%ymm7,%%ymm7          \n"
7655
913
      "vpunpcklbw  %%ymm6,%%ymm7,%%ymm7          \n"
7656
913
      "sub         %0,%1                         \n"
7657
7658
      // 8 pixel loop.
7659
913
      LABELALIGN
7660
913
      "1:          \n"
7661
913
      "vmovdqu     (%0),%%ymm6                   \n"
7662
913
      "vpunpcklbw  %%ymm5,%%ymm6,%%ymm0          \n"
7663
913
      "vpunpckhbw  %%ymm5,%%ymm6,%%ymm1          \n"
7664
913
      "vpshufb     %%ymm4,%%ymm0,%%ymm2          \n"
7665
913
      "vpshufb     %%ymm4,%%ymm1,%%ymm3          \n"
7666
913
      "vpmullw     %%ymm2,%%ymm0,%%ymm0          \n"
7667
913
      "vpmullw     %%ymm3,%%ymm1,%%ymm1          \n"
7668
913
      "vpaddw      %%ymm7,%%ymm0,%%ymm0          \n"
7669
913
      "vpaddw      %%ymm7,%%ymm1,%%ymm1          \n"
7670
913
      "vpsrlw      $0x8,%%ymm0,%%ymm0            \n"
7671
913
      "vpsrlw      $0x8,%%ymm1,%%ymm1            \n"
7672
913
      "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"
7673
913
      "vpand       %%ymm5,%%ymm6,%%ymm1          \n"
7674
913
      "vpor        %%ymm1,%%ymm0,%%ymm0          \n"
7675
913
      "vmovdqu     %%ymm0,0x00(%0,%1,1)          \n"
7676
913
      "lea         0x20(%0),%0                   \n"
7677
913
      "sub         $0x8,%2                       \n"
7678
913
      "jg          1b                            \n"
7679
913
      "vzeroupper  \n"
7680
913
      : "+r"(src_argb),              // %0
7681
913
        "+r"(dst_argb),              // %1
7682
913
        "+r"(width)                  // %2
7683
913
      : "m"(kAttenuateShuffle_AVX2)  // %3
7684
913
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
7685
913
        "xmm7");
7686
913
}
7687
#endif  // HAS_ARGBATTENUATEROW_AVX2
7688
7689
#ifdef HAS_ARGBUNATTENUATEROW_SSE2
7690
// Unattenuate 4 pixels at a time.
7691
void ARGBUnattenuateRow_SSE2(const uint8_t* src_argb,
7692
                             uint8_t* dst_argb,
7693
0
                             int width) {
7694
0
  uintptr_t alpha;
7695
0
  asm volatile(
7696
      // 4 pixel loop.
7697
0
      LABELALIGN
7698
0
      "1:          \n"
7699
0
      "movdqu      (%0),%%xmm0                   \n"
7700
0
      "movzb       0x03(%0),%3                   \n"
7701
0
      "punpcklbw   %%xmm0,%%xmm0                 \n"
7702
0
      "movd        0x00(%4,%3,4),%%xmm2          \n"
7703
0
      "movzb       0x07(%0),%3                   \n"
7704
0
      "movd        0x00(%4,%3,4),%%xmm3          \n"
7705
0
      "pshuflw     $0x40,%%xmm2,%%xmm2           \n"
7706
0
      "pshuflw     $0x40,%%xmm3,%%xmm3           \n"
7707
0
      "movlhps     %%xmm3,%%xmm2                 \n"
7708
0
      "pmulhuw     %%xmm2,%%xmm0                 \n"
7709
0
      "movdqu      (%0),%%xmm1                   \n"
7710
0
      "movzb       0x0b(%0),%3                   \n"
7711
0
      "punpckhbw   %%xmm1,%%xmm1                 \n"
7712
0
      "movd        0x00(%4,%3,4),%%xmm2          \n"
7713
0
      "movzb       0x0f(%0),%3                   \n"
7714
0
      "movd        0x00(%4,%3,4),%%xmm3          \n"
7715
0
      "pshuflw     $0x40,%%xmm2,%%xmm2           \n"
7716
0
      "pshuflw     $0x40,%%xmm3,%%xmm3           \n"
7717
0
      "movlhps     %%xmm3,%%xmm2                 \n"
7718
0
      "pmulhuw     %%xmm2,%%xmm1                 \n"
7719
0
      "lea         0x10(%0),%0                   \n"
7720
0
      "packuswb    %%xmm1,%%xmm0                 \n"
7721
0
      "movdqu      %%xmm0,(%1)                   \n"
7722
0
      "lea         0x10(%1),%1                   \n"
7723
0
      "sub         $0x4,%2                       \n"
7724
0
      "jg          1b                            \n"
7725
0
      : "+r"(src_argb),     // %0
7726
0
        "+r"(dst_argb),     // %1
7727
0
        "+r"(width),        // %2
7728
0
        "=&r"(alpha)        // %3
7729
0
      : "r"(fixed_invtbl8)  // %4
7730
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
7731
0
}
7732
#endif  // HAS_ARGBUNATTENUATEROW_SSE2
7733
7734
#ifdef HAS_ARGBUNATTENUATEROW_AVX2
7735
// Shuffle table duplicating alpha.
7736
static const uvec8 kUnattenShuffleAlpha_AVX2 = {
7737
    0u, 1u, 0u, 1u, 0u, 1u, 6u, 7u, 8u, 9u, 8u, 9u, 8u, 9u, 14u, 15u};
7738
// Unattenuate 8 pixels at a time.
7739
void ARGBUnattenuateRow_AVX2(const uint8_t* src_argb,
7740
                             uint8_t* dst_argb,
7741
0
                             int width) {
7742
0
  uintptr_t alpha;
7743
0
  asm volatile(
7744
0
      "sub         %0,%1                         \n"
7745
0
      "vbroadcasti128 %5,%%ymm5                  \n"
7746
7747
      // 8 pixel loop.
7748
0
      LABELALIGN
7749
0
      "1:          \n"
7750
      // replace VPGATHER
7751
0
      "movzb       0x03(%0),%3                   \n"
7752
0
      "vmovd       0x00(%4,%3,4),%%xmm0          \n"
7753
0
      "movzb       0x07(%0),%3                   \n"
7754
0
      "vmovd       0x00(%4,%3,4),%%xmm1          \n"
7755
0
      "movzb       0x0b(%0),%3                   \n"
7756
0
      "vpunpckldq  %%xmm1,%%xmm0,%%xmm6          \n"
7757
0
      "vmovd       0x00(%4,%3,4),%%xmm2          \n"
7758
0
      "movzb       0x0f(%0),%3                   \n"
7759
0
      "vmovd       0x00(%4,%3,4),%%xmm3          \n"
7760
0
      "movzb       0x13(%0),%3                   \n"
7761
0
      "vpunpckldq  %%xmm3,%%xmm2,%%xmm7          \n"
7762
0
      "vmovd       0x00(%4,%3,4),%%xmm0          \n"
7763
0
      "movzb       0x17(%0),%3                   \n"
7764
0
      "vmovd       0x00(%4,%3,4),%%xmm1          \n"
7765
0
      "movzb       0x1b(%0),%3                   \n"
7766
0
      "vpunpckldq  %%xmm1,%%xmm0,%%xmm0          \n"
7767
0
      "vmovd       0x00(%4,%3,4),%%xmm2          \n"
7768
0
      "movzb       0x1f(%0),%3                   \n"
7769
0
      "vmovd       0x00(%4,%3,4),%%xmm3          \n"
7770
0
      "vpunpckldq  %%xmm3,%%xmm2,%%xmm2          \n"
7771
0
      "vpunpcklqdq %%xmm7,%%xmm6,%%xmm3          \n"
7772
0
      "vpunpcklqdq %%xmm2,%%xmm0,%%xmm0          \n"
7773
0
      "vinserti128 $0x1,%%xmm0,%%ymm3,%%ymm3     \n"
7774
      // end of VPGATHER
7775
7776
0
      "vmovdqu     (%0),%%ymm6                   \n"
7777
0
      "vpunpcklbw  %%ymm6,%%ymm6,%%ymm0          \n"
7778
0
      "vpunpckhbw  %%ymm6,%%ymm6,%%ymm1          \n"
7779
0
      "vpunpcklwd  %%ymm3,%%ymm3,%%ymm2          \n"
7780
0
      "vpunpckhwd  %%ymm3,%%ymm3,%%ymm3          \n"
7781
0
      "vpshufb     %%ymm5,%%ymm2,%%ymm2          \n"
7782
0
      "vpshufb     %%ymm5,%%ymm3,%%ymm3          \n"
7783
0
      "vpmulhuw    %%ymm2,%%ymm0,%%ymm0          \n"
7784
0
      "vpmulhuw    %%ymm3,%%ymm1,%%ymm1          \n"
7785
0
      "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"
7786
0
      "vmovdqu     %%ymm0,0x00(%0,%1,1)          \n"
7787
0
      "lea         0x20(%0),%0                   \n"
7788
0
      "sub         $0x8,%2                       \n"
7789
0
      "jg          1b                            \n"
7790
0
      "vzeroupper  \n"
7791
0
      : "+r"(src_argb),                 // %0
7792
0
        "+r"(dst_argb),                 // %1
7793
0
        "+r"(width),                    // %2
7794
0
        "=&r"(alpha)                    // %3
7795
0
      : "r"(fixed_invtbl8),             // %4
7796
0
        "m"(kUnattenShuffleAlpha_AVX2)  // %5
7797
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
7798
0
        "xmm7");
7799
0
}
7800
#endif  // HAS_ARGBUNATTENUATEROW_AVX2
7801
7802
#ifdef HAS_ARGBGRAYROW_SSSE3
7803
// Convert 8 ARGB pixels (64 bytes) to 8 Gray ARGB pixels
7804
0
void ARGBGrayRow_SSSE3(const uint8_t* src_argb, uint8_t* dst_argb, int width) {
7805
0
  asm volatile(
7806
0
      "movdqa      %3,%%xmm4                     \n"
7807
0
      "movdqa      %4,%%xmm5                     \n"
7808
7809
      // 8 pixel loop.
7810
0
      LABELALIGN
7811
0
      "1:          \n"
7812
0
      "movdqu      (%0),%%xmm0                   \n"
7813
0
      "movdqu      0x10(%0),%%xmm1               \n"
7814
0
      "psubb       %%xmm5,%%xmm0                 \n"
7815
0
      "psubb       %%xmm5,%%xmm1                 \n"
7816
0
      "movdqu      %%xmm4,%%xmm6                 \n"
7817
0
      "pmaddubsw   %%xmm0,%%xmm6                 \n"
7818
0
      "movdqu      %%xmm4,%%xmm0                 \n"
7819
0
      "pmaddubsw   %%xmm1,%%xmm0                 \n"
7820
0
      "phaddw      %%xmm0,%%xmm6                 \n"
7821
0
      "paddw       %%xmm5,%%xmm6                 \n"
7822
0
      "psrlw       $0x8,%%xmm6                   \n"
7823
0
      "packuswb    %%xmm6,%%xmm6                 \n"
7824
0
      "movdqu      (%0),%%xmm2                   \n"
7825
0
      "movdqu      0x10(%0),%%xmm3               \n"
7826
0
      "lea         0x20(%0),%0                   \n"
7827
0
      "psrld       $0x18,%%xmm2                  \n"
7828
0
      "psrld       $0x18,%%xmm3                  \n"
7829
0
      "packuswb    %%xmm3,%%xmm2                 \n"
7830
0
      "packuswb    %%xmm2,%%xmm2                 \n"
7831
0
      "movdqa      %%xmm6,%%xmm3                 \n"
7832
0
      "punpcklbw   %%xmm6,%%xmm6                 \n"
7833
0
      "punpcklbw   %%xmm2,%%xmm3                 \n"
7834
0
      "movdqa      %%xmm6,%%xmm1                 \n"
7835
0
      "punpcklwd   %%xmm3,%%xmm6                 \n"
7836
0
      "punpckhwd   %%xmm3,%%xmm1                 \n"
7837
0
      "movdqu      %%xmm6,(%1)                   \n"
7838
0
      "movdqu      %%xmm1,0x10(%1)               \n"
7839
0
      "lea         0x20(%1),%1                   \n"
7840
0
      "sub         $0x8,%2                       \n"
7841
0
      "jg          1b                            \n"
7842
0
      : "+r"(src_argb),  // %0
7843
0
        "+r"(dst_argb),  // %1
7844
0
        "+r"(width)      // %2
7845
0
      : "m"(kARGBToYJ),  // %3
7846
0
        "m"(kSub128)     // %4
7847
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
7848
0
}
7849
#endif  // HAS_ARGBGRAYROW_SSSE3
7850
7851
#ifdef HAS_ARGBSEPIAROW_SSSE3
7852
//    b = (r * 35 + g * 68 + b * 17) >> 7
7853
//    g = (r * 45 + g * 88 + b * 22) >> 7
7854
//    r = (r * 50 + g * 98 + b * 24) >> 7
7855
// Constant for ARGB color to sepia tone
7856
static const vec8 kARGBToSepiaB = {17, 68, 35, 0, 17, 68, 35, 0,
7857
                                   17, 68, 35, 0, 17, 68, 35, 0};
7858
7859
static const vec8 kARGBToSepiaG = {22, 88, 45, 0, 22, 88, 45, 0,
7860
                                   22, 88, 45, 0, 22, 88, 45, 0};
7861
7862
static const vec8 kARGBToSepiaR = {24, 98, 50, 0, 24, 98, 50, 0,
7863
                                   24, 98, 50, 0, 24, 98, 50, 0};
7864
7865
// Convert 8 ARGB pixels (32 bytes) to 8 Sepia ARGB pixels.
7866
0
void ARGBSepiaRow_SSSE3(uint8_t* dst_argb, int width) {
7867
0
  asm volatile(
7868
0
      "movdqa      %2,%%xmm2                     \n"
7869
0
      "movdqa      %3,%%xmm3                     \n"
7870
0
      "movdqa      %4,%%xmm4                     \n"
7871
7872
      // 8 pixel loop.
7873
0
      LABELALIGN
7874
0
      "1:          \n"
7875
0
      "movdqu      (%0),%%xmm0                   \n"
7876
0
      "movdqu      0x10(%0),%%xmm6               \n"
7877
0
      "pmaddubsw   %%xmm2,%%xmm0                 \n"
7878
0
      "pmaddubsw   %%xmm2,%%xmm6                 \n"
7879
0
      "phaddw      %%xmm6,%%xmm0                 \n"
7880
0
      "psrlw       $0x7,%%xmm0                   \n"
7881
0
      "packuswb    %%xmm0,%%xmm0                 \n"
7882
0
      "movdqu      (%0),%%xmm5                   \n"
7883
0
      "movdqu      0x10(%0),%%xmm1               \n"
7884
0
      "pmaddubsw   %%xmm3,%%xmm5                 \n"
7885
0
      "pmaddubsw   %%xmm3,%%xmm1                 \n"
7886
0
      "phaddw      %%xmm1,%%xmm5                 \n"
7887
0
      "psrlw       $0x7,%%xmm5                   \n"
7888
0
      "packuswb    %%xmm5,%%xmm5                 \n"
7889
0
      "punpcklbw   %%xmm5,%%xmm0                 \n"
7890
0
      "movdqu      (%0),%%xmm5                   \n"
7891
0
      "movdqu      0x10(%0),%%xmm1               \n"
7892
0
      "pmaddubsw   %%xmm4,%%xmm5                 \n"
7893
0
      "pmaddubsw   %%xmm4,%%xmm1                 \n"
7894
0
      "phaddw      %%xmm1,%%xmm5                 \n"
7895
0
      "psrlw       $0x7,%%xmm5                   \n"
7896
0
      "packuswb    %%xmm5,%%xmm5                 \n"
7897
0
      "movdqu      (%0),%%xmm6                   \n"
7898
0
      "movdqu      0x10(%0),%%xmm1               \n"
7899
0
      "psrld       $0x18,%%xmm6                  \n"
7900
0
      "psrld       $0x18,%%xmm1                  \n"
7901
0
      "packuswb    %%xmm1,%%xmm6                 \n"
7902
0
      "packuswb    %%xmm6,%%xmm6                 \n"
7903
0
      "punpcklbw   %%xmm6,%%xmm5                 \n"
7904
0
      "movdqa      %%xmm0,%%xmm1                 \n"
7905
0
      "punpcklwd   %%xmm5,%%xmm0                 \n"
7906
0
      "punpckhwd   %%xmm5,%%xmm1                 \n"
7907
0
      "movdqu      %%xmm0,(%0)                   \n"
7908
0
      "movdqu      %%xmm1,0x10(%0)               \n"
7909
0
      "lea         0x20(%0),%0                   \n"
7910
0
      "sub         $0x8,%1                       \n"
7911
0
      "jg          1b                            \n"
7912
0
      : "+r"(dst_argb),      // %0
7913
0
        "+r"(width)          // %1
7914
0
      : "m"(kARGBToSepiaB),  // %2
7915
0
        "m"(kARGBToSepiaG),  // %3
7916
0
        "m"(kARGBToSepiaR)   // %4
7917
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
7918
0
}
7919
#endif  // HAS_ARGBSEPIAROW_SSSE3
7920
7921
#ifdef HAS_ARGBCOLORMATRIXROW_SSSE3
7922
// Tranform 8 ARGB pixels (32 bytes) with color matrix.
7923
// Same as Sepia except matrix is provided.
7924
void ARGBColorMatrixRow_SSSE3(const uint8_t* src_argb,
7925
                              uint8_t* dst_argb,
7926
                              const int8_t* matrix_argb,
7927
0
                              int width) {
7928
0
  asm volatile(
7929
0
      "movdqu      (%3),%%xmm5                   \n"
7930
0
      "pshufd      $0x00,%%xmm5,%%xmm2           \n"
7931
0
      "pshufd      $0x55,%%xmm5,%%xmm3           \n"
7932
0
      "pshufd      $0xaa,%%xmm5,%%xmm4           \n"
7933
0
      "pshufd      $0xff,%%xmm5,%%xmm5           \n"
7934
7935
      // 8 pixel loop.
7936
0
      LABELALIGN
7937
0
      "1:          \n"
7938
0
      "movdqu      (%0),%%xmm0                   \n"
7939
0
      "movdqu      0x10(%0),%%xmm7               \n"
7940
0
      "pmaddubsw   %%xmm2,%%xmm0                 \n"
7941
0
      "pmaddubsw   %%xmm2,%%xmm7                 \n"
7942
0
      "movdqu      (%0),%%xmm6                   \n"
7943
0
      "movdqu      0x10(%0),%%xmm1               \n"
7944
0
      "pmaddubsw   %%xmm3,%%xmm6                 \n"
7945
0
      "pmaddubsw   %%xmm3,%%xmm1                 \n"
7946
0
      "phaddsw     %%xmm7,%%xmm0                 \n"
7947
0
      "phaddsw     %%xmm1,%%xmm6                 \n"
7948
0
      "psraw       $0x6,%%xmm0                   \n"
7949
0
      "psraw       $0x6,%%xmm6                   \n"
7950
0
      "packuswb    %%xmm0,%%xmm0                 \n"
7951
0
      "packuswb    %%xmm6,%%xmm6                 \n"
7952
0
      "punpcklbw   %%xmm6,%%xmm0                 \n"
7953
0
      "movdqu      (%0),%%xmm1                   \n"
7954
0
      "movdqu      0x10(%0),%%xmm7               \n"
7955
0
      "pmaddubsw   %%xmm4,%%xmm1                 \n"
7956
0
      "pmaddubsw   %%xmm4,%%xmm7                 \n"
7957
0
      "phaddsw     %%xmm7,%%xmm1                 \n"
7958
0
      "movdqu      (%0),%%xmm6                   \n"
7959
0
      "movdqu      0x10(%0),%%xmm7               \n"
7960
0
      "pmaddubsw   %%xmm5,%%xmm6                 \n"
7961
0
      "pmaddubsw   %%xmm5,%%xmm7                 \n"
7962
0
      "phaddsw     %%xmm7,%%xmm6                 \n"
7963
0
      "psraw       $0x6,%%xmm1                   \n"
7964
0
      "psraw       $0x6,%%xmm6                   \n"
7965
0
      "packuswb    %%xmm1,%%xmm1                 \n"
7966
0
      "packuswb    %%xmm6,%%xmm6                 \n"
7967
0
      "punpcklbw   %%xmm6,%%xmm1                 \n"
7968
0
      "movdqa      %%xmm0,%%xmm6                 \n"
7969
0
      "punpcklwd   %%xmm1,%%xmm0                 \n"
7970
0
      "punpckhwd   %%xmm1,%%xmm6                 \n"
7971
0
      "movdqu      %%xmm0,(%1)                   \n"
7972
0
      "movdqu      %%xmm6,0x10(%1)               \n"
7973
0
      "lea         0x20(%0),%0                   \n"
7974
0
      "lea         0x20(%1),%1                   \n"
7975
0
      "sub         $0x8,%2                       \n"
7976
0
      "jg          1b                            \n"
7977
0
      : "+r"(src_argb),   // %0
7978
0
        "+r"(dst_argb),   // %1
7979
0
        "+r"(width)       // %2
7980
0
      : "r"(matrix_argb)  // %3
7981
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
7982
0
        "xmm7");
7983
0
}
7984
#endif  // HAS_ARGBCOLORMATRIXROW_SSSE3
7985
7986
#ifdef HAS_ARGBQUANTIZEROW_SSE2
7987
// Quantize 4 ARGB pixels (16 bytes).
7988
void ARGBQuantizeRow_SSE2(uint8_t* dst_argb,
7989
                          int scale,
7990
                          int interval_size,
7991
                          int interval_offset,
7992
0
                          int width) {
7993
0
  asm volatile(
7994
0
      "movd        %2,%%xmm2                     \n"
7995
0
      "movd        %3,%%xmm3                     \n"
7996
0
      "movd        %4,%%xmm4                     \n"
7997
0
      "pshuflw     $0x40,%%xmm2,%%xmm2           \n"
7998
0
      "pshufd      $0x44,%%xmm2,%%xmm2           \n"
7999
0
      "pshuflw     $0x40,%%xmm3,%%xmm3           \n"
8000
0
      "pshufd      $0x44,%%xmm3,%%xmm3           \n"
8001
0
      "pshuflw     $0x40,%%xmm4,%%xmm4           \n"
8002
0
      "pshufd      $0x44,%%xmm4,%%xmm4           \n"
8003
0
      "pxor        %%xmm5,%%xmm5                 \n"
8004
0
      "pcmpeqb     %%xmm6,%%xmm6                 \n"
8005
0
      "pslld       $0x18,%%xmm6                  \n"
8006
8007
      // 4 pixel loop.
8008
0
      LABELALIGN
8009
0
      "1:          \n"
8010
0
      "movdqu      (%0),%%xmm0                   \n"
8011
0
      "punpcklbw   %%xmm5,%%xmm0                 \n"
8012
0
      "pmulhuw     %%xmm2,%%xmm0                 \n"
8013
0
      "movdqu      (%0),%%xmm1                   \n"
8014
0
      "punpckhbw   %%xmm5,%%xmm1                 \n"
8015
0
      "pmulhuw     %%xmm2,%%xmm1                 \n"
8016
0
      "pmullw      %%xmm3,%%xmm0                 \n"
8017
0
      "movdqu      (%0),%%xmm7                   \n"
8018
0
      "pmullw      %%xmm3,%%xmm1                 \n"
8019
0
      "pand        %%xmm6,%%xmm7                 \n"
8020
0
      "paddw       %%xmm4,%%xmm0                 \n"
8021
0
      "paddw       %%xmm4,%%xmm1                 \n"
8022
0
      "packuswb    %%xmm1,%%xmm0                 \n"
8023
0
      "por         %%xmm7,%%xmm0                 \n"
8024
0
      "movdqu      %%xmm0,(%0)                   \n"
8025
0
      "lea         0x10(%0),%0                   \n"
8026
0
      "sub         $0x4,%1                       \n"
8027
0
      "jg          1b                            \n"
8028
0
      : "+r"(dst_argb),       // %0
8029
0
        "+r"(width)           // %1
8030
0
      : "r"(scale),           // %2
8031
0
        "r"(interval_size),   // %3
8032
0
        "r"(interval_offset)  // %4
8033
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
8034
0
        "xmm7");
8035
0
}
8036
#endif  // HAS_ARGBQUANTIZEROW_SSE2
8037
8038
#ifdef HAS_ARGBSHADEROW_SSE2
8039
// Shade 4 pixels at a time by specified value.
8040
void ARGBShadeRow_SSE2(const uint8_t* src_argb,
8041
                       uint8_t* dst_argb,
8042
                       int width,
8043
0
                       uint32_t value) {
8044
0
  asm volatile(
8045
0
      "movd        %3,%%xmm2                     \n"
8046
0
      "punpcklbw   %%xmm2,%%xmm2                 \n"
8047
0
      "punpcklqdq  %%xmm2,%%xmm2                 \n"
8048
8049
      // 4 pixel loop.
8050
0
      LABELALIGN
8051
0
      "1:          \n"
8052
0
      "movdqu      (%0),%%xmm0                   \n"
8053
0
      "lea         0x10(%0),%0                   \n"
8054
0
      "movdqa      %%xmm0,%%xmm1                 \n"
8055
0
      "punpcklbw   %%xmm0,%%xmm0                 \n"
8056
0
      "punpckhbw   %%xmm1,%%xmm1                 \n"
8057
0
      "pmulhuw     %%xmm2,%%xmm0                 \n"
8058
0
      "pmulhuw     %%xmm2,%%xmm1                 \n"
8059
0
      "psrlw       $0x8,%%xmm0                   \n"
8060
0
      "psrlw       $0x8,%%xmm1                   \n"
8061
0
      "packuswb    %%xmm1,%%xmm0                 \n"
8062
0
      "movdqu      %%xmm0,(%1)                   \n"
8063
0
      "lea         0x10(%1),%1                   \n"
8064
0
      "sub         $0x4,%2                       \n"
8065
0
      "jg          1b                            \n"
8066
0
      : "+r"(src_argb),  // %0
8067
0
        "+r"(dst_argb),  // %1
8068
0
        "+r"(width)      // %2
8069
0
      : "r"(value)       // %3
8070
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2");
8071
0
}
8072
#endif  // HAS_ARGBSHADEROW_SSE2
8073
8074
#ifdef HAS_ARGBMULTIPLYROW_SSE2
8075
// Multiply 2 rows of ARGB pixels together, 4 pixels at a time.
8076
void ARGBMultiplyRow_SSE2(const uint8_t* src_argb,
8077
                          const uint8_t* src_argb1,
8078
                          uint8_t* dst_argb,
8079
                          int width) {
8080
  asm volatile("pxor        %%xmm5,%%xmm5                 \n"
8081
8082
               // 4 pixel loop.
8083
               LABELALIGN
8084
               "1:          \n"
8085
               "movdqu      (%0),%%xmm0                   \n"
8086
               "lea         0x10(%0),%0                   \n"
8087
               "movdqu      (%1),%%xmm2                   \n"
8088
               "lea         0x10(%1),%1                   \n"
8089
               "movdqu      %%xmm0,%%xmm1                 \n"
8090
               "movdqu      %%xmm2,%%xmm3                 \n"
8091
               "punpcklbw   %%xmm0,%%xmm0                 \n"
8092
               "punpckhbw   %%xmm1,%%xmm1                 \n"
8093
               "punpcklbw   %%xmm5,%%xmm2                 \n"
8094
               "punpckhbw   %%xmm5,%%xmm3                 \n"
8095
               "pmulhuw     %%xmm2,%%xmm0                 \n"
8096
               "pmulhuw     %%xmm3,%%xmm1                 \n"
8097
               "packuswb    %%xmm1,%%xmm0                 \n"
8098
               "movdqu      %%xmm0,(%2)                   \n"
8099
               "lea         0x10(%2),%2                   \n"
8100
               "sub         $0x4,%3                       \n"
8101
               "jg          1b                            \n"
8102
               : "+r"(src_argb),   // %0
8103
                 "+r"(src_argb1),  // %1
8104
                 "+r"(dst_argb),   // %2
8105
                 "+r"(width)       // %3
8106
               :
8107
               : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5");
8108
}
8109
#endif  // HAS_ARGBMULTIPLYROW_SSE2
8110
8111
#ifdef HAS_ARGBMULTIPLYROW_AVX2
8112
// Multiply 2 rows of ARGB pixels together, 8 pixels at a time.
8113
void ARGBMultiplyRow_AVX2(const uint8_t* src_argb,
8114
                          const uint8_t* src_argb1,
8115
                          uint8_t* dst_argb,
8116
                          int width) {
8117
  asm volatile("vpxor       %%ymm5,%%ymm5,%%ymm5          \n"
8118
8119
               // 4 pixel loop.
8120
               LABELALIGN
8121
               "1:          \n"
8122
               "vmovdqu     (%0),%%ymm1                   \n"
8123
               "lea         0x20(%0),%0                   \n"
8124
               "vmovdqu     (%1),%%ymm3                   \n"
8125
               "lea         0x20(%1),%1                   \n"
8126
               "vpunpcklbw  %%ymm1,%%ymm1,%%ymm0          \n"
8127
               "vpunpckhbw  %%ymm1,%%ymm1,%%ymm1          \n"
8128
               "vpunpcklbw  %%ymm5,%%ymm3,%%ymm2          \n"
8129
               "vpunpckhbw  %%ymm5,%%ymm3,%%ymm3          \n"
8130
               "vpmulhuw    %%ymm2,%%ymm0,%%ymm0          \n"
8131
               "vpmulhuw    %%ymm3,%%ymm1,%%ymm1          \n"
8132
               "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"
8133
               "vmovdqu     %%ymm0,(%2)                   \n"
8134
               "lea         0x20(%2),%2                   \n"
8135
               "sub         $0x8,%3                       \n"
8136
               "jg          1b                            \n"
8137
               "vzeroupper  \n"
8138
               : "+r"(src_argb),   // %0
8139
                 "+r"(src_argb1),  // %1
8140
                 "+r"(dst_argb),   // %2
8141
                 "+r"(width)       // %3
8142
               :
8143
               : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5");
8144
}
8145
#endif  // HAS_ARGBMULTIPLYROW_AVX2
8146
8147
#ifdef HAS_ARGBADDROW_SSE2
8148
// Add 2 rows of ARGB pixels together, 4 pixels at a time.
8149
void ARGBAddRow_SSE2(const uint8_t* src_argb,
8150
                     const uint8_t* src_argb1,
8151
                     uint8_t* dst_argb,
8152
0
                     int width) {
8153
0
  asm volatile(
8154
      // 4 pixel loop.
8155
0
      LABELALIGN
8156
0
      "1:          \n"
8157
0
      "movdqu      (%0),%%xmm0                   \n"
8158
0
      "lea         0x10(%0),%0                   \n"
8159
0
      "movdqu      (%1),%%xmm1                   \n"
8160
0
      "lea         0x10(%1),%1                   \n"
8161
0
      "paddusb     %%xmm1,%%xmm0                 \n"
8162
0
      "movdqu      %%xmm0,(%2)                   \n"
8163
0
      "lea         0x10(%2),%2                   \n"
8164
0
      "sub         $0x4,%3                       \n"
8165
0
      "jg          1b                            \n"
8166
0
      : "+r"(src_argb),   // %0
8167
0
        "+r"(src_argb1),  // %1
8168
0
        "+r"(dst_argb),   // %2
8169
0
        "+r"(width)       // %3
8170
0
      :
8171
0
      : "memory", "cc", "xmm0", "xmm1");
8172
0
}
8173
#endif  // HAS_ARGBADDROW_SSE2
8174
8175
#ifdef HAS_ARGBADDROW_AVX2
8176
// Add 2 rows of ARGB pixels together, 4 pixels at a time.
8177
void ARGBAddRow_AVX2(const uint8_t* src_argb,
8178
                     const uint8_t* src_argb1,
8179
                     uint8_t* dst_argb,
8180
0
                     int width) {
8181
0
  asm volatile(
8182
      // 4 pixel loop.
8183
0
      LABELALIGN
8184
0
      "1:          \n"
8185
0
      "vmovdqu     (%0),%%ymm0                   \n"
8186
0
      "lea         0x20(%0),%0                   \n"
8187
0
      "vpaddusb    (%1),%%ymm0,%%ymm0            \n"
8188
0
      "lea         0x20(%1),%1                   \n"
8189
0
      "vmovdqu     %%ymm0,(%2)                   \n"
8190
0
      "lea         0x20(%2),%2                   \n"
8191
0
      "sub         $0x8,%3                       \n"
8192
0
      "jg          1b                            \n"
8193
0
      "vzeroupper  \n"
8194
0
      : "+r"(src_argb),   // %0
8195
0
        "+r"(src_argb1),  // %1
8196
0
        "+r"(dst_argb),   // %2
8197
0
        "+r"(width)       // %3
8198
0
      :
8199
0
      : "memory", "cc", "xmm0");
8200
0
}
8201
#endif  // HAS_ARGBADDROW_AVX2
8202
8203
#ifdef HAS_ARGBSUBTRACTROW_SSE2
8204
// Subtract 2 rows of ARGB pixels, 4 pixels at a time.
8205
void ARGBSubtractRow_SSE2(const uint8_t* src_argb,
8206
                          const uint8_t* src_argb1,
8207
                          uint8_t* dst_argb,
8208
0
                          int width) {
8209
0
  asm volatile(
8210
      // 4 pixel loop.
8211
0
      LABELALIGN
8212
0
      "1:          \n"
8213
0
      "movdqu      (%0),%%xmm0                   \n"
8214
0
      "lea         0x10(%0),%0                   \n"
8215
0
      "movdqu      (%1),%%xmm1                   \n"
8216
0
      "lea         0x10(%1),%1                   \n"
8217
0
      "psubusb     %%xmm1,%%xmm0                 \n"
8218
0
      "movdqu      %%xmm0,(%2)                   \n"
8219
0
      "lea         0x10(%2),%2                   \n"
8220
0
      "sub         $0x4,%3                       \n"
8221
0
      "jg          1b                            \n"
8222
0
      : "+r"(src_argb),   // %0
8223
0
        "+r"(src_argb1),  // %1
8224
0
        "+r"(dst_argb),   // %2
8225
0
        "+r"(width)       // %3
8226
0
      :
8227
0
      : "memory", "cc", "xmm0", "xmm1");
8228
0
}
8229
#endif  // HAS_ARGBSUBTRACTROW_SSE2
8230
8231
#ifdef HAS_ARGBSUBTRACTROW_AVX2
8232
// Subtract 2 rows of ARGB pixels, 8 pixels at a time.
8233
void ARGBSubtractRow_AVX2(const uint8_t* src_argb,
8234
                          const uint8_t* src_argb1,
8235
                          uint8_t* dst_argb,
8236
0
                          int width) {
8237
0
  asm volatile(
8238
      // 4 pixel loop.
8239
0
      LABELALIGN
8240
0
      "1:          \n"
8241
0
      "vmovdqu     (%0),%%ymm0                   \n"
8242
0
      "lea         0x20(%0),%0                   \n"
8243
0
      "vpsubusb    (%1),%%ymm0,%%ymm0            \n"
8244
0
      "lea         0x20(%1),%1                   \n"
8245
0
      "vmovdqu     %%ymm0,(%2)                   \n"
8246
0
      "lea         0x20(%2),%2                   \n"
8247
0
      "sub         $0x8,%3                       \n"
8248
0
      "jg          1b                            \n"
8249
0
      "vzeroupper  \n"
8250
0
      : "+r"(src_argb),   // %0
8251
0
        "+r"(src_argb1),  // %1
8252
0
        "+r"(dst_argb),   // %2
8253
0
        "+r"(width)       // %3
8254
0
      :
8255
0
      : "memory", "cc", "xmm0");
8256
0
}
8257
#endif  // HAS_ARGBSUBTRACTROW_AVX2
8258
8259
#ifdef HAS_SOBELXROW_SSE2
8260
// SobelX as a matrix is
8261
// -1  0  1
8262
// -2  0  2
8263
// -1  0  1
8264
void SobelXRow_SSE2(const uint8_t* src_y0,
8265
                    const uint8_t* src_y1,
8266
                    const uint8_t* src_y2,
8267
                    uint8_t* dst_sobelx,
8268
0
                    int width) {
8269
0
  asm volatile(
8270
0
      "sub         %0,%1                         \n"
8271
0
      "sub         %0,%2                         \n"
8272
0
      "sub         %0,%3                         \n"
8273
0
      "pxor        %%xmm5,%%xmm5                 \n"
8274
8275
      // 8 pixel loop.
8276
0
      LABELALIGN
8277
0
      "1:          \n"
8278
0
      "movq        (%0),%%xmm0                   \n"
8279
0
      "movq        0x2(%0),%%xmm1                \n"
8280
0
      "punpcklbw   %%xmm5,%%xmm0                 \n"
8281
0
      "punpcklbw   %%xmm5,%%xmm1                 \n"
8282
0
      "psubw       %%xmm1,%%xmm0                 \n"
8283
0
      "movq        0x00(%0,%1,1),%%xmm1          \n"
8284
0
      "movq        0x02(%0,%1,1),%%xmm2          \n"
8285
0
      "punpcklbw   %%xmm5,%%xmm1                 \n"
8286
0
      "punpcklbw   %%xmm5,%%xmm2                 \n"
8287
0
      "psubw       %%xmm2,%%xmm1                 \n"
8288
0
      "movq        0x00(%0,%2,1),%%xmm2          \n"
8289
0
      "movq        0x02(%0,%2,1),%%xmm3          \n"
8290
0
      "punpcklbw   %%xmm5,%%xmm2                 \n"
8291
0
      "punpcklbw   %%xmm5,%%xmm3                 \n"
8292
0
      "psubw       %%xmm3,%%xmm2                 \n"
8293
0
      "paddw       %%xmm2,%%xmm0                 \n"
8294
0
      "paddw       %%xmm1,%%xmm0                 \n"
8295
0
      "paddw       %%xmm1,%%xmm0                 \n"
8296
0
      "pxor        %%xmm1,%%xmm1                 \n"
8297
0
      "psubw       %%xmm0,%%xmm1                 \n"
8298
0
      "pmaxsw      %%xmm1,%%xmm0                 \n"
8299
0
      "packuswb    %%xmm0,%%xmm0                 \n"
8300
0
      "movq        %%xmm0,0x00(%0,%3,1)          \n"
8301
0
      "lea         0x8(%0),%0                    \n"
8302
0
      "sub         $0x8,%4                       \n"
8303
0
      "jg          1b                            \n"
8304
0
      : "+r"(src_y0),      // %0
8305
0
        "+r"(src_y1),      // %1
8306
0
        "+r"(src_y2),      // %2
8307
0
        "+r"(dst_sobelx),  // %3
8308
0
        "+r"(width)        // %4
8309
0
      :
8310
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5");
8311
0
}
8312
#endif  // HAS_SOBELXROW_SSE2
8313
8314
#ifdef HAS_SOBELYROW_SSE2
8315
// SobelY as a matrix is
8316
// -1 -2 -1
8317
//  0  0  0
8318
//  1  2  1
8319
void SobelYRow_SSE2(const uint8_t* src_y0,
8320
                    const uint8_t* src_y1,
8321
                    uint8_t* dst_sobely,
8322
0
                    int width) {
8323
0
  asm volatile(
8324
0
      "sub         %0,%1                         \n"
8325
0
      "sub         %0,%2                         \n"
8326
0
      "pxor        %%xmm5,%%xmm5                 \n"
8327
8328
      // 8 pixel loop.
8329
0
      LABELALIGN
8330
0
      "1:          \n"
8331
0
      "movq        (%0),%%xmm0                   \n"
8332
0
      "movq        0x00(%0,%1,1),%%xmm1          \n"
8333
0
      "punpcklbw   %%xmm5,%%xmm0                 \n"
8334
0
      "punpcklbw   %%xmm5,%%xmm1                 \n"
8335
0
      "psubw       %%xmm1,%%xmm0                 \n"
8336
0
      "movq        0x1(%0),%%xmm1                \n"
8337
0
      "movq        0x01(%0,%1,1),%%xmm2          \n"
8338
0
      "punpcklbw   %%xmm5,%%xmm1                 \n"
8339
0
      "punpcklbw   %%xmm5,%%xmm2                 \n"
8340
0
      "psubw       %%xmm2,%%xmm1                 \n"
8341
0
      "movq        0x2(%0),%%xmm2                \n"
8342
0
      "movq        0x02(%0,%1,1),%%xmm3          \n"
8343
0
      "punpcklbw   %%xmm5,%%xmm2                 \n"
8344
0
      "punpcklbw   %%xmm5,%%xmm3                 \n"
8345
0
      "psubw       %%xmm3,%%xmm2                 \n"
8346
0
      "paddw       %%xmm2,%%xmm0                 \n"
8347
0
      "paddw       %%xmm1,%%xmm0                 \n"
8348
0
      "paddw       %%xmm1,%%xmm0                 \n"
8349
0
      "pxor        %%xmm1,%%xmm1                 \n"
8350
0
      "psubw       %%xmm0,%%xmm1                 \n"
8351
0
      "pmaxsw      %%xmm1,%%xmm0                 \n"
8352
0
      "packuswb    %%xmm0,%%xmm0                 \n"
8353
0
      "movq        %%xmm0,0x00(%0,%2,1)          \n"
8354
0
      "lea         0x8(%0),%0                    \n"
8355
0
      "sub         $0x8,%3                       \n"
8356
0
      "jg          1b                            \n"
8357
0
      : "+r"(src_y0),      // %0
8358
0
        "+r"(src_y1),      // %1
8359
0
        "+r"(dst_sobely),  // %2
8360
0
        "+r"(width)        // %3
8361
0
      :
8362
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5");
8363
0
}
8364
#endif  // HAS_SOBELYROW_SSE2
8365
8366
#ifdef HAS_SOBELROW_SSE2
8367
// Adds Sobel X and Sobel Y and stores Sobel into ARGB.
8368
// A = 255
8369
// R = Sobel
8370
// G = Sobel
8371
// B = Sobel
8372
void SobelRow_SSE2(const uint8_t* src_sobelx,
8373
                   const uint8_t* src_sobely,
8374
                   uint8_t* dst_argb,
8375
0
                   int width) {
8376
0
  asm volatile(
8377
0
      "sub         %0,%1                         \n"
8378
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
8379
0
      "pslld       $0x18,%%xmm5                  \n"
8380
8381
      // 8 pixel loop.
8382
0
      LABELALIGN
8383
0
      "1:          \n"
8384
0
      "movdqu      (%0),%%xmm0                   \n"
8385
0
      "movdqu      0x00(%0,%1,1),%%xmm1          \n"
8386
0
      "lea         0x10(%0),%0                   \n"
8387
0
      "paddusb     %%xmm1,%%xmm0                 \n"
8388
0
      "movdqa      %%xmm0,%%xmm2                 \n"
8389
0
      "punpcklbw   %%xmm0,%%xmm2                 \n"
8390
0
      "punpckhbw   %%xmm0,%%xmm0                 \n"
8391
0
      "movdqa      %%xmm2,%%xmm1                 \n"
8392
0
      "punpcklwd   %%xmm2,%%xmm1                 \n"
8393
0
      "punpckhwd   %%xmm2,%%xmm2                 \n"
8394
0
      "por         %%xmm5,%%xmm1                 \n"
8395
0
      "por         %%xmm5,%%xmm2                 \n"
8396
0
      "movdqa      %%xmm0,%%xmm3                 \n"
8397
0
      "punpcklwd   %%xmm0,%%xmm3                 \n"
8398
0
      "punpckhwd   %%xmm0,%%xmm0                 \n"
8399
0
      "por         %%xmm5,%%xmm3                 \n"
8400
0
      "por         %%xmm5,%%xmm0                 \n"
8401
0
      "movdqu      %%xmm1,(%2)                   \n"
8402
0
      "movdqu      %%xmm2,0x10(%2)               \n"
8403
0
      "movdqu      %%xmm3,0x20(%2)               \n"
8404
0
      "movdqu      %%xmm0,0x30(%2)               \n"
8405
0
      "lea         0x40(%2),%2                   \n"
8406
0
      "sub         $0x10,%3                      \n"
8407
0
      "jg          1b                            \n"
8408
0
      : "+r"(src_sobelx),  // %0
8409
0
        "+r"(src_sobely),  // %1
8410
0
        "+r"(dst_argb),    // %2
8411
0
        "+r"(width)        // %3
8412
0
      :
8413
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5");
8414
0
}
8415
#endif  // HAS_SOBELROW_SSE2
8416
8417
#ifdef HAS_SOBELTOPLANEROW_SSE2
8418
// Adds Sobel X and Sobel Y and stores Sobel into a plane.
8419
void SobelToPlaneRow_SSE2(const uint8_t* src_sobelx,
8420
                          const uint8_t* src_sobely,
8421
                          uint8_t* dst_y,
8422
0
                          int width) {
8423
0
  asm volatile(
8424
0
      "sub         %0,%1                         \n"
8425
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
8426
0
      "pslld       $0x18,%%xmm5                  \n"
8427
8428
      // 8 pixel loop.
8429
0
      LABELALIGN
8430
0
      "1:          \n"
8431
0
      "movdqu      (%0),%%xmm0                   \n"
8432
0
      "movdqu      0x00(%0,%1,1),%%xmm1          \n"
8433
0
      "lea         0x10(%0),%0                   \n"
8434
0
      "paddusb     %%xmm1,%%xmm0                 \n"
8435
0
      "movdqu      %%xmm0,(%2)                   \n"
8436
0
      "lea         0x10(%2),%2                   \n"
8437
0
      "sub         $0x10,%3                      \n"
8438
0
      "jg          1b                            \n"
8439
0
      : "+r"(src_sobelx),  // %0
8440
0
        "+r"(src_sobely),  // %1
8441
0
        "+r"(dst_y),       // %2
8442
0
        "+r"(width)        // %3
8443
0
      :
8444
0
      : "memory", "cc", "xmm0", "xmm1");
8445
0
}
8446
#endif  // HAS_SOBELTOPLANEROW_SSE2
8447
8448
#ifdef HAS_SOBELXYROW_SSE2
8449
// Mixes Sobel X, Sobel Y and Sobel into ARGB.
8450
// A = 255
8451
// R = Sobel X
8452
// G = Sobel
8453
// B = Sobel Y
8454
void SobelXYRow_SSE2(const uint8_t* src_sobelx,
8455
                     const uint8_t* src_sobely,
8456
                     uint8_t* dst_argb,
8457
0
                     int width) {
8458
0
  asm volatile(
8459
0
      "sub         %0,%1                         \n"
8460
0
      "pcmpeqb     %%xmm5,%%xmm5                 \n"
8461
8462
      // 8 pixel loop.
8463
0
      LABELALIGN
8464
0
      "1:          \n"
8465
0
      "movdqu      (%0),%%xmm0                   \n"
8466
0
      "movdqu      0x00(%0,%1,1),%%xmm1          \n"
8467
0
      "lea         0x10(%0),%0                   \n"
8468
0
      "movdqa      %%xmm0,%%xmm2                 \n"
8469
0
      "paddusb     %%xmm1,%%xmm2                 \n"
8470
0
      "movdqa      %%xmm0,%%xmm3                 \n"
8471
0
      "punpcklbw   %%xmm5,%%xmm3                 \n"
8472
0
      "punpckhbw   %%xmm5,%%xmm0                 \n"
8473
0
      "movdqa      %%xmm1,%%xmm4                 \n"
8474
0
      "punpcklbw   %%xmm2,%%xmm4                 \n"
8475
0
      "punpckhbw   %%xmm2,%%xmm1                 \n"
8476
0
      "movdqa      %%xmm4,%%xmm6                 \n"
8477
0
      "punpcklwd   %%xmm3,%%xmm6                 \n"
8478
0
      "punpckhwd   %%xmm3,%%xmm4                 \n"
8479
0
      "movdqa      %%xmm1,%%xmm7                 \n"
8480
0
      "punpcklwd   %%xmm0,%%xmm7                 \n"
8481
0
      "punpckhwd   %%xmm0,%%xmm1                 \n"
8482
0
      "movdqu      %%xmm6,(%2)                   \n"
8483
0
      "movdqu      %%xmm4,0x10(%2)               \n"
8484
0
      "movdqu      %%xmm7,0x20(%2)               \n"
8485
0
      "movdqu      %%xmm1,0x30(%2)               \n"
8486
0
      "lea         0x40(%2),%2                   \n"
8487
0
      "sub         $0x10,%3                      \n"
8488
0
      "jg          1b                            \n"
8489
0
      : "+r"(src_sobelx),  // %0
8490
0
        "+r"(src_sobely),  // %1
8491
0
        "+r"(dst_argb),    // %2
8492
0
        "+r"(width)        // %3
8493
0
      :
8494
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
8495
0
        "xmm7");
8496
0
}
8497
#endif  // HAS_SOBELXYROW_SSE2
8498
8499
#ifdef HAS_COMPUTECUMULATIVESUMROW_SSE2
8500
// Creates a table of cumulative sums where each value is a sum of all values
8501
// above and to the left of the value, inclusive of the value.
8502
void ComputeCumulativeSumRow_SSE2(const uint8_t* row,
8503
                                  int32_t* cumsum,
8504
                                  const int32_t* previous_cumsum,
8505
0
                                  int width) {
8506
0
  asm volatile(
8507
0
      "pxor        %%xmm0,%%xmm0                 \n"
8508
0
      "pxor        %%xmm1,%%xmm1                 \n"
8509
0
      "sub         $0x4,%3                       \n"
8510
0
      "jl          49f                           \n"
8511
0
      "test        $0xf,%1                       \n"
8512
0
      "jne         49f                           \n"
8513
8514
      // 4 pixel loop.
8515
0
      LABELALIGN
8516
0
      "40:         \n"
8517
0
      "movdqu      (%0),%%xmm2                   \n"
8518
0
      "lea         0x10(%0),%0                   \n"
8519
0
      "movdqa      %%xmm2,%%xmm4                 \n"
8520
0
      "punpcklbw   %%xmm1,%%xmm2                 \n"
8521
0
      "movdqa      %%xmm2,%%xmm3                 \n"
8522
0
      "punpcklwd   %%xmm1,%%xmm2                 \n"
8523
0
      "punpckhwd   %%xmm1,%%xmm3                 \n"
8524
0
      "punpckhbw   %%xmm1,%%xmm4                 \n"
8525
0
      "movdqa      %%xmm4,%%xmm5                 \n"
8526
0
      "punpcklwd   %%xmm1,%%xmm4                 \n"
8527
0
      "punpckhwd   %%xmm1,%%xmm5                 \n"
8528
0
      "paddd       %%xmm2,%%xmm0                 \n"
8529
0
      "movdqu      (%2),%%xmm2                   \n"
8530
0
      "paddd       %%xmm0,%%xmm2                 \n"
8531
0
      "paddd       %%xmm3,%%xmm0                 \n"
8532
0
      "movdqu      0x10(%2),%%xmm3               \n"
8533
0
      "paddd       %%xmm0,%%xmm3                 \n"
8534
0
      "paddd       %%xmm4,%%xmm0                 \n"
8535
0
      "movdqu      0x20(%2),%%xmm4               \n"
8536
0
      "paddd       %%xmm0,%%xmm4                 \n"
8537
0
      "paddd       %%xmm5,%%xmm0                 \n"
8538
0
      "movdqu      0x30(%2),%%xmm5               \n"
8539
0
      "lea         0x40(%2),%2                   \n"
8540
0
      "paddd       %%xmm0,%%xmm5                 \n"
8541
0
      "movdqu      %%xmm2,(%1)                   \n"
8542
0
      "movdqu      %%xmm3,0x10(%1)               \n"
8543
0
      "movdqu      %%xmm4,0x20(%1)               \n"
8544
0
      "movdqu      %%xmm5,0x30(%1)               \n"
8545
0
      "lea         0x40(%1),%1                   \n"
8546
0
      "sub         $0x4,%3                       \n"
8547
0
      "jge         40b                           \n"
8548
8549
0
      "49:         \n"
8550
0
      "add         $0x3,%3                       \n"
8551
0
      "jl          19f                           \n"
8552
8553
      // 1 pixel loop.
8554
0
      LABELALIGN
8555
0
      "10:         \n"
8556
0
      "movd        (%0),%%xmm2                   \n"
8557
0
      "lea         0x4(%0),%0                    \n"
8558
0
      "punpcklbw   %%xmm1,%%xmm2                 \n"
8559
0
      "punpcklwd   %%xmm1,%%xmm2                 \n"
8560
0
      "paddd       %%xmm2,%%xmm0                 \n"
8561
0
      "movdqu      (%2),%%xmm2                   \n"
8562
0
      "lea         0x10(%2),%2                   \n"
8563
0
      "paddd       %%xmm0,%%xmm2                 \n"
8564
0
      "movdqu      %%xmm2,(%1)                   \n"
8565
0
      "lea         0x10(%1),%1                   \n"
8566
0
      "sub         $0x1,%3                       \n"
8567
0
      "jge         10b                           \n"
8568
8569
0
      "19:         \n"
8570
0
      : "+r"(row),              // %0
8571
0
        "+r"(cumsum),           // %1
8572
0
        "+r"(previous_cumsum),  // %2
8573
0
        "+r"(width)             // %3
8574
0
      :
8575
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
8576
0
}
8577
#endif  // HAS_COMPUTECUMULATIVESUMROW_SSE2
8578
8579
#ifdef HAS_CUMULATIVESUMTOAVERAGEROW_SSE2
8580
void CumulativeSumToAverageRow_SSE2(const int32_t* topleft,
8581
                                    const int32_t* botleft,
8582
                                    int width,
8583
                                    int area,
8584
                                    uint8_t* dst,
8585
0
                                    int count) {
8586
0
  asm volatile(
8587
0
      "movd        %5,%%xmm5                     \n"
8588
0
      "cvtdq2ps    %%xmm5,%%xmm5                 \n"
8589
0
      "rcpss       %%xmm5,%%xmm4                 \n"
8590
0
      "pshufd      $0x0,%%xmm4,%%xmm4            \n"
8591
0
      "sub         $0x4,%3                       \n"
8592
0
      "jl          49f                           \n"
8593
0
      "cmpl        $0x80,%5                      \n"
8594
0
      "ja          40f                           \n"
8595
8596
0
      "pshufd      $0x0,%%xmm5,%%xmm5            \n"
8597
0
      "pcmpeqb     %%xmm6,%%xmm6                 \n"
8598
0
      "psrld       $0x10,%%xmm6                  \n"
8599
0
      "cvtdq2ps    %%xmm6,%%xmm6                 \n"
8600
0
      "addps       %%xmm6,%%xmm5                 \n"
8601
0
      "mulps       %%xmm4,%%xmm5                 \n"
8602
0
      "cvtps2dq    %%xmm5,%%xmm5                 \n"
8603
0
      "packssdw    %%xmm5,%%xmm5                 \n"
8604
8605
      // 4 pixel small loop.
8606
0
      LABELALIGN
8607
0
      "4:          \n"
8608
0
      "movdqu      (%0),%%xmm0                   \n"
8609
0
      "movdqu      0x10(%0),%%xmm1               \n"
8610
0
      "movdqu      0x20(%0),%%xmm2               \n"
8611
0
      "movdqu      0x30(%0),%%xmm3               \n"
8612
0
      "psubd       0x00(%0,%4,4),%%xmm0          \n"
8613
0
      "psubd       0x10(%0,%4,4),%%xmm1          \n"
8614
0
      "psubd       0x20(%0,%4,4),%%xmm2          \n"
8615
0
      "psubd       0x30(%0,%4,4),%%xmm3          \n"
8616
0
      "lea         0x40(%0),%0                   \n"
8617
0
      "psubd       (%1),%%xmm0                   \n"
8618
0
      "psubd       0x10(%1),%%xmm1               \n"
8619
0
      "psubd       0x20(%1),%%xmm2               \n"
8620
0
      "psubd       0x30(%1),%%xmm3               \n"
8621
0
      "paddd       0x00(%1,%4,4),%%xmm0          \n"
8622
0
      "paddd       0x10(%1,%4,4),%%xmm1          \n"
8623
0
      "paddd       0x20(%1,%4,4),%%xmm2          \n"
8624
0
      "paddd       0x30(%1,%4,4),%%xmm3          \n"
8625
0
      "lea         0x40(%1),%1                   \n"
8626
0
      "packssdw    %%xmm1,%%xmm0                 \n"
8627
0
      "packssdw    %%xmm3,%%xmm2                 \n"
8628
0
      "pmulhuw     %%xmm5,%%xmm0                 \n"
8629
0
      "pmulhuw     %%xmm5,%%xmm2                 \n"
8630
0
      "packuswb    %%xmm2,%%xmm0                 \n"
8631
0
      "movdqu      %%xmm0,(%2)                   \n"
8632
0
      "lea         0x10(%2),%2                   \n"
8633
0
      "sub         $0x4,%3                       \n"
8634
0
      "jge         4b                            \n"
8635
0
      "jmp         49f                           \n"
8636
8637
      // 4 pixel loop
8638
0
      LABELALIGN
8639
0
      "40:         \n"
8640
0
      "movdqu      (%0),%%xmm0                   \n"
8641
0
      "movdqu      0x10(%0),%%xmm1               \n"
8642
0
      "movdqu      0x20(%0),%%xmm2               \n"
8643
0
      "movdqu      0x30(%0),%%xmm3               \n"
8644
0
      "psubd       0x00(%0,%4,4),%%xmm0          \n"
8645
0
      "psubd       0x10(%0,%4,4),%%xmm1          \n"
8646
0
      "psubd       0x20(%0,%4,4),%%xmm2          \n"
8647
0
      "psubd       0x30(%0,%4,4),%%xmm3          \n"
8648
0
      "lea         0x40(%0),%0                   \n"
8649
0
      "psubd       (%1),%%xmm0                   \n"
8650
0
      "psubd       0x10(%1),%%xmm1               \n"
8651
0
      "psubd       0x20(%1),%%xmm2               \n"
8652
0
      "psubd       0x30(%1),%%xmm3               \n"
8653
0
      "paddd       0x00(%1,%4,4),%%xmm0          \n"
8654
0
      "paddd       0x10(%1,%4,4),%%xmm1          \n"
8655
0
      "paddd       0x20(%1,%4,4),%%xmm2          \n"
8656
0
      "paddd       0x30(%1,%4,4),%%xmm3          \n"
8657
0
      "lea         0x40(%1),%1                   \n"
8658
0
      "cvtdq2ps    %%xmm0,%%xmm0                 \n"
8659
0
      "cvtdq2ps    %%xmm1,%%xmm1                 \n"
8660
0
      "mulps       %%xmm4,%%xmm0                 \n"
8661
0
      "mulps       %%xmm4,%%xmm1                 \n"
8662
0
      "cvtdq2ps    %%xmm2,%%xmm2                 \n"
8663
0
      "cvtdq2ps    %%xmm3,%%xmm3                 \n"
8664
0
      "mulps       %%xmm4,%%xmm2                 \n"
8665
0
      "mulps       %%xmm4,%%xmm3                 \n"
8666
0
      "cvtps2dq    %%xmm0,%%xmm0                 \n"
8667
0
      "cvtps2dq    %%xmm1,%%xmm1                 \n"
8668
0
      "cvtps2dq    %%xmm2,%%xmm2                 \n"
8669
0
      "cvtps2dq    %%xmm3,%%xmm3                 \n"
8670
0
      "packssdw    %%xmm1,%%xmm0                 \n"
8671
0
      "packssdw    %%xmm3,%%xmm2                 \n"
8672
0
      "packuswb    %%xmm2,%%xmm0                 \n"
8673
0
      "movdqu      %%xmm0,(%2)                   \n"
8674
0
      "lea         0x10(%2),%2                   \n"
8675
0
      "sub         $0x4,%3                       \n"
8676
0
      "jge         40b                           \n"
8677
8678
0
      "49:         \n"
8679
0
      "add         $0x3,%3                       \n"
8680
0
      "jl          19f                           \n"
8681
8682
      // 1 pixel loop
8683
0
      LABELALIGN
8684
0
      "10:         \n"
8685
0
      "movdqu      (%0),%%xmm0                   \n"
8686
0
      "psubd       0x00(%0,%4,4),%%xmm0          \n"
8687
0
      "lea         0x10(%0),%0                   \n"
8688
0
      "psubd       (%1),%%xmm0                   \n"
8689
0
      "paddd       0x00(%1,%4,4),%%xmm0          \n"
8690
0
      "lea         0x10(%1),%1                   \n"
8691
0
      "cvtdq2ps    %%xmm0,%%xmm0                 \n"
8692
0
      "mulps       %%xmm4,%%xmm0                 \n"
8693
0
      "cvtps2dq    %%xmm0,%%xmm0                 \n"
8694
0
      "packssdw    %%xmm0,%%xmm0                 \n"
8695
0
      "packuswb    %%xmm0,%%xmm0                 \n"
8696
0
      "movd        %%xmm0,(%2)                   \n"
8697
0
      "lea         0x4(%2),%2                    \n"
8698
0
      "sub         $0x1,%3                       \n"
8699
0
      "jge         10b                           \n"
8700
0
      "19:         \n"
8701
0
      : "+r"(topleft),            // %0
8702
0
        "+r"(botleft),            // %1
8703
0
        "+r"(dst),                // %2
8704
0
        "+rm"(count)              // %3
8705
0
      : "r"((ptrdiff_t)(width)),  // %4
8706
0
        "rm"(area)                // %5
8707
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
8708
0
}
8709
#endif  // HAS_CUMULATIVESUMTOAVERAGEROW_SSE2
8710
8711
#ifdef HAS_ARGBAFFINEROW_SSE2
8712
// Copy ARGB pixels from source image with slope to a row of destination.
8713
LIBYUV_API
8714
void ARGBAffineRow_SSE2(const uint8_t* src_argb,
8715
                        int src_argb_stride,
8716
                        uint8_t* dst_argb,
8717
                        const float* src_dudv,
8718
0
                        int width) {
8719
0
  ptrdiff_t src_argb_stride_temp = src_argb_stride;
8720
0
  intptr_t temp;
8721
0
  asm volatile(
8722
0
      "movq        (%3),%%xmm2                   \n"
8723
0
      "movq        0x08(%3),%%xmm7               \n"
8724
0
      "shl         $0x10,%1                      \n"
8725
0
      "add         $0x4,%1                       \n"
8726
0
      "movd        %1,%%xmm5                     \n"
8727
0
      "sub         $0x4,%4                       \n"
8728
0
      "jl          49f                           \n"
8729
8730
0
      "pshufd      $0x44,%%xmm7,%%xmm7           \n"
8731
0
      "pshufd      $0x0,%%xmm5,%%xmm5            \n"
8732
0
      "movdqa      %%xmm2,%%xmm0                 \n"
8733
0
      "addps       %%xmm7,%%xmm0                 \n"
8734
0
      "movlhps     %%xmm0,%%xmm2                 \n"
8735
0
      "movdqa      %%xmm7,%%xmm4                 \n"
8736
0
      "addps       %%xmm4,%%xmm4                 \n"
8737
0
      "movdqa      %%xmm2,%%xmm3                 \n"
8738
0
      "addps       %%xmm4,%%xmm3                 \n"
8739
0
      "addps       %%xmm4,%%xmm4                 \n"
8740
8741
      // 4 pixel loop
8742
0
      LABELALIGN
8743
0
      "40:         \n"
8744
0
      "cvttps2dq   %%xmm2,%%xmm0                 \n"  // x,y float->int first 2
8745
0
      "cvttps2dq   %%xmm3,%%xmm1                 \n"  // x,y float->int next 2
8746
0
      "packssdw    %%xmm1,%%xmm0                 \n"  // x, y as 8 shorts
8747
0
      "pmaddwd     %%xmm5,%%xmm0                 \n"  // off = x*4 + y*stride
8748
0
      "movd        %%xmm0,%k1                    \n"
8749
0
      "pshufd      $0x39,%%xmm0,%%xmm0           \n"
8750
0
      "movd        %%xmm0,%k5                    \n"
8751
0
      "pshufd      $0x39,%%xmm0,%%xmm0           \n"
8752
0
      "movd        0x00(%0,%1,1),%%xmm1          \n"
8753
0
      "movd        0x00(%0,%5,1),%%xmm6          \n"
8754
0
      "punpckldq   %%xmm6,%%xmm1                 \n"
8755
0
      "addps       %%xmm4,%%xmm2                 \n"
8756
0
      "movq        %%xmm1,(%2)                   \n"
8757
0
      "movd        %%xmm0,%k1                    \n"
8758
0
      "pshufd      $0x39,%%xmm0,%%xmm0           \n"
8759
0
      "movd        %%xmm0,%k5                    \n"
8760
0
      "movd        0x00(%0,%1,1),%%xmm0          \n"
8761
0
      "movd        0x00(%0,%5,1),%%xmm6          \n"
8762
0
      "punpckldq   %%xmm6,%%xmm0                 \n"
8763
0
      "addps       %%xmm4,%%xmm3                 \n"
8764
0
      "movq        %%xmm0,0x08(%2)               \n"
8765
0
      "lea         0x10(%2),%2                   \n"
8766
0
      "sub         $0x4,%4                       \n"
8767
0
      "jge         40b                           \n"
8768
8769
0
      "49:         \n"
8770
0
      "add         $0x3,%4                       \n"
8771
0
      "jl          19f                           \n"
8772
8773
      // 1 pixel loop
8774
0
      LABELALIGN
8775
0
      "10:         \n"
8776
0
      "cvttps2dq   %%xmm2,%%xmm0                 \n"
8777
0
      "packssdw    %%xmm0,%%xmm0                 \n"
8778
0
      "pmaddwd     %%xmm5,%%xmm0                 \n"
8779
0
      "addps       %%xmm7,%%xmm2                 \n"
8780
0
      "movd        %%xmm0,%k1                    \n"
8781
0
      "movd        0x00(%0,%1,1),%%xmm0          \n"
8782
0
      "movd        %%xmm0,(%2)                   \n"
8783
0
      "lea         0x04(%2),%2                   \n"
8784
0
      "sub         $0x1,%4                       \n"
8785
0
      "jge         10b                           \n"
8786
0
      "19:         \n"
8787
0
      : "+r"(src_argb),              // %0
8788
0
        "+r"(src_argb_stride_temp),  // %1
8789
0
        "+r"(dst_argb),              // %2
8790
0
        "+r"(src_dudv),              // %3
8791
0
        "+rm"(width),                // %4
8792
0
        "=&r"(temp)                  // %5
8793
0
      :
8794
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
8795
0
        "xmm7");
8796
0
}
8797
#endif  // HAS_ARGBAFFINEROW_SSE2
8798
8799
#ifdef HAS_INTERPOLATEROW_AVX2
8800
// Bilinear filter 32x2 -> 32x1
8801
void InterpolateRow_AVX2(uint8_t* dst_ptr,
8802
                         const uint8_t* src_ptr,
8803
                         ptrdiff_t src_stride,
8804
                         int width,
8805
4.84M
                         int source_y_fraction) {
8806
4.84M
  asm volatile(
8807
4.84M
      "sub         %1,%0                         \n"
8808
4.84M
      "cmp         $0x0,%3                       \n"
8809
4.84M
      "je          100f                          \n"
8810
4.84M
      "cmp         $0x80,%3                      \n"
8811
4.84M
      "je          50f                           \n"
8812
8813
4.84M
      "vmovd       %3,%%xmm0                     \n"
8814
4.84M
      "neg         %3                            \n"
8815
4.84M
      "add         $0x100,%3                     \n"
8816
4.84M
      "vmovd       %3,%%xmm5                     \n"
8817
4.84M
      "vpunpcklbw  %%xmm0,%%xmm5,%%xmm5          \n"
8818
4.84M
      "vpunpcklwd  %%xmm5,%%xmm5,%%xmm5          \n"
8819
4.84M
      "vbroadcastss %%xmm5,%%ymm5                \n"
8820
4.84M
      "mov         $0x80808080,%%eax             \n"
8821
4.84M
      "vmovd       %%eax,%%xmm4                  \n"
8822
4.84M
      "vbroadcastss %%xmm4,%%ymm4                \n"
8823
8824
      // General purpose row blend.
8825
4.84M
      LABELALIGN
8826
4.84M
      "1:          \n"
8827
4.84M
      "vmovdqu     (%1),%%ymm0                   \n"
8828
4.84M
      "vmovdqu     0x00(%1,%4,1),%%ymm2          \n"
8829
4.84M
      "vpunpckhbw  %%ymm2,%%ymm0,%%ymm1          \n"
8830
4.84M
      "vpunpcklbw  %%ymm2,%%ymm0,%%ymm0          \n"
8831
4.84M
      "vpsubb      %%ymm4,%%ymm1,%%ymm1          \n"
8832
4.84M
      "vpsubb      %%ymm4,%%ymm0,%%ymm0          \n"
8833
4.84M
      "vpmaddubsw  %%ymm1,%%ymm5,%%ymm1          \n"
8834
4.84M
      "vpmaddubsw  %%ymm0,%%ymm5,%%ymm0          \n"
8835
4.84M
      "vpaddw      %%ymm4,%%ymm1,%%ymm1          \n"
8836
4.84M
      "vpaddw      %%ymm4,%%ymm0,%%ymm0          \n"
8837
4.84M
      "vpsrlw      $0x8,%%ymm1,%%ymm1            \n"
8838
4.84M
      "vpsrlw      $0x8,%%ymm0,%%ymm0            \n"
8839
4.84M
      "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"
8840
4.84M
      "vmovdqu     %%ymm0,0x00(%1,%0,1)          \n"
8841
4.84M
      "lea         0x20(%1),%1                   \n"
8842
4.84M
      "sub         $0x20,%2                      \n"
8843
4.84M
      "jg          1b                            \n"
8844
4.84M
      "jmp         99f                           \n"
8845
8846
      // Blend 50 / 50.
8847
4.84M
      LABELALIGN
8848
4.84M
      "50:         \n"
8849
4.84M
      "vmovdqu     (%1),%%ymm0                   \n"
8850
4.84M
      "vpavgb      0x00(%1,%4,1),%%ymm0,%%ymm0   \n"
8851
4.84M
      "vmovdqu     %%ymm0,0x00(%1,%0,1)          \n"
8852
4.84M
      "lea         0x20(%1),%1                   \n"
8853
4.84M
      "sub         $0x20,%2                      \n"
8854
4.84M
      "jg          50b                           \n"
8855
4.84M
      "jmp         99f                           \n"
8856
8857
      // Blend 100 / 0 - Copy row unchanged.
8858
4.84M
      LABELALIGN
8859
4.84M
      "100:        \n"
8860
4.84M
      "vmovdqu     (%1),%%ymm0                   \n"
8861
4.84M
      "vmovdqu     %%ymm0,0x00(%1,%0,1)          \n"
8862
4.84M
      "lea         0x20(%1),%1                   \n"
8863
4.84M
      "sub         $0x20,%2                      \n"
8864
4.84M
      "jg          100b                          \n"
8865
8866
4.84M
      "99:         \n"
8867
4.84M
      "vzeroupper  \n"
8868
4.84M
      : "+r"(dst_ptr),           // %0
8869
4.84M
        "+r"(src_ptr),           // %1
8870
4.84M
        "+r"(width),             // %2
8871
4.84M
        "+r"(source_y_fraction)  // %3
8872
4.84M
      : "r"(src_stride)          // %4
8873
4.84M
      : "memory", "cc", "eax", "xmm0", "xmm1", "xmm2", "xmm4", "xmm5");
8874
4.84M
}
8875
#endif  // HAS_INTERPOLATEROW_AVX2
8876
8877
#ifdef HAS_INTERPOLATEROW_16_AVX2
8878
// Bilinear filter 16x2 -> 16x1
8879
void InterpolateRow_16_AVX2(uint16_t* dst_ptr,
8880
                            const uint16_t* src_ptr,
8881
                            ptrdiff_t src_stride,
8882
                            int width,
8883
7.49M
                            int source_y_fraction) {
8884
7.49M
  asm volatile(
8885
7.49M
      "sub         %1,%0                         \n"
8886
7.49M
      "cmp         $0x0,%3                       \n"
8887
7.49M
      "je          100f                          \n"
8888
7.49M
      "cmp         $0x80,%3                      \n"
8889
7.49M
      "je          50f                           \n"
8890
8891
7.49M
      "vmovd       %3,%%xmm0                     \n"
8892
7.49M
      "neg         %3                            \n"
8893
7.49M
      "add         $0x100,%3                     \n"
8894
7.49M
      "vmovd       %3,%%xmm5                     \n"
8895
7.49M
      "vpunpcklwd  %%xmm0,%%xmm5,%%xmm5          \n"
8896
7.49M
      "vpbroadcastd %%xmm5,%%ymm5                \n"
8897
7.49M
      "mov         $0x80008000,%%eax             \n"  // 0x80008000 used to bias
8898
                                                      // unsigned words to
8899
                                                      // signed range for
8900
                                                      // vpmaddwd.
8901
7.49M
      "vmovd       %%eax,%%xmm4                  \n"
8902
7.49M
      "vbroadcastss %%xmm4,%%ymm4                \n"
8903
7.49M
      "mov         $8388736,%%eax                \n"  // 32768 * 256 + 128
8904
                                                      // rounding constant.
8905
7.49M
      "vmovd       %%eax,%%xmm3                  \n"
8906
7.49M
      "vbroadcastss %%xmm3,%%ymm3                \n"
8907
8908
7.49M
      LABELALIGN
8909
7.49M
      "1:          \n"
8910
7.49M
      "vmovdqu     (%1),%%ymm0                   \n"
8911
7.49M
      "vmovdqu     (%1,%4,2),%%ymm1              \n"
8912
7.49M
      "vpunpckhwd  %%ymm1,%%ymm0,%%ymm2          \n"
8913
7.49M
      "vpunpcklwd  %%ymm1,%%ymm0,%%ymm0          \n"
8914
7.49M
      "vpsubw      %%ymm4,%%ymm2,%%ymm2          \n"
8915
7.49M
      "vpsubw      %%ymm4,%%ymm0,%%ymm0          \n"
8916
7.49M
      "vpmaddwd    %%ymm5,%%ymm2,%%ymm2          \n"
8917
7.49M
      "vpmaddwd    %%ymm5,%%ymm0,%%ymm0          \n"
8918
7.49M
      "vpaddd      %%ymm3,%%ymm2,%%ymm2          \n"
8919
7.49M
      "vpaddd      %%ymm3,%%ymm0,%%ymm0          \n"
8920
7.49M
      "vpsrad      $0x8,%%ymm2,%%ymm2            \n"
8921
7.49M
      "vpsrad      $0x8,%%ymm0,%%ymm0            \n"
8922
7.49M
      "vpackusdw   %%ymm2,%%ymm0,%%ymm0          \n"
8923
7.49M
      "vmovdqu     %%ymm0,0x00(%1,%0,1)          \n"
8924
7.49M
      "lea         0x20(%1),%1                   \n"
8925
7.49M
      "sub         $0x10,%2                      \n"
8926
7.49M
      "jg          1b                            \n"
8927
7.49M
      "jmp         99f                           \n"
8928
8929
7.49M
      "50:         \n" LABELALIGN
8930
7.49M
      "2:          \n"
8931
7.49M
      "vmovdqu     (%1),%%ymm0                   \n"
8932
7.49M
      "vpavgw      (%1,%4,2),%%ymm0,%%ymm0       \n"
8933
7.49M
      "vmovdqu     %%ymm0,0x00(%1,%0,1)          \n"
8934
7.49M
      "lea         0x20(%1),%1                   \n"
8935
7.49M
      "sub         $0x10,%2                      \n"
8936
7.49M
      "jg          2b                            \n"
8937
7.49M
      "jmp         99f                           \n"
8938
8939
7.49M
      "100:        \n" LABELALIGN
8940
7.49M
      "3:          \n"
8941
7.49M
      "vmovdqu     (%1),%%ymm0                   \n"
8942
7.49M
      "vmovdqu     %%ymm0,0x00(%1,%0,1)          \n"
8943
7.49M
      "lea         0x20(%1),%1                   \n"
8944
7.49M
      "sub         $0x10,%2                      \n"
8945
7.49M
      "jg          3b                            \n"
8946
8947
7.49M
      "99:         \n"
8948
7.49M
      "vzeroupper  \n"
8949
7.49M
      : "+r"(dst_ptr),           // %0
8950
7.49M
        "+r"(src_ptr),           // %1
8951
7.49M
        "+r"(width),             // %2
8952
7.49M
        "+r"(source_y_fraction)  // %3
8953
7.49M
      : "r"(src_stride)          // %4
8954
7.49M
      : "memory", "cc", "eax", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
8955
7.49M
}
8956
#endif  // HAS_INTERPOLATEROW_16_AVX2
8957
8958
#ifdef HAS_ARGBSHUFFLEROW_SSSE3
8959
// For BGRAToARGB, ABGRToARGB, RGBAToARGB, and ARGBToRGBA.
8960
void ARGBShuffleRow_SSSE3(const uint8_t* src_argb,
8961
                          uint8_t* dst_argb,
8962
                          const uint8_t* shuffler,
8963
0
                          int width) {
8964
0
  asm volatile("movdqu      (%3),%%xmm5                   \n"
8965
8966
0
               LABELALIGN
8967
0
               "1:          \n"
8968
0
               "movdqu      (%0),%%xmm0                   \n"
8969
0
               "movdqu      0x10(%0),%%xmm1               \n"
8970
0
               "lea         0x20(%0),%0                   \n"
8971
0
               "pshufb      %%xmm5,%%xmm0                 \n"
8972
0
               "pshufb      %%xmm5,%%xmm1                 \n"
8973
0
               "movdqu      %%xmm0,(%1)                   \n"
8974
0
               "movdqu      %%xmm1,0x10(%1)               \n"
8975
0
               "lea         0x20(%1),%1                   \n"
8976
0
               "sub         $0x8,%2                       \n"
8977
0
               "jg          1b                            \n"
8978
0
               : "+r"(src_argb),  // %0
8979
0
                 "+r"(dst_argb),  // %1
8980
0
                 "+r"(width)      // %2
8981
0
               : "r"(shuffler)    // %3
8982
0
               : "memory", "cc", "xmm0", "xmm1", "xmm5");
8983
0
}
8984
#endif  // HAS_ARGBSHUFFLEROW_SSSE3
8985
8986
#ifdef HAS_ARGBSHUFFLEROW_AVX2
8987
// For BGRAToARGB, ABGRToARGB, RGBAToARGB, and ARGBToRGBA.
8988
void ARGBShuffleRow_AVX2(const uint8_t* src_argb,
8989
                         uint8_t* dst_argb,
8990
                         const uint8_t* shuffler,
8991
0
                         int width) {
8992
0
  asm volatile("vbroadcasti128 (%3),%%ymm5                \n"
8993
8994
0
               LABELALIGN
8995
0
               "1:          \n"
8996
0
               "vmovdqu     (%0),%%ymm0                   \n"
8997
0
               "vmovdqu     0x20(%0),%%ymm1               \n"
8998
0
               "lea         0x40(%0),%0                   \n"
8999
0
               "vpshufb     %%ymm5,%%ymm0,%%ymm0          \n"
9000
0
               "vpshufb     %%ymm5,%%ymm1,%%ymm1          \n"
9001
0
               "vmovdqu     %%ymm0,(%1)                   \n"
9002
0
               "vmovdqu     %%ymm1,0x20(%1)               \n"
9003
0
               "lea         0x40(%1),%1                   \n"
9004
0
               "sub         $0x10,%2                      \n"
9005
0
               "jg          1b                            \n"
9006
0
               "vzeroupper  \n"
9007
0
               : "+r"(src_argb),  // %0
9008
0
                 "+r"(dst_argb),  // %1
9009
0
                 "+r"(width)      // %2
9010
0
               : "r"(shuffler)    // %3
9011
0
               : "memory", "cc", "xmm0", "xmm1", "xmm5");
9012
0
}
9013
#endif  // HAS_ARGBSHUFFLEROW_AVX2
9014
9015
#ifdef HAS_ARGBSHUFFLEROW_AVX512BW
9016
// For BGRAToARGB, ABGRToARGB, RGBAToARGB, and ARGBToRGBA.
9017
void ARGBShuffleRow_AVX512BW(const uint8_t* src_argb,
9018
                             uint8_t* dst_argb,
9019
                             const uint8_t* shuffler,
9020
0
                             int width) {
9021
0
  asm volatile("vbroadcasti32x4 (%3),%%zmm5               \n"
9022
9023
0
               LABELALIGN
9024
0
               "1:          \n"
9025
0
               "vmovdqu8    (%0),%%zmm0                   \n"
9026
0
               "vmovdqu8    0x40(%0),%%zmm1               \n"
9027
0
               "lea         0x80(%0),%0                   \n"
9028
0
               "vpshufb     %%zmm5,%%zmm0,%%zmm0          \n"
9029
0
               "vpshufb     %%zmm5,%%zmm1,%%zmm1          \n"
9030
0
               "vmovdqu8    %%zmm0,(%1)                   \n"
9031
0
               "vmovdqu8    %%zmm1,0x40(%1)               \n"
9032
0
               "lea         0x80(%1),%1                   \n"
9033
0
               "sub         $0x20,%2                      \n"
9034
0
               "jg          1b                            \n"
9035
0
               "vzeroupper  \n"
9036
0
               : "+r"(src_argb),  // %0
9037
0
                 "+r"(dst_argb),  // %1
9038
0
                 "+r"(width)      // %2
9039
0
               : "r"(shuffler)    // %3
9040
0
               : "memory", "cc", "xmm0", "xmm1", "xmm5");
9041
0
}
9042
#endif  // HAS_ARGBSHUFFLEROW_AVX512BW
9043
9044
#ifdef HAS_I422TOYUY2ROW_SSE2
9045
void I422ToYUY2Row_SSE2(const uint8_t* src_y,
9046
                        const uint8_t* src_u,
9047
                        const uint8_t* src_v,
9048
                        uint8_t* dst_yuy2,
9049
0
                        int width) {
9050
0
  asm volatile("sub         %1,%2                         \n"
9051
9052
0
               LABELALIGN
9053
0
               "1:          \n"
9054
0
               "movq        (%1),%%xmm2                   \n"
9055
0
               "movq        0x00(%1,%2,1),%%xmm1          \n"
9056
0
               "add         $0x8,%1                       \n"
9057
0
               "punpcklbw   %%xmm1,%%xmm2                 \n"
9058
0
               "movdqu      (%0),%%xmm0                   \n"
9059
0
               "add         $0x10,%0                      \n"
9060
0
               "movdqa      %%xmm0,%%xmm1                 \n"
9061
0
               "punpcklbw   %%xmm2,%%xmm0                 \n"
9062
0
               "punpckhbw   %%xmm2,%%xmm1                 \n"
9063
0
               "movdqu      %%xmm0,(%3)                   \n"
9064
0
               "movdqu      %%xmm1,0x10(%3)               \n"
9065
0
               "lea         0x20(%3),%3                   \n"
9066
0
               "sub         $0x10,%4                      \n"
9067
0
               "jg          1b                            \n"
9068
0
               : "+r"(src_y),     // %0
9069
0
                 "+r"(src_u),     // %1
9070
0
                 "+r"(src_v),     // %2
9071
0
                 "+r"(dst_yuy2),  // %3
9072
0
                 "+rm"(width)     // %4
9073
0
               :
9074
0
               : "memory", "cc", "xmm0", "xmm1", "xmm2");
9075
0
}
9076
#endif  // HAS_I422TOYUY2ROW_SSE2
9077
9078
#ifdef HAS_I422TOUYVYROW_SSE2
9079
void I422ToUYVYRow_SSE2(const uint8_t* src_y,
9080
                        const uint8_t* src_u,
9081
                        const uint8_t* src_v,
9082
                        uint8_t* dst_uyvy,
9083
0
                        int width) {
9084
0
  asm volatile("sub         %1,%2                         \n"
9085
9086
0
               LABELALIGN
9087
0
               "1:          \n"
9088
0
               "movq        (%1),%%xmm2                   \n"
9089
0
               "movq        0x00(%1,%2,1),%%xmm1          \n"
9090
0
               "add         $0x8,%1                       \n"
9091
0
               "punpcklbw   %%xmm1,%%xmm2                 \n"
9092
0
               "movdqu      (%0),%%xmm0                   \n"
9093
0
               "movdqa      %%xmm2,%%xmm1                 \n"
9094
0
               "add         $0x10,%0                      \n"
9095
0
               "punpcklbw   %%xmm0,%%xmm1                 \n"
9096
0
               "punpckhbw   %%xmm0,%%xmm2                 \n"
9097
0
               "movdqu      %%xmm1,(%3)                   \n"
9098
0
               "movdqu      %%xmm2,0x10(%3)               \n"
9099
0
               "lea         0x20(%3),%3                   \n"
9100
0
               "sub         $0x10,%4                      \n"
9101
0
               "jg          1b                            \n"
9102
0
               : "+r"(src_y),     // %0
9103
0
                 "+r"(src_u),     // %1
9104
0
                 "+r"(src_v),     // %2
9105
0
                 "+r"(dst_uyvy),  // %3
9106
0
                 "+rm"(width)     // %4
9107
0
               :
9108
0
               : "memory", "cc", "xmm0", "xmm1", "xmm2");
9109
0
}
9110
#endif  // HAS_I422TOUYVYROW_SSE2
9111
9112
#ifdef HAS_I422TOYUY2ROW_AVX2
9113
void I422ToYUY2Row_AVX2(const uint8_t* src_y,
9114
                        const uint8_t* src_u,
9115
                        const uint8_t* src_v,
9116
                        uint8_t* dst_yuy2,
9117
0
                        int width) {
9118
0
  asm volatile("sub         %1,%2                         \n"
9119
9120
0
               LABELALIGN
9121
0
               "1:          \n"
9122
0
               "vpmovzxbw   (%1),%%ymm1                   \n"
9123
0
               "vpmovzxbw   0x00(%1,%2,1),%%ymm2          \n"
9124
0
               "add         $0x10,%1                      \n"
9125
0
               "vpsllw      $0x8,%%ymm2,%%ymm2            \n"
9126
0
               "vpor        %%ymm1,%%ymm2,%%ymm2          \n"
9127
0
               "vmovdqu     (%0),%%ymm0                   \n"
9128
0
               "add         $0x20,%0                      \n"
9129
0
               "vpunpcklbw  %%ymm2,%%ymm0,%%ymm1          \n"
9130
0
               "vpunpckhbw  %%ymm2,%%ymm0,%%ymm2          \n"
9131
0
               "vextractf128 $0x0,%%ymm1,(%3)             \n"
9132
0
               "vextractf128 $0x0,%%ymm2,0x10(%3)         \n"
9133
0
               "vextractf128 $0x1,%%ymm1,0x20(%3)         \n"
9134
0
               "vextractf128 $0x1,%%ymm2,0x30(%3)         \n"
9135
0
               "lea         0x40(%3),%3                   \n"
9136
0
               "sub         $0x20,%4                      \n"
9137
0
               "jg          1b                            \n"
9138
0
               "vzeroupper  \n"
9139
0
               : "+r"(src_y),     // %0
9140
0
                 "+r"(src_u),     // %1
9141
0
                 "+r"(src_v),     // %2
9142
0
                 "+r"(dst_yuy2),  // %3
9143
0
                 "+rm"(width)     // %4
9144
0
               :
9145
0
               : "memory", "cc", "xmm0", "xmm1", "xmm2");
9146
0
}
9147
#endif  // HAS_I422TOYUY2ROW_AVX2
9148
9149
#ifdef HAS_I422TOUYVYROW_AVX2
9150
void I422ToUYVYRow_AVX2(const uint8_t* src_y,
9151
                        const uint8_t* src_u,
9152
                        const uint8_t* src_v,
9153
                        uint8_t* dst_uyvy,
9154
0
                        int width) {
9155
0
  asm volatile("sub         %1,%2                         \n"
9156
9157
0
               LABELALIGN
9158
0
               "1:          \n"
9159
0
               "vpmovzxbw   (%1),%%ymm1                   \n"
9160
0
               "vpmovzxbw   0x00(%1,%2,1),%%ymm2          \n"
9161
0
               "add         $0x10,%1                      \n"
9162
0
               "vpsllw      $0x8,%%ymm2,%%ymm2            \n"
9163
0
               "vpor        %%ymm1,%%ymm2,%%ymm2          \n"
9164
0
               "vmovdqu     (%0),%%ymm0                   \n"
9165
0
               "add         $0x20,%0                      \n"
9166
0
               "vpunpcklbw  %%ymm0,%%ymm2,%%ymm1          \n"
9167
0
               "vpunpckhbw  %%ymm0,%%ymm2,%%ymm2          \n"
9168
0
               "vextractf128 $0x0,%%ymm1,(%3)             \n"
9169
0
               "vextractf128 $0x0,%%ymm2,0x10(%3)         \n"
9170
0
               "vextractf128 $0x1,%%ymm1,0x20(%3)         \n"
9171
0
               "vextractf128 $0x1,%%ymm2,0x30(%3)         \n"
9172
0
               "lea         0x40(%3),%3                   \n"
9173
0
               "sub         $0x20,%4                      \n"
9174
0
               "jg          1b                            \n"
9175
0
               "vzeroupper  \n"
9176
0
               : "+r"(src_y),     // %0
9177
0
                 "+r"(src_u),     // %1
9178
0
                 "+r"(src_v),     // %2
9179
0
                 "+r"(dst_uyvy),  // %3
9180
0
                 "+rm"(width)     // %4
9181
0
               :
9182
0
               : "memory", "cc", "xmm0", "xmm1", "xmm2");
9183
0
}
9184
#endif  // HAS_I422TOUYVYROW_AVX2
9185
9186
#ifdef HAS_ARGBPOLYNOMIALROW_SSE2
9187
void ARGBPolynomialRow_SSE2(const uint8_t* src_argb,
9188
                            uint8_t* dst_argb,
9189
                            const float* poly,
9190
0
                            int width) {
9191
0
  asm volatile("pxor        %%xmm3,%%xmm3                 \n"
9192
9193
               // 2 pixel loop.
9194
0
               LABELALIGN
9195
0
               "1:          \n"
9196
0
               "movq        (%0),%%xmm0                   \n"
9197
0
               "lea         0x8(%0),%0                    \n"
9198
0
               "punpcklbw   %%xmm3,%%xmm0                 \n"
9199
0
               "movdqa      %%xmm0,%%xmm4                 \n"
9200
0
               "punpcklwd   %%xmm3,%%xmm0                 \n"
9201
0
               "punpckhwd   %%xmm3,%%xmm4                 \n"
9202
0
               "cvtdq2ps    %%xmm0,%%xmm0                 \n"
9203
0
               "cvtdq2ps    %%xmm4,%%xmm4                 \n"
9204
0
               "movdqa      %%xmm0,%%xmm1                 \n"
9205
0
               "movdqa      %%xmm4,%%xmm5                 \n"
9206
0
               "mulps       0x10(%3),%%xmm0               \n"
9207
0
               "mulps       0x10(%3),%%xmm4               \n"
9208
0
               "addps       (%3),%%xmm0                   \n"
9209
0
               "addps       (%3),%%xmm4                   \n"
9210
0
               "movdqa      %%xmm1,%%xmm2                 \n"
9211
0
               "movdqa      %%xmm5,%%xmm6                 \n"
9212
0
               "mulps       %%xmm1,%%xmm2                 \n"
9213
0
               "mulps       %%xmm5,%%xmm6                 \n"
9214
0
               "mulps       %%xmm2,%%xmm1                 \n"
9215
0
               "mulps       %%xmm6,%%xmm5                 \n"
9216
0
               "mulps       0x20(%3),%%xmm2               \n"
9217
0
               "mulps       0x20(%3),%%xmm6               \n"
9218
0
               "mulps       0x30(%3),%%xmm1               \n"
9219
0
               "mulps       0x30(%3),%%xmm5               \n"
9220
0
               "addps       %%xmm2,%%xmm0                 \n"
9221
0
               "addps       %%xmm6,%%xmm4                 \n"
9222
0
               "addps       %%xmm1,%%xmm0                 \n"
9223
0
               "addps       %%xmm5,%%xmm4                 \n"
9224
0
               "cvttps2dq   %%xmm0,%%xmm0                 \n"
9225
0
               "cvttps2dq   %%xmm4,%%xmm4                 \n"
9226
0
               "packuswb    %%xmm4,%%xmm0                 \n"
9227
0
               "packuswb    %%xmm0,%%xmm0                 \n"
9228
0
               "movq        %%xmm0,(%1)                   \n"
9229
0
               "lea         0x8(%1),%1                    \n"
9230
0
               "sub         $0x2,%2                       \n"
9231
0
               "jg          1b                            \n"
9232
0
               : "+r"(src_argb),  // %0
9233
0
                 "+r"(dst_argb),  // %1
9234
0
                 "+r"(width)      // %2
9235
0
               : "r"(poly)        // %3
9236
0
               : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5",
9237
0
                 "xmm6");
9238
0
}
9239
#endif  // HAS_ARGBPOLYNOMIALROW_SSE2
9240
9241
#ifdef HAS_ARGBPOLYNOMIALROW_AVX2
9242
void ARGBPolynomialRow_AVX2(const uint8_t* src_argb,
9243
                            uint8_t* dst_argb,
9244
                            const float* poly,
9245
0
                            int width) {
9246
0
  asm volatile(
9247
0
      "vbroadcasti128 (%3),%%ymm4                \n"
9248
0
      "vbroadcasti128 0x10(%3),%%ymm5            \n"
9249
0
      "vbroadcasti128 0x20(%3),%%ymm6            \n"
9250
0
      "vbroadcasti128 0x30(%3),%%ymm7            \n"
9251
9252
      // 2 pixel loop.
9253
0
      LABELALIGN
9254
0
      "1:          \n"
9255
0
      "vpmovzxbd   (%0),%%ymm0                   \n"  // 2 ARGB pixels
9256
0
      "lea         0x8(%0),%0                    \n"
9257
0
      "vcvtdq2ps   %%ymm0,%%ymm0                 \n"  // X 8 floats
9258
0
      "vmulps      %%ymm0,%%ymm0,%%ymm2          \n"  // X * X
9259
0
      "vmulps      %%ymm7,%%ymm0,%%ymm3          \n"  // C3 * X
9260
0
      "vfmadd132ps %%ymm5,%%ymm4,%%ymm0          \n"  // result = C0 + C1 * X
9261
0
      "vfmadd231ps %%ymm6,%%ymm2,%%ymm0          \n"  // result += C2 * X * X
9262
0
      "vfmadd231ps %%ymm3,%%ymm2,%%ymm0          \n"  // result += C3 * X * X *
9263
                                                      // X
9264
0
      "vcvttps2dq  %%ymm0,%%ymm0                 \n"
9265
0
      "vpackusdw   %%ymm0,%%ymm0,%%ymm0          \n"
9266
0
      "vpermq      $0xd8,%%ymm0,%%ymm0           \n"
9267
0
      "vpackuswb   %%xmm0,%%xmm0,%%xmm0          \n"
9268
0
      "vmovq       %%xmm0,(%1)                   \n"
9269
0
      "lea         0x8(%1),%1                    \n"
9270
0
      "sub         $0x2,%2                       \n"
9271
0
      "jg          1b                            \n"
9272
0
      "vzeroupper  \n"
9273
0
      : "+r"(src_argb),  // %0
9274
0
        "+r"(dst_argb),  // %1
9275
0
        "+r"(width)      // %2
9276
0
      : "r"(poly)        // %3
9277
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
9278
0
        "xmm7");
9279
0
}
9280
#endif  // HAS_ARGBPOLYNOMIALROW_AVX2
9281
9282
#ifdef HAS_HALFFLOATROW_AVX2
9283
static float kScaleBias = 1.9259299444e-34f;
9284
void HalfFloatRow_AVX2(const uint16_t* src,
9285
                       uint16_t* dst,
9286
                       float scale,
9287
382
                       int width) {
9288
382
  scale *= kScaleBias;
9289
382
  asm volatile(
9290
382
      "vbroadcastss %3, %%ymm4                   \n"
9291
382
      "vpxor       %%ymm5,%%ymm5,%%ymm5          \n"
9292
382
      "sub         %0,%1                         \n"
9293
9294
      // 16 pixel loop.
9295
382
      LABELALIGN
9296
382
      "1:          \n"
9297
382
      "vmovdqu     (%0),%%ymm2                   \n"  // 16 shorts
9298
382
      "add         $0x20,%0                      \n"
9299
382
      "vpunpckhwd  %%ymm5,%%ymm2,%%ymm3          \n"  // mutates
9300
382
      "vpunpcklwd  %%ymm5,%%ymm2,%%ymm2          \n"
9301
382
      "vcvtdq2ps   %%ymm3,%%ymm3                 \n"
9302
382
      "vcvtdq2ps   %%ymm2,%%ymm2                 \n"
9303
382
      "vmulps      %%ymm3,%%ymm4,%%ymm3          \n"
9304
382
      "vmulps      %%ymm2,%%ymm4,%%ymm2          \n"
9305
382
      "vpsrld      $0xd,%%ymm3,%%ymm3            \n"
9306
382
      "vpsrld      $0xd,%%ymm2,%%ymm2            \n"
9307
382
      "vpackssdw   %%ymm3, %%ymm2, %%ymm2        \n"  // unmutates
9308
382
      "vmovdqu     %%ymm2,-0x20(%0,%1,1)         \n"
9309
382
      "sub         $0x10,%2                      \n"
9310
382
      "jg          1b                            \n"
9311
9312
382
      "vzeroupper  \n"
9313
382
      : "+r"(src),   // %0
9314
382
        "+r"(dst),   // %1
9315
382
        "+r"(width)  // %2
9316
382
#if defined(__x86_64__)
9317
382
      : "x"(scale)  // %3
9318
#else
9319
      : "m"(scale)  // %3
9320
#endif
9321
382
      : "memory", "cc", "xmm2", "xmm3", "xmm4", "xmm5");
9322
382
}
9323
#endif  // HAS_HALFFLOATROW_AVX2
9324
9325
#ifdef HAS_HALFFLOATROW_F16C
9326
void HalfFloatRow_F16C(const uint16_t* src,
9327
                       uint16_t* dst,
9328
                       float scale,
9329
                       int width) {
9330
  asm volatile(
9331
      "vbroadcastss %3, %%ymm4                   \n"
9332
      "sub         %0,%1                         \n"
9333
9334
      // 16 pixel loop.
9335
      LABELALIGN
9336
      "1:          \n"
9337
      "vpmovzxwd   (%0),%%ymm2                   \n"  // 16 shorts -> 16 ints
9338
      "vpmovzxwd   0x10(%0),%%ymm3               \n"
9339
      "vcvtdq2ps   %%ymm2,%%ymm2                 \n"
9340
      "vcvtdq2ps   %%ymm3,%%ymm3                 \n"
9341
      "vmulps      %%ymm2,%%ymm4,%%ymm2          \n"
9342
      "vmulps      %%ymm3,%%ymm4,%%ymm3          \n"
9343
      "vcvtps2ph   $3, %%ymm2, %%xmm2            \n"
9344
      "vcvtps2ph   $3, %%ymm3, %%xmm3            \n"
9345
      "vmovdqu     %%xmm2,0x00(%0,%1,1)          \n"
9346
      "vmovdqu     %%xmm3,0x10(%0,%1,1)          \n"
9347
      "add         $0x20,%0                      \n"
9348
      "sub         $0x10,%2                      \n"
9349
      "jg          1b                            \n"
9350
      "vzeroupper  \n"
9351
      : "+r"(src),   // %0
9352
        "+r"(dst),   // %1
9353
        "+r"(width)  // %2
9354
#if defined(__x86_64__)
9355
      : "x"(scale)  // %3
9356
#else
9357
      : "m"(scale)  // %3
9358
#endif
9359
      : "memory", "cc", "xmm2", "xmm3", "xmm4");
9360
}
9361
#endif  // HAS_HALFFLOATROW_F16C
9362
9363
#ifdef HAS_HALFFLOATROW_F16C
9364
void HalfFloat1Row_F16C(const uint16_t* src, uint16_t* dst, float, int width) {
9365
  asm volatile(
9366
      "sub         %0,%1                         \n"
9367
      // 16 pixel loop.
9368
      LABELALIGN
9369
      "1:          \n"
9370
      "vpmovzxwd   (%0),%%ymm2                   \n"  // 16 shorts -> 16 ints
9371
      "vpmovzxwd   0x10(%0),%%ymm3               \n"
9372
      "vcvtdq2ps   %%ymm2,%%ymm2                 \n"
9373
      "vcvtdq2ps   %%ymm3,%%ymm3                 \n"
9374
      "vcvtps2ph   $3, %%ymm2, %%xmm2            \n"
9375
      "vcvtps2ph   $3, %%ymm3, %%xmm3            \n"
9376
      "vmovdqu     %%xmm2,0x00(%0,%1,1)          \n"
9377
      "vmovdqu     %%xmm3,0x10(%0,%1,1)          \n"
9378
      "add         $0x20,%0                      \n"
9379
      "sub         $0x10,%2                      \n"
9380
      "jg          1b                            \n"
9381
      "vzeroupper  \n"
9382
      : "+r"(src),   // %0
9383
        "+r"(dst),   // %1
9384
        "+r"(width)  // %2
9385
      :
9386
      : "memory", "cc", "xmm2", "xmm3");
9387
}
9388
#endif  // HAS_HALFFLOATROW_F16C
9389
9390
#ifdef HAS_ARGBCOLORTABLEROW_X86
9391
// Tranform ARGB pixels with color table.
9392
void ARGBColorTableRow_X86(uint8_t* dst_argb,
9393
                           const uint8_t* table_argb,
9394
0
                           int width) {
9395
0
  uintptr_t pixel_temp;
9396
0
  asm volatile(
9397
      // 1 pixel loop.
9398
0
      LABELALIGN
9399
0
      "1:          \n"
9400
0
      "movzb       (%0),%1                       \n"
9401
0
      "lea         0x4(%0),%0                    \n"
9402
0
      "movzb       0x00(%3,%1,4),%1              \n"
9403
0
      "mov         %b1,-0x4(%0)                  \n"
9404
0
      "movzb       -0x3(%0),%1                   \n"
9405
0
      "movzb       0x01(%3,%1,4),%1              \n"
9406
0
      "mov         %b1,-0x3(%0)                  \n"
9407
0
      "movzb       -0x2(%0),%1                   \n"
9408
0
      "movzb       0x02(%3,%1,4),%1              \n"
9409
0
      "mov         %b1,-0x2(%0)                  \n"
9410
0
      "movzb       -0x1(%0),%1                   \n"
9411
0
      "movzb       0x03(%3,%1,4),%1              \n"
9412
0
      "mov         %b1,-0x1(%0)                  \n"
9413
0
      "dec         %2                            \n"
9414
0
      "jg          1b                            \n"
9415
0
      : "+r"(dst_argb),     // %0
9416
0
        "=&d"(pixel_temp),  // %1
9417
0
        "+r"(width)         // %2
9418
0
      : "r"(table_argb)     // %3
9419
0
      : "memory", "cc");
9420
0
}
9421
#endif  // HAS_ARGBCOLORTABLEROW_X86
9422
9423
#ifdef HAS_RGBCOLORTABLEROW_X86
9424
// Tranform RGB pixels with color table.
9425
void RGBColorTableRow_X86(uint8_t* dst_argb,
9426
                          const uint8_t* table_argb,
9427
0
                          int width) {
9428
0
  uintptr_t pixel_temp;
9429
0
  asm volatile(
9430
      // 1 pixel loop.
9431
0
      LABELALIGN
9432
0
      "1:          \n"
9433
0
      "movzb       (%0),%1                       \n"
9434
0
      "lea         0x4(%0),%0                    \n"
9435
0
      "movzb       0x00(%3,%1,4),%1              \n"
9436
0
      "mov         %b1,-0x4(%0)                  \n"
9437
0
      "movzb       -0x3(%0),%1                   \n"
9438
0
      "movzb       0x01(%3,%1,4),%1              \n"
9439
0
      "mov         %b1,-0x3(%0)                  \n"
9440
0
      "movzb       -0x2(%0),%1                   \n"
9441
0
      "movzb       0x02(%3,%1,4),%1              \n"
9442
0
      "mov         %b1,-0x2(%0)                  \n"
9443
0
      "dec         %2                            \n"
9444
0
      "jg          1b                            \n"
9445
0
      : "+r"(dst_argb),     // %0
9446
0
        "=&d"(pixel_temp),  // %1
9447
0
        "+r"(width)         // %2
9448
0
      : "r"(table_argb)     // %3
9449
0
      : "memory", "cc");
9450
0
}
9451
#endif  // HAS_RGBCOLORTABLEROW_X86
9452
9453
#ifdef HAS_ARGBLUMACOLORTABLEROW_SSSE3
9454
// Tranform RGB pixels with luma table.
9455
void ARGBLumaColorTableRow_SSSE3(const uint8_t* src_argb,
9456
                                 uint8_t* dst_argb,
9457
                                 int width,
9458
                                 const uint8_t* luma,
9459
0
                                 uint32_t lumacoeff) {
9460
0
  uintptr_t pixel_temp;
9461
0
  uintptr_t table_temp;
9462
0
  asm volatile(
9463
0
      "movd        %6,%%xmm3                     \n"
9464
0
      "pshufd      $0x0,%%xmm3,%%xmm3            \n"
9465
0
      "pcmpeqb     %%xmm4,%%xmm4                 \n"
9466
0
      "psllw       $0x8,%%xmm4                   \n"
9467
0
      "pxor        %%xmm5,%%xmm5                 \n"
9468
9469
      // 4 pixel loop.
9470
0
      LABELALIGN
9471
0
      "1:          \n"
9472
0
      "movdqu      (%2),%%xmm0                   \n"
9473
0
      "pmaddubsw   %%xmm3,%%xmm0                 \n"
9474
0
      "phaddw      %%xmm0,%%xmm0                 \n"
9475
0
      "pand        %%xmm4,%%xmm0                 \n"
9476
0
      "punpcklwd   %%xmm5,%%xmm0                 \n"
9477
0
      "movd        %%xmm0,%k1                    \n"  // 32 bit offset
9478
0
      "add         %5,%1                         \n"
9479
0
      "pshufd      $0x39,%%xmm0,%%xmm0           \n"
9480
9481
0
      "movzb       (%2),%0                       \n"
9482
0
      "movzb       0x00(%1,%0,1),%0              \n"
9483
0
      "mov         %b0,(%3)                      \n"
9484
0
      "movzb       0x1(%2),%0                    \n"
9485
0
      "movzb       0x00(%1,%0,1),%0              \n"
9486
0
      "mov         %b0,0x1(%3)                   \n"
9487
0
      "movzb       0x2(%2),%0                    \n"
9488
0
      "movzb       0x00(%1,%0,1),%0              \n"
9489
0
      "mov         %b0,0x2(%3)                   \n"
9490
0
      "movzb       0x3(%2),%0                    \n"
9491
0
      "mov         %b0,0x3(%3)                   \n"
9492
9493
0
      "movd        %%xmm0,%k1                    \n"  // 32 bit offset
9494
0
      "add         %5,%1                         \n"
9495
0
      "pshufd      $0x39,%%xmm0,%%xmm0           \n"
9496
9497
0
      "movzb       0x4(%2),%0                    \n"
9498
0
      "movzb       0x00(%1,%0,1),%0              \n"
9499
0
      "mov         %b0,0x4(%3)                   \n"
9500
0
      "movzb       0x5(%2),%0                    \n"
9501
0
      "movzb       0x00(%1,%0,1),%0              \n"
9502
0
      "mov         %b0,0x5(%3)                   \n"
9503
0
      "movzb       0x6(%2),%0                    \n"
9504
0
      "movzb       0x00(%1,%0,1),%0              \n"
9505
0
      "mov         %b0,0x6(%3)                   \n"
9506
0
      "movzb       0x7(%2),%0                    \n"
9507
0
      "mov         %b0,0x7(%3)                   \n"
9508
9509
0
      "movd        %%xmm0,%k1                    \n"  // 32 bit offset
9510
0
      "add         %5,%1                         \n"
9511
0
      "pshufd      $0x39,%%xmm0,%%xmm0           \n"
9512
9513
0
      "movzb       0x8(%2),%0                    \n"
9514
0
      "movzb       0x00(%1,%0,1),%0              \n"
9515
0
      "mov         %b0,0x8(%3)                   \n"
9516
0
      "movzb       0x9(%2),%0                    \n"
9517
0
      "movzb       0x00(%1,%0,1),%0              \n"
9518
0
      "mov         %b0,0x9(%3)                   \n"
9519
0
      "movzb       0xa(%2),%0                    \n"
9520
0
      "movzb       0x00(%1,%0,1),%0              \n"
9521
0
      "mov         %b0,0xa(%3)                   \n"
9522
0
      "movzb       0xb(%2),%0                    \n"
9523
0
      "mov         %b0,0xb(%3)                   \n"
9524
9525
0
      "movd        %%xmm0,%k1                    \n"  // 32 bit offset
9526
0
      "add         %5,%1                         \n"
9527
9528
0
      "movzb       0xc(%2),%0                    \n"
9529
0
      "movzb       0x00(%1,%0,1),%0              \n"
9530
0
      "mov         %b0,0xc(%3)                   \n"
9531
0
      "movzb       0xd(%2),%0                    \n"
9532
0
      "movzb       0x00(%1,%0,1),%0              \n"
9533
0
      "mov         %b0,0xd(%3)                   \n"
9534
0
      "movzb       0xe(%2),%0                    \n"
9535
0
      "movzb       0x00(%1,%0,1),%0              \n"
9536
0
      "mov         %b0,0xe(%3)                   \n"
9537
0
      "movzb       0xf(%2),%0                    \n"
9538
0
      "mov         %b0,0xf(%3)                   \n"
9539
0
      "lea         0x10(%2),%2                   \n"
9540
0
      "lea         0x10(%3),%3                   \n"
9541
0
      "sub         $0x4,%4                       \n"
9542
0
      "jg          1b                            \n"
9543
0
      : "=&d"(pixel_temp),  // %0
9544
0
        "=&a"(table_temp),  // %1
9545
0
        "+r"(src_argb),     // %2
9546
0
        "+r"(dst_argb),     // %3
9547
0
        "+rm"(width)        // %4
9548
0
      : "r"(luma),          // %5
9549
0
        "rm"(lumacoeff)     // %6
9550
0
      : "memory", "cc", "xmm0", "xmm3", "xmm4", "xmm5");
9551
0
}
9552
#endif  // HAS_ARGBLUMACOLORTABLEROW_SSSE3
9553
9554
static const uvec8 kYUV24Shuffle[3] = {
9555
    {8, 9, 0, 8, 9, 1, 10, 11, 2, 10, 11, 3, 12, 13, 4, 12},
9556
    {9, 1, 10, 11, 2, 10, 11, 3, 12, 13, 4, 12, 13, 5, 14, 15},
9557
    {2, 10, 11, 3, 12, 13, 4, 12, 13, 5, 14, 15, 6, 14, 15, 7}};
9558
9559
// Convert biplanar NV21 to packed YUV24
9560
// NV21 has VU in memory for chroma.
9561
// YUV24 is VUY in memory
9562
void NV21ToYUV24Row_SSSE3(const uint8_t* src_y,
9563
                          const uint8_t* src_vu,
9564
                          uint8_t* dst_yuv24,
9565
0
                          int width) {
9566
0
  asm volatile(
9567
0
      "sub         %0,%1                         \n"
9568
0
      "movdqa      (%4),%%xmm4                   \n"  // 3 shuffler constants
9569
0
      "movdqa      16(%4),%%xmm5                 \n"
9570
0
      "movdqa      32(%4),%%xmm6                 \n"
9571
0
      "1:          \n"
9572
0
      "movdqu      (%0),%%xmm2                   \n"  // load 16 Y values
9573
0
      "movdqu      (%0,%1),%%xmm3                \n"  // load 8 VU values
9574
0
      "lea         16(%0),%0                     \n"
9575
0
      "movdqa      %%xmm2,%%xmm0                 \n"
9576
0
      "movdqa      %%xmm2,%%xmm1                 \n"
9577
0
      "shufps      $0x44,%%xmm3,%%xmm0           \n"  // Y 0..7,  UV 0..3
9578
0
      "shufps      $0x99,%%xmm3,%%xmm1           \n"  // Y 4..11, UV 2..5
9579
0
      "shufps      $0xee,%%xmm3,%%xmm2           \n"  // Y 8..15, UV 4..7
9580
0
      "pshufb      %%xmm4, %%xmm0                \n"  // weave into YUV24
9581
0
      "pshufb      %%xmm5, %%xmm1                \n"
9582
0
      "pshufb      %%xmm6, %%xmm2                \n"
9583
0
      "movdqu      %%xmm0,(%2)                   \n"
9584
0
      "movdqu      %%xmm1,16(%2)                 \n"
9585
0
      "movdqu      %%xmm2,32(%2)                 \n"
9586
0
      "lea         48(%2),%2                     \n"
9587
0
      "sub         $16,%3                        \n"  // 16 pixels per loop
9588
0
      "jg          1b                            \n"
9589
0
      : "+r"(src_y),            // %0
9590
0
        "+r"(src_vu),           // %1
9591
0
        "+r"(dst_yuv24),        // %2
9592
0
        "+r"(width)             // %3
9593
0
      : "r"(&kYUV24Shuffle[0])  // %4
9594
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
9595
0
}
9596
9597
// Convert biplanar NV21 to packed YUV24
9598
// NV21 has VU in memory for chroma.
9599
// YUV24 is VUY in memory
9600
void NV21ToYUV24Row_AVX2(const uint8_t* src_y,
9601
                         const uint8_t* src_vu,
9602
                         uint8_t* dst_yuv24,
9603
0
                         int width) {
9604
0
  asm volatile(
9605
0
      "sub         %0,%1                         \n"
9606
0
      "vbroadcasti128 (%4),%%ymm4                \n"  // 3 shuffler constants
9607
0
      "vbroadcasti128 16(%4),%%ymm5              \n"
9608
0
      "vbroadcasti128 32(%4),%%ymm6              \n"
9609
9610
0
      "1:          \n"
9611
0
      "vmovdqu     (%0),%%ymm2                   \n"  // load 32 Y values
9612
0
      "vmovdqu     (%0,%1),%%ymm3                \n"  // load 16 VU values
9613
0
      "lea         32(%0),%0                     \n"
9614
0
      "vshufps     $0x44,%%ymm3,%%ymm2,%%ymm0    \n"  // Y 0..7,  UV 0..3
9615
0
      "vshufps     $0x99,%%ymm3,%%ymm2,%%ymm1    \n"  // Y 4..11, UV 2..5
9616
0
      "vshufps     $0xee,%%ymm3,%%ymm2,%%ymm2    \n"  // Y 8..15, UV 4..7
9617
0
      "vpshufb     %%ymm4,%%ymm0,%%ymm0          \n"  // weave into YUV24
9618
0
      "vpshufb     %%ymm5,%%ymm1,%%ymm1          \n"
9619
0
      "vpshufb     %%ymm6,%%ymm2,%%ymm2          \n"
9620
0
      "vperm2i128  $0x20,%%ymm1,%%ymm0,%%ymm3    \n"
9621
0
      "vperm2i128  $0x30,%%ymm0,%%ymm2,%%ymm0    \n"
9622
0
      "vperm2i128  $0x31,%%ymm2,%%ymm1,%%ymm1    \n"
9623
0
      "vmovdqu     %%ymm3,(%2)                   \n"
9624
0
      "vmovdqu     %%ymm0,32(%2)                 \n"
9625
0
      "vmovdqu     %%ymm1,64(%2)                 \n"
9626
0
      "lea         96(%2),%2                     \n"
9627
0
      "sub         $32,%3                        \n"  // 32 pixels per loop
9628
0
      "jg          1b                            \n"
9629
0
      "vzeroupper  \n"
9630
0
      : "+r"(src_y),            // %0
9631
0
        "+r"(src_vu),           // %1
9632
0
        "+r"(dst_yuv24),        // %2
9633
0
        "+r"(width)             // %3
9634
0
      : "r"(&kYUV24Shuffle[0])  // %4
9635
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
9636
0
}
9637
9638
#ifdef HAS_NV21ToYUV24ROW_AVX512
9639
// The following VMBI VEX256 code tests okay with the intelsde emulator.
9640
static const lvec8 kYUV24Perm[3] = {
9641
    {32, 33, 0,  32, 33, 1,  34, 35, 2,  34, 35, 3,  36, 37, 4,  36,
9642
     37, 5,  38, 39, 6,  38, 39, 7,  40, 41, 8,  40, 41, 9,  42, 43},
9643
    {10, 42, 43, 11, 44, 45, 12, 44, 45, 13, 46, 47, 14, 46, 47, 15,
9644
     48, 49, 16, 48, 49, 17, 50, 51, 18, 50, 51, 19, 52, 53, 20, 52},
9645
    {53, 21, 54, 55, 22, 54, 55, 23, 56, 57, 24, 56, 57, 25, 58, 59,
9646
     26, 58, 59, 27, 60, 61, 28, 60, 61, 29, 62, 63, 30, 62, 63, 31}};
9647
9648
void NV21ToYUV24Row_AVX512(const uint8_t* src_y,
9649
                           const uint8_t* src_vu,
9650
                           uint8_t* dst_yuv24,
9651
                           int width) {
9652
  asm volatile(
9653
      "sub         %0,%1                         \n"
9654
      "vmovdqa     (%4),%%ymm4                   \n"  // 3 shuffler constants
9655
      "vmovdqa     32(%4),%%ymm5                 \n"
9656
      "vmovdqa     64(%4),%%ymm6                 \n" LABELALIGN
9657
      "1:          \n"
9658
      "vmovdqu     (%0),%%ymm2                   \n"  // load 32 Y values
9659
      "vmovdqu     (%0,%1),%%ymm3                \n"  // load 16 VU values
9660
      "lea         32(%0),%0                     \n"
9661
      "vmovdqa     %%ymm2, %%ymm0                \n"
9662
      "vmovdqa     %%ymm2, %%ymm1                \n"
9663
      "vpermt2b    %%ymm3,%%ymm4,%%ymm0          \n"
9664
      "vpermt2b    %%ymm3,%%ymm5,%%ymm1          \n"
9665
      "vpermt2b    %%ymm3,%%ymm6,%%ymm2          \n"
9666
      "vmovdqu     %%ymm0,(%2)                   \n"
9667
      "vmovdqu     %%ymm1,32(%2)                 \n"
9668
      "vmovdqu     %%ymm2,64(%2)                 \n"
9669
      "lea         96(%2),%2                     \n"
9670
      "sub         $32,%3                        \n"
9671
      "jg          1b                            \n"
9672
      "vzeroupper  \n"
9673
      : "+r"(src_y),         // %0
9674
        "+r"(src_vu),        // %1
9675
        "+r"(dst_yuv24),     // %2
9676
        "+r"(width)          // %3
9677
      : "r"(&kYUV24Perm[0])  // %4
9678
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6");
9679
}
9680
9681
#endif  // HAS_NV21ToYUV24ROW_AVX512
9682
9683
#ifdef HAS_SWAPUVROW_SSSE3
9684
9685
// Shuffle table for reversing the bytes.
9686
static const uvec8 kShuffleUVToVU = {1u, 0u, 3u,  2u,  5u,  4u,  7u,  6u,
9687
                                     9u, 8u, 11u, 10u, 13u, 12u, 15u, 14u};
9688
9689
// Convert UV plane of NV12 to VU of NV21.
9690
0
void SwapUVRow_SSSE3(const uint8_t* src_uv, uint8_t* dst_vu, int width) {
9691
0
  asm volatile("movdqu      %3,%%xmm5                     \n"
9692
9693
0
               LABELALIGN
9694
0
               "1:          \n"
9695
0
               "movdqu      (%0),%%xmm0                   \n"
9696
0
               "movdqu      0x10(%0),%%xmm1               \n"
9697
0
               "lea         0x20(%0),%0                   \n"
9698
0
               "pshufb      %%xmm5,%%xmm0                 \n"
9699
0
               "pshufb      %%xmm5,%%xmm1                 \n"
9700
0
               "movdqu      %%xmm0,(%1)                   \n"
9701
0
               "movdqu      %%xmm1,0x10(%1)               \n"
9702
0
               "lea         0x20(%1),%1                   \n"
9703
0
               "sub         $0x10,%2                      \n"
9704
0
               "jg          1b                            \n"
9705
0
               : "+r"(src_uv),        // %0
9706
0
                 "+r"(dst_vu),        // %1
9707
0
                 "+r"(width)          // %2
9708
0
               : "m"(kShuffleUVToVU)  // %3
9709
0
               : "memory", "cc", "xmm0", "xmm1", "xmm5");
9710
0
}
9711
#endif  // HAS_SWAPUVROW_SSSE3
9712
9713
#ifdef HAS_SWAPUVROW_AVX2
9714
0
void SwapUVRow_AVX2(const uint8_t* src_uv, uint8_t* dst_vu, int width) {
9715
0
  asm volatile("vbroadcasti128 %3,%%ymm5                  \n"
9716
9717
0
               LABELALIGN
9718
0
               "1:          \n"
9719
0
               "vmovdqu     (%0),%%ymm0                   \n"
9720
0
               "vmovdqu     0x20(%0),%%ymm1               \n"
9721
0
               "lea         0x40(%0),%0                   \n"
9722
0
               "vpshufb     %%ymm5,%%ymm0,%%ymm0          \n"
9723
0
               "vpshufb     %%ymm5,%%ymm1,%%ymm1          \n"
9724
0
               "vmovdqu     %%ymm0,(%1)                   \n"
9725
0
               "vmovdqu     %%ymm1,0x20(%1)               \n"
9726
0
               "lea         0x40(%1),%1                   \n"
9727
0
               "sub         $0x20,%2                      \n"
9728
0
               "jg          1b                            \n"
9729
0
               "vzeroupper  \n"
9730
0
               : "+r"(src_uv),        // %0
9731
0
                 "+r"(dst_vu),        // %1
9732
0
                 "+r"(width)          // %2
9733
0
               : "m"(kShuffleUVToVU)  // %3
9734
0
               : "memory", "cc", "xmm0", "xmm1", "xmm5");
9735
0
}
9736
#endif  // HAS_SWAPUVROW_AVX2
9737
9738
void HalfMergeUVRow_SSSE3(const uint8_t* src_u,
9739
                          int src_stride_u,
9740
                          const uint8_t* src_v,
9741
                          int src_stride_v,
9742
                          uint8_t* dst_uv,
9743
0
                          int width) {
9744
0
  asm volatile(
9745
0
      "pcmpeqb     %%xmm4,%%xmm4                 \n"  // 0x0101
9746
0
      "pabsb       %%xmm4,%%xmm4                 \n"
9747
0
      "pxor        %%xmm5,%%xmm5                 \n"
9748
9749
0
      LABELALIGN
9750
0
      "1:          \n"
9751
0
      "movdqu      (%0),%%xmm0                   \n"  // load 16 U values
9752
0
      "movdqu      (%1),%%xmm1                   \n"  // load 16 V values
9753
0
      "movdqu      0(%0,%4,1),%%xmm2             \n"  // 16 from next row
9754
0
      "movdqu      0(%1,%5,1),%%xmm3             \n"
9755
0
      "lea         0x10(%0),%0                   \n"
9756
0
      "pmaddubsw   %%xmm4,%%xmm0                 \n"  // half size
9757
0
      "pmaddubsw   %%xmm4,%%xmm1                 \n"
9758
0
      "pmaddubsw   %%xmm4,%%xmm2                 \n"
9759
0
      "pmaddubsw   %%xmm4,%%xmm3                 \n"
9760
0
      "lea         0x10(%1),%1                   \n"
9761
0
      "paddw       %%xmm2,%%xmm0                 \n"
9762
0
      "paddw       %%xmm3,%%xmm1                 \n"
9763
0
      "psrlw       $0x1,%%xmm0                   \n"
9764
0
      "psrlw       $0x1,%%xmm1                   \n"
9765
0
      "pavgw       %%xmm5,%%xmm0                 \n"
9766
0
      "pavgw       %%xmm5,%%xmm1                 \n"
9767
0
      "packuswb    %%xmm0,%%xmm0                 \n"
9768
0
      "packuswb    %%xmm1,%%xmm1                 \n"
9769
0
      "punpcklbw   %%xmm1,%%xmm0                 \n"
9770
0
      "movdqu      %%xmm0,(%2)                   \n"  // store 8 UV pixels
9771
0
      "lea         0x10(%2),%2                   \n"
9772
0
      "sub         $0x10,%3                      \n"  // 16 src pixels per loop
9773
0
      "jg          1b                            \n"
9774
0
      : "+r"(src_u),                     // %0
9775
0
        "+r"(src_v),                     // %1
9776
0
        "+r"(dst_uv),                    // %2
9777
0
        "+r"(width)                      // %3
9778
0
      : "r"((ptrdiff_t)(src_stride_u)),  // %4
9779
0
        "r"((ptrdiff_t)(src_stride_v))   // %5
9780
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
9781
0
}
9782
9783
void HalfMergeUVRow_AVX2(const uint8_t* src_u,
9784
                         int src_stride_u,
9785
                         const uint8_t* src_v,
9786
                         int src_stride_v,
9787
                         uint8_t* dst_uv,
9788
0
                         int width) {
9789
0
  asm volatile(
9790
0
      "vpcmpeqb    %%ymm4,%%ymm4,%%ymm4          \n"
9791
0
      "vpabsb      %%ymm4,%%ymm4                 \n"
9792
0
      "vpxor       %%ymm5,%%ymm5,%%ymm5          \n"
9793
9794
0
      LABELALIGN
9795
0
      "1:          \n"
9796
0
      "vmovdqu     (%0),%%ymm0                   \n"  // load 32 U values
9797
0
      "vmovdqu     (%1),%%ymm1                   \n"  // load 32 V values
9798
0
      "vmovdqu     0(%0,%4,1),%%ymm2             \n"  // 32 from next row
9799
0
      "vmovdqu     0(%1,%5,1),%%ymm3             \n"
9800
0
      "lea         0x20(%0),%0                   \n"
9801
0
      "vpmaddubsw  %%ymm4,%%ymm0,%%ymm0          \n"  // half size
9802
0
      "vpmaddubsw  %%ymm4,%%ymm1,%%ymm1          \n"
9803
0
      "vpmaddubsw  %%ymm4,%%ymm2,%%ymm2          \n"
9804
0
      "vpmaddubsw  %%ymm4,%%ymm3,%%ymm3          \n"
9805
0
      "lea         0x20(%1),%1                   \n"
9806
0
      "vpaddw      %%ymm2,%%ymm0,%%ymm0          \n"
9807
0
      "vpaddw      %%ymm3,%%ymm1,%%ymm1          \n"
9808
0
      "vpsrlw      $0x1,%%ymm0,%%ymm0            \n"
9809
0
      "vpsrlw      $0x1,%%ymm1,%%ymm1            \n"
9810
0
      "vpavgw      %%ymm5,%%ymm0,%%ymm0          \n"
9811
0
      "vpavgw      %%ymm5,%%ymm1,%%ymm1          \n"
9812
0
      "vpackuswb   %%ymm0,%%ymm0,%%ymm0          \n"
9813
0
      "vpackuswb   %%ymm1,%%ymm1,%%ymm1          \n"
9814
0
      "vpunpcklbw  %%ymm1,%%ymm0,%%ymm0          \n"
9815
0
      "vmovdqu     %%ymm0,(%2)                   \n"  // store 16 UV pixels
9816
0
      "lea         0x20(%2),%2                   \n"
9817
0
      "sub         $0x20,%3                      \n"  // 32 src pixels per loop
9818
0
      "jg          1b                            \n"
9819
0
      "vzeroupper  \n"
9820
0
      : "+r"(src_u),                     // %0
9821
0
        "+r"(src_v),                     // %1
9822
0
        "+r"(dst_uv),                    // %2
9823
0
        "+r"(width)                      // %3
9824
0
      : "r"((ptrdiff_t)(src_stride_u)),  // %4
9825
0
        "r"((ptrdiff_t)(src_stride_v))   // %5
9826
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
9827
0
}
9828
9829
0
void ClampFloatToZero_SSE2(const float* src_x, float* dst_y, int width) {
9830
0
  asm volatile(
9831
0
      "pxor        %%xmm1,%%xmm1                 \n"
9832
9833
0
      LABELALIGN
9834
0
      "1:          \n"
9835
0
      "movd        (%0),%%xmm0                   \n"  // load float
9836
0
      "maxss       %%xmm1, %%xmm0                \n"  // clamp to zero
9837
0
      "add         4, %0                         \n"
9838
0
      "movd        %%xmm0, (%1)                  \n"  // store float
9839
0
      "add         4, %1                         \n"
9840
0
      "sub         $0x4,%2                       \n"  // 1 float per loop
9841
0
      "jg          1b                            \n"
9842
0
      : "+r"(src_x),  // %0
9843
0
        "+r"(dst_y),  // %1
9844
0
        "+r"(width)   // %2
9845
0
      :
9846
0
      : "memory", "cc", "xmm0", "xmm1");
9847
0
}
9848
9849
#ifdef HAS_CONVERT16TO8ROW_AVX2
9850
void Convert8To8Row_AVX2(const uint8_t* src_y,
9851
                         uint8_t* dst_y,
9852
                         int scale,
9853
                         int bias,
9854
0
                         int width) {
9855
0
  asm volatile(
9856
0
      "sub         %0,%1                         \n"
9857
0
      "vmovd       %3,%%xmm2                     \n"
9858
0
      "vmovd       %4,%%xmm3                     \n"
9859
0
      "vpbroadcastw %%xmm2,%%ymm2                \n"
9860
0
      "vpbroadcastb %%xmm3,%%ymm3                \n"
9861
0
      "vpxor       %%ymm4,%%ymm4,%%ymm4          \n"
9862
0
      "vpsllw      $8,%%ymm2,%%ymm2              \n"
9863
9864
      // 32 pixels per loop.
9865
0
      LABELALIGN
9866
0
      "1:          \n"
9867
0
      "vmovdqu     (%0),%%ymm0                   \n"
9868
0
      "vpunpckhbw  %%ymm4,%%ymm0,%%ymm1          \n"  // mutates
9869
0
      "vpunpcklbw  %%ymm4,%%ymm0,%%ymm0          \n"
9870
0
      "vpmulhuw    %%ymm2,%%ymm0,%%ymm0          \n"
9871
0
      "vpmulhuw    %%ymm2,%%ymm1,%%ymm1          \n"
9872
0
      "vpackuswb   %%ymm1,%%ymm0,%%ymm0          \n"  // unmutates
9873
0
      "vpaddb      %%ymm3,%%ymm0,%%ymm0          \n"
9874
0
      "vmovdqu     %%ymm0,(%0,%1)                \n"
9875
0
      "add         $0x20,%0                      \n"
9876
0
      "sub         $0x20,%2                      \n"
9877
0
      "jg          1b                            \n"
9878
0
      "vzeroupper  \n"
9879
0
      : "+r"(src_y),  // %0
9880
0
        "+r"(dst_y),  // %1
9881
0
        "+r"(width)   // %2
9882
0
      : "r"(scale),   // %3
9883
0
        "r"(bias)     // %4
9884
0
      : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4");
9885
0
}
9886
#endif  // HAS_CONVERT16TO8ROW_AVX2
9887
9888
#endif  // defined(__x86_64__) || defined(__i386__)
9889
9890
#ifdef __cplusplus
9891
}  // extern "C"
9892
}  // namespace libyuv
9893
#endif