github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/image/webp/libwebp/src/dsp/enc_neon.c (about)

     1  // Copyright 2012 Google Inc. All Rights Reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style license
     4  // that can be found in the COPYING file in the root of the source
     5  // tree. An additional intellectual property rights grant can be found
     6  // in the file PATENTS. All contributing project authors may
     7  // be found in the AUTHORS file in the root of the source tree.
     8  // -----------------------------------------------------------------------------
     9  //
    10  // ARM NEON version of speed-critical encoding functions.
    11  //
    12  // adapted from libvpx (http://www.webmproject.org/code/)
    13  
    14  #include "./dsp.h"
    15  
    16  #if defined(WEBP_USE_NEON)
    17  
    18  #include "../enc/vp8enci.h"
    19  
    20  //------------------------------------------------------------------------------
    21  // Transforms (Paragraph 14.4)
    22  
    23  // Inverse transform.
    24  // This code is pretty much the same as TransformOneNEON in the decoder, except
    25  // for subtraction to *ref. See the comments there for algorithmic explanations.
    26  static void ITransformOne(const uint8_t* ref,
    27                            const int16_t* in, uint8_t* dst) {
    28    const int kBPS = BPS;
    29    const int16_t kC1C2[] = { 20091, 17734, 0, 0 };  // kC1 / (kC2 >> 1) / 0 / 0
    30  
    31    __asm__ volatile (
    32      "vld1.16         {q1, q2}, [%[in]]           \n"
    33      "vld1.16         {d0}, [%[kC1C2]]            \n"
    34  
    35      // d2: in[0]
    36      // d3: in[8]
    37      // d4: in[4]
    38      // d5: in[12]
    39      "vswp            d3, d4                      \n"
    40  
    41      // q8 = {in[4], in[12]} * kC1 * 2 >> 16
    42      // q9 = {in[4], in[12]} * kC2 >> 16
    43      "vqdmulh.s16     q8, q2, d0[0]               \n"
    44      "vqdmulh.s16     q9, q2, d0[1]               \n"
    45  
    46      // d22 = a = in[0] + in[8]
    47      // d23 = b = in[0] - in[8]
    48      "vqadd.s16       d22, d2, d3                 \n"
    49      "vqsub.s16       d23, d2, d3                 \n"
    50  
    51      //  q8 = in[4]/[12] * kC1 >> 16
    52      "vshr.s16        q8, q8, #1                  \n"
    53  
    54      // Add {in[4], in[12]} back after the multiplication.
    55      "vqadd.s16       q8, q2, q8                  \n"
    56  
    57      // d20 = c = in[4]*kC2 - in[12]*kC1
    58      // d21 = d = in[4]*kC1 + in[12]*kC2
    59      "vqsub.s16       d20, d18, d17               \n"
    60      "vqadd.s16       d21, d19, d16               \n"
    61  
    62      // d2 = tmp[0] = a + d
    63      // d3 = tmp[1] = b + c
    64      // d4 = tmp[2] = b - c
    65      // d5 = tmp[3] = a - d
    66      "vqadd.s16       d2, d22, d21                \n"
    67      "vqadd.s16       d3, d23, d20                \n"
    68      "vqsub.s16       d4, d23, d20                \n"
    69      "vqsub.s16       d5, d22, d21                \n"
    70  
    71      "vzip.16         q1, q2                      \n"
    72      "vzip.16         q1, q2                      \n"
    73  
    74      "vswp            d3, d4                      \n"
    75  
    76      // q8 = {tmp[4], tmp[12]} * kC1 * 2 >> 16
    77      // q9 = {tmp[4], tmp[12]} * kC2 >> 16
    78      "vqdmulh.s16     q8, q2, d0[0]               \n"
    79      "vqdmulh.s16     q9, q2, d0[1]               \n"
    80  
    81      // d22 = a = tmp[0] + tmp[8]
    82      // d23 = b = tmp[0] - tmp[8]
    83      "vqadd.s16       d22, d2, d3                 \n"
    84      "vqsub.s16       d23, d2, d3                 \n"
    85  
    86      "vshr.s16        q8, q8, #1                  \n"
    87      "vqadd.s16       q8, q2, q8                  \n"
    88  
    89      // d20 = c = in[4]*kC2 - in[12]*kC1
    90      // d21 = d = in[4]*kC1 + in[12]*kC2
    91      "vqsub.s16       d20, d18, d17               \n"
    92      "vqadd.s16       d21, d19, d16               \n"
    93  
    94      // d2 = tmp[0] = a + d
    95      // d3 = tmp[1] = b + c
    96      // d4 = tmp[2] = b - c
    97      // d5 = tmp[3] = a - d
    98      "vqadd.s16       d2, d22, d21                \n"
    99      "vqadd.s16       d3, d23, d20                \n"
   100      "vqsub.s16       d4, d23, d20                \n"
   101      "vqsub.s16       d5, d22, d21                \n"
   102  
   103      "vld1.32         d6[0], [%[ref]], %[kBPS]    \n"
   104      "vld1.32         d6[1], [%[ref]], %[kBPS]    \n"
   105      "vld1.32         d7[0], [%[ref]], %[kBPS]    \n"
   106      "vld1.32         d7[1], [%[ref]], %[kBPS]    \n"
   107  
   108      "sub         %[ref], %[ref], %[kBPS], lsl #2 \n"
   109  
   110      // (val) + 4 >> 3
   111      "vrshr.s16       d2, d2, #3                  \n"
   112      "vrshr.s16       d3, d3, #3                  \n"
   113      "vrshr.s16       d4, d4, #3                  \n"
   114      "vrshr.s16       d5, d5, #3                  \n"
   115  
   116      "vzip.16         q1, q2                      \n"
   117      "vzip.16         q1, q2                      \n"
   118  
   119      // Must accumulate before saturating
   120      "vmovl.u8        q8, d6                      \n"
   121      "vmovl.u8        q9, d7                      \n"
   122  
   123      "vqadd.s16       q1, q1, q8                  \n"
   124      "vqadd.s16       q2, q2, q9                  \n"
   125  
   126      "vqmovun.s16     d0, q1                      \n"
   127      "vqmovun.s16     d1, q2                      \n"
   128  
   129      "vst1.32         d0[0], [%[dst]], %[kBPS]    \n"
   130      "vst1.32         d0[1], [%[dst]], %[kBPS]    \n"
   131      "vst1.32         d1[0], [%[dst]], %[kBPS]    \n"
   132      "vst1.32         d1[1], [%[dst]]             \n"
   133  
   134      : [in] "+r"(in), [dst] "+r"(dst)               // modified registers
   135      : [kBPS] "r"(kBPS), [kC1C2] "r"(kC1C2), [ref] "r"(ref)  // constants
   136      : "memory", "q0", "q1", "q2", "q8", "q9", "q10", "q11"  // clobbered
   137    );
   138  }
   139  
   140  static void ITransform(const uint8_t* ref,
   141                         const int16_t* in, uint8_t* dst, int do_two) {
   142    ITransformOne(ref, in, dst);
   143    if (do_two) {
   144      ITransformOne(ref + 4, in + 16, dst + 4);
   145    }
   146  }
   147  
   148  // Same code as dec_neon.c
   149  static void ITransformWHT(const int16_t* in, int16_t* out) {
   150    const int kStep = 32;  // The store is only incrementing the pointer as if we
   151                           // had stored a single byte.
   152    __asm__ volatile (
   153      // part 1
   154      // load data into q0, q1
   155      "vld1.16         {q0, q1}, [%[in]]           \n"
   156  
   157      "vaddl.s16       q2, d0, d3                  \n" // a0 = in[0] + in[12]
   158      "vaddl.s16       q3, d1, d2                  \n" // a1 = in[4] + in[8]
   159      "vsubl.s16       q4, d1, d2                  \n" // a2 = in[4] - in[8]
   160      "vsubl.s16       q5, d0, d3                  \n" // a3 = in[0] - in[12]
   161  
   162      "vadd.s32        q0, q2, q3                  \n" // tmp[0] = a0 + a1
   163      "vsub.s32        q2, q2, q3                  \n" // tmp[8] = a0 - a1
   164      "vadd.s32        q1, q5, q4                  \n" // tmp[4] = a3 + a2
   165      "vsub.s32        q3, q5, q4                  \n" // tmp[12] = a3 - a2
   166  
   167      // Transpose
   168      // q0 = tmp[0, 4, 8, 12], q1 = tmp[2, 6, 10, 14]
   169      // q2 = tmp[1, 5, 9, 13], q3 = tmp[3, 7, 11, 15]
   170      "vswp            d1, d4                      \n" // vtrn.64 q0, q2
   171      "vswp            d3, d6                      \n" // vtrn.64 q1, q3
   172      "vtrn.32         q0, q1                      \n"
   173      "vtrn.32         q2, q3                      \n"
   174  
   175      "vmov.s32        q4, #3                      \n" // dc = 3
   176      "vadd.s32        q0, q0, q4                  \n" // dc = tmp[0] + 3
   177      "vadd.s32        q6, q0, q3                  \n" // a0 = dc + tmp[3]
   178      "vadd.s32        q7, q1, q2                  \n" // a1 = tmp[1] + tmp[2]
   179      "vsub.s32        q8, q1, q2                  \n" // a2 = tmp[1] - tmp[2]
   180      "vsub.s32        q9, q0, q3                  \n" // a3 = dc - tmp[3]
   181  
   182      "vadd.s32        q0, q6, q7                  \n"
   183      "vshrn.s32       d0, q0, #3                  \n" // (a0 + a1) >> 3
   184      "vadd.s32        q1, q9, q8                  \n"
   185      "vshrn.s32       d1, q1, #3                  \n" // (a3 + a2) >> 3
   186      "vsub.s32        q2, q6, q7                  \n"
   187      "vshrn.s32       d2, q2, #3                  \n" // (a0 - a1) >> 3
   188      "vsub.s32        q3, q9, q8                  \n"
   189      "vshrn.s32       d3, q3, #3                  \n" // (a3 - a2) >> 3
   190  
   191      // set the results to output
   192      "vst1.16         d0[0], [%[out]], %[kStep]      \n"
   193      "vst1.16         d1[0], [%[out]], %[kStep]      \n"
   194      "vst1.16         d2[0], [%[out]], %[kStep]      \n"
   195      "vst1.16         d3[0], [%[out]], %[kStep]      \n"
   196      "vst1.16         d0[1], [%[out]], %[kStep]      \n"
   197      "vst1.16         d1[1], [%[out]], %[kStep]      \n"
   198      "vst1.16         d2[1], [%[out]], %[kStep]      \n"
   199      "vst1.16         d3[1], [%[out]], %[kStep]      \n"
   200      "vst1.16         d0[2], [%[out]], %[kStep]      \n"
   201      "vst1.16         d1[2], [%[out]], %[kStep]      \n"
   202      "vst1.16         d2[2], [%[out]], %[kStep]      \n"
   203      "vst1.16         d3[2], [%[out]], %[kStep]      \n"
   204      "vst1.16         d0[3], [%[out]], %[kStep]      \n"
   205      "vst1.16         d1[3], [%[out]], %[kStep]      \n"
   206      "vst1.16         d2[3], [%[out]], %[kStep]      \n"
   207      "vst1.16         d3[3], [%[out]], %[kStep]      \n"
   208  
   209      : [out] "+r"(out)  // modified registers
   210      : [in] "r"(in), [kStep] "r"(kStep)  // constants
   211      : "memory", "q0", "q1", "q2", "q3", "q4",
   212        "q5", "q6", "q7", "q8", "q9" // clobbered
   213    );
   214  }
   215  
   216  // Forward transform.
   217  
   218  // adapted from vp8/encoder/arm/neon/shortfdct_neon.asm
   219  static const int16_t kCoeff16[] = {
   220    5352,  5352,  5352, 5352, 2217,  2217,  2217, 2217
   221  };
   222  static const int32_t kCoeff32[] = {
   223     1812,  1812,  1812,  1812,
   224      937,   937,   937,   937,
   225    12000, 12000, 12000, 12000,
   226    51000, 51000, 51000, 51000
   227  };
   228  
   229  static void FTransform(const uint8_t* src, const uint8_t* ref,
   230                         int16_t* out) {
   231    const int kBPS = BPS;
   232    const uint8_t* src_ptr = src;
   233    const uint8_t* ref_ptr = ref;
   234    const int16_t* coeff16 = kCoeff16;
   235    const int32_t* coeff32 = kCoeff32;
   236  
   237    __asm__ volatile (
   238      // load src into q4, q5 in high half
   239      "vld1.8 {d8},  [%[src_ptr]], %[kBPS]      \n"
   240      "vld1.8 {d10}, [%[src_ptr]], %[kBPS]      \n"
   241      "vld1.8 {d9},  [%[src_ptr]], %[kBPS]      \n"
   242      "vld1.8 {d11}, [%[src_ptr]]               \n"
   243  
   244      // load ref into q6, q7 in high half
   245      "vld1.8 {d12}, [%[ref_ptr]], %[kBPS]      \n"
   246      "vld1.8 {d14}, [%[ref_ptr]], %[kBPS]      \n"
   247      "vld1.8 {d13}, [%[ref_ptr]], %[kBPS]      \n"
   248      "vld1.8 {d15}, [%[ref_ptr]]               \n"
   249  
   250      // Pack the high values in to q4 and q6
   251      "vtrn.32     q4, q5                       \n"
   252      "vtrn.32     q6, q7                       \n"
   253  
   254      // d[0-3] = src - ref
   255      "vsubl.u8    q0, d8, d12                  \n"
   256      "vsubl.u8    q1, d9, d13                  \n"
   257  
   258      // load coeff16 into q8(d16=5352, d17=2217)
   259      "vld1.16     {q8}, [%[coeff16]]           \n"
   260  
   261      // load coeff32 high half into q9 = 1812, q10 = 937
   262      "vld1.32     {q9, q10}, [%[coeff32]]!     \n"
   263  
   264      // load coeff32 low half into q11=12000, q12=51000
   265      "vld1.32     {q11,q12}, [%[coeff32]]      \n"
   266  
   267      // part 1
   268      // Transpose. Register dN is the same as dN in C
   269      "vtrn.32         d0, d2                   \n"
   270      "vtrn.32         d1, d3                   \n"
   271      "vtrn.16         d0, d1                   \n"
   272      "vtrn.16         d2, d3                   \n"
   273  
   274      "vadd.s16        d4, d0, d3               \n" // a0 = d0 + d3
   275      "vadd.s16        d5, d1, d2               \n" // a1 = d1 + d2
   276      "vsub.s16        d6, d1, d2               \n" // a2 = d1 - d2
   277      "vsub.s16        d7, d0, d3               \n" // a3 = d0 - d3
   278  
   279      "vadd.s16        d0, d4, d5               \n" // a0 + a1
   280      "vshl.s16        d0, d0, #3               \n" // temp[0+i*4] = (a0+a1) << 3
   281      "vsub.s16        d2, d4, d5               \n" // a0 - a1
   282      "vshl.s16        d2, d2, #3               \n" // (temp[2+i*4] = (a0-a1) << 3
   283  
   284      "vmlal.s16       q9, d7, d16              \n" // a3*5352 + 1812
   285      "vmlal.s16       q10, d7, d17             \n" // a3*2217 + 937
   286      "vmlal.s16       q9, d6, d17              \n" // a2*2217 + a3*5352 + 1812
   287      "vmlsl.s16       q10, d6, d16             \n" // a3*2217 + 937 - a2*5352
   288  
   289      // temp[1+i*4] = (d2*2217 + d3*5352 + 1812) >> 9
   290      // temp[3+i*4] = (d3*2217 + 937 - d2*5352) >> 9
   291      "vshrn.s32       d1, q9, #9               \n"
   292      "vshrn.s32       d3, q10, #9              \n"
   293  
   294      // part 2
   295      // transpose d0=ip[0], d1=ip[4], d2=ip[8], d3=ip[12]
   296      "vtrn.32         d0, d2                   \n"
   297      "vtrn.32         d1, d3                   \n"
   298      "vtrn.16         d0, d1                   \n"
   299      "vtrn.16         d2, d3                   \n"
   300  
   301      "vmov.s16        d26, #7                  \n"
   302  
   303      "vadd.s16        d4, d0, d3               \n" // a1 = ip[0] + ip[12]
   304      "vadd.s16        d5, d1, d2               \n" // b1 = ip[4] + ip[8]
   305      "vsub.s16        d6, d1, d2               \n" // c1 = ip[4] - ip[8]
   306      "vadd.s16        d4, d4, d26              \n" // a1 + 7
   307      "vsub.s16        d7, d0, d3               \n" // d1 = ip[0] - ip[12]
   308  
   309      "vadd.s16        d0, d4, d5               \n" // op[0] = a1 + b1 + 7
   310      "vsub.s16        d2, d4, d5               \n" // op[8] = a1 - b1 + 7
   311  
   312      "vmlal.s16       q11, d7, d16             \n" // d1*5352 + 12000
   313      "vmlal.s16       q12, d7, d17             \n" // d1*2217 + 51000
   314  
   315      "vceq.s16        d4, d7, #0               \n"
   316  
   317      "vshr.s16        d0, d0, #4               \n"
   318      "vshr.s16        d2, d2, #4               \n"
   319  
   320      "vmlal.s16       q11, d6, d17             \n" // c1*2217 + d1*5352 + 12000
   321      "vmlsl.s16       q12, d6, d16             \n" // d1*2217 - c1*5352 + 51000
   322  
   323      "vmvn            d4, d4                   \n" // !(d1 == 0)
   324      // op[4] = (c1*2217 + d1*5352 + 12000)>>16
   325      "vshrn.s32       d1, q11, #16             \n"
   326      // op[4] += (d1!=0)
   327      "vsub.s16        d1, d1, d4               \n"
   328      // op[12]= (d1*2217 - c1*5352 + 51000)>>16
   329      "vshrn.s32       d3, q12, #16             \n"
   330  
   331      // set result to out array
   332      "vst1.16         {q0, q1}, [%[out]]   \n"
   333      : [src_ptr] "+r"(src_ptr), [ref_ptr] "+r"(ref_ptr),
   334        [coeff32] "+r"(coeff32)          // modified registers
   335      : [kBPS] "r"(kBPS), [coeff16] "r"(coeff16),
   336        [out] "r"(out)                   // constants
   337      : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9",
   338        "q10", "q11", "q12", "q13"       // clobbered
   339    );
   340  }
   341  
   342  static void FTransformWHT(const int16_t* in, int16_t* out) {
   343    const int kStep = 32;
   344    __asm__ volatile (
   345      // d0 = in[0 * 16] , d1 = in[1 * 16]
   346      // d2 = in[2 * 16] , d3 = in[3 * 16]
   347      "vld1.16         d0[0], [%[in]], %[kStep]   \n"
   348      "vld1.16         d1[0], [%[in]], %[kStep]   \n"
   349      "vld1.16         d2[0], [%[in]], %[kStep]   \n"
   350      "vld1.16         d3[0], [%[in]], %[kStep]   \n"
   351      "vld1.16         d0[1], [%[in]], %[kStep]   \n"
   352      "vld1.16         d1[1], [%[in]], %[kStep]   \n"
   353      "vld1.16         d2[1], [%[in]], %[kStep]   \n"
   354      "vld1.16         d3[1], [%[in]], %[kStep]   \n"
   355      "vld1.16         d0[2], [%[in]], %[kStep]   \n"
   356      "vld1.16         d1[2], [%[in]], %[kStep]   \n"
   357      "vld1.16         d2[2], [%[in]], %[kStep]   \n"
   358      "vld1.16         d3[2], [%[in]], %[kStep]   \n"
   359      "vld1.16         d0[3], [%[in]], %[kStep]   \n"
   360      "vld1.16         d1[3], [%[in]], %[kStep]   \n"
   361      "vld1.16         d2[3], [%[in]], %[kStep]   \n"
   362      "vld1.16         d3[3], [%[in]], %[kStep]   \n"
   363  
   364      "vaddl.s16       q2, d0, d2                 \n" // a0=(in[0*16]+in[2*16])
   365      "vaddl.s16       q3, d1, d3                 \n" // a1=(in[1*16]+in[3*16])
   366      "vsubl.s16       q4, d1, d3                 \n" // a2=(in[1*16]-in[3*16])
   367      "vsubl.s16       q5, d0, d2                 \n" // a3=(in[0*16]-in[2*16])
   368  
   369      "vqadd.s32       q6, q2, q3                 \n" // a0 + a1
   370      "vqadd.s32       q7, q5, q4                 \n" // a3 + a2
   371      "vqsub.s32       q8, q5, q4                 \n" // a3 - a2
   372      "vqsub.s32       q9, q2, q3                 \n" // a0 - a1
   373  
   374      // Transpose
   375      // q6 = tmp[0, 1,  2,  3] ; q7 = tmp[ 4,  5,  6,  7]
   376      // q8 = tmp[8, 9, 10, 11] ; q9 = tmp[12, 13, 14, 15]
   377      "vswp            d13, d16                   \n" // vtrn.64 q0, q2
   378      "vswp            d15, d18                   \n" // vtrn.64 q1, q3
   379      "vtrn.32         q6, q7                     \n"
   380      "vtrn.32         q8, q9                     \n"
   381  
   382      "vqadd.s32       q0, q6, q8                 \n" // a0 = tmp[0] + tmp[8]
   383      "vqadd.s32       q1, q7, q9                 \n" // a1 = tmp[4] + tmp[12]
   384      "vqsub.s32       q2, q7, q9                 \n" // a2 = tmp[4] - tmp[12]
   385      "vqsub.s32       q3, q6, q8                 \n" // a3 = tmp[0] - tmp[8]
   386  
   387      "vqadd.s32       q4, q0, q1                 \n" // b0 = a0 + a1
   388      "vqadd.s32       q5, q3, q2                 \n" // b1 = a3 + a2
   389      "vqsub.s32       q6, q3, q2                 \n" // b2 = a3 - a2
   390      "vqsub.s32       q7, q0, q1                 \n" // b3 = a0 - a1
   391  
   392      "vshrn.s32       d18, q4, #1                \n" // b0 >> 1
   393      "vshrn.s32       d19, q5, #1                \n" // b1 >> 1
   394      "vshrn.s32       d20, q6, #1                \n" // b2 >> 1
   395      "vshrn.s32       d21, q7, #1                \n" // b3 >> 1
   396  
   397      "vst1.16         {q9, q10}, [%[out]]        \n"
   398  
   399      : [in] "+r"(in)
   400      : [kStep] "r"(kStep), [out] "r"(out)
   401      : "memory", "q0", "q1", "q2", "q3", "q4", "q5",
   402        "q6", "q7", "q8", "q9", "q10"       // clobbered
   403    ) ;
   404  }
   405  
   406  //------------------------------------------------------------------------------
   407  // Texture distortion
   408  //
   409  // We try to match the spectral content (weighted) between source and
   410  // reconstructed samples.
   411  
   412  // Hadamard transform
   413  // Returns the weighted sum of the absolute value of transformed coefficients.
   414  // This uses a TTransform helper function in C
   415  static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
   416                      const uint16_t* const w) {
   417    const int kBPS = BPS;
   418    const uint8_t* A = a;
   419    const uint8_t* B = b;
   420    const uint16_t* W = w;
   421    int sum;
   422    __asm__ volatile (
   423      "vld1.32         d0[0], [%[a]], %[kBPS]   \n"
   424      "vld1.32         d0[1], [%[a]], %[kBPS]   \n"
   425      "vld1.32         d2[0], [%[a]], %[kBPS]   \n"
   426      "vld1.32         d2[1], [%[a]]            \n"
   427  
   428      "vld1.32         d1[0], [%[b]], %[kBPS]   \n"
   429      "vld1.32         d1[1], [%[b]], %[kBPS]   \n"
   430      "vld1.32         d3[0], [%[b]], %[kBPS]   \n"
   431      "vld1.32         d3[1], [%[b]]            \n"
   432  
   433      // a d0/d2, b d1/d3
   434      // d0/d1: 01 01 01 01
   435      // d2/d3: 23 23 23 23
   436      // But: it goes 01 45 23 67
   437      // Notice the middle values are transposed
   438      "vtrn.16         q0, q1                   \n"
   439  
   440      // {a0, a1} = {in[0] + in[2], in[1] + in[3]}
   441      "vaddl.u8        q2, d0, d2               \n"
   442      "vaddl.u8        q10, d1, d3              \n"
   443      // {a3, a2} = {in[0] - in[2], in[1] - in[3]}
   444      "vsubl.u8        q3, d0, d2               \n"
   445      "vsubl.u8        q11, d1, d3              \n"
   446  
   447      // tmp[0] = a0 + a1
   448      "vpaddl.s16      q0, q2                   \n"
   449      "vpaddl.s16      q8, q10                  \n"
   450  
   451      // tmp[1] = a3 + a2
   452      "vpaddl.s16      q1, q3                   \n"
   453      "vpaddl.s16      q9, q11                  \n"
   454  
   455      // No pair subtract
   456      // q2 = {a0, a3}
   457      // q3 = {a1, a2}
   458      "vtrn.16         q2, q3                   \n"
   459      "vtrn.16         q10, q11                 \n"
   460  
   461      // {tmp[3], tmp[2]} = {a0 - a1, a3 - a2}
   462      "vsubl.s16       q12, d4, d6              \n"
   463      "vsubl.s16       q13, d5, d7              \n"
   464      "vsubl.s16       q14, d20, d22            \n"
   465      "vsubl.s16       q15, d21, d23            \n"
   466  
   467      // separate tmp[3] and tmp[2]
   468      // q12 = tmp[3]
   469      // q13 = tmp[2]
   470      "vtrn.32         q12, q13                 \n"
   471      "vtrn.32         q14, q15                 \n"
   472  
   473      // Transpose tmp for a
   474      "vswp            d1, d26                  \n" // vtrn.64
   475      "vswp            d3, d24                  \n" // vtrn.64
   476      "vtrn.32         q0, q1                   \n"
   477      "vtrn.32         q13, q12                 \n"
   478  
   479      // Transpose tmp for b
   480      "vswp            d17, d30                 \n" // vtrn.64
   481      "vswp            d19, d28                 \n" // vtrn.64
   482      "vtrn.32         q8, q9                   \n"
   483      "vtrn.32         q15, q14                 \n"
   484  
   485      // The first Q register is a, the second b.
   486      // q0/8 tmp[0-3]
   487      // q13/15 tmp[4-7]
   488      // q1/9 tmp[8-11]
   489      // q12/14 tmp[12-15]
   490  
   491      // These are still in 01 45 23 67 order. We fix it easily in the addition
   492      // case but the subtraction propagates them.
   493      "vswp            d3, d27                  \n"
   494      "vswp            d19, d31                 \n"
   495  
   496      // a0 = tmp[0] + tmp[8]
   497      "vadd.s32        q2, q0, q1               \n"
   498      "vadd.s32        q3, q8, q9               \n"
   499  
   500      // a1 = tmp[4] + tmp[12]
   501      "vadd.s32        q10, q13, q12            \n"
   502      "vadd.s32        q11, q15, q14            \n"
   503  
   504      // a2 = tmp[4] - tmp[12]
   505      "vsub.s32        q13, q13, q12            \n"
   506      "vsub.s32        q15, q15, q14            \n"
   507  
   508      // a3 = tmp[0] - tmp[8]
   509      "vsub.s32        q0, q0, q1               \n"
   510      "vsub.s32        q8, q8, q9               \n"
   511  
   512      // b0 = a0 + a1
   513      "vadd.s32        q1, q2, q10              \n"
   514      "vadd.s32        q9, q3, q11              \n"
   515  
   516      // b1 = a3 + a2
   517      "vadd.s32        q12, q0, q13             \n"
   518      "vadd.s32        q14, q8, q15             \n"
   519  
   520      // b2 = a3 - a2
   521      "vsub.s32        q0, q0, q13              \n"
   522      "vsub.s32        q8, q8, q15              \n"
   523  
   524      // b3 = a0 - a1
   525      "vsub.s32        q2, q2, q10              \n"
   526      "vsub.s32        q3, q3, q11              \n"
   527  
   528      "vld1.64         {q10, q11}, [%[w]]       \n"
   529  
   530      // abs(b0)
   531      "vabs.s32        q1, q1                   \n"
   532      "vabs.s32        q9, q9                   \n"
   533      // abs(b1)
   534      "vabs.s32        q12, q12                 \n"
   535      "vabs.s32        q14, q14                 \n"
   536      // abs(b2)
   537      "vabs.s32        q0, q0                   \n"
   538      "vabs.s32        q8, q8                   \n"
   539      // abs(b3)
   540      "vabs.s32        q2, q2                   \n"
   541      "vabs.s32        q3, q3                   \n"
   542  
   543      // expand w before using.
   544      "vmovl.u16       q13, d20                 \n"
   545      "vmovl.u16       q15, d21                 \n"
   546  
   547      // w[0] * abs(b0)
   548      "vmul.u32        q1, q1, q13              \n"
   549      "vmul.u32        q9, q9, q13              \n"
   550  
   551      // w[4] * abs(b1)
   552      "vmla.u32        q1, q12, q15             \n"
   553      "vmla.u32        q9, q14, q15             \n"
   554  
   555      // expand w before using.
   556      "vmovl.u16       q13, d22                 \n"
   557      "vmovl.u16       q15, d23                 \n"
   558  
   559      // w[8] * abs(b1)
   560      "vmla.u32        q1, q0, q13              \n"
   561      "vmla.u32        q9, q8, q13              \n"
   562  
   563      // w[12] * abs(b1)
   564      "vmla.u32        q1, q2, q15              \n"
   565      "vmla.u32        q9, q3, q15              \n"
   566  
   567      // Sum the arrays
   568      "vpaddl.u32      q1, q1                   \n"
   569      "vpaddl.u32      q9, q9                   \n"
   570      "vadd.u64        d2, d3                   \n"
   571      "vadd.u64        d18, d19                 \n"
   572  
   573      // Hadamard transform needs 4 bits of extra precision (2 bits in each
   574      // direction) for dynamic raw. Weights w[] are 16bits at max, so the maximum
   575      // precision for coeff is 8bit of input + 4bits of Hadamard transform +
   576      // 16bits for w[] + 2 bits of abs() summation.
   577      //
   578      // This uses a maximum of 31 bits (signed). Discarding the top 32 bits is
   579      // A-OK.
   580  
   581      // sum2 - sum1
   582      "vsub.u32        d0, d2, d18              \n"
   583      // abs(sum2 - sum1)
   584      "vabs.s32        d0, d0                   \n"
   585      // abs(sum2 - sum1) >> 5
   586      "vshr.u32        d0, #5                   \n"
   587  
   588      // It would be better to move the value straight into r0 but I'm not
   589      // entirely sure how this works with inline assembly.
   590      "vmov.32         %[sum], d0[0]            \n"
   591  
   592      : [sum] "=r"(sum), [a] "+r"(A), [b] "+r"(B), [w] "+r"(W)
   593      : [kBPS] "r"(kBPS)
   594      : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9",
   595        "q10", "q11", "q12", "q13", "q14", "q15"  // clobbered
   596    ) ;
   597  
   598    return sum;
   599  }
   600  
   601  static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
   602                        const uint16_t* const w) {
   603    int D = 0;
   604    int x, y;
   605    for (y = 0; y < 16 * BPS; y += 4 * BPS) {
   606      for (x = 0; x < 16; x += 4) {
   607        D += Disto4x4(a + x + y, b + x + y, w);
   608      }
   609    }
   610    return D;
   611  }
   612  
   613  #endif   // WEBP_USE_NEON
   614  
   615  //------------------------------------------------------------------------------
   616  // Entry point
   617  
   618  extern void VP8EncDspInitNEON(void);
   619  
   620  void VP8EncDspInitNEON(void) {
   621  #if defined(WEBP_USE_NEON)
   622    VP8ITransform = ITransform;
   623    VP8FTransform = FTransform;
   624  
   625    VP8ITransformWHT = ITransformWHT;
   626    VP8FTransformWHT = FTransformWHT;
   627  
   628    VP8TDisto4x4 = Disto4x4;
   629    VP8TDisto16x16 = Disto16x16;
   630  #endif   // WEBP_USE_NEON
   631  }
   632