1ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/* 2ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Copyright (c) 2012 The WebM project authors. All Rights Reserved. 3ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * 4ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Use of this source code is governed by a BSD-style license 5ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * that can be found in the LICENSE file in the root of the source 6ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * tree. An additional intellectual property rights grant can be found 7ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * in the file PATENTS. All contributing project authors may 8ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * be found in the AUTHORS file in the root of the source tree. 9ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */ 10ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 11ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include <emmintrin.h> // SSE2 12ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "vp9/common/vp9_idct.h" // for cospi constants 1391037db265ecdd914a26e056cf69207b4f50924ehkuang#include "vpx_ports/mem.h" 14ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 155ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangvoid vp9_fdct4x4_sse2(const int16_t *input, int16_t *output, int stride) { 16b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // This 2D transform implements 4 vertical 1D transforms followed 17b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // by 4 horizontal 1D transforms. The multiplies and adds are as given 18b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // by Chen, Smith and Fralick ('77). The commands for moving the data 19b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // around have been minimized by hand. 20b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // For the purposes of the comments, the 16 inputs are referred to at i0 21b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // through iF (in raster order), intermediate variables are a0, b0, c0 22b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // through f, and correspond to the in-place computations mapped to input 23b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // locations. The outputs, o0 through oF are labeled according to the 24b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // output locations. 25b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 26ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Constants 27b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // These are the coefficients used for the multiplies. 28b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // In the comments, pN means cos(N pi /64) and mN is -cos(N pi /64), 29b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // where cospi_N_64 = cos(N pi /64) 30b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i k__cospi_A = _mm_setr_epi16(cospi_16_64, cospi_16_64, 31b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_16_64, cospi_16_64, 32b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_16_64, -cospi_16_64, 33b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_16_64, -cospi_16_64); 34b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i k__cospi_B = _mm_setr_epi16(cospi_16_64, -cospi_16_64, 35b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_16_64, -cospi_16_64, 36b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_16_64, cospi_16_64, 37b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_16_64, cospi_16_64); 38b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i k__cospi_C = _mm_setr_epi16(cospi_8_64, cospi_24_64, 39b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_8_64, cospi_24_64, 40b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_24_64, -cospi_8_64, 41b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_24_64, -cospi_8_64); 42b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i k__cospi_D = _mm_setr_epi16(cospi_24_64, -cospi_8_64, 43b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_24_64, -cospi_8_64, 44b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_8_64, cospi_24_64, 45b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_8_64, cospi_24_64); 46b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i k__cospi_E = _mm_setr_epi16(cospi_16_64, cospi_16_64, 47b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_16_64, cospi_16_64, 48b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_16_64, cospi_16_64, 49b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_16_64, cospi_16_64); 50b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i k__cospi_F = _mm_setr_epi16(cospi_16_64, -cospi_16_64, 51b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_16_64, -cospi_16_64, 52b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_16_64, -cospi_16_64, 53b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_16_64, -cospi_16_64); 54b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i k__cospi_G = _mm_setr_epi16(cospi_8_64, cospi_24_64, 55b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_8_64, cospi_24_64, 56b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian -cospi_8_64, -cospi_24_64, 57b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian -cospi_8_64, -cospi_24_64); 58b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i k__cospi_H = _mm_setr_epi16(cospi_24_64, -cospi_8_64, 59b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian cospi_24_64, -cospi_8_64, 60b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian -cospi_24_64, cospi_8_64, 61b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian -cospi_24_64, cospi_8_64); 62b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 63ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i k__DCT_CONST_ROUNDING = _mm_set1_epi32(DCT_CONST_ROUNDING); 64b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // This second rounding constant saves doing some extra adds at the end 65b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i k__DCT_CONST_ROUNDING2 = _mm_set1_epi32(DCT_CONST_ROUNDING 66b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian +(DCT_CONST_ROUNDING << 1)); 67b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const int DCT_CONST_BITS2 = DCT_CONST_BITS+2; 68ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i k__nonzero_bias_a = _mm_setr_epi16(0, 1, 1, 1, 1, 1, 1, 1); 69ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i k__nonzero_bias_b = _mm_setr_epi16(1, 0, 0, 0, 0, 0, 0, 0); 70b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian __m128i in0, in1; 71b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 72ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Load inputs. 73ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang { 74ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in0 = _mm_loadl_epi64((const __m128i *)(input + 0 * stride)); 75ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in1 = _mm_loadl_epi64((const __m128i *)(input + 1 * stride)); 76b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian in1 = _mm_unpacklo_epi64(in1, _mm_loadl_epi64((const __m128i *) 77b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian (input + 2 * stride))); 78b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian in0 = _mm_unpacklo_epi64(in0, _mm_loadl_epi64((const __m128i *) 79b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian (input + 3 * stride))); 80b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // in0 = [i0 i1 i2 i3 iC iD iE iF] 81b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // in1 = [i4 i5 i6 i7 i8 i9 iA iB] 82b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 83b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 84b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // multiply by 16 to give some extra precision 85ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in0 = _mm_slli_epi16(in0, 4); 86ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in1 = _mm_slli_epi16(in1, 4); 87ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // if (i == 0 && input[0]) input[0] += 1; 88b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // add 1 to the upper left pixel if it is non-zero, which helps reduce 89b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // the round-trip error 90ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang { 91b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // The mask will only contain whether the first value is zero, all 92ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // other comparison will fail as something shifted by 4 (above << 4) 93ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // can never be equal to one. To increment in the non-zero case, we 94ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // add the mask and one for the first element: 95ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // - if zero, mask = -1, v = v - 1 + 1 = v 96ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // - if non-zero, mask = 0, v = v + 0 + 1 = v + 1 97ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang __m128i mask = _mm_cmpeq_epi16(in0, k__nonzero_bias_a); 98ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in0 = _mm_add_epi16(in0, mask); 99ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in0 = _mm_add_epi16(in0, k__nonzero_bias_b); 100ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 101ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 102b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // There are 4 total stages, alternating between an add/subtract stage 103b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // followed by an multiply-and-add stage. 104b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian { 105b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // Stage 1: Add/subtract 106b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 107b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // in0 = [i0 i1 i2 i3 iC iD iE iF] 108b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // in1 = [i4 i5 i6 i7 i8 i9 iA iB] 109b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i r0 = _mm_unpacklo_epi16(in0, in1); 110b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i r1 = _mm_unpackhi_epi16(in0, in1); 111b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // r0 = [i0 i4 i1 i5 i2 i6 i3 i7] 112b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // r1 = [iC i8 iD i9 iE iA iF iB] 113b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i r2 = _mm_shuffle_epi32(r0, 0xB4); 114b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i r3 = _mm_shuffle_epi32(r1, 0xB4); 115b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // r2 = [i0 i4 i1 i5 i3 i7 i2 i6] 116b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // r3 = [iC i8 iD i9 iF iB iE iA] 117b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 118b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i t0 = _mm_add_epi16(r2, r3); 119b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i t1 = _mm_sub_epi16(r2, r3); 120b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // t0 = [a0 a4 a1 a5 a3 a7 a2 a6] 121b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // t1 = [aC a8 aD a9 aF aB aE aA] 122b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 123b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // Stage 2: multiply by constants (which gets us into 32 bits). 124b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // The constants needed here are: 125b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // k__cospi_A = [p16 p16 p16 p16 p16 m16 p16 m16] 126b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // k__cospi_B = [p16 m16 p16 m16 p16 p16 p16 p16] 127b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // k__cospi_C = [p08 p24 p08 p24 p24 m08 p24 m08] 128b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // k__cospi_D = [p24 m08 p24 m08 p08 p24 p08 p24] 129b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i u0 = _mm_madd_epi16(t0, k__cospi_A); 130b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i u2 = _mm_madd_epi16(t0, k__cospi_B); 131b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i u1 = _mm_madd_epi16(t1, k__cospi_C); 132b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i u3 = _mm_madd_epi16(t1, k__cospi_D); 133b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // Then add and right-shift to get back to 16-bit range 134ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v0 = _mm_add_epi32(u0, k__DCT_CONST_ROUNDING); 135b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i v1 = _mm_add_epi32(u1, k__DCT_CONST_ROUNDING); 136ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v2 = _mm_add_epi32(u2, k__DCT_CONST_ROUNDING); 137b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i v3 = _mm_add_epi32(u3, k__DCT_CONST_ROUNDING); 138ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w0 = _mm_srai_epi32(v0, DCT_CONST_BITS); 139b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i w1 = _mm_srai_epi32(v1, DCT_CONST_BITS); 140ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w2 = _mm_srai_epi32(v2, DCT_CONST_BITS); 141b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i w3 = _mm_srai_epi32(v3, DCT_CONST_BITS); 142b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // w0 = [b0 b1 b7 b6] 143b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // w1 = [b8 b9 bF bE] 144b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // w2 = [b4 b5 b3 b2] 145b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // w3 = [bC bD bB bA] 146b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i x0 = _mm_packs_epi32(w0, w1); 147b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i x1 = _mm_packs_epi32(w2, w3); 148b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // x0 = [b0 b1 b7 b6 b8 b9 bF bE] 149b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // x1 = [b4 b5 b3 b2 bC bD bB bA] 150b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian in0 = _mm_shuffle_epi32(x0, 0xD8); 151b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian in1 = _mm_shuffle_epi32(x1, 0x8D); 152b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // in0 = [b0 b1 b8 b9 b7 b6 bF bE] 153b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // in1 = [b3 b2 bB bA b4 b5 bC bD] 154b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian } 155b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian { 156b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // vertical DCTs finished. Now we do the horizontal DCTs. 157b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // Stage 3: Add/subtract 158b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 159b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i t0 = _mm_add_epi16(in0, in1); 160b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i t1 = _mm_sub_epi16(in0, in1); 161b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // t0 = [c0 c1 c8 c9 c4 c5 cC cD] 162b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // t1 = [c3 c2 cB cA -c7 -c6 -cF -cE] 163b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 164b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // Stage 4: multiply by constants (which gets us into 32 bits). 165b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // The constants needed here are: 166b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // k__cospi_E = [p16 p16 p16 p16 p16 p16 p16 p16] 167b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // k__cospi_F = [p16 m16 p16 m16 p16 m16 p16 m16] 168b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // k__cospi_G = [p08 p24 p08 p24 m08 m24 m08 m24] 169b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // k__cospi_H = [p24 m08 p24 m08 m24 p08 m24 p08] 170b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i u0 = _mm_madd_epi16(t0, k__cospi_E); 171b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i u1 = _mm_madd_epi16(t0, k__cospi_F); 172b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i u2 = _mm_madd_epi16(t1, k__cospi_G); 173b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i u3 = _mm_madd_epi16(t1, k__cospi_H); 174b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // Then add and right-shift to get back to 16-bit range 175b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // but this combines the final right-shift as well to save operations 176b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // This unusual rounding operations is to maintain bit-accurate 177b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // compatibility with the c version of this function which has two 178b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // rounding steps in a row. 179b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i v0 = _mm_add_epi32(u0, k__DCT_CONST_ROUNDING2); 180b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i v1 = _mm_add_epi32(u1, k__DCT_CONST_ROUNDING2); 181b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i v2 = _mm_add_epi32(u2, k__DCT_CONST_ROUNDING2); 182b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i v3 = _mm_add_epi32(u3, k__DCT_CONST_ROUNDING2); 183b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i w0 = _mm_srai_epi32(v0, DCT_CONST_BITS2); 184b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i w1 = _mm_srai_epi32(v1, DCT_CONST_BITS2); 185b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i w2 = _mm_srai_epi32(v2, DCT_CONST_BITS2); 186b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i w3 = _mm_srai_epi32(v3, DCT_CONST_BITS2); 187b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // w0 = [o0 o4 o8 oC] 188b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // w1 = [o2 o6 oA oE] 189b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // w2 = [o1 o5 o9 oD] 190b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // w3 = [o3 o7 oB oF] 191b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // remember the o's are numbered according to the correct output location 192b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i x0 = _mm_packs_epi32(w0, w1); 193b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i x1 = _mm_packs_epi32(w2, w3); 194b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // x0 = [o0 o4 o8 oC o2 o6 oA oE] 195b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // x1 = [o1 o5 o9 oD o3 o7 oB oF] 196b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i y0 = _mm_unpacklo_epi16(x0, x1); 197b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const __m128i y1 = _mm_unpackhi_epi16(x0, x1); 198b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // y0 = [o0 o1 o4 o5 o8 o9 oC oD] 199b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // y1 = [o2 o3 o6 o7 oA oB oE oF] 200b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian in0 = _mm_unpacklo_epi32(y0, y1); 201b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // in0 = [o0 o1 o2 o3 o4 o5 o6 o7] 202b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian in1 = _mm_unpackhi_epi32(y0, y1); 203b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // in1 = [o8 o9 oA oB oC oD oE oF] 204b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian } 205b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // Post-condition (v + 1) >> 2 is now incorporated into previous 206b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // add and right-shift commands. Only 2 store instructions needed 207b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // because we are using the fact that 1/3 are stored just after 0/2. 208b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian { 209b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian _mm_storeu_si128((__m128i *)(output + 0 * 4), in0); 210b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian _mm_storeu_si128((__m128i *)(output + 2 * 4), in1); 211ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 212ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang} 213ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 214b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 2155ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangstatic INLINE void load_buffer_4x4(const int16_t *input, __m128i *in, 2165ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang int stride) { 21791037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__nonzero_bias_a = _mm_setr_epi16(0, 1, 1, 1, 1, 1, 1, 1); 21891037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__nonzero_bias_b = _mm_setr_epi16(1, 0, 0, 0, 0, 0, 0, 0); 21991037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i mask; 22091037db265ecdd914a26e056cf69207b4f50924ehkuang 22191037db265ecdd914a26e056cf69207b4f50924ehkuang in[0] = _mm_loadl_epi64((const __m128i *)(input + 0 * stride)); 22291037db265ecdd914a26e056cf69207b4f50924ehkuang in[1] = _mm_loadl_epi64((const __m128i *)(input + 1 * stride)); 22391037db265ecdd914a26e056cf69207b4f50924ehkuang in[2] = _mm_loadl_epi64((const __m128i *)(input + 2 * stride)); 22491037db265ecdd914a26e056cf69207b4f50924ehkuang in[3] = _mm_loadl_epi64((const __m128i *)(input + 3 * stride)); 22591037db265ecdd914a26e056cf69207b4f50924ehkuang 22691037db265ecdd914a26e056cf69207b4f50924ehkuang in[0] = _mm_slli_epi16(in[0], 4); 22791037db265ecdd914a26e056cf69207b4f50924ehkuang in[1] = _mm_slli_epi16(in[1], 4); 22891037db265ecdd914a26e056cf69207b4f50924ehkuang in[2] = _mm_slli_epi16(in[2], 4); 22991037db265ecdd914a26e056cf69207b4f50924ehkuang in[3] = _mm_slli_epi16(in[3], 4); 23091037db265ecdd914a26e056cf69207b4f50924ehkuang 23191037db265ecdd914a26e056cf69207b4f50924ehkuang mask = _mm_cmpeq_epi16(in[0], k__nonzero_bias_a); 23291037db265ecdd914a26e056cf69207b4f50924ehkuang in[0] = _mm_add_epi16(in[0], mask); 23391037db265ecdd914a26e056cf69207b4f50924ehkuang in[0] = _mm_add_epi16(in[0], k__nonzero_bias_b); 23491037db265ecdd914a26e056cf69207b4f50924ehkuang} 23591037db265ecdd914a26e056cf69207b4f50924ehkuang 23691037db265ecdd914a26e056cf69207b4f50924ehkuangstatic INLINE void write_buffer_4x4(int16_t *output, __m128i *res) { 23791037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i kOne = _mm_set1_epi16(1); 23891037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i in01 = _mm_unpacklo_epi64(res[0], res[1]); 23991037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i in23 = _mm_unpacklo_epi64(res[2], res[3]); 24091037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i out01 = _mm_add_epi16(in01, kOne); 24191037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i out23 = _mm_add_epi16(in23, kOne); 24291037db265ecdd914a26e056cf69207b4f50924ehkuang out01 = _mm_srai_epi16(out01, 2); 24391037db265ecdd914a26e056cf69207b4f50924ehkuang out23 = _mm_srai_epi16(out23, 2); 24491037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 0 * 8), out01); 24591037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 1 * 8), out23); 24691037db265ecdd914a26e056cf69207b4f50924ehkuang} 24791037db265ecdd914a26e056cf69207b4f50924ehkuang 24891037db265ecdd914a26e056cf69207b4f50924ehkuangstatic INLINE void transpose_4x4(__m128i *res) { 24991037db265ecdd914a26e056cf69207b4f50924ehkuang // Combine and transpose 25091037db265ecdd914a26e056cf69207b4f50924ehkuang // 00 01 02 03 20 21 22 23 25191037db265ecdd914a26e056cf69207b4f50924ehkuang // 10 11 12 13 30 31 32 33 25291037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr0_0 = _mm_unpacklo_epi16(res[0], res[1]); 25391037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr0_1 = _mm_unpackhi_epi16(res[0], res[1]); 25491037db265ecdd914a26e056cf69207b4f50924ehkuang 25591037db265ecdd914a26e056cf69207b4f50924ehkuang // 00 10 01 11 02 12 03 13 25691037db265ecdd914a26e056cf69207b4f50924ehkuang // 20 30 21 31 22 32 23 33 25791037db265ecdd914a26e056cf69207b4f50924ehkuang res[0] = _mm_unpacklo_epi32(tr0_0, tr0_1); 25891037db265ecdd914a26e056cf69207b4f50924ehkuang res[2] = _mm_unpackhi_epi32(tr0_0, tr0_1); 25991037db265ecdd914a26e056cf69207b4f50924ehkuang 26091037db265ecdd914a26e056cf69207b4f50924ehkuang // 00 10 20 30 01 11 21 31 26191037db265ecdd914a26e056cf69207b4f50924ehkuang // 02 12 22 32 03 13 23 33 26291037db265ecdd914a26e056cf69207b4f50924ehkuang // only use the first 4 16-bit integers 26391037db265ecdd914a26e056cf69207b4f50924ehkuang res[1] = _mm_unpackhi_epi64(res[0], res[0]); 26491037db265ecdd914a26e056cf69207b4f50924ehkuang res[3] = _mm_unpackhi_epi64(res[2], res[2]); 26591037db265ecdd914a26e056cf69207b4f50924ehkuang} 26691037db265ecdd914a26e056cf69207b4f50924ehkuang 267b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianvoid fdct4_sse2(__m128i *in) { 26891037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__cospi_p16_p16 = _mm_set1_epi16(cospi_16_64); 26991037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__cospi_p16_m16 = pair_set_epi16(cospi_16_64, -cospi_16_64); 2705ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang const __m128i k__cospi_p08_p24 = pair_set_epi16(cospi_8_64, cospi_24_64); 2715ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang const __m128i k__cospi_p24_m08 = pair_set_epi16(cospi_24_64, -cospi_8_64); 27291037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__DCT_CONST_ROUNDING = _mm_set1_epi32(DCT_CONST_ROUNDING); 27391037db265ecdd914a26e056cf69207b4f50924ehkuang 27491037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i u[4], v[4]; 2755ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang u[0]=_mm_unpacklo_epi16(in[0], in[1]); 2765ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang u[1]=_mm_unpacklo_epi16(in[3], in[2]); 2775ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 2785ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang v[0] = _mm_add_epi16(u[0], u[1]); 2795ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang v[1] = _mm_sub_epi16(u[0], u[1]); 28091037db265ecdd914a26e056cf69207b4f50924ehkuang 28191037db265ecdd914a26e056cf69207b4f50924ehkuang u[0] = _mm_madd_epi16(v[0], k__cospi_p16_p16); // 0 28291037db265ecdd914a26e056cf69207b4f50924ehkuang u[1] = _mm_madd_epi16(v[0], k__cospi_p16_m16); // 2 2835ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang u[2] = _mm_madd_epi16(v[1], k__cospi_p08_p24); // 1 2845ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang u[3] = _mm_madd_epi16(v[1], k__cospi_p24_m08); // 3 28591037db265ecdd914a26e056cf69207b4f50924ehkuang 28691037db265ecdd914a26e056cf69207b4f50924ehkuang v[0] = _mm_add_epi32(u[0], k__DCT_CONST_ROUNDING); 28791037db265ecdd914a26e056cf69207b4f50924ehkuang v[1] = _mm_add_epi32(u[1], k__DCT_CONST_ROUNDING); 28891037db265ecdd914a26e056cf69207b4f50924ehkuang v[2] = _mm_add_epi32(u[2], k__DCT_CONST_ROUNDING); 28991037db265ecdd914a26e056cf69207b4f50924ehkuang v[3] = _mm_add_epi32(u[3], k__DCT_CONST_ROUNDING); 29091037db265ecdd914a26e056cf69207b4f50924ehkuang u[0] = _mm_srai_epi32(v[0], DCT_CONST_BITS); 29191037db265ecdd914a26e056cf69207b4f50924ehkuang u[1] = _mm_srai_epi32(v[1], DCT_CONST_BITS); 29291037db265ecdd914a26e056cf69207b4f50924ehkuang u[2] = _mm_srai_epi32(v[2], DCT_CONST_BITS); 29391037db265ecdd914a26e056cf69207b4f50924ehkuang u[3] = _mm_srai_epi32(v[3], DCT_CONST_BITS); 29491037db265ecdd914a26e056cf69207b4f50924ehkuang 29591037db265ecdd914a26e056cf69207b4f50924ehkuang in[0] = _mm_packs_epi32(u[0], u[1]); 29691037db265ecdd914a26e056cf69207b4f50924ehkuang in[1] = _mm_packs_epi32(u[2], u[3]); 29791037db265ecdd914a26e056cf69207b4f50924ehkuang transpose_4x4(in); 29891037db265ecdd914a26e056cf69207b4f50924ehkuang} 29991037db265ecdd914a26e056cf69207b4f50924ehkuang 300b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianvoid fadst4_sse2(__m128i *in) { 30191037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__sinpi_p01_p02 = pair_set_epi16(sinpi_1_9, sinpi_2_9); 30291037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__sinpi_p04_m01 = pair_set_epi16(sinpi_4_9, -sinpi_1_9); 30391037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__sinpi_p03_p04 = pair_set_epi16(sinpi_3_9, sinpi_4_9); 30491037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__sinpi_m03_p02 = pair_set_epi16(-sinpi_3_9, sinpi_2_9); 30591037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__sinpi_p03_p03 = _mm_set1_epi16(sinpi_3_9); 30691037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i kZero = _mm_set1_epi16(0); 30791037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__DCT_CONST_ROUNDING = _mm_set1_epi32(DCT_CONST_ROUNDING); 30891037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i u[8], v[8]; 30991037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i in7 = _mm_add_epi16(in[0], in[1]); 31091037db265ecdd914a26e056cf69207b4f50924ehkuang 31191037db265ecdd914a26e056cf69207b4f50924ehkuang u[0] = _mm_unpacklo_epi16(in[0], in[1]); 31291037db265ecdd914a26e056cf69207b4f50924ehkuang u[1] = _mm_unpacklo_epi16(in[2], in[3]); 31391037db265ecdd914a26e056cf69207b4f50924ehkuang u[2] = _mm_unpacklo_epi16(in7, kZero); 31491037db265ecdd914a26e056cf69207b4f50924ehkuang u[3] = _mm_unpacklo_epi16(in[2], kZero); 3159b35249446b07f40ac5fcc3205f2c048616efacchkuang u[4] = _mm_unpacklo_epi16(in[3], kZero); 31691037db265ecdd914a26e056cf69207b4f50924ehkuang 31791037db265ecdd914a26e056cf69207b4f50924ehkuang v[0] = _mm_madd_epi16(u[0], k__sinpi_p01_p02); // s0 + s2 31891037db265ecdd914a26e056cf69207b4f50924ehkuang v[1] = _mm_madd_epi16(u[1], k__sinpi_p03_p04); // s4 + s5 31991037db265ecdd914a26e056cf69207b4f50924ehkuang v[2] = _mm_madd_epi16(u[2], k__sinpi_p03_p03); // x1 32091037db265ecdd914a26e056cf69207b4f50924ehkuang v[3] = _mm_madd_epi16(u[0], k__sinpi_p04_m01); // s1 - s3 32191037db265ecdd914a26e056cf69207b4f50924ehkuang v[4] = _mm_madd_epi16(u[1], k__sinpi_m03_p02); // -s4 + s6 32291037db265ecdd914a26e056cf69207b4f50924ehkuang v[5] = _mm_madd_epi16(u[3], k__sinpi_p03_p03); // s4 3239b35249446b07f40ac5fcc3205f2c048616efacchkuang v[6] = _mm_madd_epi16(u[4], k__sinpi_p03_p03); 32491037db265ecdd914a26e056cf69207b4f50924ehkuang 32591037db265ecdd914a26e056cf69207b4f50924ehkuang u[0] = _mm_add_epi32(v[0], v[1]); 3269b35249446b07f40ac5fcc3205f2c048616efacchkuang u[1] = _mm_sub_epi32(v[2], v[6]); 32791037db265ecdd914a26e056cf69207b4f50924ehkuang u[2] = _mm_add_epi32(v[3], v[4]); 32891037db265ecdd914a26e056cf69207b4f50924ehkuang u[3] = _mm_sub_epi32(u[2], u[0]); 32991037db265ecdd914a26e056cf69207b4f50924ehkuang u[4] = _mm_slli_epi32(v[5], 2); 33091037db265ecdd914a26e056cf69207b4f50924ehkuang u[5] = _mm_sub_epi32(u[4], v[5]); 33191037db265ecdd914a26e056cf69207b4f50924ehkuang u[6] = _mm_add_epi32(u[3], u[5]); 33291037db265ecdd914a26e056cf69207b4f50924ehkuang 33391037db265ecdd914a26e056cf69207b4f50924ehkuang v[0] = _mm_add_epi32(u[0], k__DCT_CONST_ROUNDING); 33491037db265ecdd914a26e056cf69207b4f50924ehkuang v[1] = _mm_add_epi32(u[1], k__DCT_CONST_ROUNDING); 33591037db265ecdd914a26e056cf69207b4f50924ehkuang v[2] = _mm_add_epi32(u[2], k__DCT_CONST_ROUNDING); 33691037db265ecdd914a26e056cf69207b4f50924ehkuang v[3] = _mm_add_epi32(u[6], k__DCT_CONST_ROUNDING); 33791037db265ecdd914a26e056cf69207b4f50924ehkuang 33891037db265ecdd914a26e056cf69207b4f50924ehkuang u[0] = _mm_srai_epi32(v[0], DCT_CONST_BITS); 33991037db265ecdd914a26e056cf69207b4f50924ehkuang u[1] = _mm_srai_epi32(v[1], DCT_CONST_BITS); 34091037db265ecdd914a26e056cf69207b4f50924ehkuang u[2] = _mm_srai_epi32(v[2], DCT_CONST_BITS); 34191037db265ecdd914a26e056cf69207b4f50924ehkuang u[3] = _mm_srai_epi32(v[3], DCT_CONST_BITS); 34291037db265ecdd914a26e056cf69207b4f50924ehkuang 34391037db265ecdd914a26e056cf69207b4f50924ehkuang in[0] = _mm_packs_epi32(u[0], u[2]); 34491037db265ecdd914a26e056cf69207b4f50924ehkuang in[1] = _mm_packs_epi32(u[1], u[3]); 34591037db265ecdd914a26e056cf69207b4f50924ehkuang transpose_4x4(in); 34691037db265ecdd914a26e056cf69207b4f50924ehkuang} 34791037db265ecdd914a26e056cf69207b4f50924ehkuang 348b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianvoid vp9_fht4x4_sse2(const int16_t *input, int16_t *output, 349b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian int stride, int tx_type) { 35091037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i in[4]; 351b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 35291037db265ecdd914a26e056cf69207b4f50924ehkuang switch (tx_type) { 353b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian case DCT_DCT: 354b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian vp9_fdct4x4_sse2(input, output, stride); 35591037db265ecdd914a26e056cf69207b4f50924ehkuang break; 356b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian case ADST_DCT: 357b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian load_buffer_4x4(input, in, stride); 358b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian fadst4_sse2(in); 359b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian fdct4_sse2(in); 360b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian write_buffer_4x4(output, in); 36191037db265ecdd914a26e056cf69207b4f50924ehkuang break; 362b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian case DCT_ADST: 363b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian load_buffer_4x4(input, in, stride); 364b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian fdct4_sse2(in); 365b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian fadst4_sse2(in); 366b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian write_buffer_4x4(output, in); 36791037db265ecdd914a26e056cf69207b4f50924ehkuang break; 368b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian case ADST_ADST: 369b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian load_buffer_4x4(input, in, stride); 370b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian fadst4_sse2(in); 371b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian fadst4_sse2(in); 372b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian write_buffer_4x4(output, in); 37391037db265ecdd914a26e056cf69207b4f50924ehkuang break; 374b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian default: 375b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian assert(0); 376b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian break; 37791037db265ecdd914a26e056cf69207b4f50924ehkuang } 37891037db265ecdd914a26e056cf69207b4f50924ehkuang} 37991037db265ecdd914a26e056cf69207b4f50924ehkuang 3805ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangvoid vp9_fdct8x8_sse2(const int16_t *input, int16_t *output, int stride) { 381ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int pass; 382ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Constants 383ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // When we use them, in one case, they are all the same. In all others 384ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // it's a pair of them that we need to repeat four times. This is done 385ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // by constructing the 32 bit constant corresponding to that pair. 386ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i k__cospi_p16_p16 = _mm_set1_epi16(cospi_16_64); 387ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i k__cospi_p16_m16 = pair_set_epi16(cospi_16_64, -cospi_16_64); 388ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i k__cospi_p24_p08 = pair_set_epi16(cospi_24_64, cospi_8_64); 389ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i k__cospi_m08_p24 = pair_set_epi16(-cospi_8_64, cospi_24_64); 390ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i k__cospi_p28_p04 = pair_set_epi16(cospi_28_64, cospi_4_64); 391ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i k__cospi_m04_p28 = pair_set_epi16(-cospi_4_64, cospi_28_64); 392ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i k__cospi_p12_p20 = pair_set_epi16(cospi_12_64, cospi_20_64); 393ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i k__cospi_m20_p12 = pair_set_epi16(-cospi_20_64, cospi_12_64); 394ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i k__DCT_CONST_ROUNDING = _mm_set1_epi32(DCT_CONST_ROUNDING); 395ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Load input 39691037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i in0 = _mm_load_si128((const __m128i *)(input + 0 * stride)); 39791037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i in1 = _mm_load_si128((const __m128i *)(input + 1 * stride)); 39891037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i in2 = _mm_load_si128((const __m128i *)(input + 2 * stride)); 39991037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i in3 = _mm_load_si128((const __m128i *)(input + 3 * stride)); 40091037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i in4 = _mm_load_si128((const __m128i *)(input + 4 * stride)); 40191037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i in5 = _mm_load_si128((const __m128i *)(input + 5 * stride)); 40291037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i in6 = _mm_load_si128((const __m128i *)(input + 6 * stride)); 40391037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i in7 = _mm_load_si128((const __m128i *)(input + 7 * stride)); 404ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Pre-condition input (shift by two) 405ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in0 = _mm_slli_epi16(in0, 2); 406ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in1 = _mm_slli_epi16(in1, 2); 407ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in2 = _mm_slli_epi16(in2, 2); 408ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in3 = _mm_slli_epi16(in3, 2); 409ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in4 = _mm_slli_epi16(in4, 2); 410ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in5 = _mm_slli_epi16(in5, 2); 411ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in6 = _mm_slli_epi16(in6, 2); 412ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in7 = _mm_slli_epi16(in7, 2); 413ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 414ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // We do two passes, first the columns, then the rows. The results of the 415ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // first pass are transposed so that the same column code can be reused. The 416ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // results of the second pass are also transposed so that the rows (processed 417ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // as columns) are put back in row positions. 418ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang for (pass = 0; pass < 2; pass++) { 419ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // To store results of each pass before the transpose. 420ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang __m128i res0, res1, res2, res3, res4, res5, res6, res7; 421b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // Add/subtract 422ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i q0 = _mm_add_epi16(in0, in7); 423ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i q1 = _mm_add_epi16(in1, in6); 424ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i q2 = _mm_add_epi16(in2, in5); 425ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i q3 = _mm_add_epi16(in3, in4); 426ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i q4 = _mm_sub_epi16(in3, in4); 427ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i q5 = _mm_sub_epi16(in2, in5); 428ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i q6 = _mm_sub_epi16(in1, in6); 429ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i q7 = _mm_sub_epi16(in0, in7); 430ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Work on first four results 431ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang { 432b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // Add/subtract 433ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i r0 = _mm_add_epi16(q0, q3); 434ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i r1 = _mm_add_epi16(q1, q2); 435ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i r2 = _mm_sub_epi16(q1, q2); 436ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i r3 = _mm_sub_epi16(q0, q3); 437ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Interleave to do the multiply by constants which gets us into 32bits 438ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i t0 = _mm_unpacklo_epi16(r0, r1); 439ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i t1 = _mm_unpackhi_epi16(r0, r1); 440ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i t2 = _mm_unpacklo_epi16(r2, r3); 441ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i t3 = _mm_unpackhi_epi16(r2, r3); 442ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u0 = _mm_madd_epi16(t0, k__cospi_p16_p16); 443ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u1 = _mm_madd_epi16(t1, k__cospi_p16_p16); 444ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u2 = _mm_madd_epi16(t0, k__cospi_p16_m16); 445ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u3 = _mm_madd_epi16(t1, k__cospi_p16_m16); 446ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u4 = _mm_madd_epi16(t2, k__cospi_p24_p08); 447ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u5 = _mm_madd_epi16(t3, k__cospi_p24_p08); 448ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u6 = _mm_madd_epi16(t2, k__cospi_m08_p24); 449ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u7 = _mm_madd_epi16(t3, k__cospi_m08_p24); 450ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // dct_const_round_shift 451ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v0 = _mm_add_epi32(u0, k__DCT_CONST_ROUNDING); 452ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v1 = _mm_add_epi32(u1, k__DCT_CONST_ROUNDING); 453ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v2 = _mm_add_epi32(u2, k__DCT_CONST_ROUNDING); 454ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v3 = _mm_add_epi32(u3, k__DCT_CONST_ROUNDING); 455ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v4 = _mm_add_epi32(u4, k__DCT_CONST_ROUNDING); 456ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v5 = _mm_add_epi32(u5, k__DCT_CONST_ROUNDING); 457ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v6 = _mm_add_epi32(u6, k__DCT_CONST_ROUNDING); 458ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v7 = _mm_add_epi32(u7, k__DCT_CONST_ROUNDING); 459ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w0 = _mm_srai_epi32(v0, DCT_CONST_BITS); 460ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w1 = _mm_srai_epi32(v1, DCT_CONST_BITS); 461ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w2 = _mm_srai_epi32(v2, DCT_CONST_BITS); 462ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w3 = _mm_srai_epi32(v3, DCT_CONST_BITS); 463ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w4 = _mm_srai_epi32(v4, DCT_CONST_BITS); 464ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w5 = _mm_srai_epi32(v5, DCT_CONST_BITS); 465ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w6 = _mm_srai_epi32(v6, DCT_CONST_BITS); 466ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w7 = _mm_srai_epi32(v7, DCT_CONST_BITS); 467ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Combine 468ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang res0 = _mm_packs_epi32(w0, w1); 469ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang res4 = _mm_packs_epi32(w2, w3); 470ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang res2 = _mm_packs_epi32(w4, w5); 471ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang res6 = _mm_packs_epi32(w6, w7); 472ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 473ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Work on next four results 474ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang { 475ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Interleave to do the multiply by constants which gets us into 32bits 476ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i d0 = _mm_unpacklo_epi16(q6, q5); 477ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i d1 = _mm_unpackhi_epi16(q6, q5); 478ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i e0 = _mm_madd_epi16(d0, k__cospi_p16_m16); 479ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i e1 = _mm_madd_epi16(d1, k__cospi_p16_m16); 480ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i e2 = _mm_madd_epi16(d0, k__cospi_p16_p16); 481ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i e3 = _mm_madd_epi16(d1, k__cospi_p16_p16); 482ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // dct_const_round_shift 483ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i f0 = _mm_add_epi32(e0, k__DCT_CONST_ROUNDING); 484ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i f1 = _mm_add_epi32(e1, k__DCT_CONST_ROUNDING); 485ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i f2 = _mm_add_epi32(e2, k__DCT_CONST_ROUNDING); 486ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i f3 = _mm_add_epi32(e3, k__DCT_CONST_ROUNDING); 487ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i s0 = _mm_srai_epi32(f0, DCT_CONST_BITS); 488ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i s1 = _mm_srai_epi32(f1, DCT_CONST_BITS); 489ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i s2 = _mm_srai_epi32(f2, DCT_CONST_BITS); 490ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i s3 = _mm_srai_epi32(f3, DCT_CONST_BITS); 491ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Combine 492ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i r0 = _mm_packs_epi32(s0, s1); 493ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i r1 = _mm_packs_epi32(s2, s3); 494b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // Add/subtract 495ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i x0 = _mm_add_epi16(q4, r0); 496ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i x1 = _mm_sub_epi16(q4, r0); 497ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i x2 = _mm_sub_epi16(q7, r1); 498ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i x3 = _mm_add_epi16(q7, r1); 499ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Interleave to do the multiply by constants which gets us into 32bits 500ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i t0 = _mm_unpacklo_epi16(x0, x3); 501ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i t1 = _mm_unpackhi_epi16(x0, x3); 502ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i t2 = _mm_unpacklo_epi16(x1, x2); 503ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i t3 = _mm_unpackhi_epi16(x1, x2); 504ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u0 = _mm_madd_epi16(t0, k__cospi_p28_p04); 505ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u1 = _mm_madd_epi16(t1, k__cospi_p28_p04); 506ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u2 = _mm_madd_epi16(t0, k__cospi_m04_p28); 507ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u3 = _mm_madd_epi16(t1, k__cospi_m04_p28); 508ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u4 = _mm_madd_epi16(t2, k__cospi_p12_p20); 509ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u5 = _mm_madd_epi16(t3, k__cospi_p12_p20); 510ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u6 = _mm_madd_epi16(t2, k__cospi_m20_p12); 511ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i u7 = _mm_madd_epi16(t3, k__cospi_m20_p12); 512ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // dct_const_round_shift 513ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v0 = _mm_add_epi32(u0, k__DCT_CONST_ROUNDING); 514ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v1 = _mm_add_epi32(u1, k__DCT_CONST_ROUNDING); 515ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v2 = _mm_add_epi32(u2, k__DCT_CONST_ROUNDING); 516ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v3 = _mm_add_epi32(u3, k__DCT_CONST_ROUNDING); 517ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v4 = _mm_add_epi32(u4, k__DCT_CONST_ROUNDING); 518ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v5 = _mm_add_epi32(u5, k__DCT_CONST_ROUNDING); 519ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v6 = _mm_add_epi32(u6, k__DCT_CONST_ROUNDING); 520ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i v7 = _mm_add_epi32(u7, k__DCT_CONST_ROUNDING); 521ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w0 = _mm_srai_epi32(v0, DCT_CONST_BITS); 522ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w1 = _mm_srai_epi32(v1, DCT_CONST_BITS); 523ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w2 = _mm_srai_epi32(v2, DCT_CONST_BITS); 524ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w3 = _mm_srai_epi32(v3, DCT_CONST_BITS); 525ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w4 = _mm_srai_epi32(v4, DCT_CONST_BITS); 526ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w5 = _mm_srai_epi32(v5, DCT_CONST_BITS); 527ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w6 = _mm_srai_epi32(v6, DCT_CONST_BITS); 528ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i w7 = _mm_srai_epi32(v7, DCT_CONST_BITS); 529ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Combine 530ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang res1 = _mm_packs_epi32(w0, w1); 531ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang res7 = _mm_packs_epi32(w2, w3); 532ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang res5 = _mm_packs_epi32(w4, w5); 533ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang res3 = _mm_packs_epi32(w6, w7); 534ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 535ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Transpose the 8x8. 536ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang { 537ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 00 01 02 03 04 05 06 07 538ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 10 11 12 13 14 15 16 17 539ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 20 21 22 23 24 25 26 27 540ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 30 31 32 33 34 35 36 37 541ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 40 41 42 43 44 45 46 47 542ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 50 51 52 53 54 55 56 57 543ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 60 61 62 63 64 65 66 67 544ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 70 71 72 73 74 75 76 77 545ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr0_0 = _mm_unpacklo_epi16(res0, res1); 546ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr0_1 = _mm_unpacklo_epi16(res2, res3); 547ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr0_2 = _mm_unpackhi_epi16(res0, res1); 548ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr0_3 = _mm_unpackhi_epi16(res2, res3); 549ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr0_4 = _mm_unpacklo_epi16(res4, res5); 550ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr0_5 = _mm_unpacklo_epi16(res6, res7); 551ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr0_6 = _mm_unpackhi_epi16(res4, res5); 552ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr0_7 = _mm_unpackhi_epi16(res6, res7); 553ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 00 10 01 11 02 12 03 13 554ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 20 30 21 31 22 32 23 33 555ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 04 14 05 15 06 16 07 17 556ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 24 34 25 35 26 36 27 37 557ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 40 50 41 51 42 52 43 53 558ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 60 70 61 71 62 72 63 73 559ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 54 54 55 55 56 56 57 57 560ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 64 74 65 75 66 76 67 77 561ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr1_0 = _mm_unpacklo_epi32(tr0_0, tr0_1); 562ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr1_1 = _mm_unpacklo_epi32(tr0_2, tr0_3); 563ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr1_2 = _mm_unpackhi_epi32(tr0_0, tr0_1); 564ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr1_3 = _mm_unpackhi_epi32(tr0_2, tr0_3); 565ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr1_4 = _mm_unpacklo_epi32(tr0_4, tr0_5); 566ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr1_5 = _mm_unpacklo_epi32(tr0_6, tr0_7); 567ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr1_6 = _mm_unpackhi_epi32(tr0_4, tr0_5); 568ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i tr1_7 = _mm_unpackhi_epi32(tr0_6, tr0_7); 569ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 00 10 20 30 01 11 21 31 570ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 40 50 60 70 41 51 61 71 571ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 02 12 22 32 03 13 23 33 572ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 42 52 62 72 43 53 63 73 573ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 04 14 24 34 05 15 21 36 574ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 44 54 64 74 45 55 61 76 575ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 06 16 26 36 07 17 27 37 576ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 46 56 66 76 47 57 67 77 577ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in0 = _mm_unpacklo_epi64(tr1_0, tr1_4); 578ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in1 = _mm_unpackhi_epi64(tr1_0, tr1_4); 579ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in2 = _mm_unpacklo_epi64(tr1_2, tr1_6); 580ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in3 = _mm_unpackhi_epi64(tr1_2, tr1_6); 581ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in4 = _mm_unpacklo_epi64(tr1_1, tr1_5); 582ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in5 = _mm_unpackhi_epi64(tr1_1, tr1_5); 583ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in6 = _mm_unpacklo_epi64(tr1_3, tr1_7); 584ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in7 = _mm_unpackhi_epi64(tr1_3, tr1_7); 585ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 00 10 20 30 40 50 60 70 586ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 01 11 21 31 41 51 61 71 587ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 02 12 22 32 42 52 62 72 588ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 03 13 23 33 43 53 63 73 589ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 04 14 24 34 44 54 64 74 590ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 05 15 25 35 45 55 65 75 591ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 06 16 26 36 46 56 66 76 592ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // 07 17 27 37 47 57 67 77 593ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 594ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 595ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Post-condition output and store it 596ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang { 597ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Post-condition (division by two) 598ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // division of two 16 bits signed numbers using shifts 599ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // n / 2 = (n - (n >> 15)) >> 1 600ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i sign_in0 = _mm_srai_epi16(in0, 15); 601ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i sign_in1 = _mm_srai_epi16(in1, 15); 602ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i sign_in2 = _mm_srai_epi16(in2, 15); 603ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i sign_in3 = _mm_srai_epi16(in3, 15); 604ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i sign_in4 = _mm_srai_epi16(in4, 15); 605ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i sign_in5 = _mm_srai_epi16(in5, 15); 606ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i sign_in6 = _mm_srai_epi16(in6, 15); 607ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const __m128i sign_in7 = _mm_srai_epi16(in7, 15); 608ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in0 = _mm_sub_epi16(in0, sign_in0); 609ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in1 = _mm_sub_epi16(in1, sign_in1); 610ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in2 = _mm_sub_epi16(in2, sign_in2); 611ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in3 = _mm_sub_epi16(in3, sign_in3); 612ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in4 = _mm_sub_epi16(in4, sign_in4); 613ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in5 = _mm_sub_epi16(in5, sign_in5); 614ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in6 = _mm_sub_epi16(in6, sign_in6); 615ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in7 = _mm_sub_epi16(in7, sign_in7); 616ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in0 = _mm_srai_epi16(in0, 1); 617ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in1 = _mm_srai_epi16(in1, 1); 618ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in2 = _mm_srai_epi16(in2, 1); 619ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in3 = _mm_srai_epi16(in3, 1); 620ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in4 = _mm_srai_epi16(in4, 1); 621ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in5 = _mm_srai_epi16(in5, 1); 622ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in6 = _mm_srai_epi16(in6, 1); 623ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang in7 = _mm_srai_epi16(in7, 1); 624ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // store results 62591037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 0 * 8), in0); 62691037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 1 * 8), in1); 62791037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 2 * 8), in2); 62891037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 3 * 8), in3); 62991037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 4 * 8), in4); 63091037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 5 * 8), in5); 63191037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 6 * 8), in6); 63291037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 7 * 8), in7); 63391037db265ecdd914a26e056cf69207b4f50924ehkuang } 63491037db265ecdd914a26e056cf69207b4f50924ehkuang} 63591037db265ecdd914a26e056cf69207b4f50924ehkuang 63691037db265ecdd914a26e056cf69207b4f50924ehkuang// load 8x8 array 6375ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangstatic INLINE void load_buffer_8x8(const int16_t *input, __m128i *in, 6385ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang int stride) { 6395ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang in[0] = _mm_load_si128((const __m128i *)(input + 0 * stride)); 6405ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang in[1] = _mm_load_si128((const __m128i *)(input + 1 * stride)); 6415ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang in[2] = _mm_load_si128((const __m128i *)(input + 2 * stride)); 6425ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang in[3] = _mm_load_si128((const __m128i *)(input + 3 * stride)); 6435ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang in[4] = _mm_load_si128((const __m128i *)(input + 4 * stride)); 6445ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang in[5] = _mm_load_si128((const __m128i *)(input + 5 * stride)); 6455ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang in[6] = _mm_load_si128((const __m128i *)(input + 6 * stride)); 6465ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang in[7] = _mm_load_si128((const __m128i *)(input + 7 * stride)); 64791037db265ecdd914a26e056cf69207b4f50924ehkuang 64891037db265ecdd914a26e056cf69207b4f50924ehkuang in[0] = _mm_slli_epi16(in[0], 2); 64991037db265ecdd914a26e056cf69207b4f50924ehkuang in[1] = _mm_slli_epi16(in[1], 2); 65091037db265ecdd914a26e056cf69207b4f50924ehkuang in[2] = _mm_slli_epi16(in[2], 2); 65191037db265ecdd914a26e056cf69207b4f50924ehkuang in[3] = _mm_slli_epi16(in[3], 2); 65291037db265ecdd914a26e056cf69207b4f50924ehkuang in[4] = _mm_slli_epi16(in[4], 2); 65391037db265ecdd914a26e056cf69207b4f50924ehkuang in[5] = _mm_slli_epi16(in[5], 2); 65491037db265ecdd914a26e056cf69207b4f50924ehkuang in[6] = _mm_slli_epi16(in[6], 2); 65591037db265ecdd914a26e056cf69207b4f50924ehkuang in[7] = _mm_slli_epi16(in[7], 2); 65691037db265ecdd914a26e056cf69207b4f50924ehkuang} 65791037db265ecdd914a26e056cf69207b4f50924ehkuang 65891037db265ecdd914a26e056cf69207b4f50924ehkuang// right shift and rounding 65991037db265ecdd914a26e056cf69207b4f50924ehkuangstatic INLINE void right_shift_8x8(__m128i *res, int const bit) { 66091037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i kOne = _mm_set1_epi16(1); 66191037db265ecdd914a26e056cf69207b4f50924ehkuang const int bit_m02 = bit - 2; 66291037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i sign0 = _mm_srai_epi16(res[0], 15); 66391037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i sign1 = _mm_srai_epi16(res[1], 15); 66491037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i sign2 = _mm_srai_epi16(res[2], 15); 66591037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i sign3 = _mm_srai_epi16(res[3], 15); 66691037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i sign4 = _mm_srai_epi16(res[4], 15); 66791037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i sign5 = _mm_srai_epi16(res[5], 15); 66891037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i sign6 = _mm_srai_epi16(res[6], 15); 66991037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i sign7 = _mm_srai_epi16(res[7], 15); 67091037db265ecdd914a26e056cf69207b4f50924ehkuang 67191037db265ecdd914a26e056cf69207b4f50924ehkuang if (bit_m02 >= 0) { 67291037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i k_const_rounding = _mm_slli_epi16(kOne, bit_m02); 67391037db265ecdd914a26e056cf69207b4f50924ehkuang res[0] = _mm_add_epi16(res[0], k_const_rounding); 67491037db265ecdd914a26e056cf69207b4f50924ehkuang res[1] = _mm_add_epi16(res[1], k_const_rounding); 67591037db265ecdd914a26e056cf69207b4f50924ehkuang res[2] = _mm_add_epi16(res[2], k_const_rounding); 67691037db265ecdd914a26e056cf69207b4f50924ehkuang res[3] = _mm_add_epi16(res[3], k_const_rounding); 67791037db265ecdd914a26e056cf69207b4f50924ehkuang res[4] = _mm_add_epi16(res[4], k_const_rounding); 67891037db265ecdd914a26e056cf69207b4f50924ehkuang res[5] = _mm_add_epi16(res[5], k_const_rounding); 67991037db265ecdd914a26e056cf69207b4f50924ehkuang res[6] = _mm_add_epi16(res[6], k_const_rounding); 68091037db265ecdd914a26e056cf69207b4f50924ehkuang res[7] = _mm_add_epi16(res[7], k_const_rounding); 68191037db265ecdd914a26e056cf69207b4f50924ehkuang } 68291037db265ecdd914a26e056cf69207b4f50924ehkuang 68391037db265ecdd914a26e056cf69207b4f50924ehkuang res[0] = _mm_sub_epi16(res[0], sign0); 68491037db265ecdd914a26e056cf69207b4f50924ehkuang res[1] = _mm_sub_epi16(res[1], sign1); 68591037db265ecdd914a26e056cf69207b4f50924ehkuang res[2] = _mm_sub_epi16(res[2], sign2); 68691037db265ecdd914a26e056cf69207b4f50924ehkuang res[3] = _mm_sub_epi16(res[3], sign3); 68791037db265ecdd914a26e056cf69207b4f50924ehkuang res[4] = _mm_sub_epi16(res[4], sign4); 68891037db265ecdd914a26e056cf69207b4f50924ehkuang res[5] = _mm_sub_epi16(res[5], sign5); 68991037db265ecdd914a26e056cf69207b4f50924ehkuang res[6] = _mm_sub_epi16(res[6], sign6); 69091037db265ecdd914a26e056cf69207b4f50924ehkuang res[7] = _mm_sub_epi16(res[7], sign7); 69191037db265ecdd914a26e056cf69207b4f50924ehkuang 69291037db265ecdd914a26e056cf69207b4f50924ehkuang res[0] = _mm_srai_epi16(res[0], bit); 69391037db265ecdd914a26e056cf69207b4f50924ehkuang res[1] = _mm_srai_epi16(res[1], bit); 69491037db265ecdd914a26e056cf69207b4f50924ehkuang res[2] = _mm_srai_epi16(res[2], bit); 69591037db265ecdd914a26e056cf69207b4f50924ehkuang res[3] = _mm_srai_epi16(res[3], bit); 69691037db265ecdd914a26e056cf69207b4f50924ehkuang res[4] = _mm_srai_epi16(res[4], bit); 69791037db265ecdd914a26e056cf69207b4f50924ehkuang res[5] = _mm_srai_epi16(res[5], bit); 69891037db265ecdd914a26e056cf69207b4f50924ehkuang res[6] = _mm_srai_epi16(res[6], bit); 69991037db265ecdd914a26e056cf69207b4f50924ehkuang res[7] = _mm_srai_epi16(res[7], bit); 70091037db265ecdd914a26e056cf69207b4f50924ehkuang} 70191037db265ecdd914a26e056cf69207b4f50924ehkuang 70291037db265ecdd914a26e056cf69207b4f50924ehkuang// write 8x8 array 70391037db265ecdd914a26e056cf69207b4f50924ehkuangstatic INLINE void write_buffer_8x8(int16_t *output, __m128i *res, int stride) { 70491037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 0 * stride), res[0]); 70591037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 1 * stride), res[1]); 70691037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 2 * stride), res[2]); 70791037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 3 * stride), res[3]); 70891037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 4 * stride), res[4]); 70991037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 5 * stride), res[5]); 71091037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 6 * stride), res[6]); 71191037db265ecdd914a26e056cf69207b4f50924ehkuang _mm_store_si128((__m128i *)(output + 7 * stride), res[7]); 71291037db265ecdd914a26e056cf69207b4f50924ehkuang} 71391037db265ecdd914a26e056cf69207b4f50924ehkuang 71491037db265ecdd914a26e056cf69207b4f50924ehkuang// perform in-place transpose 71591037db265ecdd914a26e056cf69207b4f50924ehkuangstatic INLINE void array_transpose_8x8(__m128i *in, __m128i *res) { 71691037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr0_0 = _mm_unpacklo_epi16(in[0], in[1]); 71791037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr0_1 = _mm_unpacklo_epi16(in[2], in[3]); 71891037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr0_2 = _mm_unpackhi_epi16(in[0], in[1]); 71991037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr0_3 = _mm_unpackhi_epi16(in[2], in[3]); 72091037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr0_4 = _mm_unpacklo_epi16(in[4], in[5]); 72191037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr0_5 = _mm_unpacklo_epi16(in[6], in[7]); 72291037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr0_6 = _mm_unpackhi_epi16(in[4], in[5]); 72391037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr0_7 = _mm_unpackhi_epi16(in[6], in[7]); 72491037db265ecdd914a26e056cf69207b4f50924ehkuang // 00 10 01 11 02 12 03 13 72591037db265ecdd914a26e056cf69207b4f50924ehkuang // 20 30 21 31 22 32 23 33 72691037db265ecdd914a26e056cf69207b4f50924ehkuang // 04 14 05 15 06 16 07 17 72791037db265ecdd914a26e056cf69207b4f50924ehkuang // 24 34 25 35 26 36 27 37 72891037db265ecdd914a26e056cf69207b4f50924ehkuang // 40 50 41 51 42 52 43 53 72991037db265ecdd914a26e056cf69207b4f50924ehkuang // 60 70 61 71 62 72 63 73 73091037db265ecdd914a26e056cf69207b4f50924ehkuang // 44 54 45 55 46 56 47 57 73191037db265ecdd914a26e056cf69207b4f50924ehkuang // 64 74 65 75 66 76 67 77 73291037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr1_0 = _mm_unpacklo_epi32(tr0_0, tr0_1); 73391037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr1_1 = _mm_unpacklo_epi32(tr0_4, tr0_5); 73491037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr1_2 = _mm_unpackhi_epi32(tr0_0, tr0_1); 73591037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr1_3 = _mm_unpackhi_epi32(tr0_4, tr0_5); 73691037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr1_4 = _mm_unpacklo_epi32(tr0_2, tr0_3); 73791037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr1_5 = _mm_unpacklo_epi32(tr0_6, tr0_7); 73891037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr1_6 = _mm_unpackhi_epi32(tr0_2, tr0_3); 73991037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i tr1_7 = _mm_unpackhi_epi32(tr0_6, tr0_7); 74091037db265ecdd914a26e056cf69207b4f50924ehkuang // 00 10 20 30 01 11 21 31 74191037db265ecdd914a26e056cf69207b4f50924ehkuang // 40 50 60 70 41 51 61 71 74291037db265ecdd914a26e056cf69207b4f50924ehkuang // 02 12 22 32 03 13 23 33 74391037db265ecdd914a26e056cf69207b4f50924ehkuang // 42 52 62 72 43 53 63 73 74491037db265ecdd914a26e056cf69207b4f50924ehkuang // 04 14 24 34 05 15 25 35 74591037db265ecdd914a26e056cf69207b4f50924ehkuang // 44 54 64 74 45 55 65 75 74691037db265ecdd914a26e056cf69207b4f50924ehkuang // 06 16 26 36 07 17 27 37 74791037db265ecdd914a26e056cf69207b4f50924ehkuang // 46 56 66 76 47 57 67 77 74891037db265ecdd914a26e056cf69207b4f50924ehkuang res[0] = _mm_unpacklo_epi64(tr1_0, tr1_1); 74991037db265ecdd914a26e056cf69207b4f50924ehkuang res[1] = _mm_unpackhi_epi64(tr1_0, tr1_1); 75091037db265ecdd914a26e056cf69207b4f50924ehkuang res[2] = _mm_unpacklo_epi64(tr1_2, tr1_3); 75191037db265ecdd914a26e056cf69207b4f50924ehkuang res[3] = _mm_unpackhi_epi64(tr1_2, tr1_3); 75291037db265ecdd914a26e056cf69207b4f50924ehkuang res[4] = _mm_unpacklo_epi64(tr1_4, tr1_5); 75391037db265ecdd914a26e056cf69207b4f50924ehkuang res[5] = _mm_unpackhi_epi64(tr1_4, tr1_5); 75491037db265ecdd914a26e056cf69207b4f50924ehkuang res[6] = _mm_unpacklo_epi64(tr1_6, tr1_7); 75591037db265ecdd914a26e056cf69207b4f50924ehkuang res[7] = _mm_unpackhi_epi64(tr1_6, tr1_7); 75691037db265ecdd914a26e056cf69207b4f50924ehkuang // 00 10 20 30 40 50 60 70 75791037db265ecdd914a26e056cf69207b4f50924ehkuang // 01 11 21 31 41 51 61 71 75891037db265ecdd914a26e056cf69207b4f50924ehkuang // 02 12 22 32 42 52 62 72 75991037db265ecdd914a26e056cf69207b4f50924ehkuang // 03 13 23 33 43 53 63 73 76091037db265ecdd914a26e056cf69207b4f50924ehkuang // 04 14 24 34 44 54 64 74 76191037db265ecdd914a26e056cf69207b4f50924ehkuang // 05 15 25 35 45 55 65 75 76291037db265ecdd914a26e056cf69207b4f50924ehkuang // 06 16 26 36 46 56 66 76 76391037db265ecdd914a26e056cf69207b4f50924ehkuang // 07 17 27 37 47 57 67 77 76491037db265ecdd914a26e056cf69207b4f50924ehkuang} 76591037db265ecdd914a26e056cf69207b4f50924ehkuang 766b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianvoid fdct8_sse2(__m128i *in) { 76791037db265ecdd914a26e056cf69207b4f50924ehkuang // constants 76891037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__cospi_p16_p16 = _mm_set1_epi16(cospi_16_64); 76991037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__cospi_p16_m16 = pair_set_epi16(cospi_16_64, -cospi_16_64); 77091037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__cospi_p24_p08 = pair_set_epi16(cospi_24_64, cospi_8_64); 77191037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__cospi_m08_p24 = pair_set_epi16(-cospi_8_64, cospi_24_64); 77291037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__cospi_p28_p04 = pair_set_epi16(cospi_28_64, cospi_4_64); 77391037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__cospi_m04_p28 = pair_set_epi16(-cospi_4_64, cospi_28_64); 77491037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__cospi_p12_p20 = pair_set_epi16(cospi_12_64, cospi_20_64); 77591037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__cospi_m20_p12 = pair_set_epi16(-cospi_20_64, cospi_12_64); 77691037db265ecdd914a26e056cf69207b4f50924ehkuang const __m128i k__DCT_CONST_ROUNDING = _mm_set1_epi32(DCT_CONST_ROUNDING); 77791037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i u0, u1, u2, u3, u4, u5, u6, u7; 77891037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i v0, v1, v2, v3, v4, v5, v6, v7; 77991037db265ecdd914a26e056cf69207b4f50924ehkuang __m128i s0, s1, s2, s3, s4, s5, s6, s7; 78091037db265ecdd914a26e056cf69207b4f50924ehkuang 78191037db265ecdd914a26e056cf69207b4f50924ehkuang // stage 1 78291037db265ecdd914a26e056cf69207b4f50924ehkuang s0 = _mm_add_epi16(in[0], in[7]); 78391037db265ecdd914a26e056cf69207b4f50924ehkuang s1 = _mm_add_epi16(in[1], in[6]); 78491037db265ecdd914a26e056cf69207b4f50924ehkuang s2 = _mm_add_epi16(in[2], in[5]); 78591037db265ecdd914a26e056cf69207b4f50924ehkuang s3 = _mm_add_epi16(in[3], in[4]); 78691037db265ecdd914a26e056cf69207b4f50924ehkuang s4 = _mm_sub_epi16(in[3], in[4]); 78791037db265ecdd914a26e056cf69207b4f50924ehkuang s5 = _mm_sub_epi16(in[2], in[5]); 78891037db265ecdd914a26e056cf69207b4f50924ehkuang s6 = _mm_sub_epi16(in[1], in[6]); 78991037db265ecdd914a26e056cf69207b4f50924ehkuang s7 = _mm_sub_epi16(in[0], in[7]); 79091037db265ecdd914a26e056cf69207b4f50924ehkuang 79191037db265ecdd914a26e056cf69207b4f50924ehkuang u0 = _mm_add_epi16(s0, s3); 79291037db265ecdd914a26e056cf69207b4f50924ehkuang u1 = _mm_add_epi16(s1, s2); 79391037db265ecdd914a26e056cf69207b4f50924ehkuang u2 = _mm_sub_epi16(s1, s2); 79491037db265ecdd914a26e056cf69207b4f50924ehkuang u3 = _mm_sub_epi16(s0, s3); 79591037db265ecdd914a26e056cf69207b4f50924ehkuang // interleave and perform butterfly multiplication/addition 796