summaryrefslogtreecommitdiffstats
path: root/media/libvpx/libvpx/vpx_dsp/ppc/subtract_vsx.c
blob: 76ad302da606423dc32c1e67a2f8cfd3da14248e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
 *  Copyright (c) 2018 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <assert.h>

#include "./vpx_config.h"
#include "./vpx_dsp_rtcd.h"
#include "vpx/vpx_integer.h"
#include "vpx_dsp/ppc/types_vsx.h"

static VPX_FORCE_INLINE void subtract_block4x4(
    int16_t *diff, ptrdiff_t diff_stride, const uint8_t *src,
    ptrdiff_t src_stride, const uint8_t *pred, ptrdiff_t pred_stride) {
  int16_t *diff1 = diff + 2 * diff_stride;
  const uint8_t *src1 = src + 2 * src_stride;
  const uint8_t *pred1 = pred + 2 * pred_stride;

  const int16x8_t d0 = vec_vsx_ld(0, diff);
  const int16x8_t d1 = vec_vsx_ld(0, diff + diff_stride);
  const int16x8_t d2 = vec_vsx_ld(0, diff1);
  const int16x8_t d3 = vec_vsx_ld(0, diff1 + diff_stride);

  const uint8x16_t s0 = read4x2(src, (int)src_stride);
  const uint8x16_t p0 = read4x2(pred, (int)pred_stride);
  const uint8x16_t s1 = read4x2(src1, (int)src_stride);
  const uint8x16_t p1 = read4x2(pred1, (int)pred_stride);

  const int16x8_t da = vec_sub(unpack_to_s16_h(s0), unpack_to_s16_h(p0));
  const int16x8_t db = vec_sub(unpack_to_s16_h(s1), unpack_to_s16_h(p1));

  vec_vsx_st(xxpermdi(da, d0, 1), 0, diff);
  vec_vsx_st(xxpermdi(da, d1, 3), 0, diff + diff_stride);
  vec_vsx_st(xxpermdi(db, d2, 1), 0, diff1);
  vec_vsx_st(xxpermdi(db, d3, 3), 0, diff1 + diff_stride);
}

void vpx_subtract_block_vsx(int rows, int cols, int16_t *diff,
                            ptrdiff_t diff_stride, const uint8_t *src,
                            ptrdiff_t src_stride, const uint8_t *pred,
                            ptrdiff_t pred_stride) {
  int r = rows, c;

  switch (cols) {
    case 64:
    case 32:
      do {
        for (c = 0; c < cols; c += 32) {
          const uint8x16_t s0 = vec_vsx_ld(0, src + c);
          const uint8x16_t s1 = vec_vsx_ld(16, src + c);
          const uint8x16_t p0 = vec_vsx_ld(0, pred + c);
          const uint8x16_t p1 = vec_vsx_ld(16, pred + c);
          const int16x8_t d0l =
              vec_sub(unpack_to_s16_l(s0), unpack_to_s16_l(p0));
          const int16x8_t d0h =
              vec_sub(unpack_to_s16_h(s0), unpack_to_s16_h(p0));
          const int16x8_t d1l =
              vec_sub(unpack_to_s16_l(s1), unpack_to_s16_l(p1));
          const int16x8_t d1h =
              vec_sub(unpack_to_s16_h(s1), unpack_to_s16_h(p1));
          vec_vsx_st(d0h, 0, diff + c);
          vec_vsx_st(d0l, 16, diff + c);
          vec_vsx_st(d1h, 0, diff + c + 16);
          vec_vsx_st(d1l, 16, diff + c + 16);
        }
        diff += diff_stride;
        pred += pred_stride;
        src += src_stride;
      } while (--r);
      break;
    case 16:
      do {
        const uint8x16_t s0 = vec_vsx_ld(0, src);
        const uint8x16_t p0 = vec_vsx_ld(0, pred);
        const int16x8_t d0l = vec_sub(unpack_to_s16_l(s0), unpack_to_s16_l(p0));
        const int16x8_t d0h = vec_sub(unpack_to_s16_h(s0), unpack_to_s16_h(p0));
        vec_vsx_st(d0h, 0, diff);
        vec_vsx_st(d0l, 16, diff);
        diff += diff_stride;
        pred += pred_stride;
        src += src_stride;
      } while (--r);
      break;
    case 8:
      do {
        const uint8x16_t s0 = vec_vsx_ld(0, src);
        const uint8x16_t p0 = vec_vsx_ld(0, pred);
        const int16x8_t d0h = vec_sub(unpack_to_s16_h(s0), unpack_to_s16_h(p0));
        vec_vsx_st(d0h, 0, diff);
        diff += diff_stride;
        pred += pred_stride;
        src += src_stride;
      } while (--r);
      break;
    case 4:
      subtract_block4x4(diff, diff_stride, src, src_stride, pred, pred_stride);
      if (r > 4) {
        diff += 4 * diff_stride;
        pred += 4 * pred_stride;
        src += 4 * src_stride;

        subtract_block4x4(diff, diff_stride,

                          src, src_stride,

                          pred, pred_stride);
      }
      break;
    default: assert(0);  // unreachable
  }
}