vpx/vp9/common/x86/vp9_idct_intrin_sse2.c
Jingning Han 49b6302044 SSE2 4x4 invserse ADST/DCT transform
Enable SSE2 4x4 inverse ADST/DCT transform. The runtime goes from
292 cycles down to 89 cycles. Running bus_cif at 2000 kbps, the
overall runtime of speed 0 goes from 301s to 295s (2% speed-up).

Change-Id: I24098136e7fee7ab2fbf1c11755bdf2ca37f3628
2013-07-10 20:16:02 -07:00

2135 lines
84 KiB
C

/*
* Copyright (c) 2012 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <assert.h>
#include <emmintrin.h> // SSE2
#include "./vpx_config.h"
#include "vpx/vpx_integer.h"
#include "vp9/common/vp9_common.h"
#include "vp9/common/vp9_idct.h"
// In order to improve performance, clip absolute diff values to [0, 255],
// which allows to keep the additions/subtractions in 8 bits.
void vp9_dc_only_idct_add_sse2(int input_dc, uint8_t *pred_ptr,
uint8_t *dst_ptr, int pitch, int stride) {
int a1;
int16_t out;
uint8_t abs_diff;
__m128i p0, p1, p2, p3;
unsigned int extended_diff;
__m128i diff;
out = dct_const_round_shift(input_dc * cospi_16_64);
out = dct_const_round_shift(out * cospi_16_64);
a1 = ROUND_POWER_OF_TWO(out, 4);
// Read prediction data.
p0 = _mm_cvtsi32_si128 (*(const int *)(pred_ptr + 0 * pitch));
p1 = _mm_cvtsi32_si128 (*(const int *)(pred_ptr + 1 * pitch));
p2 = _mm_cvtsi32_si128 (*(const int *)(pred_ptr + 2 * pitch));
p3 = _mm_cvtsi32_si128 (*(const int *)(pred_ptr + 3 * pitch));
// Unpack prediction data, and store 4x4 array in 1 XMM register.
p0 = _mm_unpacklo_epi32(p0, p1);
p2 = _mm_unpacklo_epi32(p2, p3);
p0 = _mm_unpacklo_epi64(p0, p2);
// Clip dc value to [0, 255] range. Then, do addition or subtraction
// according to its sign.
if (a1 >= 0) {
abs_diff = (a1 > 255) ? 255 : a1;
extended_diff = abs_diff * 0x01010101u;
diff = _mm_shuffle_epi32(_mm_cvtsi32_si128((int)extended_diff), 0);
p1 = _mm_adds_epu8(p0, diff);
} else {
abs_diff = (a1 < -255) ? 255 : -a1;
extended_diff = abs_diff * 0x01010101u;
diff = _mm_shuffle_epi32(_mm_cvtsi32_si128((int)extended_diff), 0);
p1 = _mm_subs_epu8(p0, diff);
}
// Store results to dst.
*(int *)dst_ptr = _mm_cvtsi128_si32(p1);
dst_ptr += stride;
p1 = _mm_srli_si128(p1, 4);
*(int *)dst_ptr = _mm_cvtsi128_si32(p1);
dst_ptr += stride;
p1 = _mm_srli_si128(p1, 4);
*(int *)dst_ptr = _mm_cvtsi128_si32(p1);
dst_ptr += stride;
p1 = _mm_srli_si128(p1, 4);
*(int *)dst_ptr = _mm_cvtsi128_si32(p1);
}
void vp9_short_idct4x4_add_sse2(int16_t *input, uint8_t *dest, int stride) {
const __m128i zero = _mm_setzero_si128();
const __m128i eight = _mm_set1_epi16(8);
const __m128i cst = _mm_setr_epi16((int16_t)cospi_16_64, (int16_t)cospi_16_64,
(int16_t)cospi_16_64, (int16_t)-cospi_16_64,
(int16_t)cospi_24_64, (int16_t)-cospi_8_64,
(int16_t)cospi_8_64, (int16_t)cospi_24_64);
const __m128i rounding = _mm_set1_epi32(DCT_CONST_ROUNDING);
__m128i input0, input1, input2, input3;
// Rows
input0 = _mm_loadl_epi64((__m128i *)input);
input1 = _mm_loadl_epi64((__m128i *)(input + 4));
input2 = _mm_loadl_epi64((__m128i *)(input + 8));
input3 = _mm_loadl_epi64((__m128i *)(input + 12));
// Construct i3, i1, i3, i1, i2, i0, i2, i0
input0 = _mm_shufflelo_epi16(input0, 0xd8);
input1 = _mm_shufflelo_epi16(input1, 0xd8);
input2 = _mm_shufflelo_epi16(input2, 0xd8);
input3 = _mm_shufflelo_epi16(input3, 0xd8);
input0 = _mm_unpacklo_epi32(input0, input0);
input1 = _mm_unpacklo_epi32(input1, input1);
input2 = _mm_unpacklo_epi32(input2, input2);
input3 = _mm_unpacklo_epi32(input3, input3);
// Stage 1
input0 = _mm_madd_epi16(input0, cst);
input1 = _mm_madd_epi16(input1, cst);
input2 = _mm_madd_epi16(input2, cst);
input3 = _mm_madd_epi16(input3, cst);
input0 = _mm_add_epi32(input0, rounding);
input1 = _mm_add_epi32(input1, rounding);
input2 = _mm_add_epi32(input2, rounding);
input3 = _mm_add_epi32(input3, rounding);
input0 = _mm_srai_epi32(input0, DCT_CONST_BITS);
input1 = _mm_srai_epi32(input1, DCT_CONST_BITS);
input2 = _mm_srai_epi32(input2, DCT_CONST_BITS);
input3 = _mm_srai_epi32(input3, DCT_CONST_BITS);
// Stage 2
input0 = _mm_packs_epi32(input0, zero);
input1 = _mm_packs_epi32(input1, zero);
input2 = _mm_packs_epi32(input2, zero);
input3 = _mm_packs_epi32(input3, zero);
// Transpose
input1 = _mm_unpacklo_epi16(input0, input1);
input3 = _mm_unpacklo_epi16(input2, input3);
input0 = _mm_unpacklo_epi32(input1, input3);
input1 = _mm_unpackhi_epi32(input1, input3);
// Switch column2, column 3, and then, we got:
// input2: column1, column 0; input3: column2, column 3.
input1 = _mm_shuffle_epi32(input1, 0x4e);
input2 = _mm_add_epi16(input0, input1);
input3 = _mm_sub_epi16(input0, input1);
// Columns
// Construct i3, i1, i3, i1, i2, i0, i2, i0
input0 = _mm_shufflelo_epi16(input2, 0xd8);
input1 = _mm_shufflehi_epi16(input2, 0xd8);
input2 = _mm_shufflehi_epi16(input3, 0xd8);
input3 = _mm_shufflelo_epi16(input3, 0xd8);
input0 = _mm_unpacklo_epi32(input0, input0);
input1 = _mm_unpackhi_epi32(input1, input1);
input2 = _mm_unpackhi_epi32(input2, input2);
input3 = _mm_unpacklo_epi32(input3, input3);
// Stage 1
input0 = _mm_madd_epi16(input0, cst);
input1 = _mm_madd_epi16(input1, cst);
input2 = _mm_madd_epi16(input2, cst);
input3 = _mm_madd_epi16(input3, cst);
input0 = _mm_add_epi32(input0, rounding);
input1 = _mm_add_epi32(input1, rounding);
input2 = _mm_add_epi32(input2, rounding);
input3 = _mm_add_epi32(input3, rounding);
input0 = _mm_srai_epi32(input0, DCT_CONST_BITS);
input1 = _mm_srai_epi32(input1, DCT_CONST_BITS);
input2 = _mm_srai_epi32(input2, DCT_CONST_BITS);
input3 = _mm_srai_epi32(input3, DCT_CONST_BITS);
// Stage 2
input0 = _mm_packs_epi32(input0, zero);
input1 = _mm_packs_epi32(input1, zero);
input2 = _mm_packs_epi32(input2, zero);
input3 = _mm_packs_epi32(input3, zero);
// Transpose
input1 = _mm_unpacklo_epi16(input0, input1);
input3 = _mm_unpacklo_epi16(input2, input3);
input0 = _mm_unpacklo_epi32(input1, input3);
input1 = _mm_unpackhi_epi32(input1, input3);
// Switch column2, column 3, and then, we got:
// input2: column1, column 0; input3: column2, column 3.
input1 = _mm_shuffle_epi32(input1, 0x4e);
input2 = _mm_add_epi16(input0, input1);
input3 = _mm_sub_epi16(input0, input1);
// Final round and shift
input2 = _mm_add_epi16(input2, eight);
input3 = _mm_add_epi16(input3, eight);
input2 = _mm_srai_epi16(input2, 4);
input3 = _mm_srai_epi16(input3, 4);
#define RECON_AND_STORE4X4(dest, in_x) \
{ \
__m128i d0 = _mm_cvtsi32_si128(*(const int *)(dest)); \
d0 = _mm_unpacklo_epi8(d0, zero); \
d0 = _mm_add_epi16(in_x, d0); \
d0 = _mm_packus_epi16(d0, d0); \
*(int *)dest = _mm_cvtsi128_si32(d0); \
dest += stride; \
}
input0 = _mm_srli_si128(input2, 8);
input1 = _mm_srli_si128(input3, 8);
RECON_AND_STORE4X4(dest, input2);
RECON_AND_STORE4X4(dest, input0);
RECON_AND_STORE4X4(dest, input1);
RECON_AND_STORE4X4(dest, input3);
}
void vp9_idct4_1d_sse2(int16_t *input, int16_t *output) {
const __m128i zero = _mm_setzero_si128();
const __m128i c1 = _mm_setr_epi16((int16_t)cospi_16_64, (int16_t)cospi_16_64,
(int16_t)cospi_16_64, (int16_t)-cospi_16_64,
(int16_t)cospi_24_64, (int16_t)-cospi_8_64,
(int16_t)cospi_8_64, (int16_t)cospi_24_64);
const __m128i c2 = _mm_setr_epi16(1, 1, 1, 1, 1, -1, 1, -1);
const __m128i rounding = _mm_set1_epi32(DCT_CONST_ROUNDING);
__m128i in, temp;
// Load input data.
in = _mm_loadl_epi64((__m128i *)input);
// Construct i3, i1, i3, i1, i2, i0, i2, i0
in = _mm_shufflelo_epi16(in, 0xd8);
in = _mm_unpacklo_epi32(in, in);
// Stage 1
in = _mm_madd_epi16(in, c1);
in = _mm_add_epi32(in, rounding);
in = _mm_srai_epi32(in, DCT_CONST_BITS);
in = _mm_packs_epi32(in, zero);
// Stage 2
temp = _mm_shufflelo_epi16(in, 0x9c);
in = _mm_shufflelo_epi16(in, 0xc9);
in = _mm_unpacklo_epi64(temp, in);
in = _mm_madd_epi16(in, c2);
in = _mm_packs_epi32(in, zero);
// Store results
_mm_storel_epi64((__m128i *)output, in);
}
static INLINE void transpose_4x4(__m128i *res) {
const __m128i tr0_0 = _mm_unpacklo_epi16(res[0], res[1]);
const __m128i tr0_1 = _mm_unpacklo_epi16(res[2], res[3]);
res[0] = _mm_unpacklo_epi32(tr0_0, tr0_1);
res[2] = _mm_unpackhi_epi32(tr0_0, tr0_1);
res[1] = _mm_unpackhi_epi64(res[0], res[0]);
res[3] = _mm_unpackhi_epi64(res[2], res[2]);
}
void idct4_1d_sse2(__m128i *in) {
const __m128i k__cospi_p16_p16 = pair_set_epi16(cospi_16_64, cospi_16_64);
const __m128i k__cospi_p16_m16 = pair_set_epi16(cospi_16_64, -cospi_16_64);
const __m128i k__cospi_p24_m08 = pair_set_epi16(cospi_24_64, -cospi_8_64);
const __m128i k__cospi_p08_p24 = pair_set_epi16(cospi_8_64, cospi_24_64);
const __m128i k__DCT_CONST_ROUNDING = _mm_set1_epi32(DCT_CONST_ROUNDING);
__m128i u[8], v[8];
transpose_4x4(in);
// stage 1
u[0] = _mm_unpacklo_epi16(in[0], in[2]);
u[1] = _mm_unpacklo_epi16(in[1], in[3]);
v[0] = _mm_madd_epi16(u[0], k__cospi_p16_p16);
v[1] = _mm_madd_epi16(u[0], k__cospi_p16_m16);
v[2] = _mm_madd_epi16(u[1], k__cospi_p24_m08);
v[3] = _mm_madd_epi16(u[1], k__cospi_p08_p24);
u[0] = _mm_add_epi32(v[0], k__DCT_CONST_ROUNDING);
u[1] = _mm_add_epi32(v[1], k__DCT_CONST_ROUNDING);
u[2] = _mm_add_epi32(v[2], k__DCT_CONST_ROUNDING);
u[3] = _mm_add_epi32(v[3], k__DCT_CONST_ROUNDING);
v[0] = _mm_srai_epi32(u[0], DCT_CONST_BITS);
v[1] = _mm_srai_epi32(u[1], DCT_CONST_BITS);
v[2] = _mm_srai_epi32(u[2], DCT_CONST_BITS);
v[3] = _mm_srai_epi32(u[3], DCT_CONST_BITS);
u[0] = _mm_packs_epi32(v[0], v[2]);
u[1] = _mm_packs_epi32(v[1], v[3]);
u[2] = _mm_unpackhi_epi64(u[0], u[0]);
u[3] = _mm_unpackhi_epi64(u[1], u[1]);
// stage 2
in[0] = _mm_add_epi16(u[0], u[3]);
in[1] = _mm_add_epi16(u[1], u[2]);
in[2] = _mm_sub_epi16(u[1], u[2]);
in[3] = _mm_sub_epi16(u[0], u[3]);
}
void iadst4_1d_sse2(__m128i *in) {
const __m128i k__sinpi_p01_p04 = pair_set_epi16(sinpi_1_9, sinpi_4_9);
const __m128i k__sinpi_p03_p02 = pair_set_epi16(sinpi_3_9, sinpi_2_9);
const __m128i k__sinpi_p02_m01 = pair_set_epi16(sinpi_2_9, -sinpi_1_9);
const __m128i k__sinpi_p03_m04 = pair_set_epi16(sinpi_3_9, -sinpi_4_9);
const __m128i k__sinpi_p03_p03 = _mm_set1_epi16(sinpi_3_9);
const __m128i kZero = _mm_set1_epi16(0);
const __m128i k__DCT_CONST_ROUNDING = _mm_set1_epi32(DCT_CONST_ROUNDING);
__m128i u[8], v[8], in7;
transpose_4x4(in);
in7 = _mm_add_epi16(in[0], in[3]);
in7 = _mm_sub_epi16(in7, in[2]);
u[0] = _mm_unpacklo_epi16(in[0], in[2]);
u[1] = _mm_unpacklo_epi16(in[1], in[3]);
u[2] = _mm_unpacklo_epi16(in7, kZero);
u[3] = _mm_unpacklo_epi16(in[1], kZero);
v[0] = _mm_madd_epi16(u[0], k__sinpi_p01_p04); // s0 + s3
v[1] = _mm_madd_epi16(u[1], k__sinpi_p03_p02); // s2 + s5
v[2] = _mm_madd_epi16(u[2], k__sinpi_p03_p03); // x2
v[3] = _mm_madd_epi16(u[0], k__sinpi_p02_m01); // s1 - s4
v[4] = _mm_madd_epi16(u[1], k__sinpi_p03_m04); // s2 - s6
v[5] = _mm_madd_epi16(u[3], k__sinpi_p03_p03); // s2
u[0] = _mm_add_epi32(v[0], v[1]);
u[1] = _mm_add_epi32(v[3], v[4]);
u[2] = v[2];
u[3] = _mm_add_epi32(u[0], u[1]);
u[4] = _mm_slli_epi32(v[5], 2);
u[5] = _mm_add_epi32(u[3], v[5]);
u[6] = _mm_sub_epi32(u[5], u[4]);
v[0] = _mm_add_epi32(u[0], k__DCT_CONST_ROUNDING);
v[1] = _mm_add_epi32(u[1], k__DCT_CONST_ROUNDING);
v[2] = _mm_add_epi32(u[2], k__DCT_CONST_ROUNDING);
v[3] = _mm_add_epi32(u[6], k__DCT_CONST_ROUNDING);
u[0] = _mm_srai_epi32(v[0], DCT_CONST_BITS);
u[1] = _mm_srai_epi32(v[1], DCT_CONST_BITS);
u[2] = _mm_srai_epi32(v[2], DCT_CONST_BITS);
u[3] = _mm_srai_epi32(v[3], DCT_CONST_BITS);
in[0] = _mm_packs_epi32(u[0], u[2]);
in[1] = _mm_packs_epi32(u[1], u[3]);
in[2] = _mm_unpackhi_epi64(in[0], in[0]);
in[3] = _mm_unpackhi_epi64(in[1], in[1]);
}
void vp9_short_iht4x4_add_sse2(int16_t *input, uint8_t *dest, int stride,
int tx_type) {
__m128i in[4];
const __m128i zero = _mm_setzero_si128();
const __m128i eight = _mm_set1_epi16(8);
in[0] = _mm_loadl_epi64((__m128i *)input);
in[1] = _mm_loadl_epi64((__m128i *)(input + 4));
in[2] = _mm_loadl_epi64((__m128i *)(input + 8));
in[3] = _mm_loadl_epi64((__m128i *)(input + 12));
switch (tx_type) {
case 0: // DCT_DCT
idct4_1d_sse2(in);
idct4_1d_sse2(in);
break;
case 1: // ADST_DCT
idct4_1d_sse2(in);
iadst4_1d_sse2(in);
break;
case 2: // DCT_ADST
iadst4_1d_sse2(in);
idct4_1d_sse2(in);
break;
case 3: // ADST_ADST
iadst4_1d_sse2(in);
iadst4_1d_sse2(in);
break;
default:
assert(0);
break;
}
// Final round and shift
in[0] = _mm_add_epi16(in[0], eight);
in[1] = _mm_add_epi16(in[1], eight);
in[2] = _mm_add_epi16(in[2], eight);
in[3] = _mm_add_epi16(in[3], eight);
in[0] = _mm_srai_epi16(in[0], 4);
in[1] = _mm_srai_epi16(in[1], 4);
in[2] = _mm_srai_epi16(in[2], 4);
in[3] = _mm_srai_epi16(in[3], 4);
RECON_AND_STORE4X4(dest, in[0]);
RECON_AND_STORE4X4(dest, in[1]);
RECON_AND_STORE4X4(dest, in[2]);
RECON_AND_STORE4X4(dest, in[3]);
}
#define TRANSPOSE_8X8(in0, in1, in2, in3, in4, in5, in6, in7, \
out0, out1, out2, out3, out4, out5, out6, out7) \
{ \
const __m128i tr0_0 = _mm_unpacklo_epi16(in0, in1); \
const __m128i tr0_1 = _mm_unpacklo_epi16(in2, in3); \
const __m128i tr0_2 = _mm_unpackhi_epi16(in0, in1); \
const __m128i tr0_3 = _mm_unpackhi_epi16(in2, in3); \
const __m128i tr0_4 = _mm_unpacklo_epi16(in4, in5); \
const __m128i tr0_5 = _mm_unpacklo_epi16(in6, in7); \
const __m128i tr0_6 = _mm_unpackhi_epi16(in4, in5); \
const __m128i tr0_7 = _mm_unpackhi_epi16(in6, in7); \
\
const __m128i tr1_0 = _mm_unpacklo_epi32(tr0_0, tr0_1); \
const __m128i tr1_1 = _mm_unpacklo_epi32(tr0_2, tr0_3); \
const __m128i tr1_2 = _mm_unpackhi_epi32(tr0_0, tr0_1); \
const __m128i tr1_3 = _mm_unpackhi_epi32(tr0_2, tr0_3); \
const __m128i tr1_4 = _mm_unpacklo_epi32(tr0_4, tr0_5); \
const __m128i tr1_5 = _mm_unpacklo_epi32(tr0_6, tr0_7); \
const __m128i tr1_6 = _mm_unpackhi_epi32(tr0_4, tr0_5); \
const __m128i tr1_7 = _mm_unpackhi_epi32(tr0_6, tr0_7); \
\
out0 = _mm_unpacklo_epi64(tr1_0, tr1_4); \
out1 = _mm_unpackhi_epi64(tr1_0, tr1_4); \
out2 = _mm_unpacklo_epi64(tr1_2, tr1_6); \
out3 = _mm_unpackhi_epi64(tr1_2, tr1_6); \
out4 = _mm_unpacklo_epi64(tr1_1, tr1_5); \
out5 = _mm_unpackhi_epi64(tr1_1, tr1_5); \
out6 = _mm_unpacklo_epi64(tr1_3, tr1_7); \
out7 = _mm_unpackhi_epi64(tr1_3, tr1_7); \
}
#define TRANSPOSE_4X8(in0, in1, in2, in3, in4, in5, in6, in7, \
out0, out1, out2, out3, out4, out5, out6, out7) \
{ \
const __m128i tr0_0 = _mm_unpacklo_epi16(in0, in1); \
const __m128i tr0_1 = _mm_unpacklo_epi16(in2, in3); \
const __m128i tr0_4 = _mm_unpacklo_epi16(in4, in5); \
const __m128i tr0_5 = _mm_unpacklo_epi16(in6, in7); \
\
const __m128i tr1_0 = _mm_unpacklo_epi32(tr0_0, tr0_1); \
const __m128i tr1_2 = _mm_unpackhi_epi32(tr0_0, tr0_1); \
const __m128i tr1_4 = _mm_unpacklo_epi32(tr0_4, tr0_5); \
const __m128i tr1_6 = _mm_unpackhi_epi32(tr0_4, tr0_5); \
\
out0 = _mm_unpacklo_epi64(tr1_0, tr1_4); \
out1 = _mm_unpackhi_epi64(tr1_0, tr1_4); \
out2 = _mm_unpacklo_epi64(tr1_2, tr1_6); \
out3 = _mm_unpackhi_epi64(tr1_2, tr1_6); \
out4 = out5 = out6 = out7 = zero; \
}
#define TRANSPOSE_8X4(in0, in1, in2, in3, out0, out1, out2, out3) \
{ \
const __m128i tr0_0 = _mm_unpacklo_epi16(in0, in1); \
const __m128i tr0_1 = _mm_unpacklo_epi16(in2, in3); \
const __m128i tr0_2 = _mm_unpackhi_epi16(in0, in1); \
const __m128i tr0_3 = _mm_unpackhi_epi16(in2, in3); \
\
in0 = _mm_unpacklo_epi32(tr0_0, tr0_1); /* i1 i0 */ \
in1 = _mm_unpackhi_epi32(tr0_0, tr0_1); /* i3 i2 */ \
in2 = _mm_unpacklo_epi32(tr0_2, tr0_3); /* i5 i4 */ \
in3 = _mm_unpackhi_epi32(tr0_2, tr0_3); /* i7 i6 */ \
}
// Define Macro for multiplying elements by constants and adding them together.
#define MULTIPLICATION_AND_ADD(lo_0, hi_0, lo_1, hi_1, \
cst0, cst1, cst2, cst3, res0, res1, res2, res3) \
{ \
tmp0 = _mm_madd_epi16(lo_0, cst0); \
tmp1 = _mm_madd_epi16(hi_0, cst0); \
tmp2 = _mm_madd_epi16(lo_0, cst1); \
tmp3 = _mm_madd_epi16(hi_0, cst1); \
tmp4 = _mm_madd_epi16(lo_1, cst2); \
tmp5 = _mm_madd_epi16(hi_1, cst2); \
tmp6 = _mm_madd_epi16(lo_1, cst3); \
tmp7 = _mm_madd_epi16(hi_1, cst3); \
\
tmp0 = _mm_add_epi32(tmp0, rounding); \
tmp1 = _mm_add_epi32(tmp1, rounding); \
tmp2 = _mm_add_epi32(tmp2, rounding); \
tmp3 = _mm_add_epi32(tmp3, rounding); \
tmp4 = _mm_add_epi32(tmp4, rounding); \
tmp5 = _mm_add_epi32(tmp5, rounding); \
tmp6 = _mm_add_epi32(tmp6, rounding); \
tmp7 = _mm_add_epi32(tmp7, rounding); \
\
tmp0 = _mm_srai_epi32(tmp0, DCT_CONST_BITS); \
tmp1 = _mm_srai_epi32(tmp1, DCT_CONST_BITS); \
tmp2 = _mm_srai_epi32(tmp2, DCT_CONST_BITS); \
tmp3 = _mm_srai_epi32(tmp3, DCT_CONST_BITS); \
tmp4 = _mm_srai_epi32(tmp4, DCT_CONST_BITS); \
tmp5 = _mm_srai_epi32(tmp5, DCT_CONST_BITS); \
tmp6 = _mm_srai_epi32(tmp6, DCT_CONST_BITS); \
tmp7 = _mm_srai_epi32(tmp7, DCT_CONST_BITS); \
\
res0 = _mm_packs_epi32(tmp0, tmp1); \
res1 = _mm_packs_epi32(tmp2, tmp3); \
res2 = _mm_packs_epi32(tmp4, tmp5); \
res3 = _mm_packs_epi32(tmp6, tmp7); \
}
#define IDCT8x8_1D \
/* Stage1 */ \
{ \
const __m128i lo_17 = _mm_unpacklo_epi16(in1, in7); \
const __m128i hi_17 = _mm_unpackhi_epi16(in1, in7); \
const __m128i lo_35 = _mm_unpacklo_epi16(in3, in5); \
const __m128i hi_35 = _mm_unpackhi_epi16(in3, in5); \
\
MULTIPLICATION_AND_ADD(lo_17, hi_17, lo_35, hi_35, stg1_0, \
stg1_1, stg1_2, stg1_3, stp1_4, \
stp1_7, stp1_5, stp1_6) \
} \
\
/* Stage2 */ \
{ \
const __m128i lo_04 = _mm_unpacklo_epi16(in0, in4); \
const __m128i hi_04 = _mm_unpackhi_epi16(in0, in4); \
const __m128i lo_26 = _mm_unpacklo_epi16(in2, in6); \
const __m128i hi_26 = _mm_unpackhi_epi16(in2, in6); \
\
MULTIPLICATION_AND_ADD(lo_04, hi_04, lo_26, hi_26, stg2_0, \
stg2_1, stg2_2, stg2_3, stp2_0, \
stp2_1, stp2_2, stp2_3) \
\
stp2_4 = _mm_adds_epi16(stp1_4, stp1_5); \
stp2_5 = _mm_subs_epi16(stp1_4, stp1_5); \
stp2_6 = _mm_subs_epi16(stp1_7, stp1_6); \
stp2_7 = _mm_adds_epi16(stp1_7, stp1_6); \
} \
\
/* Stage3 */ \
{ \
const __m128i lo_56 = _mm_unpacklo_epi16(stp2_6, stp2_5); \
const __m128i hi_56 = _mm_unpackhi_epi16(stp2_6, stp2_5); \
\
stp1_0 = _mm_adds_epi16(stp2_0, stp2_3); \
stp1_1 = _mm_adds_epi16(stp2_1, stp2_2); \
stp1_2 = _mm_subs_epi16(stp2_1, stp2_2); \
stp1_3 = _mm_subs_epi16(stp2_0, stp2_3); \
\
tmp0 = _mm_madd_epi16(lo_56, stg2_1); \
tmp1 = _mm_madd_epi16(hi_56, stg2_1); \
tmp2 = _mm_madd_epi16(lo_56, stg2_0); \
tmp3 = _mm_madd_epi16(hi_56, stg2_0); \
\
tmp0 = _mm_add_epi32(tmp0, rounding); \
tmp1 = _mm_add_epi32(tmp1, rounding); \
tmp2 = _mm_add_epi32(tmp2, rounding); \
tmp3 = _mm_add_epi32(tmp3, rounding); \
\
tmp0 = _mm_srai_epi32(tmp0, DCT_CONST_BITS); \
tmp1 = _mm_srai_epi32(tmp1, DCT_CONST_BITS); \
tmp2 = _mm_srai_epi32(tmp2, DCT_CONST_BITS); \
tmp3 = _mm_srai_epi32(tmp3, DCT_CONST_BITS); \
\
stp1_5 = _mm_packs_epi32(tmp0, tmp1); \
stp1_6 = _mm_packs_epi32(tmp2, tmp3); \
} \
\
/* Stage4 */ \
in0 = _mm_adds_epi16(stp1_0, stp2_7); \
in1 = _mm_adds_epi16(stp1_1, stp1_6); \
in2 = _mm_adds_epi16(stp1_2, stp1_5); \
in3 = _mm_adds_epi16(stp1_3, stp2_4); \
in4 = _mm_subs_epi16(stp1_3, stp2_4); \
in5 = _mm_subs_epi16(stp1_2, stp1_5); \
in6 = _mm_subs_epi16(stp1_1, stp1_6); \
in7 = _mm_subs_epi16(stp1_0, stp2_7);
#define RECON_AND_STORE(dest, in_x) \
{ \
__m128i d0 = _mm_loadl_epi64((__m128i *)(dest)); \
d0 = _mm_unpacklo_epi8(d0, zero); \
in_x = _mm_add_epi16(in_x, d0); \
in_x = _mm_packus_epi16(in_x, in_x); \
_mm_storel_epi64((__m128i *)(dest), in_x); \
dest += stride; \
}
void vp9_short_idct8x8_add_sse2(int16_t *input, uint8_t *dest, int stride) {
const __m128i zero = _mm_setzero_si128();
const __m128i rounding = _mm_set1_epi32(DCT_CONST_ROUNDING);
const __m128i final_rounding = _mm_set1_epi16(1<<4);
const __m128i stg1_0 = pair_set_epi16(cospi_28_64, -cospi_4_64);
const __m128i stg1_1 = pair_set_epi16(cospi_4_64, cospi_28_64);
const __m128i stg1_2 = pair_set_epi16(-cospi_20_64, cospi_12_64);
const __m128i stg1_3 = pair_set_epi16(cospi_12_64, cospi_20_64);
const __m128i stg2_0 = pair_set_epi16(cospi_16_64, cospi_16_64);
const __m128i stg2_1 = pair_set_epi16(cospi_16_64, -cospi_16_64);
const __m128i stg2_2 = pair_set_epi16(cospi_24_64, -cospi_8_64);
const __m128i stg2_3 = pair_set_epi16(cospi_8_64, cospi_24_64);
__m128i in0, in1, in2, in3, in4, in5, in6, in7;
__m128i stp1_0, stp1_1, stp1_2, stp1_3, stp1_4, stp1_5, stp1_6, stp1_7;
__m128i stp2_0, stp2_1, stp2_2, stp2_3, stp2_4, stp2_5, stp2_6, stp2_7;
__m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
int i;
// Load input data.
in0 = _mm_load_si128((__m128i *)input);
in1 = _mm_load_si128((__m128i *)(input + 8 * 1));
in2 = _mm_load_si128((__m128i *)(input + 8 * 2));
in3 = _mm_load_si128((__m128i *)(input + 8 * 3));
in4 = _mm_load_si128((__m128i *)(input + 8 * 4));
in5 = _mm_load_si128((__m128i *)(input + 8 * 5));
in6 = _mm_load_si128((__m128i *)(input + 8 * 6));
in7 = _mm_load_si128((__m128i *)(input + 8 * 7));
// 2-D
for (i = 0; i < 2; i++) {
// 8x8 Transpose is copied from vp9_short_fdct8x8_sse2()
TRANSPOSE_8X8(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3,
in4, in5, in6, in7);
// 4-stage 1D idct8x8
IDCT8x8_1D
}
// Final rounding and shift
in0 = _mm_adds_epi16(in0, final_rounding);
in1 = _mm_adds_epi16(in1, final_rounding);
in2 = _mm_adds_epi16(in2, final_rounding);
in3 = _mm_adds_epi16(in3, final_rounding);
in4 = _mm_adds_epi16(in4, final_rounding);
in5 = _mm_adds_epi16(in5, final_rounding);
in6 = _mm_adds_epi16(in6, final_rounding);
in7 = _mm_adds_epi16(in7, final_rounding);
in0 = _mm_srai_epi16(in0, 5);
in1 = _mm_srai_epi16(in1, 5);
in2 = _mm_srai_epi16(in2, 5);
in3 = _mm_srai_epi16(in3, 5);
in4 = _mm_srai_epi16(in4, 5);
in5 = _mm_srai_epi16(in5, 5);
in6 = _mm_srai_epi16(in6, 5);
in7 = _mm_srai_epi16(in7, 5);
RECON_AND_STORE(dest, in0);
RECON_AND_STORE(dest, in1);
RECON_AND_STORE(dest, in2);
RECON_AND_STORE(dest, in3);
RECON_AND_STORE(dest, in4);
RECON_AND_STORE(dest, in5);
RECON_AND_STORE(dest, in6);
RECON_AND_STORE(dest, in7);
}
void vp9_short_idct10_8x8_add_sse2(int16_t *input, uint8_t *dest, int stride) {
const __m128i zero = _mm_setzero_si128();
const __m128i rounding = _mm_set1_epi32(DCT_CONST_ROUNDING);
const __m128i final_rounding = _mm_set1_epi16(1<<4);
const __m128i stg1_0 = pair_set_epi16(cospi_28_64, -cospi_4_64);
const __m128i stg1_1 = pair_set_epi16(cospi_4_64, cospi_28_64);
const __m128i stg1_2 = pair_set_epi16(-cospi_20_64, cospi_12_64);
const __m128i stg1_3 = pair_set_epi16(cospi_12_64, cospi_20_64);
const __m128i stg2_0 = pair_set_epi16(cospi_16_64, cospi_16_64);
const __m128i stg2_1 = pair_set_epi16(cospi_16_64, -cospi_16_64);
const __m128i stg2_2 = pair_set_epi16(cospi_24_64, -cospi_8_64);
const __m128i stg2_3 = pair_set_epi16(cospi_8_64, cospi_24_64);
const __m128i stg3_0 = pair_set_epi16(-cospi_16_64, cospi_16_64);
__m128i in0, in1, in2, in3, in4, in5, in6, in7;
__m128i stp1_0, stp1_1, stp1_2, stp1_3, stp1_4, stp1_5, stp1_6, stp1_7;
__m128i stp2_0, stp2_1, stp2_2, stp2_3, stp2_4, stp2_5, stp2_6, stp2_7;
__m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
// Rows. Load 4-row input data.
in0 = _mm_load_si128((__m128i *)input);
in1 = _mm_load_si128((__m128i *)(input + 8 * 1));
in2 = _mm_load_si128((__m128i *)(input + 8 * 2));
in3 = _mm_load_si128((__m128i *)(input + 8 * 3));
// 8x4 Transpose
TRANSPOSE_8X4(in0, in1, in2, in3, in0, in1, in2, in3)
// Stage1
{
const __m128i lo_17 = _mm_unpackhi_epi16(in0, in3);
const __m128i lo_35 = _mm_unpackhi_epi16(in1, in2);
tmp0 = _mm_madd_epi16(lo_17, stg1_0);
tmp2 = _mm_madd_epi16(lo_17, stg1_1);
tmp4 = _mm_madd_epi16(lo_35, stg1_2);
tmp6 = _mm_madd_epi16(lo_35, stg1_3);
tmp0 = _mm_add_epi32(tmp0, rounding);
tmp2 = _mm_add_epi32(tmp2, rounding);
tmp4 = _mm_add_epi32(tmp4, rounding);
tmp6 = _mm_add_epi32(tmp6, rounding);
tmp0 = _mm_srai_epi32(tmp0, DCT_CONST_BITS);
tmp2 = _mm_srai_epi32(tmp2, DCT_CONST_BITS);
tmp4 = _mm_srai_epi32(tmp4, DCT_CONST_BITS);
tmp6 = _mm_srai_epi32(tmp6, DCT_CONST_BITS);
stp1_4 = _mm_packs_epi32(tmp0, zero);
stp1_7 = _mm_packs_epi32(tmp2, zero);
stp1_5 = _mm_packs_epi32(tmp4, zero);
stp1_6 = _mm_packs_epi32(tmp6, zero);
}
// Stage2
{
const __m128i lo_04 = _mm_unpacklo_epi16(in0, in2);
const __m128i lo_26 = _mm_unpacklo_epi16(in1, in3);
tmp0 = _mm_madd_epi16(lo_04, stg2_0);
tmp2 = _mm_madd_epi16(lo_04, stg2_1);
tmp4 = _mm_madd_epi16(lo_26, stg2_2);
tmp6 = _mm_madd_epi16(lo_26, stg2_3);
tmp0 = _mm_add_epi32(tmp0, rounding);
tmp2 = _mm_add_epi32(tmp2, rounding);
tmp4 = _mm_add_epi32(tmp4, rounding);
tmp6 = _mm_add_epi32(tmp6, rounding);
tmp0 = _mm_srai_epi32(tmp0, DCT_CONST_BITS);
tmp2 = _mm_srai_epi32(tmp2, DCT_CONST_BITS);
tmp4 = _mm_srai_epi32(tmp4, DCT_CONST_BITS);
tmp6 = _mm_srai_epi32(tmp6, DCT_CONST_BITS);
stp2_0 = _mm_packs_epi32(tmp0, zero);
stp2_1 = _mm_packs_epi32(tmp2, zero);
stp2_2 = _mm_packs_epi32(tmp4, zero);
stp2_3 = _mm_packs_epi32(tmp6, zero);
stp2_4 = _mm_adds_epi16(stp1_4, stp1_5);
stp2_5 = _mm_subs_epi16(stp1_4, stp1_5);
stp2_6 = _mm_subs_epi16(stp1_7, stp1_6);
stp2_7 = _mm_adds_epi16(stp1_7, stp1_6);
}
// Stage3
{
const __m128i lo_56 = _mm_unpacklo_epi16(stp2_5, stp2_6);
stp1_0 = _mm_adds_epi16(stp2_0, stp2_3);
stp1_1 = _mm_adds_epi16(stp2_1, stp2_2);
stp1_2 = _mm_subs_epi16(stp2_1, stp2_2);
stp1_3 = _mm_subs_epi16(stp2_0, stp2_3);
tmp0 = _mm_madd_epi16(lo_56, stg3_0);
tmp2 = _mm_madd_epi16(lo_56, stg2_0); // stg3_1 = stg2_0
tmp0 = _mm_add_epi32(tmp0, rounding);
tmp2 = _mm_add_epi32(tmp2, rounding);
tmp0 = _mm_srai_epi32(tmp0, DCT_CONST_BITS);
tmp2 = _mm_srai_epi32(tmp2, DCT_CONST_BITS);
stp1_5 = _mm_packs_epi32(tmp0, zero);
stp1_6 = _mm_packs_epi32(tmp2, zero);
}
// Stage4
in0 = _mm_adds_epi16(stp1_0, stp2_7);
in1 = _mm_adds_epi16(stp1_1, stp1_6);
in2 = _mm_adds_epi16(stp1_2, stp1_5);
in3 = _mm_adds_epi16(stp1_3, stp2_4);
in4 = _mm_subs_epi16(stp1_3, stp2_4);
in5 = _mm_subs_epi16(stp1_2, stp1_5);
in6 = _mm_subs_epi16(stp1_1, stp1_6);
in7 = _mm_subs_epi16(stp1_0, stp2_7);
// Columns. 4x8 Transpose
TRANSPOSE_4X8(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3,
in4, in5, in6, in7)
// 1D idct8x8
IDCT8x8_1D
// Final rounding and shift
in0 = _mm_adds_epi16(in0, final_rounding);
in1 = _mm_adds_epi16(in1, final_rounding);
in2 = _mm_adds_epi16(in2, final_rounding);
in3 = _mm_adds_epi16(in3, final_rounding);
in4 = _mm_adds_epi16(in4, final_rounding);
in5 = _mm_adds_epi16(in5, final_rounding);
in6 = _mm_adds_epi16(in6, final_rounding);
in7 = _mm_adds_epi16(in7, final_rounding);
in0 = _mm_srai_epi16(in0, 5);
in1 = _mm_srai_epi16(in1, 5);
in2 = _mm_srai_epi16(in2, 5);
in3 = _mm_srai_epi16(in3, 5);
in4 = _mm_srai_epi16(in4, 5);
in5 = _mm_srai_epi16(in5, 5);
in6 = _mm_srai_epi16(in6, 5);
in7 = _mm_srai_epi16(in7, 5);
RECON_AND_STORE(dest, in0);
RECON_AND_STORE(dest, in1);
RECON_AND_STORE(dest, in2);
RECON_AND_STORE(dest, in3);
RECON_AND_STORE(dest, in4);
RECON_AND_STORE(dest, in5);
RECON_AND_STORE(dest, in6);
RECON_AND_STORE(dest, in7);
}
#define IDCT16x16_1D \
/* Stage2 */ \
{ \
const __m128i lo_1_15 = _mm_unpacklo_epi16(in1, in15); \
const __m128i hi_1_15 = _mm_unpackhi_epi16(in1, in15); \
const __m128i lo_9_7 = _mm_unpacklo_epi16(in9, in7); \
const __m128i hi_9_7 = _mm_unpackhi_epi16(in9, in7); \
const __m128i lo_5_11 = _mm_unpacklo_epi16(in5, in11); \
const __m128i hi_5_11 = _mm_unpackhi_epi16(in5, in11); \
const __m128i lo_13_3 = _mm_unpacklo_epi16(in13, in3); \
const __m128i hi_13_3 = _mm_unpackhi_epi16(in13, in3); \
\
MULTIPLICATION_AND_ADD(lo_1_15, hi_1_15, lo_9_7, hi_9_7, \
stg2_0, stg2_1, stg2_2, stg2_3, \
stp2_8, stp2_15, stp2_9, stp2_14) \
\
MULTIPLICATION_AND_ADD(lo_5_11, hi_5_11, lo_13_3, hi_13_3, \
stg2_4, stg2_5, stg2_6, stg2_7, \
stp2_10, stp2_13, stp2_11, stp2_12) \
} \
\
/* Stage3 */ \
{ \
const __m128i lo_2_14 = _mm_unpacklo_epi16(in2, in14); \
const __m128i hi_2_14 = _mm_unpackhi_epi16(in2, in14); \
const __m128i lo_10_6 = _mm_unpacklo_epi16(in10, in6); \
const __m128i hi_10_6 = _mm_unpackhi_epi16(in10, in6); \
\
MULTIPLICATION_AND_ADD(lo_2_14, hi_2_14, lo_10_6, hi_10_6, \
stg3_0, stg3_1, stg3_2, stg3_3, \
stp1_4, stp1_7, stp1_5, stp1_6) \
\
stp1_8_0 = _mm_add_epi16(stp2_8, stp2_9); \
stp1_9 = _mm_sub_epi16(stp2_8, stp2_9); \
stp1_10 = _mm_sub_epi16(stp2_11, stp2_10); \
stp1_11 = _mm_add_epi16(stp2_11, stp2_10); \
\
stp1_12_0 = _mm_add_epi16(stp2_12, stp2_13); \
stp1_13 = _mm_sub_epi16(stp2_12, stp2_13); \
stp1_14 = _mm_sub_epi16(stp2_15, stp2_14); \
stp1_15 = _mm_add_epi16(stp2_15, stp2_14); \
} \
\
/* Stage4 */ \
{ \
const __m128i lo_0_8 = _mm_unpacklo_epi16(in0, in8); \
const __m128i hi_0_8 = _mm_unpackhi_epi16(in0, in8); \
const __m128i lo_4_12 = _mm_unpacklo_epi16(in4, in12); \
const __m128i hi_4_12 = _mm_unpackhi_epi16(in4, in12); \
\
const __m128i lo_9_14 = _mm_unpacklo_epi16(stp1_9, stp1_14); \
const __m128i hi_9_14 = _mm_unpackhi_epi16(stp1_9, stp1_14); \
const __m128i lo_10_13 = _mm_unpacklo_epi16(stp1_10, stp1_13); \
const __m128i hi_10_13 = _mm_unpackhi_epi16(stp1_10, stp1_13); \
\
MULTIPLICATION_AND_ADD(lo_0_8, hi_0_8, lo_4_12, hi_4_12, \
stg4_0, stg4_1, stg4_2, stg4_3, \
stp2_0, stp2_1, stp2_2, stp2_3) \
\
stp2_4 = _mm_add_epi16(stp1_4, stp1_5); \
stp2_5 = _mm_sub_epi16(stp1_4, stp1_5); \
stp2_6 = _mm_sub_epi16(stp1_7, stp1_6); \
stp2_7 = _mm_add_epi16(stp1_7, stp1_6); \
\
MULTIPLICATION_AND_ADD(lo_9_14, hi_9_14, lo_10_13, hi_10_13, \
stg4_4, stg4_5, stg4_6, stg4_7, \
stp2_9, stp2_14, stp2_10, stp2_13) \
} \
\
/* Stage5 */ \
{ \
const __m128i lo_6_5 = _mm_unpacklo_epi16(stp2_6, stp2_5); \
const __m128i hi_6_5 = _mm_unpackhi_epi16(stp2_6, stp2_5); \
\
stp1_0 = _mm_add_epi16(stp2_0, stp2_3); \
stp1_1 = _mm_add_epi16(stp2_1, stp2_2); \
stp1_2 = _mm_sub_epi16(stp2_1, stp2_2); \
stp1_3 = _mm_sub_epi16(stp2_0, stp2_3); \
\
tmp0 = _mm_madd_epi16(lo_6_5, stg4_1); \
tmp1 = _mm_madd_epi16(hi_6_5, stg4_1); \
tmp2 = _mm_madd_epi16(lo_6_5, stg4_0); \
tmp3 = _mm_madd_epi16(hi_6_5, stg4_0); \
\
tmp0 = _mm_add_epi32(tmp0, rounding); \
tmp1 = _mm_add_epi32(tmp1, rounding); \
tmp2 = _mm_add_epi32(tmp2, rounding); \
tmp3 = _mm_add_epi32(tmp3, rounding); \
\
tmp0 = _mm_srai_epi32(tmp0, DCT_CONST_BITS); \
tmp1 = _mm_srai_epi32(tmp1, DCT_CONST_BITS); \
tmp2 = _mm_srai_epi32(tmp2, DCT_CONST_BITS); \
tmp3 = _mm_srai_epi32(tmp3, DCT_CONST_BITS); \
\
stp1_5 = _mm_packs_epi32(tmp0, tmp1); \
stp1_6 = _mm_packs_epi32(tmp2, tmp3); \
\
stp1_8 = _mm_add_epi16(stp1_8_0, stp1_11); \
stp1_9 = _mm_add_epi16(stp2_9, stp2_10); \
stp1_10 = _mm_sub_epi16(stp2_9, stp2_10); \
stp1_11 = _mm_sub_epi16(stp1_8_0, stp1_11); \
\
stp1_12 = _mm_sub_epi16(stp1_15, stp1_12_0); \
stp1_13 = _mm_sub_epi16(stp2_14, stp2_13); \
stp1_14 = _mm_add_epi16(stp2_14, stp2_13); \
stp1_15 = _mm_add_epi16(stp1_15, stp1_12_0); \
} \
\
/* Stage6 */ \
{ \
const __m128i lo_10_13 = _mm_unpacklo_epi16(stp1_10, stp1_13); \
const __m128i hi_10_13 = _mm_unpackhi_epi16(stp1_10, stp1_13); \
const __m128i lo_11_12 = _mm_unpacklo_epi16(stp1_11, stp1_12); \
const __m128i hi_11_12 = _mm_unpackhi_epi16(stp1_11, stp1_12); \
\
stp2_0 = _mm_add_epi16(stp1_0, stp2_7); \
stp2_1 = _mm_add_epi16(stp1_1, stp1_6); \
stp2_2 = _mm_add_epi16(stp1_2, stp1_5); \
stp2_3 = _mm_add_epi16(stp1_3, stp2_4); \
stp2_4 = _mm_sub_epi16(stp1_3, stp2_4); \
stp2_5 = _mm_sub_epi16(stp1_2, stp1_5); \
stp2_6 = _mm_sub_epi16(stp1_1, stp1_6); \
stp2_7 = _mm_sub_epi16(stp1_0, stp2_7); \
\
MULTIPLICATION_AND_ADD(lo_10_13, hi_10_13, lo_11_12, hi_11_12, \
stg6_0, stg4_0, stg6_0, stg4_0, \
stp2_10, stp2_13, stp2_11, stp2_12) \
}
void vp9_short_idct16x16_add_sse2(int16_t *input, uint8_t *dest, int stride) {
const __m128i rounding = _mm_set1_epi32(DCT_CONST_ROUNDING);
const __m128i final_rounding = _mm_set1_epi16(1<<5);
const __m128i zero = _mm_setzero_si128();
const __m128i stg2_0 = pair_set_epi16(cospi_30_64, -cospi_2_64);
const __m128i stg2_1 = pair_set_epi16(cospi_2_64, cospi_30_64);
const __m128i stg2_2 = pair_set_epi16(cospi_14_64, -cospi_18_64);
const __m128i stg2_3 = pair_set_epi16(cospi_18_64, cospi_14_64);
const __m128i stg2_4 = pair_set_epi16(cospi_22_64, -cospi_10_64);
const __m128i stg2_5 = pair_set_epi16(cospi_10_64, cospi_22_64);
const __m128i stg2_6 = pair_set_epi16(cospi_6_64, -cospi_26_64);
const __m128i stg2_7 = pair_set_epi16(cospi_26_64, cospi_6_64);
const __m128i stg3_0 = pair_set_epi16(cospi_28_64, -cospi_4_64);
const __m128i stg3_1 = pair_set_epi16(cospi_4_64, cospi_28_64);
const __m128i stg3_2 = pair_set_epi16(cospi_12_64, -cospi_20_64);
const __m128i stg3_3 = pair_set_epi16(cospi_20_64, cospi_12_64);
const __m128i stg4_0 = pair_set_epi16(cospi_16_64, cospi_16_64);
const __m128i stg4_1 = pair_set_epi16(cospi_16_64, -cospi_16_64);
const __m128i stg4_2 = pair_set_epi16(cospi_24_64, -cospi_8_64);
const __m128i stg4_3 = pair_set_epi16(cospi_8_64, cospi_24_64);
const __m128i stg4_4 = pair_set_epi16(-cospi_8_64, cospi_24_64);
const __m128i stg4_5 = pair_set_epi16(cospi_24_64, cospi_8_64);
const __m128i stg4_6 = pair_set_epi16(-cospi_24_64, -cospi_8_64);
const __m128i stg4_7 = pair_set_epi16(-cospi_8_64, cospi_24_64);
const __m128i stg6_0 = pair_set_epi16(-cospi_16_64, cospi_16_64);
__m128i in0 = zero, in1 = zero, in2 = zero, in3 = zero, in4 = zero,
in5 = zero, in6 = zero, in7 = zero, in8 = zero, in9 = zero,
in10 = zero, in11 = zero, in12 = zero, in13 = zero,
in14 = zero, in15 = zero;
__m128i l0 = zero, l1 = zero, l2 = zero, l3 = zero, l4 = zero, l5 = zero,
l6 = zero, l7 = zero, l8 = zero, l9 = zero, l10 = zero, l11 = zero,
l12 = zero, l13 = zero, l14 = zero, l15 = zero;
__m128i r0 = zero, r1 = zero, r2 = zero, r3 = zero, r4 = zero, r5 = zero,
r6 = zero, r7 = zero, r8 = zero, r9 = zero, r10 = zero, r11 = zero,
r12 = zero, r13 = zero, r14 = zero, r15 = zero;
__m128i stp1_0, stp1_1, stp1_2, stp1_3, stp1_4, stp1_5, stp1_6, stp1_7,
stp1_8, stp1_9, stp1_10, stp1_11, stp1_12, stp1_13, stp1_14, stp1_15,
stp1_8_0, stp1_12_0;
__m128i stp2_0, stp2_1, stp2_2, stp2_3, stp2_4, stp2_5, stp2_6, stp2_7,
stp2_8, stp2_9, stp2_10, stp2_11, stp2_12, stp2_13, stp2_14, stp2_15;
__m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
int i;
// We work on a 8x16 block each time, and loop 4 times for 2-D 16x16 idct.
for (i = 0; i < 4; i++) {
// 1-D idct
if (i < 2) {
if (i == 1) input += 128;
// Load input data.
in0 = _mm_load_si128((__m128i *)input);
in8 = _mm_load_si128((__m128i *)(input + 8 * 1));
in1 = _mm_load_si128((__m128i *)(input + 8 * 2));
in9 = _mm_load_si128((__m128i *)(input + 8 * 3));
in2 = _mm_load_si128((__m128i *)(input + 8 * 4));
in10 = _mm_load_si128((__m128i *)(input + 8 * 5));
in3 = _mm_load_si128((__m128i *)(input + 8 * 6));
in11 = _mm_load_si128((__m128i *)(input + 8 * 7));
in4 = _mm_load_si128((__m128i *)(input + 8 * 8));
in12 = _mm_load_si128((__m128i *)(input + 8 * 9));
in5 = _mm_load_si128((__m128i *)(input + 8 * 10));
in13 = _mm_load_si128((__m128i *)(input + 8 * 11));
in6 = _mm_load_si128((__m128i *)(input + 8 * 12));
in14 = _mm_load_si128((__m128i *)(input + 8 * 13));
in7 = _mm_load_si128((__m128i *)(input + 8 * 14));
in15 = _mm_load_si128((__m128i *)(input + 8 * 15));
TRANSPOSE_8X8(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3,
in4, in5, in6, in7);
TRANSPOSE_8X8(in8, in9, in10, in11, in12, in13, in14, in15, in8, in9,
in10, in11, in12, in13, in14, in15);
}
if (i == 2) {
TRANSPOSE_8X8(l0, l1, l2, l3, l4, l5, l6, l7, in0, in1, in2, in3, in4,
in5, in6, in7);
TRANSPOSE_8X8(r0, r1, r2, r3, r4, r5, r6, r7, in8, in9, in10, in11, in12,
in13, in14, in15);
}
if (i == 3) {
TRANSPOSE_8X8(l8, l9, l10, l11, l12, l13, l14, l15, in0, in1, in2, in3,
in4, in5, in6, in7);
TRANSPOSE_8X8(r8, r9, r10, r11, r12, r13, r14, r15, in8, in9, in10, in11,
in12, in13, in14, in15);
}
IDCT16x16_1D
// Stage7
if (i == 0) {
// Left 8x16
l0 = _mm_add_epi16(stp2_0, stp1_15);
l1 = _mm_add_epi16(stp2_1, stp1_14);
l2 = _mm_add_epi16(stp2_2, stp2_13);
l3 = _mm_add_epi16(stp2_3, stp2_12);
l4 = _mm_add_epi16(stp2_4, stp2_11);
l5 = _mm_add_epi16(stp2_5, stp2_10);
l6 = _mm_add_epi16(stp2_6, stp1_9);
l7 = _mm_add_epi16(stp2_7, stp1_8);
l8 = _mm_sub_epi16(stp2_7, stp1_8);
l9 = _mm_sub_epi16(stp2_6, stp1_9);
l10 = _mm_sub_epi16(stp2_5, stp2_10);
l11 = _mm_sub_epi16(stp2_4, stp2_11);
l12 = _mm_sub_epi16(stp2_3, stp2_12);
l13 = _mm_sub_epi16(stp2_2, stp2_13);
l14 = _mm_sub_epi16(stp2_1, stp1_14);
l15 = _mm_sub_epi16(stp2_0, stp1_15);
} else if (i == 1) {
// Right 8x16
r0 = _mm_add_epi16(stp2_0, stp1_15);
r1 = _mm_add_epi16(stp2_1, stp1_14);
r2 = _mm_add_epi16(stp2_2, stp2_13);
r3 = _mm_add_epi16(stp2_3, stp2_12);
r4 = _mm_add_epi16(stp2_4, stp2_11);
r5 = _mm_add_epi16(stp2_5, stp2_10);
r6 = _mm_add_epi16(stp2_6, stp1_9);
r7 = _mm_add_epi16(stp2_7, stp1_8);
r8 = _mm_sub_epi16(stp2_7, stp1_8);
r9 = _mm_sub_epi16(stp2_6, stp1_9);
r10 = _mm_sub_epi16(stp2_5, stp2_10);
r11 = _mm_sub_epi16(stp2_4, stp2_11);
r12 = _mm_sub_epi16(stp2_3, stp2_12);
r13 = _mm_sub_epi16(stp2_2, stp2_13);
r14 = _mm_sub_epi16(stp2_1, stp1_14);
r15 = _mm_sub_epi16(stp2_0, stp1_15);
} else {
// 2-D
in0 = _mm_add_epi16(stp2_0, stp1_15);
in1 = _mm_add_epi16(stp2_1, stp1_14);
in2 = _mm_add_epi16(stp2_2, stp2_13);
in3 = _mm_add_epi16(stp2_3, stp2_12);
in4 = _mm_add_epi16(stp2_4, stp2_11);
in5 = _mm_add_epi16(stp2_5, stp2_10);
in6 = _mm_add_epi16(stp2_6, stp1_9);
in7 = _mm_add_epi16(stp2_7, stp1_8);
in8 = _mm_sub_epi16(stp2_7, stp1_8);
in9 = _mm_sub_epi16(stp2_6, stp1_9);
in10 = _mm_sub_epi16(stp2_5, stp2_10);
in11 = _mm_sub_epi16(stp2_4, stp2_11);
in12 = _mm_sub_epi16(stp2_3, stp2_12);
in13 = _mm_sub_epi16(stp2_2, stp2_13);
in14 = _mm_sub_epi16(stp2_1, stp1_14);
in15 = _mm_sub_epi16(stp2_0, stp1_15);
// Final rounding and shift
in0 = _mm_adds_epi16(in0, final_rounding);
in1 = _mm_adds_epi16(in1, final_rounding);
in2 = _mm_adds_epi16(in2, final_rounding);
in3 = _mm_adds_epi16(in3, final_rounding);
in4 = _mm_adds_epi16(in4, final_rounding);
in5 = _mm_adds_epi16(in5, final_rounding);
in6 = _mm_adds_epi16(in6, final_rounding);
in7 = _mm_adds_epi16(in7, final_rounding);
in8 = _mm_adds_epi16(in8, final_rounding);
in9 = _mm_adds_epi16(in9, final_rounding);
in10 = _mm_adds_epi16(in10, final_rounding);
in11 = _mm_adds_epi16(in11, final_rounding);
in12 = _mm_adds_epi16(in12, final_rounding);
in13 = _mm_adds_epi16(in13, final_rounding);
in14 = _mm_adds_epi16(in14, final_rounding);
in15 = _mm_adds_epi16(in15, final_rounding);
in0 = _mm_srai_epi16(in0, 6);
in1 = _mm_srai_epi16(in1, 6);
in2 = _mm_srai_epi16(in2, 6);
in3 = _mm_srai_epi16(in3, 6);
in4 = _mm_srai_epi16(in4, 6);
in5 = _mm_srai_epi16(in5, 6);
in6 = _mm_srai_epi16(in6, 6);
in7 = _mm_srai_epi16(in7, 6);
in8 = _mm_srai_epi16(in8, 6);
in9 = _mm_srai_epi16(in9, 6);
in10 = _mm_srai_epi16(in10, 6);
in11 = _mm_srai_epi16(in11, 6);
in12 = _mm_srai_epi16(in12, 6);
in13 = _mm_srai_epi16(in13, 6);
in14 = _mm_srai_epi16(in14, 6);
in15 = _mm_srai_epi16(in15, 6);
RECON_AND_STORE(dest, in0);
RECON_AND_STORE(dest, in1);
RECON_AND_STORE(dest, in2);
RECON_AND_STORE(dest, in3);
RECON_AND_STORE(dest, in4);
RECON_AND_STORE(dest, in5);
RECON_AND_STORE(dest, in6);
RECON_AND_STORE(dest, in7);
RECON_AND_STORE(dest, in8);
RECON_AND_STORE(dest, in9);
RECON_AND_STORE(dest, in10);
RECON_AND_STORE(dest, in11);
RECON_AND_STORE(dest, in12);
RECON_AND_STORE(dest, in13);
RECON_AND_STORE(dest, in14);
RECON_AND_STORE(dest, in15);
dest += 8 - (stride * 16);
}
}
}
void vp9_short_idct10_16x16_add_sse2(int16_t *input, uint8_t *dest,
int stride) {
const __m128i rounding = _mm_set1_epi32(DCT_CONST_ROUNDING);
const __m128i final_rounding = _mm_set1_epi16(1<<5);
const __m128i zero = _mm_setzero_si128();
const __m128i stg2_0 = pair_set_epi16(cospi_30_64, -cospi_2_64);
const __m128i stg2_1 = pair_set_epi16(cospi_2_64, cospi_30_64);
const __m128i stg2_2 = pair_set_epi16(cospi_14_64, -cospi_18_64);
const __m128i stg2_3 = pair_set_epi16(cospi_18_64, cospi_14_64);
const __m128i stg2_4 = pair_set_epi16(cospi_22_64, -cospi_10_64);
const __m128i stg2_5 = pair_set_epi16(cospi_10_64, cospi_22_64);
const __m128i stg2_6 = pair_set_epi16(cospi_6_64, -cospi_26_64);
const __m128i stg2_7 = pair_set_epi16(cospi_26_64, cospi_6_64);
const __m128i stg3_0 = pair_set_epi16(cospi_28_64, -cospi_4_64);
const __m128i stg3_1 = pair_set_epi16(cospi_4_64, cospi_28_64);
const __m128i stg3_2 = pair_set_epi16(cospi_12_64, -cospi_20_64);
const __m128i stg3_3 = pair_set_epi16(cospi_20_64, cospi_12_64);
const __m128i stg4_0 = pair_set_epi16(cospi_16_64, cospi_16_64);
const __m128i stg4_1 = pair_set_epi16(cospi_16_64, -cospi_16_64);
const __m128i stg4_2 = pair_set_epi16(cospi_24_64, -cospi_8_64);
const __m128i stg4_3 = pair_set_epi16(cospi_8_64, cospi_24_64);
const __m128i stg4_4 = pair_set_epi16(-cospi_8_64, cospi_24_64);
const __m128i stg4_5 = pair_set_epi16(cospi_24_64, cospi_8_64);
const __m128i stg4_6 = pair_set_epi16(-cospi_24_64, -cospi_8_64);
const __m128i stg4_7 = pair_set_epi16(-cospi_8_64, cospi_24_64);
const __m128i stg6_0 = pair_set_epi16(-cospi_16_64, cospi_16_64);
__m128i in0 = zero, in1 = zero, in2 = zero, in3 = zero, in4 = zero,
in5 = zero, in6 = zero, in7 = zero, in8 = zero, in9 = zero,
in10 = zero, in11 = zero, in12 = zero, in13 = zero,
in14 = zero, in15 = zero;
__m128i l0 = zero, l1 = zero, l2 = zero, l3 = zero, l4 = zero, l5 = zero,
l6 = zero, l7 = zero, l8 = zero, l9 = zero, l10 = zero, l11 = zero,
l12 = zero, l13 = zero, l14 = zero, l15 = zero;
__m128i stp1_0, stp1_1, stp1_2, stp1_3, stp1_4, stp1_5, stp1_6, stp1_7,
stp1_8, stp1_9, stp1_10, stp1_11, stp1_12, stp1_13, stp1_14, stp1_15,
stp1_8_0, stp1_12_0;
__m128i stp2_0, stp2_1, stp2_2, stp2_3, stp2_4, stp2_5, stp2_6, stp2_7,
stp2_8, stp2_9, stp2_10, stp2_11, stp2_12, stp2_13, stp2_14, stp2_15;
__m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
int i;
// 1-D idct. Load input data.
in0 = _mm_load_si128((__m128i *)input);
in8 = _mm_load_si128((__m128i *)(input + 8 * 1));
in1 = _mm_load_si128((__m128i *)(input + 8 * 2));
in9 = _mm_load_si128((__m128i *)(input + 8 * 3));
in2 = _mm_load_si128((__m128i *)(input + 8 * 4));
in10 = _mm_load_si128((__m128i *)(input + 8 * 5));
in3 = _mm_load_si128((__m128i *)(input + 8 * 6));
in11 = _mm_load_si128((__m128i *)(input + 8 * 7));
TRANSPOSE_8X4(in0, in1, in2, in3, in0, in1, in2, in3);
TRANSPOSE_8X4(in8, in9, in10, in11, in8, in9, in10, in11);
// Stage2
{
const __m128i lo_1_15 = _mm_unpackhi_epi16(in0, in11);
const __m128i lo_9_7 = _mm_unpackhi_epi16(in8, in3);
const __m128i lo_5_11 = _mm_unpackhi_epi16(in2, in9);
const __m128i lo_13_3 = _mm_unpackhi_epi16(in10, in1);
tmp0 = _mm_madd_epi16(lo_1_15, stg2_0);
tmp2 = _mm_madd_epi16(lo_1_15, stg2_1);
tmp4 = _mm_madd_epi16(lo_9_7, stg2_2);
tmp6 = _mm_madd_epi16(lo_9_7, stg2_3);
tmp1 = _mm_madd_epi16(lo_5_11, stg2_4);
tmp3 = _mm_madd_epi16(lo_5_11, stg2_5);
tmp5 = _mm_madd_epi16(lo_13_3, stg2_6);
tmp7 = _mm_madd_epi16(lo_13_3, stg2_7);
tmp0 = _mm_add_epi32(tmp0, rounding);
tmp2 = _mm_add_epi32(tmp2, rounding);
tmp4 = _mm_add_epi32(tmp4, rounding);
tmp6 = _mm_add_epi32(tmp6, rounding);
tmp1 = _mm_add_epi32(tmp1, rounding);
tmp3 = _mm_add_epi32(tmp3, rounding);
tmp5 = _mm_add_epi32(tmp5, rounding);
tmp7 = _mm_add_epi32(tmp7, rounding);
tmp0 = _mm_srai_epi32(tmp0, DCT_CONST_BITS);
tmp2 = _mm_srai_epi32(tmp2, DCT_CONST_BITS);
tmp4 = _mm_srai_epi32(tmp4, DCT_CONST_BITS);
tmp6 = _mm_srai_epi32(tmp6, DCT_CONST_BITS);
tmp1 = _mm_srai_epi32(tmp1, DCT_CONST_BITS);
tmp3 = _mm_srai_epi32(tmp3, DCT_CONST_BITS);
tmp5 = _mm_srai_epi32(tmp5, DCT_CONST_BITS);
tmp7 = _mm_srai_epi32(tmp7, DCT_CONST_BITS);
stp2_8 = _mm_packs_epi32(tmp0, zero);
stp2_15 = _mm_packs_epi32(tmp2, zero);
stp2_9 = _mm_packs_epi32(tmp4, zero);
stp2_14 = _mm_packs_epi32(tmp6, zero);
stp2_10 = _mm_packs_epi32(tmp1, zero);
stp2_13 = _mm_packs_epi32(tmp3, zero);
stp2_11 = _mm_packs_epi32(tmp5, zero);
stp2_12 = _mm_packs_epi32(tmp7, zero);
}
// Stage3
{
const __m128i lo_2_14 = _mm_unpacklo_epi16(in1, in11);
const __m128i lo_10_6 = _mm_unpacklo_epi16(in9, in3);
tmp0 = _mm_madd_epi16(lo_2_14, stg3_0);
tmp2 = _mm_madd_epi16(lo_2_14, stg3_1);
tmp4 = _mm_madd_epi16(lo_10_6, stg3_2);
tmp6 = _mm_madd_epi16(lo_10_6, stg3_3);
tmp0 = _mm_add_epi32(tmp0, rounding);
tmp2 = _mm_add_epi32(tmp2, rounding);
tmp4 = _mm_add_epi32(tmp4, rounding);
tmp6 = _mm_add_epi32(tmp6, rounding);
tmp0 = _mm_srai_epi32(tmp0, DCT_CONST_BITS);
tmp2 = _mm_srai_epi32(tmp2, DCT_CONST_BITS);
tmp4 = _mm_srai_epi32(tmp4, DCT_CONST_BITS);
tmp6 = _mm_srai_epi32(tmp6, DCT_CONST_BITS);
stp1_4 = _mm_packs_epi32(tmp0, zero);
stp1_7 = _mm_packs_epi32(tmp2, zero);
stp1_5 = _mm_packs_epi32(tmp4, zero);
stp1_6 = _mm_packs_epi32(tmp6, zero);
stp1_8_0 = _mm_add_epi16(stp2_8, stp2_9);
stp1_9 = _mm_sub_epi16(stp2_8, stp2_9);
stp1_10 = _mm_sub_epi16(stp2_11, stp2_10);
stp1_11 = _mm_add_epi16(stp2_11, stp2_10);
stp1_12_0 = _mm_add_epi16(stp2_12, stp2_13);
stp1_13 = _mm_sub_epi16(stp2_12, stp2_13);
stp1_14 = _mm_sub_epi16(stp2_15, stp2_14);
stp1_15 = _mm_add_epi16(stp2_15, stp2_14);
}
// Stage4
{
const __m128i lo_0_8 = _mm_unpacklo_epi16(in0, in8);
const __m128i lo_4_12 = _mm_unpacklo_epi16(in2, in10);
const __m128i lo_9_14 = _mm_unpacklo_epi16(stp1_9, stp1_14);
const __m128i lo_10_13 = _mm_unpacklo_epi16(stp1_10, stp1_13);
tmp0 = _mm_madd_epi16(lo_0_8, stg4_0);
tmp2 = _mm_madd_epi16(lo_0_8, stg4_1);
tmp4 = _mm_madd_epi16(lo_4_12, stg4_2);
tmp6 = _mm_madd_epi16(lo_4_12, stg4_3);
tmp1 = _mm_madd_epi16(lo_9_14, stg4_4);
tmp3 = _mm_madd_epi16(lo_9_14, stg4_5);
tmp5 = _mm_madd_epi16(lo_10_13, stg4_6);
tmp7 = _mm_madd_epi16(lo_10_13, stg4_7);
tmp0 = _mm_add_epi32(tmp0, rounding);
tmp2 = _mm_add_epi32(tmp2, rounding);
tmp4 = _mm_add_epi32(tmp4, rounding);
tmp6 = _mm_add_epi32(tmp6, rounding);
tmp1 = _mm_add_epi32(tmp1, rounding);
tmp3 = _mm_add_epi32(tmp3, rounding);
tmp5 = _mm_add_epi32(tmp5, rounding);
tmp7 = _mm_add_epi32(tmp7, rounding);
tmp0 = _mm_srai_epi32(tmp0, DCT_CONST_BITS);
tmp2 = _mm_srai_epi32(tmp2, DCT_CONST_BITS);
tmp4 = _mm_srai_epi32(tmp4, DCT_CONST_BITS);
tmp6 = _mm_srai_epi32(tmp6, DCT_CONST_BITS);
tmp1 = _mm_srai_epi32(tmp1, DCT_CONST_BITS);
tmp3 = _mm_srai_epi32(tmp3, DCT_CONST_BITS);
tmp5 = _mm_srai_epi32(tmp5, DCT_CONST_BITS);
tmp7 = _mm_srai_epi32(tmp7, DCT_CONST_BITS);
stp2_0 = _mm_packs_epi32(tmp0, zero);
stp2_1 = _mm_packs_epi32(tmp2, zero);
stp2_2 = _mm_packs_epi32(tmp4, zero);
stp2_3 = _mm_packs_epi32(tmp6, zero);
stp2_9 = _mm_packs_epi32(tmp1, zero);
stp2_14 = _mm_packs_epi32(tmp3, zero);
stp2_10 = _mm_packs_epi32(tmp5, zero);
stp2_13 = _mm_packs_epi32(tmp7, zero);
stp2_4 = _mm_add_epi16(stp1_4, stp1_5);
stp2_5 = _mm_sub_epi16(stp1_4, stp1_5);
stp2_6 = _mm_sub_epi16(stp1_7, stp1_6);
stp2_7 = _mm_add_epi16(stp1_7, stp1_6);
}
// Stage5 and Stage6
{
stp1_0 = _mm_add_epi16(stp2_0, stp2_3);
stp1_1 = _mm_add_epi16(stp2_1, stp2_2);
stp1_2 = _mm_sub_epi16(stp2_1, stp2_2);
stp1_3 = _mm_sub_epi16(stp2_0, stp2_3);
stp1_8 = _mm_add_epi16(stp1_8_0, stp1_11);
stp1_9 = _mm_add_epi16(stp2_9, stp2_10);
stp1_10 = _mm_sub_epi16(stp2_9, stp2_10);
stp1_11 = _mm_sub_epi16(stp1_8_0, stp1_11);
stp1_12 = _mm_sub_epi16(stp1_15, stp1_12_0);
stp1_13 = _mm_sub_epi16(stp2_14, stp2_13);
stp1_14 = _mm_add_epi16(stp2_14, stp2_13);
stp1_15 = _mm_add_epi16(stp1_15, stp1_12_0);
}
// Stage6
{
const __m128i lo_6_5 = _mm_unpacklo_epi16(stp2_6, stp2_5);
const __m128i lo_10_13 = _mm_unpacklo_epi16(stp1_10, stp1_13);
const __m128i lo_11_12 = _mm_unpacklo_epi16(stp1_11, stp1_12);
tmp1 = _mm_madd_epi16(lo_6_5, stg4_1);
tmp3 = _mm_madd_epi16(lo_6_5, stg4_0);
tmp0 = _mm_madd_epi16(lo_10_13, stg6_0);
tmp2 = _mm_madd_epi16(lo_10_13, stg4_0);
tmp4 = _mm_madd_epi16(lo_11_12, stg6_0);
tmp6 = _mm_madd_epi16(lo_11_12, stg4_0);
tmp1 = _mm_add_epi32(tmp1, rounding);
tmp3 = _mm_add_epi32(tmp3, rounding);
tmp0 = _mm_add_epi32(tmp0, rounding);
tmp2 = _mm_add_epi32(tmp2, rounding);
tmp4 = _mm_add_epi32(tmp4, rounding);
tmp6 = _mm_add_epi32(tmp6, rounding);
tmp1 = _mm_srai_epi32(tmp1, DCT_CONST_BITS);
tmp3 = _mm_srai_epi32(tmp3, DCT_CONST_BITS);
tmp0 = _mm_srai_epi32(tmp0, DCT_CONST_BITS);
tmp2 = _mm_srai_epi32(tmp2, DCT_CONST_BITS);
tmp4 = _mm_srai_epi32(tmp4, DCT_CONST_BITS);
tmp6 = _mm_srai_epi32(tmp6, DCT_CONST_BITS);
stp1_5 = _mm_packs_epi32(tmp1, zero);
stp1_6 = _mm_packs_epi32(tmp3, zero);
stp2_10 = _mm_packs_epi32(tmp0, zero);
stp2_13 = _mm_packs_epi32(tmp2, zero);
stp2_11 = _mm_packs_epi32(tmp4, zero);
stp2_12 = _mm_packs_epi32(tmp6, zero);
stp2_0 = _mm_add_epi16(stp1_0, stp2_7);
stp2_1 = _mm_add_epi16(stp1_1, stp1_6);
stp2_2 = _mm_add_epi16(stp1_2, stp1_5);
stp2_3 = _mm_add_epi16(stp1_3, stp2_4);
stp2_4 = _mm_sub_epi16(stp1_3, stp2_4);
stp2_5 = _mm_sub_epi16(stp1_2, stp1_5);
stp2_6 = _mm_sub_epi16(stp1_1, stp1_6);
stp2_7 = _mm_sub_epi16(stp1_0, stp2_7);
}
// Stage7. Left 8x16 only.
l0 = _mm_add_epi16(stp2_0, stp1_15);
l1 = _mm_add_epi16(stp2_1, stp1_14);
l2 = _mm_add_epi16(stp2_2, stp2_13);
l3 = _mm_add_epi16(stp2_3, stp2_12);
l4 = _mm_add_epi16(stp2_4, stp2_11);
l5 = _mm_add_epi16(stp2_5, stp2_10);
l6 = _mm_add_epi16(stp2_6, stp1_9);
l7 = _mm_add_epi16(stp2_7, stp1_8);
l8 = _mm_sub_epi16(stp2_7, stp1_8);
l9 = _mm_sub_epi16(stp2_6, stp1_9);
l10 = _mm_sub_epi16(stp2_5, stp2_10);
l11 = _mm_sub_epi16(stp2_4, stp2_11);
l12 = _mm_sub_epi16(stp2_3, stp2_12);
l13 = _mm_sub_epi16(stp2_2, stp2_13);
l14 = _mm_sub_epi16(stp2_1, stp1_14);
l15 = _mm_sub_epi16(stp2_0, stp1_15);
// 2-D idct. We do 2 8x16 blocks.
for (i = 0; i < 2; i++) {
if (i == 0)
TRANSPOSE_4X8(l0, l1, l2, l3, l4, l5, l6, l7, in0, in1, in2, in3, in4,
in5, in6, in7);
if (i == 1)
TRANSPOSE_4X8(l8, l9, l10, l11, l12, l13, l14, l15, in0, in1, in2, in3,
in4, in5, in6, in7);
in8 = in9 = in10 = in11 = in12 = in13 = in14 = in15 = zero;
IDCT16x16_1D
// Stage7
in0 = _mm_add_epi16(stp2_0, stp1_15);
in1 = _mm_add_epi16(stp2_1, stp1_14);
in2 = _mm_add_epi16(stp2_2, stp2_13);
in3 = _mm_add_epi16(stp2_3, stp2_12);
in4 = _mm_add_epi16(stp2_4, stp2_11);
in5 = _mm_add_epi16(stp2_5, stp2_10);
in6 = _mm_add_epi16(stp2_6, stp1_9);
in7 = _mm_add_epi16(stp2_7, stp1_8);
in8 = _mm_sub_epi16(stp2_7, stp1_8);
in9 = _mm_sub_epi16(stp2_6, stp1_9);
in10 = _mm_sub_epi16(stp2_5, stp2_10);
in11 = _mm_sub_epi16(stp2_4, stp2_11);
in12 = _mm_sub_epi16(stp2_3, stp2_12);
in13 = _mm_sub_epi16(stp2_2, stp2_13);
in14 = _mm_sub_epi16(stp2_1, stp1_14);
in15 = _mm_sub_epi16(stp2_0, stp1_15);
// Final rounding and shift
in0 = _mm_adds_epi16(in0, final_rounding);
in1 = _mm_adds_epi16(in1, final_rounding);
in2 = _mm_adds_epi16(in2, final_rounding);
in3 = _mm_adds_epi16(in3, final_rounding);
in4 = _mm_adds_epi16(in4, final_rounding);
in5 = _mm_adds_epi16(in5, final_rounding);
in6 = _mm_adds_epi16(in6, final_rounding);
in7 = _mm_adds_epi16(in7, final_rounding);
in8 = _mm_adds_epi16(in8, final_rounding);
in9 = _mm_adds_epi16(in9, final_rounding);
in10 = _mm_adds_epi16(in10, final_rounding);
in11 = _mm_adds_epi16(in11, final_rounding);
in12 = _mm_adds_epi16(in12, final_rounding);
in13 = _mm_adds_epi16(in13, final_rounding);
in14 = _mm_adds_epi16(in14, final_rounding);
in15 = _mm_adds_epi16(in15, final_rounding);
in0 = _mm_srai_epi16(in0, 6);
in1 = _mm_srai_epi16(in1, 6);
in2 = _mm_srai_epi16(in2, 6);
in3 = _mm_srai_epi16(in3, 6);
in4 = _mm_srai_epi16(in4, 6);
in5 = _mm_srai_epi16(in5, 6);
in6 = _mm_srai_epi16(in6, 6);
in7 = _mm_srai_epi16(in7, 6);
in8 = _mm_srai_epi16(in8, 6);
in9 = _mm_srai_epi16(in9, 6);
in10 = _mm_srai_epi16(in10, 6);
in11 = _mm_srai_epi16(in11, 6);
in12 = _mm_srai_epi16(in12, 6);
in13 = _mm_srai_epi16(in13, 6);
in14 = _mm_srai_epi16(in14, 6);
in15 = _mm_srai_epi16(in15, 6);
RECON_AND_STORE(dest, in0);
RECON_AND_STORE(dest, in1);
RECON_AND_STORE(dest, in2);
RECON_AND_STORE(dest, in3);
RECON_AND_STORE(dest, in4);
RECON_AND_STORE(dest, in5);
RECON_AND_STORE(dest, in6);
RECON_AND_STORE(dest, in7);
RECON_AND_STORE(dest, in8);
RECON_AND_STORE(dest, in9);
RECON_AND_STORE(dest, in10);
RECON_AND_STORE(dest, in11);
RECON_AND_STORE(dest, in12);
RECON_AND_STORE(dest, in13);
RECON_AND_STORE(dest, in14);
RECON_AND_STORE(dest, in15);
dest += 8 - (stride * 16);
}
}
void vp9_short_idct32x32_add_sse2(int16_t *input, uint8_t *dest, int stride) {
const __m128i rounding = _mm_set1_epi32(DCT_CONST_ROUNDING);
const __m128i final_rounding = _mm_set1_epi16(1<<5);
// idct constants for each stage
const __m128i stg1_0 = pair_set_epi16(cospi_31_64, -cospi_1_64);
const __m128i stg1_1 = pair_set_epi16(cospi_1_64, cospi_31_64);
const __m128i stg1_2 = pair_set_epi16(cospi_15_64, -cospi_17_64);
const __m128i stg1_3 = pair_set_epi16(cospi_17_64, cospi_15_64);
const __m128i stg1_4 = pair_set_epi16(cospi_23_64, -cospi_9_64);
const __m128i stg1_5 = pair_set_epi16(cospi_9_64, cospi_23_64);
const __m128i stg1_6 = pair_set_epi16(cospi_7_64, -cospi_25_64);
const __m128i stg1_7 = pair_set_epi16(cospi_25_64, cospi_7_64);
const __m128i stg1_8 = pair_set_epi16(cospi_27_64, -cospi_5_64);
const __m128i stg1_9 = pair_set_epi16(cospi_5_64, cospi_27_64);
const __m128i stg1_10 = pair_set_epi16(cospi_11_64, -cospi_21_64);
const __m128i stg1_11 = pair_set_epi16(cospi_21_64, cospi_11_64);
const __m128i stg1_12 = pair_set_epi16(cospi_19_64, -cospi_13_64);
const __m128i stg1_13 = pair_set_epi16(cospi_13_64, cospi_19_64);
const __m128i stg1_14 = pair_set_epi16(cospi_3_64, -cospi_29_64);
const __m128i stg1_15 = pair_set_epi16(cospi_29_64, cospi_3_64);
const __m128i stg2_0 = pair_set_epi16(cospi_30_64, -cospi_2_64);
const __m128i stg2_1 = pair_set_epi16(cospi_2_64, cospi_30_64);
const __m128i stg2_2 = pair_set_epi16(cospi_14_64, -cospi_18_64);
const __m128i stg2_3 = pair_set_epi16(cospi_18_64, cospi_14_64);
const __m128i stg2_4 = pair_set_epi16(cospi_22_64, -cospi_10_64);
const __m128i stg2_5 = pair_set_epi16(cospi_10_64, cospi_22_64);
const __m128i stg2_6 = pair_set_epi16(cospi_6_64, -cospi_26_64);
const __m128i stg2_7 = pair_set_epi16(cospi_26_64, cospi_6_64);
const __m128i stg3_0 = pair_set_epi16(cospi_28_64, -cospi_4_64);
const __m128i stg3_1 = pair_set_epi16(cospi_4_64, cospi_28_64);
const __m128i stg3_2 = pair_set_epi16(cospi_12_64, -cospi_20_64);
const __m128i stg3_3 = pair_set_epi16(cospi_20_64, cospi_12_64);
const __m128i stg3_4 = pair_set_epi16(-cospi_4_64, cospi_28_64);
const __m128i stg3_5 = pair_set_epi16(cospi_28_64, cospi_4_64);
const __m128i stg3_6 = pair_set_epi16(-cospi_28_64, -cospi_4_64);
const __m128i stg3_8 = pair_set_epi16(-cospi_20_64, cospi_12_64);
const __m128i stg3_9 = pair_set_epi16(cospi_12_64, cospi_20_64);
const __m128i stg3_10 = pair_set_epi16(-cospi_12_64, -cospi_20_64);
const __m128i stg4_0 = pair_set_epi16(cospi_16_64, cospi_16_64);
const __m128i stg4_1 = pair_set_epi16(cospi_16_64, -cospi_16_64);
const __m128i stg4_2 = pair_set_epi16(cospi_24_64, -cospi_8_64);
const __m128i stg4_3 = pair_set_epi16(cospi_8_64, cospi_24_64);
const __m128i stg4_4 = pair_set_epi16(-cospi_8_64, cospi_24_64);
const __m128i stg4_5 = pair_set_epi16(cospi_24_64, cospi_8_64);
const __m128i stg4_6 = pair_set_epi16(-cospi_24_64, -cospi_8_64);
const __m128i stg6_0 = pair_set_epi16(-cospi_16_64, cospi_16_64);
__m128i in0, in1, in2, in3, in4, in5, in6, in7, in8, in9, in10, in11, in12,
in13, in14, in15, in16, in17, in18, in19, in20, in21, in22, in23,
in24, in25, in26, in27, in28, in29, in30, in31;
__m128i col[128];
__m128i stp1_0, stp1_1, stp1_2, stp1_3, stp1_4, stp1_5, stp1_6, stp1_7,
stp1_8, stp1_9, stp1_10, stp1_11, stp1_12, stp1_13, stp1_14, stp1_15,
stp1_16, stp1_17, stp1_18, stp1_19, stp1_20, stp1_21, stp1_22,
stp1_23, stp1_24, stp1_25, stp1_26, stp1_27, stp1_28, stp1_29,
stp1_30, stp1_31;
__m128i stp2_0, stp2_1, stp2_2, stp2_3, stp2_4, stp2_5, stp2_6, stp2_7,
stp2_8, stp2_9, stp2_10, stp2_11, stp2_12, stp2_13, stp2_14, stp2_15,
stp2_16, stp2_17, stp2_18, stp2_19, stp2_20, stp2_21, stp2_22,
stp2_23, stp2_24, stp2_25, stp2_26, stp2_27, stp2_28, stp2_29,
stp2_30, stp2_31;
__m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
int i, j;
// We work on a 8x32 block each time, and loop 8 times for 2-D 32x32 idct.
for (i = 0; i < 8; i++) {
if (i < 4) {
// First 1-D idct
// Load input data.
in0 = _mm_load_si128((__m128i *)input);
in8 = _mm_load_si128((__m128i *)(input + 8 * 1));
in16 = _mm_load_si128((__m128i *)(input + 8 * 2));
in24 = _mm_load_si128((__m128i *)(input + 8 * 3));
in1 = _mm_load_si128((__m128i *)(input + 8 * 4));
in9 = _mm_load_si128((__m128i *)(input + 8 * 5));
in17 = _mm_load_si128((__m128i *)(input + 8 * 6));
in25 = _mm_load_si128((__m128i *)(input + 8 * 7));
in2 = _mm_load_si128((__m128i *)(input + 8 * 8));
in10 = _mm_load_si128((__m128i *)(input + 8 * 9));
in18 = _mm_load_si128((__m128i *)(input + 8 * 10));
in26 = _mm_load_si128((__m128i *)(input + 8 * 11));
in3 = _mm_load_si128((__m128i *)(input + 8 * 12));
in11 = _mm_load_si128((__m128i *)(input + 8 * 13));
in19 = _mm_load_si128((__m128i *)(input + 8 * 14));
in27 = _mm_load_si128((__m128i *)(input + 8 * 15));
in4 = _mm_load_si128((__m128i *)(input + 8 * 16));
in12 = _mm_load_si128((__m128i *)(input + 8 * 17));
in20 = _mm_load_si128((__m128i *)(input + 8 * 18));
in28 = _mm_load_si128((__m128i *)(input + 8 * 19));
in5 = _mm_load_si128((__m128i *)(input + 8 * 20));
in13 = _mm_load_si128((__m128i *)(input + 8 * 21));
in21 = _mm_load_si128((__m128i *)(input + 8 * 22));
in29 = _mm_load_si128((__m128i *)(input + 8 * 23));
in6 = _mm_load_si128((__m128i *)(input + 8 * 24));
in14 = _mm_load_si128((__m128i *)(input + 8 * 25));
in22 = _mm_load_si128((__m128i *)(input + 8 * 26));
in30 = _mm_load_si128((__m128i *)(input + 8 * 27));
in7 = _mm_load_si128((__m128i *)(input + 8 * 28));
in15 = _mm_load_si128((__m128i *)(input + 8 * 29));
in23 = _mm_load_si128((__m128i *)(input + 8 * 30));
in31 = _mm_load_si128((__m128i *)(input + 8 * 31));
input += 256;
// Transpose 32x8 block to 8x32 block
TRANSPOSE_8X8(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3,
in4, in5, in6, in7);
TRANSPOSE_8X8(in8, in9, in10, in11, in12, in13, in14, in15, in8, in9,
in10, in11, in12, in13, in14, in15);
TRANSPOSE_8X8(in16, in17, in18, in19, in20, in21, in22, in23, in16, in17,
in18, in19, in20, in21, in22, in23);
TRANSPOSE_8X8(in24, in25, in26, in27, in28, in29, in30, in31, in24, in25,
in26, in27, in28, in29, in30, in31);
} else {
// Second 1-D idct
j = i - 4;
// Transpose 32x8 block to 8x32 block
TRANSPOSE_8X8(col[j * 8 + 0], col[j * 8 + 1], col[j * 8 + 2],
col[j * 8 + 3], col[j * 8 + 4], col[j * 8 + 5],
col[j * 8 + 6], col[j * 8 + 7], in0, in1, in2, in3, in4,
in5, in6, in7);
j += 4;
TRANSPOSE_8X8(col[j * 8 + 0], col[j * 8 + 1], col[j * 8 + 2],
col[j * 8 + 3], col[j * 8 + 4], col[j * 8 + 5],
col[j * 8 + 6], col[j * 8 + 7], in8, in9, in10,
in11, in12, in13, in14, in15);
j += 4;
TRANSPOSE_8X8(col[j * 8 + 0], col[j * 8 + 1], col[j * 8 + 2],
col[j * 8 + 3], col[j * 8 + 4], col[j * 8 + 5],
col[j * 8 + 6], col[j * 8 + 7], in16, in17, in18,
in19, in20, in21, in22, in23);
j += 4;
TRANSPOSE_8X8(col[j * 8 + 0], col[j * 8 + 1], col[j * 8 + 2],
col[j * 8 + 3], col[j * 8 + 4], col[j * 8 + 5],
col[j * 8 + 6], col[j * 8 + 7], in24, in25, in26, in27,
in28, in29, in30, in31);
}
// Stage1
{
const __m128i lo_1_31 = _mm_unpacklo_epi16(in1, in31);
const __m128i hi_1_31 = _mm_unpackhi_epi16(in1, in31);
const __m128i lo_17_15 = _mm_unpacklo_epi16(in17, in15);
const __m128i hi_17_15 = _mm_unpackhi_epi16(in17, in15);
const __m128i lo_9_23 = _mm_unpacklo_epi16(in9, in23);
const __m128i hi_9_23 = _mm_unpackhi_epi16(in9, in23);
const __m128i lo_25_7= _mm_unpacklo_epi16(in25, in7);
const __m128i hi_25_7 = _mm_unpackhi_epi16(in25, in7);
const __m128i lo_5_27 = _mm_unpacklo_epi16(in5, in27);
const __m128i hi_5_27 = _mm_unpackhi_epi16(in5, in27);
const __m128i lo_21_11 = _mm_unpacklo_epi16(in21, in11);
const __m128i hi_21_11 = _mm_unpackhi_epi16(in21, in11);
const __m128i lo_13_19 = _mm_unpacklo_epi16(in13, in19);
const __m128i hi_13_19 = _mm_unpackhi_epi16(in13, in19);
const __m128i lo_29_3 = _mm_unpacklo_epi16(in29, in3);
const __m128i hi_29_3 = _mm_unpackhi_epi16(in29, in3);
MULTIPLICATION_AND_ADD(lo_1_31, hi_1_31, lo_17_15, hi_17_15, stg1_0,
stg1_1, stg1_2, stg1_3, stp1_16, stp1_31,
stp1_17, stp1_30)
MULTIPLICATION_AND_ADD(lo_9_23, hi_9_23, lo_25_7, hi_25_7, stg1_4,
stg1_5, stg1_6, stg1_7, stp1_18, stp1_29,
stp1_19, stp1_28)
MULTIPLICATION_AND_ADD(lo_5_27, hi_5_27, lo_21_11, hi_21_11, stg1_8,
stg1_9, stg1_10, stg1_11, stp1_20, stp1_27,
stp1_21, stp1_26)
MULTIPLICATION_AND_ADD(lo_13_19, hi_13_19, lo_29_3, hi_29_3, stg1_12,
stg1_13, stg1_14, stg1_15, stp1_22, stp1_25,
stp1_23, stp1_24)
}
// Stage2
{
const __m128i lo_2_30 = _mm_unpacklo_epi16(in2, in30);
const __m128i hi_2_30 = _mm_unpackhi_epi16(in2, in30);
const __m128i lo_18_14 = _mm_unpacklo_epi16(in18, in14);
const __m128i hi_18_14 = _mm_unpackhi_epi16(in18, in14);
const __m128i lo_10_22 = _mm_unpacklo_epi16(in10, in22);
const __m128i hi_10_22 = _mm_unpackhi_epi16(in10, in22);
const __m128i lo_26_6 = _mm_unpacklo_epi16(in26, in6);
const __m128i hi_26_6 = _mm_unpackhi_epi16(in26, in6);
MULTIPLICATION_AND_ADD(lo_2_30, hi_2_30, lo_18_14, hi_18_14, stg2_0,
stg2_1, stg2_2, stg2_3, stp2_8, stp2_15, stp2_9,
stp2_14)
MULTIPLICATION_AND_ADD(lo_10_22, hi_10_22, lo_26_6, hi_26_6, stg2_4,
stg2_5, stg2_6, stg2_7, stp2_10, stp2_13,
stp2_11, stp2_12)
stp2_16 = _mm_add_epi16(stp1_16, stp1_17);
stp2_17 = _mm_sub_epi16(stp1_16, stp1_17);
stp2_18 = _mm_sub_epi16(stp1_19, stp1_18);
stp2_19 = _mm_add_epi16(stp1_19, stp1_18);
stp2_20 = _mm_add_epi16(stp1_20, stp1_21);
stp2_21 = _mm_sub_epi16(stp1_20, stp1_21);
stp2_22 = _mm_sub_epi16(stp1_23, stp1_22);
stp2_23 = _mm_add_epi16(stp1_23, stp1_22);
stp2_24 = _mm_add_epi16(stp1_24, stp1_25);
stp2_25 = _mm_sub_epi16(stp1_24, stp1_25);
stp2_26 = _mm_sub_epi16(stp1_27, stp1_26);
stp2_27 = _mm_add_epi16(stp1_27, stp1_26);
stp2_28 = _mm_add_epi16(stp1_28, stp1_29);
stp2_29 = _mm_sub_epi16(stp1_28, stp1_29);
stp2_30 = _mm_sub_epi16(stp1_31, stp1_30);
stp2_31 = _mm_add_epi16(stp1_31, stp1_30);
}
// Stage3
{
const __m128i lo_4_28 = _mm_unpacklo_epi16(in4, in28);
const __m128i hi_4_28 = _mm_unpackhi_epi16(in4, in28);
const __m128i lo_20_12 = _mm_unpacklo_epi16(in20, in12);
const __m128i hi_20_12 = _mm_unpackhi_epi16(in20, in12);
const __m128i lo_17_30 = _mm_unpacklo_epi16(stp2_17, stp2_30);
const __m128i hi_17_30 = _mm_unpackhi_epi16(stp2_17, stp2_30);
const __m128i lo_18_29 = _mm_unpacklo_epi16(stp2_18, stp2_29);
const __m128i hi_18_29 = _mm_unpackhi_epi16(stp2_18, stp2_29);
const __m128i lo_21_26 = _mm_unpacklo_epi16(stp2_21, stp2_26);
const __m128i hi_21_26 = _mm_unpackhi_epi16(stp2_21, stp2_26);
const __m128i lo_22_25 = _mm_unpacklo_epi16(stp2_22, stp2_25);
const __m128i hi_22_25 = _mm_unpackhi_epi16(stp2_22, stp2_25);
MULTIPLICATION_AND_ADD(lo_4_28, hi_4_28, lo_20_12, hi_20_12, stg3_0,
stg3_1, stg3_2, stg3_3, stp1_4, stp1_7, stp1_5,
stp1_6)
stp1_8 = _mm_add_epi16(stp2_8, stp2_9);
stp1_9 = _mm_sub_epi16(stp2_8, stp2_9);
stp1_10 = _mm_sub_epi16(stp2_11, stp2_10);
stp1_11 = _mm_add_epi16(stp2_11, stp2_10);
stp1_12 = _mm_add_epi16(stp2_12, stp2_13);
stp1_13 = _mm_sub_epi16(stp2_12, stp2_13);
stp1_14 = _mm_sub_epi16(stp2_15, stp2_14);
stp1_15 = _mm_add_epi16(stp2_15, stp2_14);
MULTIPLICATION_AND_ADD(lo_17_30, hi_17_30, lo_18_29, hi_18_29, stg3_4,
stg3_5, stg3_6, stg3_4, stp1_17, stp1_30,
stp1_18, stp1_29)
MULTIPLICATION_AND_ADD(lo_21_26, hi_21_26, lo_22_25, hi_22_25, stg3_8,
stg3_9, stg3_10, stg3_8, stp1_21, stp1_26,
stp1_22, stp1_25)
stp1_16 = stp2_16;
stp1_31 = stp2_31;
stp1_19 = stp2_19;
stp1_20 = stp2_20;
stp1_23 = stp2_23;
stp1_24 = stp2_24;
stp1_27 = stp2_27;
stp1_28 = stp2_28;
}
// Stage4
{
const __m128i lo_0_16 = _mm_unpacklo_epi16(in0, in16);
const __m128i hi_0_16 = _mm_unpackhi_epi16(in0, in16);
const __m128i lo_8_24 = _mm_unpacklo_epi16(in8, in24);
const __m128i hi_8_24 = _mm_unpackhi_epi16(in8, in24);
const __m128i lo_9_14 = _mm_unpacklo_epi16(stp1_9, stp1_14);
const __m128i hi_9_14 = _mm_unpackhi_epi16(stp1_9, stp1_14);
const __m128i lo_10_13 = _mm_unpacklo_epi16(stp1_10, stp1_13);
const __m128i hi_10_13 = _mm_unpackhi_epi16(stp1_10, stp1_13);
MULTIPLICATION_AND_ADD(lo_0_16, hi_0_16, lo_8_24, hi_8_24, stg4_0,
stg4_1, stg4_2, stg4_3, stp2_0, stp2_1,
stp2_2, stp2_3)
stp2_4 = _mm_add_epi16(stp1_4, stp1_5);
stp2_5 = _mm_sub_epi16(stp1_4, stp1_5);
stp2_6 = _mm_sub_epi16(stp1_7, stp1_6);
stp2_7 = _mm_add_epi16(stp1_7, stp1_6);
MULTIPLICATION_AND_ADD(lo_9_14, hi_9_14, lo_10_13, hi_10_13, stg4_4,
stg4_5, stg4_6, stg4_4, stp2_9, stp2_14,
stp2_10, stp2_13)
stp2_8 = stp1_8;
stp2_15 = stp1_15;
stp2_11 = stp1_11;
stp2_12 = stp1_12;
stp2_16 = _mm_add_epi16(stp1_16, stp1_19);
stp2_17 = _mm_add_epi16(stp1_17, stp1_18);
stp2_18 = _mm_sub_epi16(stp1_17, stp1_18);
stp2_19 = _mm_sub_epi16(stp1_16, stp1_19);
stp2_20 = _mm_sub_epi16(stp1_23, stp1_20);
stp2_21 = _mm_sub_epi16(stp1_22, stp1_21);
stp2_22 = _mm_add_epi16(stp1_22, stp1_21);
stp2_23 = _mm_add_epi16(stp1_23, stp1_20);
stp2_24 = _mm_add_epi16(stp1_24, stp1_27);
stp2_25 = _mm_add_epi16(stp1_25, stp1_26);
stp2_26 = _mm_sub_epi16(stp1_25, stp1_26);
stp2_27 = _mm_sub_epi16(stp1_24, stp1_27);
stp2_28 = _mm_sub_epi16(stp1_31, stp1_28);
stp2_29 = _mm_sub_epi16(stp1_30, stp1_29);
stp2_30 = _mm_add_epi16(stp1_29, stp1_30);
stp2_31 = _mm_add_epi16(stp1_28, stp1_31);
}
// Stage5
{
const __m128i lo_6_5 = _mm_unpacklo_epi16(stp2_6, stp2_5);
const __m128i hi_6_5 = _mm_unpackhi_epi16(stp2_6, stp2_5);
const __m128i lo_18_29 = _mm_unpacklo_epi16(stp2_18, stp2_29);
const __m128i hi_18_29 = _mm_unpackhi_epi16(stp2_18, stp2_29);
const __m128i lo_19_28 = _mm_unpacklo_epi16(stp2_19, stp2_28);
const __m128i hi_19_28 = _mm_unpackhi_epi16(stp2_19, stp2_28);
const __m128i lo_20_27 = _mm_unpacklo_epi16(stp2_20, stp2_27);
const __m128i hi_20_27 = _mm_unpackhi_epi16(stp2_20, stp2_27);
const __m128i lo_21_26 = _mm_unpacklo_epi16(stp2_21, stp2_26);
const __m128i hi_21_26 = _mm_unpackhi_epi16(stp2_21, stp2_26);
stp1_0 = _mm_add_epi16(stp2_0, stp2_3);
stp1_1 = _mm_add_epi16(stp2_1, stp2_2);
stp1_2 = _mm_sub_epi16(stp2_1, stp2_2);
stp1_3 = _mm_sub_epi16(stp2_0, stp2_3);
tmp0 = _mm_madd_epi16(lo_6_5, stg4_1);
tmp1 = _mm_madd_epi16(hi_6_5, stg4_1);
tmp2 = _mm_madd_epi16(lo_6_5, stg4_0);
tmp3 = _mm_madd_epi16(hi_6_5, stg4_0);
tmp0 = _mm_add_epi32(tmp0, rounding);
tmp1 = _mm_add_epi32(tmp1, rounding);
tmp2 = _mm_add_epi32(tmp2, rounding);
tmp3 = _mm_add_epi32(tmp3, rounding);
tmp0 = _mm_srai_epi32(tmp0, DCT_CONST_BITS);
tmp1 = _mm_srai_epi32(tmp1, DCT_CONST_BITS);
tmp2 = _mm_srai_epi32(tmp2, DCT_CONST_BITS);
tmp3 = _mm_srai_epi32(tmp3, DCT_CONST_BITS);
stp1_5 = _mm_packs_epi32(tmp0, tmp1);
stp1_6 = _mm_packs_epi32(tmp2, tmp3);
stp1_4 = stp2_4;
stp1_7 = stp2_7;
stp1_8 = _mm_add_epi16(stp2_8, stp2_11);
stp1_9 = _mm_add_epi16(stp2_9, stp2_10);
stp1_10 = _mm_sub_epi16(stp2_9, stp2_10);
stp1_11 = _mm_sub_epi16(stp2_8, stp2_11);
stp1_12 = _mm_sub_epi16(stp2_15, stp2_12);
stp1_13 = _mm_sub_epi16(stp2_14, stp2_13);
stp1_14 = _mm_add_epi16(stp2_14, stp2_13);
stp1_15 = _mm_add_epi16(stp2_15, stp2_12);
stp1_16 = stp2_16;
stp1_17 = stp2_17;
MULTIPLICATION_AND_ADD(lo_18_29, hi_18_29, lo_19_28, hi_19_28, stg4_4,
stg4_5, stg4_4, stg4_5, stp1_18, stp1_29,
stp1_19, stp1_28)
MULTIPLICATION_AND_ADD(lo_20_27, hi_20_27, lo_21_26, hi_21_26, stg4_6,
stg4_4, stg4_6, stg4_4, stp1_20, stp1_27,
stp1_21, stp1_26)
stp1_22 = stp2_22;
stp1_23 = stp2_23;
stp1_24 = stp2_24;
stp1_25 = stp2_25;
stp1_30 = stp2_30;
stp1_31 = stp2_31;
}
// Stage6
{
const __m128i lo_10_13 = _mm_unpacklo_epi16(stp1_10, stp1_13);
const __m128i hi_10_13 = _mm_unpackhi_epi16(stp1_10, stp1_13);
const __m128i lo_11_12 = _mm_unpacklo_epi16(stp1_11, stp1_12);
const __m128i hi_11_12 = _mm_unpackhi_epi16(stp1_11, stp1_12);
stp2_0 = _mm_add_epi16(stp1_0, stp1_7);
stp2_1 = _mm_add_epi16(stp1_1, stp1_6);
stp2_2 = _mm_add_epi16(stp1_2, stp1_5);
stp2_3 = _mm_add_epi16(stp1_3, stp1_4);
stp2_4 = _mm_sub_epi16(stp1_3, stp1_4);
stp2_5 = _mm_sub_epi16(stp1_2, stp1_5);
stp2_6 = _mm_sub_epi16(stp1_1, stp1_6);
stp2_7 = _mm_sub_epi16(stp1_0, stp1_7);
stp2_8 = stp1_8;
stp2_9 = stp1_9;
stp2_14 = stp1_14;
stp2_15 = stp1_15;
MULTIPLICATION_AND_ADD(lo_10_13, hi_10_13, lo_11_12, hi_11_12,
stg6_0, stg4_0, stg6_0, stg4_0, stp2_10,
stp2_13, stp2_11, stp2_12)
stp2_16 = _mm_add_epi16(stp1_16, stp1_23);
stp2_17 = _mm_add_epi16(stp1_17, stp1_22);
stp2_18 = _mm_add_epi16(stp1_18, stp1_21);
stp2_19 = _mm_add_epi16(stp1_19, stp1_20);
stp2_20 = _mm_sub_epi16(stp1_19, stp1_20);
stp2_21 = _mm_sub_epi16(stp1_18, stp1_21);
stp2_22 = _mm_sub_epi16(stp1_17, stp1_22);
stp2_23 = _mm_sub_epi16(stp1_16, stp1_23);
stp2_24 = _mm_sub_epi16(stp1_31, stp1_24);
stp2_25 = _mm_sub_epi16(stp1_30, stp1_25);
stp2_26 = _mm_sub_epi16(stp1_29, stp1_26);
stp2_27 = _mm_sub_epi16(stp1_28, stp1_27);
stp2_28 = _mm_add_epi16(stp1_27, stp1_28);
stp2_29 = _mm_add_epi16(stp1_26, stp1_29);
stp2_30 = _mm_add_epi16(stp1_25, stp1_30);
stp2_31 = _mm_add_epi16(stp1_24, stp1_31);
}
// Stage7
{
const __m128i lo_20_27 = _mm_unpacklo_epi16(stp2_20, stp2_27);
const __m128i hi_20_27 = _mm_unpackhi_epi16(stp2_20, stp2_27);
const __m128i lo_21_26 = _mm_unpacklo_epi16(stp2_21, stp2_26);
const __m128i hi_21_26 = _mm_unpackhi_epi16(stp2_21, stp2_26);
const __m128i lo_22_25 = _mm_unpacklo_epi16(stp2_22, stp2_25);
const __m128i hi_22_25 = _mm_unpackhi_epi16(stp2_22, stp2_25);
const __m128i lo_23_24 = _mm_unpacklo_epi16(stp2_23, stp2_24);
const __m128i hi_23_24 = _mm_unpackhi_epi16(stp2_23, stp2_24);
stp1_0 = _mm_add_epi16(stp2_0, stp2_15);
stp1_1 = _mm_add_epi16(stp2_1, stp2_14);
stp1_2 = _mm_add_epi16(stp2_2, stp2_13);
stp1_3 = _mm_add_epi16(stp2_3, stp2_12);
stp1_4 = _mm_add_epi16(stp2_4, stp2_11);
stp1_5 = _mm_add_epi16(stp2_5, stp2_10);
stp1_6 = _mm_add_epi16(stp2_6, stp2_9);
stp1_7 = _mm_add_epi16(stp2_7, stp2_8);
stp1_8 = _mm_sub_epi16(stp2_7, stp2_8);
stp1_9 = _mm_sub_epi16(stp2_6, stp2_9);
stp1_10 = _mm_sub_epi16(stp2_5, stp2_10);
stp1_11 = _mm_sub_epi16(stp2_4, stp2_11);
stp1_12 = _mm_sub_epi16(stp2_3, stp2_12);
stp1_13 = _mm_sub_epi16(stp2_2, stp2_13);
stp1_14 = _mm_sub_epi16(stp2_1, stp2_14);
stp1_15 = _mm_sub_epi16(stp2_0, stp2_15);
stp1_16 = stp2_16;
stp1_17 = stp2_17;
stp1_18 = stp2_18;
stp1_19 = stp2_19;
MULTIPLICATION_AND_ADD(lo_20_27, hi_20_27, lo_21_26, hi_21_26, stg6_0,
stg4_0, stg6_0, stg4_0, stp1_20, stp1_27,
stp1_21, stp1_26)
MULTIPLICATION_AND_ADD(lo_22_25, hi_22_25, lo_23_24, hi_23_24, stg6_0,
stg4_0, stg6_0, stg4_0, stp1_22, stp1_25,
stp1_23, stp1_24)
stp1_28 = stp2_28;
stp1_29 = stp2_29;
stp1_30 = stp2_30;
stp1_31 = stp2_31;
}
// final stage
if (i < 4) {
// 1_D: Store 32 intermediate results for each 8x32 block.
col[i * 32 + 0] = _mm_add_epi16(stp1_0, stp1_31);
col[i * 32 + 1] = _mm_add_epi16(stp1_1, stp1_30);
col[i * 32 + 2] = _mm_add_epi16(stp1_2, stp1_29);
col[i * 32 + 3] = _mm_add_epi16(stp1_3, stp1_28);
col[i * 32 + 4] = _mm_add_epi16(stp1_4, stp1_27);
col[i * 32 + 5] = _mm_add_epi16(stp1_5, stp1_26);
col[i * 32 + 6] = _mm_add_epi16(stp1_6, stp1_25);
col[i * 32 + 7] = _mm_add_epi16(stp1_7, stp1_24);
col[i * 32 + 8] = _mm_add_epi16(stp1_8, stp1_23);
col[i * 32 + 9] = _mm_add_epi16(stp1_9, stp1_22);
col[i * 32 + 10] = _mm_add_epi16(stp1_10, stp1_21);
col[i * 32 + 11] = _mm_add_epi16(stp1_11, stp1_20);
col[i * 32 + 12] = _mm_add_epi16(stp1_12, stp1_19);
col[i * 32 + 13] = _mm_add_epi16(stp1_13, stp1_18);
col[i * 32 + 14] = _mm_add_epi16(stp1_14, stp1_17);
col[i * 32 + 15] = _mm_add_epi16(stp1_15, stp1_16);
col[i * 32 + 16] = _mm_sub_epi16(stp1_15, stp1_16);
col[i * 32 + 17] = _mm_sub_epi16(stp1_14, stp1_17);
col[i * 32 + 18] = _mm_sub_epi16(stp1_13, stp1_18);
col[i * 32 + 19] = _mm_sub_epi16(stp1_12, stp1_19);
col[i * 32 + 20] = _mm_sub_epi16(stp1_11, stp1_20);
col[i * 32 + 21] = _mm_sub_epi16(stp1_10, stp1_21);
col[i * 32 + 22] = _mm_sub_epi16(stp1_9, stp1_22);
col[i * 32 + 23] = _mm_sub_epi16(stp1_8, stp1_23);
col[i * 32 + 24] = _mm_sub_epi16(stp1_7, stp1_24);
col[i * 32 + 25] = _mm_sub_epi16(stp1_6, stp1_25);
col[i * 32 + 26] = _mm_sub_epi16(stp1_5, stp1_26);
col[i * 32 + 27] = _mm_sub_epi16(stp1_4, stp1_27);
col[i * 32 + 28] = _mm_sub_epi16(stp1_3, stp1_28);
col[i * 32 + 29] = _mm_sub_epi16(stp1_2, stp1_29);
col[i * 32 + 30] = _mm_sub_epi16(stp1_1, stp1_30);
col[i * 32 + 31] = _mm_sub_epi16(stp1_0, stp1_31);
} else {
const __m128i zero = _mm_setzero_si128();
// 2_D: Calculate the results and store them to destination.
in0 = _mm_add_epi16(stp1_0, stp1_31);
in1 = _mm_add_epi16(stp1_1, stp1_30);
in2 = _mm_add_epi16(stp1_2, stp1_29);
in3 = _mm_add_epi16(stp1_3, stp1_28);
in4 = _mm_add_epi16(stp1_4, stp1_27);
in5 = _mm_add_epi16(stp1_5, stp1_26);
in6 = _mm_add_epi16(stp1_6, stp1_25);
in7 = _mm_add_epi16(stp1_7, stp1_24);
in8 = _mm_add_epi16(stp1_8, stp1_23);
in9 = _mm_add_epi16(stp1_9, stp1_22);
in10 = _mm_add_epi16(stp1_10, stp1_21);
in11 = _mm_add_epi16(stp1_11, stp1_20);
in12 = _mm_add_epi16(stp1_12, stp1_19);
in13 = _mm_add_epi16(stp1_13, stp1_18);
in14 = _mm_add_epi16(stp1_14, stp1_17);
in15 = _mm_add_epi16(stp1_15, stp1_16);
in16 = _mm_sub_epi16(stp1_15, stp1_16);
in17 = _mm_sub_epi16(stp1_14, stp1_17);
in18 = _mm_sub_epi16(stp1_13, stp1_18);
in19 = _mm_sub_epi16(stp1_12, stp1_19);
in20 = _mm_sub_epi16(stp1_11, stp1_20);
in21 = _mm_sub_epi16(stp1_10, stp1_21);
in22 = _mm_sub_epi16(stp1_9, stp1_22);
in23 = _mm_sub_epi16(stp1_8, stp1_23);
in24 = _mm_sub_epi16(stp1_7, stp1_24);
in25 = _mm_sub_epi16(stp1_6, stp1_25);
in26 = _mm_sub_epi16(stp1_5, stp1_26);
in27 = _mm_sub_epi16(stp1_4, stp1_27);
in28 = _mm_sub_epi16(stp1_3, stp1_28);
in29 = _mm_sub_epi16(stp1_2, stp1_29);
in30 = _mm_sub_epi16(stp1_1, stp1_30);
in31 = _mm_sub_epi16(stp1_0, stp1_31);
// Final rounding and shift
in0 = _mm_adds_epi16(in0, final_rounding);
in1 = _mm_adds_epi16(in1, final_rounding);
in2 = _mm_adds_epi16(in2, final_rounding);
in3 = _mm_adds_epi16(in3, final_rounding);
in4 = _mm_adds_epi16(in4, final_rounding);
in5 = _mm_adds_epi16(in5, final_rounding);
in6 = _mm_adds_epi16(in6, final_rounding);
in7 = _mm_adds_epi16(in7, final_rounding);
in8 = _mm_adds_epi16(in8, final_rounding);
in9 = _mm_adds_epi16(in9, final_rounding);
in10 = _mm_adds_epi16(in10, final_rounding);
in11 = _mm_adds_epi16(in11, final_rounding);
in12 = _mm_adds_epi16(in12, final_rounding);
in13 = _mm_adds_epi16(in13, final_rounding);
in14 = _mm_adds_epi16(in14, final_rounding);
in15 = _mm_adds_epi16(in15, final_rounding);
in16 = _mm_adds_epi16(in16, final_rounding);
in17 = _mm_adds_epi16(in17, final_rounding);
in18 = _mm_adds_epi16(in18, final_rounding);
in19 = _mm_adds_epi16(in19, final_rounding);
in20 = _mm_adds_epi16(in20, final_rounding);
in21 = _mm_adds_epi16(in21, final_rounding);
in22 = _mm_adds_epi16(in22, final_rounding);
in23 = _mm_adds_epi16(in23, final_rounding);
in24 = _mm_adds_epi16(in24, final_rounding);
in25 = _mm_adds_epi16(in25, final_rounding);
in26 = _mm_adds_epi16(in26, final_rounding);
in27 = _mm_adds_epi16(in27, final_rounding);
in28 = _mm_adds_epi16(in28, final_rounding);
in29 = _mm_adds_epi16(in29, final_rounding);
in30 = _mm_adds_epi16(in30, final_rounding);
in31 = _mm_adds_epi16(in31, final_rounding);
in0 = _mm_srai_epi16(in0, 6);
in1 = _mm_srai_epi16(in1, 6);
in2 = _mm_srai_epi16(in2, 6);
in3 = _mm_srai_epi16(in3, 6);
in4 = _mm_srai_epi16(in4, 6);
in5 = _mm_srai_epi16(in5, 6);
in6 = _mm_srai_epi16(in6, 6);
in7 = _mm_srai_epi16(in7, 6);
in8 = _mm_srai_epi16(in8, 6);
in9 = _mm_srai_epi16(in9, 6);
in10 = _mm_srai_epi16(in10, 6);
in11 = _mm_srai_epi16(in11, 6);
in12 = _mm_srai_epi16(in12, 6);
in13 = _mm_srai_epi16(in13, 6);
in14 = _mm_srai_epi16(in14, 6);
in15 = _mm_srai_epi16(in15, 6);
in16 = _mm_srai_epi16(in16, 6);
in17 = _mm_srai_epi16(in17, 6);
in18 = _mm_srai_epi16(in18, 6);
in19 = _mm_srai_epi16(in19, 6);
in20 = _mm_srai_epi16(in20, 6);
in21 = _mm_srai_epi16(in21, 6);
in22 = _mm_srai_epi16(in22, 6);
in23 = _mm_srai_epi16(in23, 6);
in24 = _mm_srai_epi16(in24, 6);
in25 = _mm_srai_epi16(in25, 6);
in26 = _mm_srai_epi16(in26, 6);
in27 = _mm_srai_epi16(in27, 6);
in28 = _mm_srai_epi16(in28, 6);
in29 = _mm_srai_epi16(in29, 6);
in30 = _mm_srai_epi16(in30, 6);
in31 = _mm_srai_epi16(in31, 6);
RECON_AND_STORE(dest, in0);
RECON_AND_STORE(dest, in1);
RECON_AND_STORE(dest, in2);
RECON_AND_STORE(dest, in3);
RECON_AND_STORE(dest, in4);
RECON_AND_STORE(dest, in5);
RECON_AND_STORE(dest, in6);
RECON_AND_STORE(dest, in7);
RECON_AND_STORE(dest, in8);
RECON_AND_STORE(dest, in9);
RECON_AND_STORE(dest, in10);
RECON_AND_STORE(dest, in11);
RECON_AND_STORE(dest, in12);
RECON_AND_STORE(dest, in13);
RECON_AND_STORE(dest, in14);
RECON_AND_STORE(dest, in15);
RECON_AND_STORE(dest, in16);
RECON_AND_STORE(dest, in17);
RECON_AND_STORE(dest, in18);
RECON_AND_STORE(dest, in19);
RECON_AND_STORE(dest, in20);
RECON_AND_STORE(dest, in21);
RECON_AND_STORE(dest, in22);
RECON_AND_STORE(dest, in23);
RECON_AND_STORE(dest, in24);
RECON_AND_STORE(dest, in25);
RECON_AND_STORE(dest, in26);
RECON_AND_STORE(dest, in27);
RECON_AND_STORE(dest, in28);
RECON_AND_STORE(dest, in29);
RECON_AND_STORE(dest, in30);
RECON_AND_STORE(dest, in31);
dest += 8 - (stride * 32);
}
}
}