]> git.sesse.net Git - x264/blob - common/x86/util.h
MMX code for predictor rounding/clipping
[x264] / common / x86 / util.h
1 /*****************************************************************************
2  * mc.h: h264 encoder library
3  *****************************************************************************
4  * Copyright (C) 2008 x264 Project
5  *
6  * Authors: Fiona Glaser <fiona@x264.com>
7  *          Loren Merritt <lorenm@u.washington.edu>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #ifndef X264_X86_UTIL_H
25 #define X264_X86_UTIL_H
26
27 #ifdef __GNUC__
28
29 #include <xmmintrin.h>
30
31 #define x264_median_mv x264_median_mv_mmxext
32 static ALWAYS_INLINE void x264_median_mv_mmxext( int16_t *dst, int16_t *a, int16_t *b, int16_t *c )
33 {
34     asm(
35         "movd   %1,    %%mm0 \n"
36         "movd   %2,    %%mm1 \n"
37         "movq   %%mm0, %%mm3 \n"
38         "movd   %3,    %%mm2 \n"
39         "pmaxsw %%mm1, %%mm0 \n"
40         "pminsw %%mm3, %%mm1 \n"
41         "pminsw %%mm2, %%mm0 \n"
42         "pmaxsw %%mm1, %%mm0 \n"
43         "movd   %%mm0, %0    \n"
44         :"=m"(*(x264_union32_t*)dst)
45         :"m"(M32( a )), "m"(M32( b )), "m"(M32( c ))
46     );
47 }
48
49 #define x264_predictor_difference x264_predictor_difference_mmxext
50 static ALWAYS_INLINE int x264_predictor_difference_mmxext( int16_t (*mvc)[2], intptr_t i_mvc )
51 {
52     int sum;
53     static const uint64_t pw_1 = 0x0001000100010001ULL;
54
55     asm(
56         "pxor    %%mm4, %%mm4 \n"
57         "test    $1, %1       \n"
58         "jnz 3f               \n"
59         "movd    -8(%2,%1,4), %%mm0 \n"
60         "movd    -4(%2,%1,4), %%mm3 \n"
61         "psubw   %%mm3, %%mm0 \n"
62         "jmp 2f               \n"
63         "3:                   \n"
64         "dec     %1           \n"
65         "1:                   \n"
66         "movq    -8(%2,%1,4), %%mm0 \n"
67         "psubw   -4(%2,%1,4), %%mm0 \n"
68         "2:                   \n"
69         "sub     $2,    %1    \n"
70         "pxor    %%mm2, %%mm2 \n"
71         "psubw   %%mm0, %%mm2 \n"
72         "pmaxsw  %%mm2, %%mm0 \n"
73         "paddusw %%mm0, %%mm4 \n"
74         "jg 1b                \n"
75         "pmaddwd %4, %%mm4    \n"
76         "pshufw $14, %%mm4, %%mm0 \n"
77         "paddd   %%mm0, %%mm4 \n"
78         "movd    %%mm4, %0    \n"
79         :"=r"(sum), "+r"(i_mvc)
80         :"r"(mvc), "m"(M64( mvc )), "m"(pw_1)
81     );
82     return sum;
83 }
84
85 #define x264_cabac_mvd_sum x264_cabac_mvd_sum_mmxext
86 static ALWAYS_INLINE uint16_t x264_cabac_mvd_sum_mmxext(uint8_t *mvdleft, uint8_t *mvdtop)
87 {
88     static const uint64_t pb_2    = 0x0202020202020202ULL;
89     static const uint64_t pb_32   = 0x2020202020202020ULL;
90     int amvd;
91     asm(
92         "movd         %1, %%mm0 \n"
93         "movd         %2, %%mm1 \n"
94         "paddb     %%mm1, %%mm0 \n"
95         "pxor      %%mm2, %%mm2 \n"
96         "movq      %%mm0, %%mm1 \n"
97         "pcmpgtb      %3, %%mm0 \n"
98         "pcmpgtb      %4, %%mm1 \n"
99         "psubb     %%mm0, %%mm2 \n"
100         "psubb     %%mm1, %%mm2 \n"
101         "movd      %%mm2, %0    \n"
102         :"=r"(amvd)
103         :"m"(M16( mvdleft )),"m"(M16( mvdtop )),
104          "m"(pb_2),"m"(pb_32)
105     );
106     return amvd;
107 }
108
109 #define x264_predictor_roundclip x264_predictor_roundclip_mmxext
110 static void ALWAYS_INLINE x264_predictor_roundclip_mmxext( int16_t (*mvc)[2], int i_mvc, int mv_x_min, int mv_x_max, int mv_y_min, int mv_y_max )
111 {
112     uint32_t mv_min = pack16to32_mask( mv_x_min, mv_y_min );
113     uint32_t mv_max = pack16to32_mask( mv_x_max, mv_y_max );
114     static const uint64_t pw_2 = 0x0002000200020002ULL;
115     intptr_t i = i_mvc;
116     asm(
117         "movd    %2, %%mm5       \n"
118         "movd    %3, %%mm6       \n"
119         "movq    %4, %%mm7       \n"
120         "punpckldq %%mm5, %%mm5  \n"
121         "punpckldq %%mm6, %%mm6  \n"
122         "test $1, %0             \n"
123         "jz 1f                   \n"
124         "movd -4(%5,%0,4), %%mm0 \n"
125         "paddw %%mm7, %%mm0      \n"
126         "psraw $2, %%mm0         \n"
127         "pmaxsw %%mm5, %%mm0     \n"
128         "pminsw %%mm6, %%mm0     \n"
129         "movd %%mm0, -4(%5,%0,4) \n"
130         "dec %0                  \n"
131         "jz 2f                   \n"
132         "1:                      \n"
133         "movq -8(%5,%0,4), %%mm0 \n"
134         "paddw %%mm7, %%mm0      \n"
135         "psraw $2, %%mm0         \n"
136         "pmaxsw %%mm5, %%mm0     \n"
137         "pminsw %%mm6, %%mm0     \n"
138         "movq %%mm0, -8(%5,%0,4) \n"
139         "sub $2, %0              \n"
140         "jnz 1b                  \n"
141         "2:                      \n"
142         :"+r"(i), "+m"(M64( mvc ))
143         :"g"(mv_min), "g"(mv_max), "m"(pw_2), "r"(mvc)
144     );
145 }
146
147 #undef M128_ZERO
148 #define M128_ZERO ((__m128){0,0,0,0})
149 #define x264_union128_t x264_union128_sse_t
150 typedef union { __m128 i; uint64_t a[2]; uint32_t b[4]; uint16_t c[8]; uint8_t d[16]; } MAY_ALIAS x264_union128_sse_t;
151
152 #endif
153
154 #endif