15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 Google Inc. All Rights Reserved.
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// that can be found in the COPYING file in the root of the source
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// tree. An additional intellectual property rights grant can be found
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// in the file PATENTS. All contributing project authors may
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// be found in the AUTHORS file in the root of the source tree.
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// -----------------------------------------------------------------------------
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// MIPS version of lossless functions
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Author(s):  Djordje Pesut    (djordje.pesut@imgtec.com)
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//             Jovan Zelincevic (jovan.zelincevic@imgtec.com)
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "./dsp.h"
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "./lossless.h"
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(WEBP_USE_MIPS32)
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <assert.h>
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <math.h>
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <stdlib.h>
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <string.h>
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define APPROX_LOG_WITH_CORRECTION_MAX  65536
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define APPROX_LOG_MAX                   4096
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static float FastSLog2Slow(uint32_t v) {
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  assert(v >= LOG_LOOKUP_IDX_MAX);
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    uint32_t log_cnt, y, correction;
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const int c24 = 24;
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const float v_f = (float)v;
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    uint32_t temp;
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Xf = 256 = 2^8
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // log_cnt is index of leading one in upper 24 bits
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    __asm__ volatile(
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      "clz      %[log_cnt], %[v]                      \n\t"
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      "addiu    %[y],       $zero,        1           \n\t"
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      "subu     %[log_cnt], %[c24],       %[log_cnt]  \n\t"
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      "sllv     %[y],       %[y],         %[log_cnt]  \n\t"
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      "srlv     %[temp],    %[v],         %[log_cnt]  \n\t"
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      : [log_cnt]"=&r"(log_cnt), [y]"=&r"(y),
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        [temp]"=r"(temp)
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      : [c24]"r"(c24), [v]"r"(v)
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    );
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Xf = floor(Xf) * (1 + (v % y) / v)
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v)
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // The correction factor: log(1 + d) ~ d; for very small d values, so
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // LOG_2_RECIPROCAL ~ 23/16
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // (v % y) = (v % 2^log_cnt) = v & (2^log_cnt - 1)
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    correction = (23 * (v & (y - 1))) >> 4;
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return v_f * (kLog2Table[temp] + log_cnt) + correction;
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return (float)(LOG_2_RECIPROCAL * v * log((double)v));
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static float FastLog2Slow(uint32_t v) {
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  assert(v >= LOG_LOOKUP_IDX_MAX);
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    uint32_t log_cnt, y;
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const int c24 = 24;
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    double log_2;
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    uint32_t temp;
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    __asm__ volatile(
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      "clz      %[log_cnt], %[v]                      \n\t"
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      "addiu    %[y],       $zero,        1           \n\t"
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      "subu     %[log_cnt], %[c24],       %[log_cnt]  \n\t"
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      "sllv     %[y],       %[y],         %[log_cnt]  \n\t"
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      "srlv     %[temp],    %[v],         %[log_cnt]  \n\t"
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      : [log_cnt]"=&r"(log_cnt), [y]"=&r"(y),
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        [temp]"=r"(temp)
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      : [c24]"r"(c24), [v]"r"(v)
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    );
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    log_2 = kLog2Table[temp] + log_cnt;
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (v >= APPROX_LOG_MAX) {
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // Since the division is still expensive, add this correction factor only
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // for large values of 'v'.
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      const uint32_t correction = (23 * (v & (y - 1))) >> 4;
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      log_2 += (double)correction / v;
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return (float)log_2;
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return (float)(LOG_2_RECIPROCAL * log((double)v));
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// C version of this function:
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//   int i = 0;
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//   int64_t cost = 0;
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//   const uint32_t* pop = &population[4];
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//   const uint32_t* LoopEnd = &population[length];
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//   while (pop != LoopEnd) {
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//     ++i;
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//     cost += i * *pop;
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//     cost += i * *(pop + 1);
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//     pop += 2;
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//   }
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//   return (double)cost;
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static double ExtraCost(const uint32_t* const population, int length) {
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int i, temp0, temp1;
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const uint32_t* pop = &population[4];
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const uint32_t* const LoopEnd = &population[length];
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  __asm__ volatile(
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "mult   $zero,    $zero                  \n\t"
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "xor    %[i],     %[i],       %[i]       \n\t"
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "beq    %[pop],   %[LoopEnd], 2f         \n\t"
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  "1:                                        \n\t"
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "lw     %[temp0], 0(%[pop])              \n\t"
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "lw     %[temp1], 4(%[pop])              \n\t"
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addiu  %[i],     %[i],       1          \n\t"
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addiu  %[pop],   %[pop],     8          \n\t"
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "madd   %[i],     %[temp0]               \n\t"
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "madd   %[i],     %[temp1]               \n\t"
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "bne    %[pop],   %[LoopEnd], 1b         \n\t"
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  "2:                                        \n\t"
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "mfhi   %[temp0]                         \n\t"
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "mflo   %[temp1]                         \n\t"
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      [i]"=&r"(i), [pop]"+r"(pop)
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : [LoopEnd]"r"(LoopEnd)
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : "memory", "hi", "lo"
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  );
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return (double)((int64_t)temp0 << 32 | temp1);
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// C version of this function:
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//   int i = 0;
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//   int64_t cost = 0;
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//   const uint32_t* pX = &X[4];
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//   const uint32_t* pY = &Y[4];
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//   const uint32_t* LoopEnd = &X[length];
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//   while (pX != LoopEnd) {
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//     const uint32_t xy0 = *pX + *pY;
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//     const uint32_t xy1 = *(pX + 1) + *(pY + 1);
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//     ++i;
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//     cost += i * xy0;
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//     cost += i * xy1;
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//     pX += 2;
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//     pY += 2;
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//   }
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//   return (double)cost;
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static double ExtraCostCombined(const uint32_t* const X,
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                const uint32_t* const Y, int length) {
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int i, temp0, temp1, temp2, temp3;
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const uint32_t* pX = &X[4];
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const uint32_t* pY = &Y[4];
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const uint32_t* const LoopEnd = &X[length];
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  __asm__ volatile(
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "mult   $zero,    $zero                  \n\t"
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "xor    %[i],     %[i],       %[i]       \n\t"
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "beq    %[pX],    %[LoopEnd], 2f         \n\t"
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  "1:                                        \n\t"
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "lw     %[temp0], 0(%[pX])               \n\t"
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "lw     %[temp1], 0(%[pY])               \n\t"
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "lw     %[temp2], 4(%[pX])               \n\t"
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "lw     %[temp3], 4(%[pY])               \n\t"
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addiu  %[i],     %[i],       1          \n\t"
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addu   %[temp0], %[temp0],   %[temp1]   \n\t"
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addu   %[temp2], %[temp2],   %[temp3]   \n\t"
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addiu  %[pX],    %[pX],      8          \n\t"
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addiu  %[pY],    %[pY],      8          \n\t"
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "madd   %[i],     %[temp0]               \n\t"
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "madd   %[i],     %[temp2]               \n\t"
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "bne    %[pX],    %[LoopEnd], 1b         \n\t"
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  "2:                                        \n\t"
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "mfhi   %[temp0]                         \n\t"
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "mflo   %[temp1]                         \n\t"
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      [i]"=&r"(i), [pX]"+r"(pX), [pY]"+r"(pY)
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : [LoopEnd]"r"(LoopEnd)
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : "memory", "hi", "lo"
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  );
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return (double)((int64_t)temp0 << 32 | temp1);
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define HUFFMAN_COST_PASS                                 \
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  __asm__ volatile(                                       \
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "sll   %[temp1],  %[temp0],    3           \n\t"      \
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addiu %[temp3],  %[streak],   -3          \n\t"      \
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addu  %[temp2],  %[pstreaks], %[temp1]    \n\t"      \
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "blez  %[temp3],  1f                       \n\t"      \
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "srl   %[temp1],  %[temp1],    1           \n\t"      \
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addu  %[temp3],  %[pcnts],    %[temp1]    \n\t"      \
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "lw    %[temp0],  4(%[temp2])              \n\t"      \
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "lw    %[temp1],  0(%[temp3])              \n\t"      \
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addu  %[temp0],  %[temp0],    %[streak]   \n\t"      \
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addiu %[temp1],  %[temp1],    1           \n\t"      \
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "sw    %[temp0],  4(%[temp2])              \n\t"      \
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "sw    %[temp1],  0(%[temp3])              \n\t"      \
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "b     2f                                  \n\t"      \
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  "1:                                          \n\t"      \
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "lw    %[temp0],  0(%[temp2])              \n\t"      \
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addu  %[temp0],  %[temp0],    %[streak]   \n\t"      \
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "sw    %[temp0],  0(%[temp2])              \n\t"      \
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  "2:                                          \n\t"      \
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),           \
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      [temp3]"=&r"(temp3), [temp0]"+r"(temp0)             \
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : [pstreaks]"r"(pstreaks), [pcnts]"r"(pcnts),         \
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      [streak]"r"(streak)                                 \
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : "memory"                                            \
2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  );
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Returns the various RLE counts
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static VP8LStreaks HuffmanCostCount(const uint32_t* population, int length) {
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int i;
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int streak = 0;
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LStreaks stats;
2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int* const pstreaks = &stats.streaks[0][0];
2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int* const pcnts = &stats.counts[0];
2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int temp0, temp1, temp2, temp3;
2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  memset(&stats, 0, sizeof(stats));
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (i = 0; i < length - 1; ++i) {
2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ++streak;
2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (population[i] == population[i + 1]) {
2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      continue;
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    temp0 = (population[i] != 0);
2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    HUFFMAN_COST_PASS
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    streak = 0;
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ++streak;
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  temp0 = (population[i] != 0);
2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  HUFFMAN_COST_PASS
2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return stats;
2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static VP8LStreaks HuffmanCostCombinedCount(const uint32_t* X,
2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            const uint32_t* Y, int length) {
2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int i;
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int streak = 0;
2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LStreaks stats;
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int* const pstreaks = &stats.streaks[0][0];
2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int* const pcnts = &stats.counts[0];
2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int temp0, temp1, temp2, temp3;
2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  memset(&stats, 0, sizeof(stats));
2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (i = 0; i < length - 1; ++i) {
2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const uint32_t xy = X[i] + Y[i];
2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const uint32_t xy_next = X[i + 1] + Y[i + 1];
2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ++streak;
2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (xy == xy_next) {
2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      continue;
2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    temp0 = (xy != 0);
2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    HUFFMAN_COST_PASS
2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    streak = 0;
2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  {
2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const uint32_t xy = X[i] + Y[i];
2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ++streak;
2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    temp0 = (xy != 0);
2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    HUFFMAN_COST_PASS
2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return stats;
2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define ASM_START                                       \
2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  __asm__ volatile(                                     \
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ".set   push                            \n\t"       \
2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ".set   at                              \n\t"       \
2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ".set   macro                           \n\t"       \
2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  "1:                                       \n\t"
2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// P2 = P0 + P1
2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// A..D - offsets
2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// E - temp variable to tell macro
2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//     if pointer should be incremented
2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// literal_ and successive histograms could be unaligned
2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// so we must use ulw and usw
2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define ADD_TO_OUT(A, B, C, D, E, P0, P1, P2)           \
2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "ulw    %[temp0], "#A"(%["#P0"])        \n\t"       \
2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "ulw    %[temp1], "#B"(%["#P0"])        \n\t"       \
2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "ulw    %[temp2], "#C"(%["#P0"])        \n\t"       \
2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "ulw    %[temp3], "#D"(%["#P0"])        \n\t"       \
2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "ulw    %[temp4], "#A"(%["#P1"])        \n\t"       \
2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "ulw    %[temp5], "#B"(%["#P1"])        \n\t"       \
2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "ulw    %[temp6], "#C"(%["#P1"])        \n\t"       \
2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "ulw    %[temp7], "#D"(%["#P1"])        \n\t"       \
2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addu   %[temp4], %[temp4],   %[temp0]  \n\t"       \
2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addu   %[temp5], %[temp5],   %[temp1]  \n\t"       \
2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addu   %[temp6], %[temp6],   %[temp2]  \n\t"       \
2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addu   %[temp7], %[temp7],   %[temp3]  \n\t"       \
3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addiu  %["#P0"],  %["#P0"],  16        \n\t"       \
3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ".if "#E" == 1                            \n\t"       \
3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addiu  %["#P1"],  %["#P1"],  16        \n\t"       \
3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ".endif                                   \n\t"       \
3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "usw    %[temp4], "#A"(%["#P2"])        \n\t"       \
3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "usw    %[temp5], "#B"(%["#P2"])        \n\t"       \
3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "usw    %[temp6], "#C"(%["#P2"])        \n\t"       \
3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "usw    %[temp7], "#D"(%["#P2"])        \n\t"       \
3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "addiu  %["#P2"], %["#P2"],   16        \n\t"       \
3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    "bne    %["#P0"], %[LoopEnd], 1b        \n\t"       \
3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ".set   pop                             \n\t"       \
3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define ASM_END_COMMON_0                                \
3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),         \
3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),         \
3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),         \
3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      [temp6]"=&r"(temp6), [temp7]"=&r"(temp7),         \
3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      [pa]"+r"(pa), [pout]"+r"(pout)
3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define ASM_END_COMMON_1                                \
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : [LoopEnd]"r"(LoopEnd)                             \
3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : "memory", "at"                                    \
3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  );
3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define ASM_END_0                                       \
3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASM_END_COMMON_0                                    \
3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      , [pb]"+r"(pb)                                    \
3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASM_END_COMMON_1
3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define ASM_END_1                                       \
3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASM_END_COMMON_0                                    \
3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASM_END_COMMON_1
3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define ADD_VECTOR(A, B, OUT, SIZE, EXTRA_SIZE)  do {   \
3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const uint32_t* pa = (const uint32_t*)(A);            \
3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const uint32_t* pb = (const uint32_t*)(B);            \
3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  uint32_t* pout = (uint32_t*)(OUT);                    \
3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const uint32_t* const LoopEnd = pa + (SIZE);          \
3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  assert((SIZE) % 4 == 0);                              \
3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASM_START                                             \
3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout)              \
3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASM_END_0                                             \
3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if ((EXTRA_SIZE) > 0) {                               \
3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const int last = (EXTRA_SIZE);                      \
3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int i;                                              \
3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (i = 0; i < last; ++i) pout[i] = pa[i] + pb[i]; \
3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }                                                     \
3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} while (0)
3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define ADD_VECTOR_EQ(A, OUT, SIZE, EXTRA_SIZE)  do {   \
3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const uint32_t* pa = (const uint32_t*)(A);            \
3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  uint32_t* pout = (uint32_t*)(OUT);                    \
3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const uint32_t* const LoopEnd = pa + (SIZE);          \
3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  assert((SIZE) % 4 == 0);                              \
3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASM_START                                             \
3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout)            \
3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASM_END_1                                             \
3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if ((EXTRA_SIZE) > 0) {                               \
3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const int last = (EXTRA_SIZE);                      \
3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int i;                                              \
3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (i = 0; i < last; ++i) pout[i] += pa[i];        \
3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }                                                     \
3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} while (0)
3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void HistogramAdd(const VP8LHistogram* const a,
3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         const VP8LHistogram* const b,
3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         VP8LHistogram* const out) {
3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int extra_cache_size = VP8LHistogramNumCodes(a->palette_code_bits_)
3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             - (NUM_LITERAL_CODES + NUM_LENGTH_CODES);
3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  assert(a->palette_code_bits_ == b->palette_code_bits_);
3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (b != out) {
3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ADD_VECTOR(a->literal_, b->literal_, out->literal_,
3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size);
3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ADD_VECTOR(a->distance_, b->distance_, out->distance_,
3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               NUM_DISTANCE_CODES, 0);
3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ADD_VECTOR(a->red_, b->red_, out->red_, NUM_LITERAL_CODES, 0);
3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ADD_VECTOR(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES, 0);
3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ADD_VECTOR(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES, 0);
3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ADD_VECTOR_EQ(a->literal_, out->literal_,
3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size);
3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ADD_VECTOR_EQ(a->distance_, out->distance_, NUM_DISTANCE_CODES, 0);
3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ADD_VECTOR_EQ(a->red_, out->red_, NUM_LITERAL_CODES, 0);
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ADD_VECTOR_EQ(a->blue_, out->blue_, NUM_LITERAL_CODES, 0);
3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ADD_VECTOR_EQ(a->alpha_, out->alpha_, NUM_LITERAL_CODES, 0);
3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#undef ADD_VECTOR_EQ
3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#undef ADD_VECTOR
3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#undef ASM_END_1
3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#undef ASM_END_0
3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#undef ASM_END_COMMON_1
3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#undef ASM_END_COMMON_0
3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#undef ADD_TO_OUT
3975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#undef ASM_START
3985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif  // WEBP_USE_MIPS32
4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//------------------------------------------------------------------------------
4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Entry point
4035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)extern void VP8LDspInitMIPS32(void);
4055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void VP8LDspInitMIPS32(void) {
4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(WEBP_USE_MIPS32)
4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LFastSLog2Slow = FastSLog2Slow;
4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LFastLog2Slow = FastLog2Slow;
4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LExtraCost = ExtraCost;
4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LExtraCostCombined = ExtraCostCombined;
4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LHuffmanCostCount = HuffmanCostCount;
4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LHuffmanCostCombinedCount = HuffmanCostCombinedCount;
4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LHistogramAdd = HistogramAdd;
4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif  // WEBP_USE_MIPS32
4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
417