Coverage Report

Created: 2026-09-14 08:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/theora/lib/x86/x86enquant.c
Line
Count
Source
1
/********************************************************************
2
 *                                                                  *
3
 * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.   *
4
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7
 *                                                                  *
8
 * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009                *
9
 * by the Xiph.Org Foundation and contributors                      *
10
 * https://www.xiph.org/                                            *
11
 *                                                                  *
12
 ********************************************************************
13
14
  function:
15
16
 ********************************************************************/
17
18
#include "x86enc.h"
19
20
#if defined(OC_X86_ASM)
21
22
23
24
/*The default enquant table is not quite suitable for SIMD purposes.
25
  First, the m and l parameters need to be separated so that an entire row full
26
   of m's or l's can be loaded at a time.
27
  Second, x86 SIMD has no element-wise arithmetic right-shift, so we have to
28
   emulate one with a multiply.
29
  Therefore we translate the shift count into a scale factor.*/
30
void oc_enc_enquant_table_init_x86(void *_enquant,
31
1.24M
 const ogg_uint16_t _dequant[64]){
32
1.24M
  ogg_int16_t *m;
33
1.24M
  ogg_int16_t *l;
34
1.24M
  int          zzi;
35
1.24M
  m=(ogg_int16_t *)_enquant;
36
1.24M
  l=m+64;
37
80.6M
  for(zzi=0;zzi<64;zzi++){
38
79.4M
    oc_iquant q;
39
79.4M
    oc_iquant_init(&q,_dequant[zzi]);
40
79.4M
    m[zzi]=q.m;
41
    /*q.l must be at least 2 for this to work; fortunately, once all the scale
42
       factors are baked in, the minimum quantizer is much larger than that.*/
43
79.4M
    l[zzi]=1<<16-q.l;
44
79.4M
  }
45
1.24M
}
46
47
68.7k
void oc_enc_enquant_table_fixup_x86(void *_enquant[3][3][2],int _nqis){
48
68.7k
  int pli;
49
68.7k
  int qii;
50
68.7k
  int qti;
51
451k
  for(pli=0;pli<3;pli++)for(qii=1;qii<_nqis;qii++)for(qti=0;qti<2;qti++){
52
301k
    ((ogg_int16_t *)_enquant[pli][qii][qti])[0]=
53
301k
     ((ogg_int16_t *)_enquant[pli][0][qti])[0];
54
301k
    ((ogg_int16_t *)_enquant[pli][qii][qti])[64]=
55
301k
     ((ogg_int16_t *)_enquant[pli][0][qti])[64];
56
301k
  }
57
68.7k
}
58
59
int __attribute__((target("sse2"))) oc_enc_quantize_sse2(ogg_int16_t _qdct[64],const ogg_int16_t _dct[64],
60
19.0M
 const ogg_uint16_t _dequant[64],const void *_enquant){
61
19.0M
  ptrdiff_t r;
62
19.0M
  __asm__ __volatile__(
63
19.0M
    "xor %[r],%[r]\n\t"
64
    /*Loop through two rows at a time.*/
65
19.0M
    ".p2align 4\n\t"
66
19.0M
    "0:\n\t"
67
    /*Load the first two rows of the data and the quant matrices.*/
68
19.0M
    "movdqa 0x00(%[dct],%[r]),%%xmm0\n\t"
69
19.0M
    "movdqa 0x10(%[dct],%[r]),%%xmm1\n\t"
70
19.0M
    "movdqa 0x00(%[dq],%[r]),%%xmm2\n\t"
71
19.0M
    "movdqa 0x10(%[dq],%[r]),%%xmm3\n\t"
72
19.0M
    "movdqa 0x00(%[q],%[r]),%%xmm4\n\t"
73
19.0M
    "movdqa 0x10(%[q],%[r]),%%xmm5\n\t"
74
    /*Double the input and propagate its sign to the rounding factor.
75
      Using SSSE3's psignw would help here, but we need the mask later anyway.*/
76
19.0M
    "movdqa %%xmm0,%%xmm6\n\t"
77
19.0M
    "psraw $15,%%xmm0\n\t"
78
19.0M
    "movdqa %%xmm1,%%xmm7\n\t"
79
19.0M
    "paddw %%xmm6,%%xmm6\n\t"
80
19.0M
    "psraw $15,%%xmm1\n\t"
81
19.0M
    "paddw %%xmm7,%%xmm7\n\t"
82
19.0M
    "paddw %%xmm0,%%xmm2\n\t"
83
19.0M
    "paddw %%xmm1,%%xmm3\n\t"
84
19.0M
    "pxor %%xmm0,%%xmm2\n\t"
85
19.0M
    "pxor %%xmm1,%%xmm3\n\t"
86
    /*Add the rounding factor and perform the first multiply.*/
87
19.0M
    "paddw %%xmm2,%%xmm6\n\t"
88
19.0M
    "paddw %%xmm3,%%xmm7\n\t"
89
19.0M
    "pmulhw %%xmm6,%%xmm4\n\t"
90
19.0M
    "pmulhw %%xmm7,%%xmm5\n\t"
91
19.0M
    "movdqa 0x80(%[q],%[r]),%%xmm2\n\t"
92
19.0M
    "movdqa 0x90(%[q],%[r]),%%xmm3\n\t"
93
19.0M
    "paddw %%xmm4,%%xmm6\n\t"
94
19.0M
    "paddw %%xmm5,%%xmm7\n\t"
95
    /*Emulate an element-wise right-shift via a second multiply.*/
96
19.0M
    "pmulhw %%xmm2,%%xmm6\n\t"
97
19.0M
    "pmulhw %%xmm3,%%xmm7\n\t"
98
19.0M
    "add $32,%[r]\n\t"
99
19.0M
    "cmp $96,%[r]\n\t"
100
    /*Correct for the sign.*/
101
19.0M
    "psubw %%xmm0,%%xmm6\n\t"
102
19.0M
    "psubw %%xmm1,%%xmm7\n\t"
103
    /*Save the result.*/
104
19.0M
    "movdqa %%xmm6,-0x20(%[qdct],%[r])\n\t"
105
19.0M
    "movdqa %%xmm7,-0x10(%[qdct],%[r])\n\t"
106
19.0M
    "jle 0b\n\t"
107
    /*Now find the location of the last non-zero value.*/
108
19.0M
    "movdqa 0x50(%[qdct]),%%xmm5\n\t"
109
19.0M
    "movdqa 0x40(%[qdct]),%%xmm4\n\t"
110
19.0M
    "packsswb %%xmm7,%%xmm6\n\t"
111
19.0M
    "packsswb %%xmm5,%%xmm4\n\t"
112
19.0M
    "pxor %%xmm0,%%xmm0\n\t"
113
19.0M
    "mov $-1,%k[dq]\n\t"
114
19.0M
    "pcmpeqb %%xmm0,%%xmm6\n\t"
115
19.0M
    "pcmpeqb %%xmm0,%%xmm4\n\t"
116
19.0M
    "pmovmskb %%xmm6,%k[q]\n\t"
117
19.0M
    "pmovmskb %%xmm4,%k[r]\n\t"
118
19.0M
    "shl $16,%k[q]\n\t"
119
19.0M
    "or %k[r],%k[q]\n\t"
120
19.0M
    "mov $32,%[r]\n\t"
121
    /*We have to use xor here instead of not in order to set the flags.*/
122
19.0M
    "xor %k[dq],%k[q]\n\t"
123
19.0M
    "jnz 1f\n\t"
124
19.0M
    "movdqa 0x30(%[qdct]),%%xmm7\n\t"
125
19.0M
    "movdqa 0x20(%[qdct]),%%xmm6\n\t"
126
19.0M
    "movdqa 0x10(%[qdct]),%%xmm5\n\t"
127
19.0M
    "movdqa 0x00(%[qdct]),%%xmm4\n\t"
128
19.0M
    "packsswb %%xmm7,%%xmm6\n\t"
129
19.0M
    "packsswb %%xmm5,%%xmm4\n\t"
130
19.0M
    "pcmpeqb %%xmm0,%%xmm6\n\t"
131
19.0M
    "pcmpeqb %%xmm0,%%xmm4\n\t"
132
19.0M
    "pmovmskb %%xmm6,%k[q]\n\t"
133
19.0M
    "pmovmskb %%xmm4,%k[r]\n\t"
134
19.0M
    "shl $16,%k[q]\n\t"
135
19.0M
    "or %k[r],%k[q]\n\t"
136
19.0M
    "xor %[r],%[r]\n\t"
137
19.0M
    "not %k[q]\n\t"
138
19.0M
    "or $1,%k[q]\n\t"
139
19.0M
    "1:\n\t"
140
19.0M
    "bsr %k[q],%k[q]\n\t"
141
19.0M
    "add %k[q],%k[r]\n\t"
142
19.0M
    :[r]"=&a"(r),[q]"+r"(_enquant),[dq]"+r"(_dequant)
143
19.0M
    :[dct]"r"(_dct),[qdct]"r"(_qdct)
144
19.0M
    :"cc","memory",
145
19.0M
     "%xmm0", "%xmm1", "%xmm2", "%xmm3",
146
19.0M
     "%xmm4", "%xmm5", "%xmm6", "%xmm7"
147
19.0M
  );
148
19.0M
  return (int)r;
149
19.0M
}
150
151
#endif