diff libavcodec/x86/dsputil_mmx.c @ 2:897f711a7157

rearrange to work with autoconf
author Nina Engelhardt <nengel@mailbox.tu-berlin.de>
date Tue, 25 Sep 2012 15:55:33 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libavcodec/x86/dsputil_mmx.c	Tue Sep 25 15:55:33 2012 +0200
     1.3 @@ -0,0 +1,821 @@
     1.4 +/*
     1.5 + * MMX optimized DSP utils
     1.6 + * Copyright (c) 2000, 2001 Fabrice Bellard
     1.7 + * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
     1.8 + *
     1.9 + * This file is part of FFmpeg.
    1.10 + *
    1.11 + * FFmpeg is free software; you can redistribute it and/or
    1.12 + * modify it under the terms of the GNU Lesser General Public
    1.13 + * License as published by the Free Software Foundation; either
    1.14 + * version 2.1 of the License, or (at your option) any later version.
    1.15 + *
    1.16 + * FFmpeg is distributed in the hope that it will be useful,
    1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.19 + * Lesser General Public License for more details.
    1.20 + *
    1.21 + * You should have received a copy of the GNU Lesser General Public
    1.22 + * License along with FFmpeg; if not, write to the Free Software
    1.23 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
    1.24 + *
    1.25 + * MMX optimization by Nick Kurshev <nickols_k@mail.ru>
    1.26 + */
    1.27 +
    1.28 +#include "libavutil/x86_cpu.h"
    1.29 +#include "libavutil/internal.h"
    1.30 +#include "libavcodec/dsputil.h"
    1.31 +#include "libavcodec/h264_dsp.h"
    1.32 +#include "dsputil_mmx.h"
    1.33 +
    1.34 +
    1.35 +//#undef NDEBUG
    1.36 +//#include <assert.h>
    1.37 +
    1.38 +int mm_flags; /* multimedia extension flags */
    1.39 +
    1.40 +/* pixel operations */
    1.41 +DECLARE_ALIGNED(8,  const uint64_t, ff_bone) = 0x0101010101010101ULL;
    1.42 +DECLARE_ALIGNED(8,  const uint64_t, ff_wtwo) = 0x0002000200020002ULL;
    1.43 +
    1.44 +DECLARE_ALIGNED(16, const uint64_t, ff_pdw_80000000)[2] =
    1.45 +{0x8000000080000000ULL, 0x8000000080000000ULL};
    1.46 +
    1.47 +DECLARE_ALIGNED(8,  const uint64_t, ff_pw_3  ) = 0x0003000300030003ULL;
    1.48 +DECLARE_ALIGNED(8,  const uint64_t, ff_pw_4  ) = 0x0004000400040004ULL;
    1.49 +DECLARE_ALIGNED(16, const xmm_reg,  ff_pw_5  ) = {0x0005000500050005ULL, 0x0005000500050005ULL};
    1.50 +DECLARE_ALIGNED(16, const xmm_reg,  ff_pw_8  ) = {0x0008000800080008ULL, 0x0008000800080008ULL};
    1.51 +DECLARE_ALIGNED(8,  const uint64_t, ff_pw_15 ) = 0x000F000F000F000FULL;
    1.52 +DECLARE_ALIGNED(16, const xmm_reg,  ff_pw_16 ) = {0x0010001000100010ULL, 0x0010001000100010ULL};
    1.53 +DECLARE_ALIGNED(8,  const uint64_t, ff_pw_20 ) = 0x0014001400140014ULL;
    1.54 +DECLARE_ALIGNED(16, const xmm_reg,  ff_pw_28 ) = {0x001C001C001C001CULL, 0x001C001C001C001CULL};
    1.55 +DECLARE_ALIGNED(16, const xmm_reg,  ff_pw_32 ) = {0x0020002000200020ULL, 0x0020002000200020ULL};
    1.56 +DECLARE_ALIGNED(8,  const uint64_t, ff_pw_42 ) = 0x002A002A002A002AULL;
    1.57 +DECLARE_ALIGNED(16, const xmm_reg,  ff_pw_64 ) = {0x0040004000400040ULL, 0x0040004000400040ULL};
    1.58 +DECLARE_ALIGNED(8,  const uint64_t, ff_pw_96 ) = 0x0060006000600060ULL;
    1.59 +DECLARE_ALIGNED(8,  const uint64_t, ff_pw_128) = 0x0080008000800080ULL;
    1.60 +DECLARE_ALIGNED(8,  const uint64_t, ff_pw_255) = 0x00ff00ff00ff00ffULL;
    1.61 +
    1.62 +DECLARE_ALIGNED(8,  const uint64_t, ff_pb_1  ) = 0x0101010101010101ULL;
    1.63 +DECLARE_ALIGNED(8,  const uint64_t, ff_pb_3  ) = 0x0303030303030303ULL;
    1.64 +DECLARE_ALIGNED(8,  const uint64_t, ff_pb_7  ) = 0x0707070707070707ULL;
    1.65 +DECLARE_ALIGNED(8,  const uint64_t, ff_pb_1F ) = 0x1F1F1F1F1F1F1F1FULL;
    1.66 +DECLARE_ALIGNED(8,  const uint64_t, ff_pb_3F ) = 0x3F3F3F3F3F3F3F3FULL;
    1.67 +DECLARE_ALIGNED(8,  const uint64_t, ff_pb_81 ) = 0x8181818181818181ULL;
    1.68 +DECLARE_ALIGNED(8,  const uint64_t, ff_pb_A1 ) = 0xA1A1A1A1A1A1A1A1ULL;
    1.69 +DECLARE_ALIGNED(8,  const uint64_t, ff_pb_FC ) = 0xFCFCFCFCFCFCFCFCULL;
    1.70 +
    1.71 +DECLARE_ALIGNED(16, const double, ff_pd_1)[2] = { 1.0, 1.0 };
    1.72 +DECLARE_ALIGNED(16, const double, ff_pd_2)[2] = { 2.0, 2.0 };
    1.73 +
    1.74 +#define ASMALIGN(ZEROBITS) ".align 1 << " #ZEROBITS "\n\t"
    1.75 +#define JUMPALIGN() __asm__ volatile (ASMALIGN(3)::)
    1.76 +#define MOVQ_ZERO(regd)  __asm__ volatile ("pxor %%" #regd ", %%" #regd ::)
    1.77 +
    1.78 +#define MOVQ_BFE(regd) \
    1.79 +    __asm__ volatile ( \
    1.80 +    "pcmpeqd %%" #regd ", %%" #regd " \n\t"\
    1.81 +    "paddb %%" #regd ", %%" #regd " \n\t" ::)
    1.82 +
    1.83 +#ifndef PIC
    1.84 +#define MOVQ_BONE(regd)  __asm__ volatile ("movq %0, %%" #regd " \n\t" ::"m"(ff_bone))
    1.85 +#define MOVQ_WTWO(regd)  __asm__ volatile ("movq %0, %%" #regd " \n\t" ::"m"(ff_wtwo))
    1.86 +#else
    1.87 +// for shared library it's better to use this way for accessing constants
    1.88 +// pcmpeqd -> -1
    1.89 +#define MOVQ_BONE(regd) \
    1.90 +    __asm__ volatile ( \
    1.91 +    "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
    1.92 +    "psrlw $15, %%" #regd " \n\t" \
    1.93 +    "packuswb %%" #regd ", %%" #regd " \n\t" ::)
    1.94 +
    1.95 +#define MOVQ_WTWO(regd) \
    1.96 +    __asm__ volatile ( \
    1.97 +    "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
    1.98 +    "psrlw $15, %%" #regd " \n\t" \
    1.99 +    "psllw $1, %%" #regd " \n\t"::)
   1.100 +
   1.101 +#endif
   1.102 +
   1.103 +// using regr as temporary and for the output result
   1.104 +// first argument is unmodifed and second is trashed
   1.105 +// regfe is supposed to contain 0xfefefefefefefefe
   1.106 +#define PAVGB_MMX_NO_RND(rega, regb, regr, regfe) \
   1.107 +    "movq " #rega ", " #regr "  \n\t"\
   1.108 +    "pand " #regb ", " #regr "  \n\t"\
   1.109 +    "pxor " #rega ", " #regb "  \n\t"\
   1.110 +    "pand " #regfe "," #regb "  \n\t"\
   1.111 +    "psrlq $1, " #regb "        \n\t"\
   1.112 +    "paddb " #regb ", " #regr " \n\t"
   1.113 +
   1.114 +#define PAVGB_MMX(rega, regb, regr, regfe) \
   1.115 +    "movq " #rega ", " #regr "  \n\t"\
   1.116 +    "por  " #regb ", " #regr "  \n\t"\
   1.117 +    "pxor " #rega ", " #regb "  \n\t"\
   1.118 +    "pand " #regfe "," #regb "  \n\t"\
   1.119 +    "psrlq $1, " #regb "        \n\t"\
   1.120 +    "psubb " #regb ", " #regr " \n\t"
   1.121 +
   1.122 +// mm6 is supposed to contain 0xfefefefefefefefe
   1.123 +#define PAVGBP_MMX_NO_RND(rega, regb, regr,  regc, regd, regp) \
   1.124 +    "movq " #rega ", " #regr "  \n\t"\
   1.125 +    "movq " #regc ", " #regp "  \n\t"\
   1.126 +    "pand " #regb ", " #regr "  \n\t"\
   1.127 +    "pand " #regd ", " #regp "  \n\t"\
   1.128 +    "pxor " #rega ", " #regb "  \n\t"\
   1.129 +    "pxor " #regc ", " #regd "  \n\t"\
   1.130 +    "pand %%mm6, " #regb "      \n\t"\
   1.131 +    "pand %%mm6, " #regd "      \n\t"\
   1.132 +    "psrlq $1, " #regb "        \n\t"\
   1.133 +    "psrlq $1, " #regd "        \n\t"\
   1.134 +    "paddb " #regb ", " #regr " \n\t"\
   1.135 +    "paddb " #regd ", " #regp " \n\t"
   1.136 +
   1.137 +#define PAVGBP_MMX(rega, regb, regr, regc, regd, regp) \
   1.138 +    "movq " #rega ", " #regr "  \n\t"\
   1.139 +    "movq " #regc ", " #regp "  \n\t"\
   1.140 +    "por  " #regb ", " #regr "  \n\t"\
   1.141 +    "por  " #regd ", " #regp "  \n\t"\
   1.142 +    "pxor " #rega ", " #regb "  \n\t"\
   1.143 +    "pxor " #regc ", " #regd "  \n\t"\
   1.144 +    "pand %%mm6, " #regb "      \n\t"\
   1.145 +    "pand %%mm6, " #regd "      \n\t"\
   1.146 +    "psrlq $1, " #regd "        \n\t"\
   1.147 +    "psrlq $1, " #regb "        \n\t"\
   1.148 +    "psubb " #regb ", " #regr " \n\t"\
   1.149 +    "psubb " #regd ", " #regp " \n\t"
   1.150 +
   1.151 +/***********************************/
   1.152 +/* MMX2 specific */
   1.153 +
   1.154 +#define DEF(x) x ## _mmx2
   1.155 +
   1.156 +/* Introduced only in MMX2 set */
   1.157 +#define PAVGB "pavgb"
   1.158 +#define OP_AVG PAVGB
   1.159 +
   1.160 +#include "dsputil_mmx_avg_template.c"
   1.161 +
   1.162 +#undef DEF
   1.163 +#undef PAVGB
   1.164 +#undef OP_AVG
   1.165 +
   1.166 +#define put_no_rnd_pixels16_mmx put_pixels16_mmx
   1.167 +#define put_no_rnd_pixels8_mmx put_pixels8_mmx
   1.168 +#define put_pixels16_mmx2 put_pixels16_mmx
   1.169 +#define put_pixels8_mmx2 put_pixels8_mmx
   1.170 +#define put_pixels4_mmx2 put_pixels4_mmx
   1.171 +#define put_no_rnd_pixels16_mmx2 put_no_rnd_pixels16_mmx
   1.172 +#define put_no_rnd_pixels8_mmx2 put_no_rnd_pixels8_mmx
   1.173 +#define put_pixels16_3dnow put_pixels16_mmx
   1.174 +#define put_pixels8_3dnow put_pixels8_mmx
   1.175 +#define put_pixels4_3dnow put_pixels4_mmx
   1.176 +#define put_no_rnd_pixels16_3dnow put_no_rnd_pixels16_mmx
   1.177 +#define put_no_rnd_pixels8_3dnow put_no_rnd_pixels8_mmx
   1.178 +
   1.179 +/***********************************/
   1.180 +/* standard MMX */
   1.181 +
   1.182 +void put_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size)
   1.183 +{
   1.184 +    const DCTELEM *p;
   1.185 +    uint8_t *pix;
   1.186 +
   1.187 +    /* read the pixels */
   1.188 +    p = block;
   1.189 +    pix = pixels;
   1.190 +    /* unrolled loop */
   1.191 +        __asm__ volatile(
   1.192 +                "movq   %3, %%mm0               \n\t"
   1.193 +                "movq   8%3, %%mm1              \n\t"
   1.194 +                "movq   16%3, %%mm2             \n\t"
   1.195 +                "movq   24%3, %%mm3             \n\t"
   1.196 +                "movq   32%3, %%mm4             \n\t"
   1.197 +                "movq   40%3, %%mm5             \n\t"
   1.198 +                "movq   48%3, %%mm6             \n\t"
   1.199 +                "movq   56%3, %%mm7             \n\t"
   1.200 +                "packuswb %%mm1, %%mm0          \n\t"
   1.201 +                "packuswb %%mm3, %%mm2          \n\t"
   1.202 +                "packuswb %%mm5, %%mm4          \n\t"
   1.203 +                "packuswb %%mm7, %%mm6          \n\t"
   1.204 +                "movq   %%mm0, (%0)             \n\t"
   1.205 +                "movq   %%mm2, (%0, %1)         \n\t"
   1.206 +                "movq   %%mm4, (%0, %1, 2)      \n\t"
   1.207 +                "movq   %%mm6, (%0, %2)         \n\t"
   1.208 +                ::"r" (pix), "r" ((x86_reg)line_size), "r" ((x86_reg)line_size*3), "m"(*p)
   1.209 +                :"memory");
   1.210 +        pix += line_size*4;
   1.211 +        p += 32;
   1.212 +
   1.213 +    // if here would be an exact copy of the code above
   1.214 +    // compiler would generate some very strange code
   1.215 +    // thus using "r"
   1.216 +    __asm__ volatile(
   1.217 +            "movq       (%3), %%mm0             \n\t"
   1.218 +            "movq       8(%3), %%mm1            \n\t"
   1.219 +            "movq       16(%3), %%mm2           \n\t"
   1.220 +            "movq       24(%3), %%mm3           \n\t"
   1.221 +            "movq       32(%3), %%mm4           \n\t"
   1.222 +            "movq       40(%3), %%mm5           \n\t"
   1.223 +            "movq       48(%3), %%mm6           \n\t"
   1.224 +            "movq       56(%3), %%mm7           \n\t"
   1.225 +            "packuswb %%mm1, %%mm0              \n\t"
   1.226 +            "packuswb %%mm3, %%mm2              \n\t"
   1.227 +            "packuswb %%mm5, %%mm4              \n\t"
   1.228 +            "packuswb %%mm7, %%mm6              \n\t"
   1.229 +            "movq       %%mm0, (%0)             \n\t"
   1.230 +            "movq       %%mm2, (%0, %1)         \n\t"
   1.231 +            "movq       %%mm4, (%0, %1, 2)      \n\t"
   1.232 +            "movq       %%mm6, (%0, %2)         \n\t"
   1.233 +            ::"r" (pix), "r" ((x86_reg)line_size), "r" ((x86_reg)line_size*3), "r"(p)
   1.234 +            :"memory");
   1.235 +}
   1.236 +
   1.237 +DECLARE_ASM_CONST(8, uint8_t, ff_vector128)[8] =
   1.238 +  { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
   1.239 +
   1.240 +#define put_signed_pixels_clamped_mmx_half(off) \
   1.241 +            "movq    "#off"(%2), %%mm1          \n\t"\
   1.242 +            "movq 16+"#off"(%2), %%mm2          \n\t"\
   1.243 +            "movq 32+"#off"(%2), %%mm3          \n\t"\
   1.244 +            "movq 48+"#off"(%2), %%mm4          \n\t"\
   1.245 +            "packsswb  8+"#off"(%2), %%mm1      \n\t"\
   1.246 +            "packsswb 24+"#off"(%2), %%mm2      \n\t"\
   1.247 +            "packsswb 40+"#off"(%2), %%mm3      \n\t"\
   1.248 +            "packsswb 56+"#off"(%2), %%mm4      \n\t"\
   1.249 +            "paddb %%mm0, %%mm1                 \n\t"\
   1.250 +            "paddb %%mm0, %%mm2                 \n\t"\
   1.251 +            "paddb %%mm0, %%mm3                 \n\t"\
   1.252 +            "paddb %%mm0, %%mm4                 \n\t"\
   1.253 +            "movq %%mm1, (%0)                   \n\t"\
   1.254 +            "movq %%mm2, (%0, %3)               \n\t"\
   1.255 +            "movq %%mm3, (%0, %3, 2)            \n\t"\
   1.256 +            "movq %%mm4, (%0, %1)               \n\t"
   1.257 +
   1.258 +void put_signed_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size)
   1.259 +{
   1.260 +    x86_reg line_skip = line_size;
   1.261 +    x86_reg line_skip3;
   1.262 +
   1.263 +    __asm__ volatile (
   1.264 +            "movq "MANGLE(ff_vector128)", %%mm0 \n\t"
   1.265 +            "lea (%3, %3, 2), %1                \n\t"
   1.266 +            put_signed_pixels_clamped_mmx_half(0)
   1.267 +            "lea (%0, %3, 4), %0                \n\t"
   1.268 +            put_signed_pixels_clamped_mmx_half(64)
   1.269 +            :"+&r" (pixels), "=&r" (line_skip3)
   1.270 +            :"r" (block), "r"(line_skip)
   1.271 +            :"memory");
   1.272 +}
   1.273 +
   1.274 +void add_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size)
   1.275 +{
   1.276 +    const DCTELEM *p;
   1.277 +    uint8_t *pix;
   1.278 +    int i;
   1.279 +
   1.280 +    /* read the pixels */
   1.281 +    p = block;
   1.282 +    pix = pixels;
   1.283 +    MOVQ_ZERO(mm7);
   1.284 +    i = 4;
   1.285 +    do {
   1.286 +        __asm__ volatile(
   1.287 +                "movq   (%2), %%mm0     \n\t"
   1.288 +                "movq   8(%2), %%mm1    \n\t"
   1.289 +                "movq   16(%2), %%mm2   \n\t"
   1.290 +                "movq   24(%2), %%mm3   \n\t"
   1.291 +                "movq   %0, %%mm4       \n\t"
   1.292 +                "movq   %1, %%mm6       \n\t"
   1.293 +                "movq   %%mm4, %%mm5    \n\t"
   1.294 +                "punpcklbw %%mm7, %%mm4 \n\t"
   1.295 +                "punpckhbw %%mm7, %%mm5 \n\t"
   1.296 +                "paddsw %%mm4, %%mm0    \n\t"
   1.297 +                "paddsw %%mm5, %%mm1    \n\t"
   1.298 +                "movq   %%mm6, %%mm5    \n\t"
   1.299 +                "punpcklbw %%mm7, %%mm6 \n\t"
   1.300 +                "punpckhbw %%mm7, %%mm5 \n\t"
   1.301 +                "paddsw %%mm6, %%mm2    \n\t"
   1.302 +                "paddsw %%mm5, %%mm3    \n\t"
   1.303 +                "packuswb %%mm1, %%mm0  \n\t"
   1.304 +                "packuswb %%mm3, %%mm2  \n\t"
   1.305 +                "movq   %%mm0, %0       \n\t"
   1.306 +                "movq   %%mm2, %1       \n\t"
   1.307 +                :"+m"(*pix), "+m"(*(pix+line_size))
   1.308 +                :"r"(p)
   1.309 +                :"memory");
   1.310 +        pix += line_size*2;
   1.311 +        p += 16;
   1.312 +    } while (--i);
   1.313 +}
   1.314 +
   1.315 +static void put_pixels8_mmx(uint8_t *block, const uint8_t *pixels, int line_size, int h)
   1.316 +{
   1.317 +    __asm__ volatile(
   1.318 +         "lea (%3, %3), %%"REG_a"       \n\t"
   1.319 +         ASMALIGN(3)
   1.320 +         "1:                            \n\t"
   1.321 +         "movq (%1), %%mm0              \n\t"
   1.322 +         "movq (%1, %3), %%mm1          \n\t"
   1.323 +         "movq %%mm0, (%2)              \n\t"
   1.324 +         "movq %%mm1, (%2, %3)          \n\t"
   1.325 +         "add %%"REG_a", %1             \n\t"
   1.326 +         "add %%"REG_a", %2             \n\t"
   1.327 +         "movq (%1), %%mm0              \n\t"
   1.328 +         "movq (%1, %3), %%mm1          \n\t"
   1.329 +         "movq %%mm0, (%2)              \n\t"
   1.330 +         "movq %%mm1, (%2, %3)          \n\t"
   1.331 +         "add %%"REG_a", %1             \n\t"
   1.332 +         "add %%"REG_a", %2             \n\t"
   1.333 +         "subl $4, %0                   \n\t"
   1.334 +         "jnz 1b                        \n\t"
   1.335 +         : "+g"(h), "+r" (pixels),  "+r" (block)
   1.336 +         : "r"((x86_reg)line_size)
   1.337 +         : "%"REG_a, "memory"
   1.338 +        );
   1.339 +}
   1.340 +
   1.341 +static void put_pixels16_sse2(uint8_t *block, const uint8_t *pixels, int line_size, int h)
   1.342 +{
   1.343 +    __asm__ volatile(
   1.344 +         "1:                            \n\t"
   1.345 +         "movdqu (%1), %%xmm0           \n\t"
   1.346 +         "movdqu (%1,%3), %%xmm1        \n\t"
   1.347 +         "movdqu (%1,%3,2), %%xmm2      \n\t"
   1.348 +         "movdqu (%1,%4), %%xmm3        \n\t"
   1.349 +         "movdqa %%xmm0, (%2)           \n\t"
   1.350 +         "movdqa %%xmm1, (%2,%3)        \n\t"
   1.351 +         "movdqa %%xmm2, (%2,%3,2)      \n\t"
   1.352 +         "movdqa %%xmm3, (%2,%4)        \n\t"
   1.353 +         "subl $4, %0                   \n\t"
   1.354 +         "lea (%1,%3,4), %1             \n\t"
   1.355 +         "lea (%2,%3,4), %2             \n\t"
   1.356 +         "jnz 1b                        \n\t"
   1.357 +         : "+g"(h), "+r" (pixels),  "+r" (block)
   1.358 +         : "r"((x86_reg)line_size), "r"((x86_reg)3L*line_size)
   1.359 +         : "memory"
   1.360 +        );
   1.361 +}
   1.362 +
   1.363 +static void avg_pixels16_sse2(uint8_t *block, const uint8_t *pixels, int line_size, int h)
   1.364 +{
   1.365 +    __asm__ volatile(
   1.366 +         "1:                            \n\t"
   1.367 +         "movdqu (%1), %%xmm0           \n\t"
   1.368 +         "movdqu (%1,%3), %%xmm1        \n\t"
   1.369 +         "movdqu (%1,%3,2), %%xmm2      \n\t"
   1.370 +         "movdqu (%1,%4), %%xmm3        \n\t"
   1.371 +         "pavgb  (%2), %%xmm0           \n\t"
   1.372 +         "pavgb  (%2,%3), %%xmm1        \n\t"
   1.373 +         "pavgb  (%2,%3,2), %%xmm2      \n\t"
   1.374 +         "pavgb  (%2,%4), %%xmm3        \n\t"
   1.375 +         "movdqa %%xmm0, (%2)           \n\t"
   1.376 +         "movdqa %%xmm1, (%2,%3)        \n\t"
   1.377 +         "movdqa %%xmm2, (%2,%3,2)      \n\t"
   1.378 +         "movdqa %%xmm3, (%2,%4)        \n\t"
   1.379 +         "subl $4, %0                   \n\t"
   1.380 +         "lea (%1,%3,4), %1             \n\t"
   1.381 +         "lea (%2,%3,4), %2             \n\t"
   1.382 +         "jnz 1b                        \n\t"
   1.383 +         : "+g"(h), "+r" (pixels),  "+r" (block)
   1.384 +         : "r"((x86_reg)line_size), "r"((x86_reg)3L*line_size)
   1.385 +         : "memory"
   1.386 +        );
   1.387 +}
   1.388 +
   1.389 +static void clear_block_sse(DCTELEM *block)
   1.390 +{
   1.391 +    __asm__ volatile(
   1.392 +        "xorps  %%xmm0, %%xmm0  \n"
   1.393 +        "movaps %%xmm0,    (%0) \n"
   1.394 +        "movaps %%xmm0,  16(%0) \n"
   1.395 +        "movaps %%xmm0,  32(%0) \n"
   1.396 +        "movaps %%xmm0,  48(%0) \n"
   1.397 +        "movaps %%xmm0,  64(%0) \n"
   1.398 +        "movaps %%xmm0,  80(%0) \n"
   1.399 +        "movaps %%xmm0,  96(%0) \n"
   1.400 +        "movaps %%xmm0, 112(%0) \n"
   1.401 +        :: "r"(block)
   1.402 +        : "memory"
   1.403 +    );
   1.404 +}
   1.405 +
   1.406 +static void clear_blocks_sse(DCTELEM *blocks)
   1.407 +{\
   1.408 +    __asm__ volatile(
   1.409 +        "xorps  %%xmm0, %%xmm0  \n"
   1.410 +        "mov     %1, %%"REG_a"  \n"
   1.411 +        "1:                     \n"
   1.412 +        "movaps %%xmm0,    (%0, %%"REG_a") \n"
   1.413 +        "movaps %%xmm0,  16(%0, %%"REG_a") \n"
   1.414 +        "movaps %%xmm0,  32(%0, %%"REG_a") \n"
   1.415 +        "movaps %%xmm0,  48(%0, %%"REG_a") \n"
   1.416 +        "movaps %%xmm0,  64(%0, %%"REG_a") \n"
   1.417 +        "movaps %%xmm0,  80(%0, %%"REG_a") \n"
   1.418 +        "movaps %%xmm0,  96(%0, %%"REG_a") \n"
   1.419 +        "movaps %%xmm0, 112(%0, %%"REG_a") \n"
   1.420 +        "add $128, %%"REG_a"    \n"
   1.421 +        " js 1b                 \n"
   1.422 +        : : "r" (((uint8_t *)blocks)+128*6),
   1.423 +            "i" (-128*6)
   1.424 +        : "%"REG_a
   1.425 +    );
   1.426 +}
   1.427 +
   1.428 +static inline void transpose4x4(uint8_t *dst, uint8_t *src, int dst_stride, int src_stride){
   1.429 +    __asm__ volatile( //FIXME could save 1 instruction if done as 8x4 ...
   1.430 +        "movd  %4, %%mm0                \n\t"
   1.431 +        "movd  %5, %%mm1                \n\t"
   1.432 +        "movd  %6, %%mm2                \n\t"
   1.433 +        "movd  %7, %%mm3                \n\t"
   1.434 +        "punpcklbw %%mm1, %%mm0         \n\t"
   1.435 +        "punpcklbw %%mm3, %%mm2         \n\t"
   1.436 +        "movq %%mm0, %%mm1              \n\t"
   1.437 +        "punpcklwd %%mm2, %%mm0         \n\t"
   1.438 +        "punpckhwd %%mm2, %%mm1         \n\t"
   1.439 +        "movd  %%mm0, %0                \n\t"
   1.440 +        "punpckhdq %%mm0, %%mm0         \n\t"
   1.441 +        "movd  %%mm0, %1                \n\t"
   1.442 +        "movd  %%mm1, %2                \n\t"
   1.443 +        "punpckhdq %%mm1, %%mm1         \n\t"
   1.444 +        "movd  %%mm1, %3                \n\t"
   1.445 +
   1.446 +        : "=m" (*(uint32_t*)(dst + 0*dst_stride)),
   1.447 +          "=m" (*(uint32_t*)(dst + 1*dst_stride)),
   1.448 +          "=m" (*(uint32_t*)(dst + 2*dst_stride)),
   1.449 +          "=m" (*(uint32_t*)(dst + 3*dst_stride))
   1.450 +        :  "m" (*(uint32_t*)(src + 0*src_stride)),
   1.451 +           "m" (*(uint32_t*)(src + 1*src_stride)),
   1.452 +           "m" (*(uint32_t*)(src + 2*src_stride)),
   1.453 +           "m" (*(uint32_t*)(src + 3*src_stride))
   1.454 +    );
   1.455 +}
   1.456 +
   1.457 +#define QPEL_OP(OPNAME, ROUNDER, RND, OP, MMX)\
   1.458 +\
   1.459 +static void OPNAME ## qpel8_mc00_ ## MMX (uint8_t *dst, uint8_t *src, int stride){\
   1.460 +    OPNAME ## pixels8_ ## MMX(dst, src, stride, 8);\
   1.461 +}\
   1.462 +\
   1.463 +static void OPNAME ## qpel8_mc10_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.464 +    uint64_t temp[8];\
   1.465 +    uint8_t * const half= (uint8_t*)temp;\
   1.466 +    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, stride, 8);\
   1.467 +    OPNAME ## pixels8_l2_ ## MMX(dst, src, half, stride, stride, 8);\
   1.468 +}\
   1.469 +\
   1.470 +static void OPNAME ## qpel8_mc20_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.471 +    OPNAME ## mpeg4_qpel8_h_lowpass_ ## MMX(dst, src, stride, stride, 8);\
   1.472 +}\
   1.473 +\
   1.474 +static void OPNAME ## qpel8_mc30_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.475 +    uint64_t temp[8];\
   1.476 +    uint8_t * const half= (uint8_t*)temp;\
   1.477 +    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, stride, 8);\
   1.478 +    OPNAME ## pixels8_l2_ ## MMX(dst, src+1, half, stride, stride, 8);\
   1.479 +}\
   1.480 +\
   1.481 +static void OPNAME ## qpel8_mc01_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.482 +    uint64_t temp[8];\
   1.483 +    uint8_t * const half= (uint8_t*)temp;\
   1.484 +    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, 8, stride);\
   1.485 +    OPNAME ## pixels8_l2_ ## MMX(dst, src, half, stride, stride, 8);\
   1.486 +}\
   1.487 +\
   1.488 +static void OPNAME ## qpel8_mc02_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.489 +    OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, src, stride, stride);\
   1.490 +}\
   1.491 +\
   1.492 +static void OPNAME ## qpel8_mc03_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.493 +    uint64_t temp[8];\
   1.494 +    uint8_t * const half= (uint8_t*)temp;\
   1.495 +    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, 8, stride);\
   1.496 +    OPNAME ## pixels8_l2_ ## MMX(dst, src+stride, half, stride, stride, 8);\
   1.497 +}\
   1.498 +static void OPNAME ## qpel8_mc11_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.499 +    uint64_t half[8 + 9];\
   1.500 +    uint8_t * const halfH= ((uint8_t*)half) + 64;\
   1.501 +    uint8_t * const halfHV= ((uint8_t*)half);\
   1.502 +    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
   1.503 +    put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, stride, 9);\
   1.504 +    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
   1.505 +    OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, stride, 8, 8);\
   1.506 +}\
   1.507 +static void OPNAME ## qpel8_mc31_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.508 +    uint64_t half[8 + 9];\
   1.509 +    uint8_t * const halfH= ((uint8_t*)half) + 64;\
   1.510 +    uint8_t * const halfHV= ((uint8_t*)half);\
   1.511 +    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
   1.512 +    put ## RND ## pixels8_l2_ ## MMX(halfH, src+1, halfH, 8, stride, 9);\
   1.513 +    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
   1.514 +    OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, stride, 8, 8);\
   1.515 +}\
   1.516 +static void OPNAME ## qpel8_mc13_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.517 +    uint64_t half[8 + 9];\
   1.518 +    uint8_t * const halfH= ((uint8_t*)half) + 64;\
   1.519 +    uint8_t * const halfHV= ((uint8_t*)half);\
   1.520 +    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
   1.521 +    put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, stride, 9);\
   1.522 +    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
   1.523 +    OPNAME ## pixels8_l2_ ## MMX(dst, halfH+8, halfHV, stride, 8, 8);\
   1.524 +}\
   1.525 +static void OPNAME ## qpel8_mc33_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.526 +    uint64_t half[8 + 9];\
   1.527 +    uint8_t * const halfH= ((uint8_t*)half) + 64;\
   1.528 +    uint8_t * const halfHV= ((uint8_t*)half);\
   1.529 +    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
   1.530 +    put ## RND ## pixels8_l2_ ## MMX(halfH, src+1, halfH, 8, stride, 9);\
   1.531 +    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
   1.532 +    OPNAME ## pixels8_l2_ ## MMX(dst, halfH+8, halfHV, stride, 8, 8);\
   1.533 +}\
   1.534 +static void OPNAME ## qpel8_mc21_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.535 +    uint64_t half[8 + 9];\
   1.536 +    uint8_t * const halfH= ((uint8_t*)half) + 64;\
   1.537 +    uint8_t * const halfHV= ((uint8_t*)half);\
   1.538 +    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
   1.539 +    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
   1.540 +    OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, stride, 8, 8);\
   1.541 +}\
   1.542 +static void OPNAME ## qpel8_mc23_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.543 +    uint64_t half[8 + 9];\
   1.544 +    uint8_t * const halfH= ((uint8_t*)half) + 64;\
   1.545 +    uint8_t * const halfHV= ((uint8_t*)half);\
   1.546 +    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
   1.547 +    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
   1.548 +    OPNAME ## pixels8_l2_ ## MMX(dst, halfH+8, halfHV, stride, 8, 8);\
   1.549 +}\
   1.550 +static void OPNAME ## qpel8_mc12_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.551 +    uint64_t half[8 + 9];\
   1.552 +    uint8_t * const halfH= ((uint8_t*)half);\
   1.553 +    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
   1.554 +    put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, stride, 9);\
   1.555 +    OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);\
   1.556 +}\
   1.557 +static void OPNAME ## qpel8_mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.558 +    uint64_t half[8 + 9];\
   1.559 +    uint8_t * const halfH= ((uint8_t*)half);\
   1.560 +    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
   1.561 +    put ## RND ## pixels8_l2_ ## MMX(halfH, src+1, halfH, 8, stride, 9);\
   1.562 +    OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);\
   1.563 +}\
   1.564 +static void OPNAME ## qpel8_mc22_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.565 +    uint64_t half[9];\
   1.566 +    uint8_t * const halfH= ((uint8_t*)half);\
   1.567 +    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
   1.568 +    OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);\
   1.569 +}\
   1.570 +static void OPNAME ## qpel16_mc00_ ## MMX (uint8_t *dst, uint8_t *src, int stride){\
   1.571 +    OPNAME ## pixels16_ ## MMX(dst, src, stride, 16);\
   1.572 +}\
   1.573 +\
   1.574 +static void OPNAME ## qpel16_mc10_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.575 +    uint64_t temp[32];\
   1.576 +    uint8_t * const half= (uint8_t*)temp;\
   1.577 +    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, stride, 16);\
   1.578 +    OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, stride, 16);\
   1.579 +}\
   1.580 +\
   1.581 +static void OPNAME ## qpel16_mc20_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.582 +    OPNAME ## mpeg4_qpel16_h_lowpass_ ## MMX(dst, src, stride, stride, 16);\
   1.583 +}\
   1.584 +\
   1.585 +static void OPNAME ## qpel16_mc30_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.586 +    uint64_t temp[32];\
   1.587 +    uint8_t * const half= (uint8_t*)temp;\
   1.588 +    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, stride, 16);\
   1.589 +    OPNAME ## pixels16_l2_ ## MMX(dst, src+1, half, stride, stride, 16);\
   1.590 +}\
   1.591 +\
   1.592 +static void OPNAME ## qpel16_mc01_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.593 +    uint64_t temp[32];\
   1.594 +    uint8_t * const half= (uint8_t*)temp;\
   1.595 +    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, stride);\
   1.596 +    OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, stride, 16);\
   1.597 +}\
   1.598 +\
   1.599 +static void OPNAME ## qpel16_mc02_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.600 +    OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, src, stride, stride);\
   1.601 +}\
   1.602 +\
   1.603 +static void OPNAME ## qpel16_mc03_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.604 +    uint64_t temp[32];\
   1.605 +    uint8_t * const half= (uint8_t*)temp;\
   1.606 +    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, stride);\
   1.607 +    OPNAME ## pixels16_l2_ ## MMX(dst, src+stride, half, stride, stride, 16);\
   1.608 +}\
   1.609 +static void OPNAME ## qpel16_mc11_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.610 +    uint64_t half[16*2 + 17*2];\
   1.611 +    uint8_t * const halfH= ((uint8_t*)half) + 256;\
   1.612 +    uint8_t * const halfHV= ((uint8_t*)half);\
   1.613 +    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
   1.614 +    put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, stride, 17);\
   1.615 +    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
   1.616 +    OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, stride, 16, 16);\
   1.617 +}\
   1.618 +static void OPNAME ## qpel16_mc31_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.619 +    uint64_t half[16*2 + 17*2];\
   1.620 +    uint8_t * const halfH= ((uint8_t*)half) + 256;\
   1.621 +    uint8_t * const halfHV= ((uint8_t*)half);\
   1.622 +    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
   1.623 +    put ## RND ## pixels16_l2_ ## MMX(halfH, src+1, halfH, 16, stride, 17);\
   1.624 +    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
   1.625 +    OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, stride, 16, 16);\
   1.626 +}\
   1.627 +static void OPNAME ## qpel16_mc13_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.628 +    uint64_t half[16*2 + 17*2];\
   1.629 +    uint8_t * const halfH= ((uint8_t*)half) + 256;\
   1.630 +    uint8_t * const halfHV= ((uint8_t*)half);\
   1.631 +    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
   1.632 +    put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, stride, 17);\
   1.633 +    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
   1.634 +    OPNAME ## pixels16_l2_ ## MMX(dst, halfH+16, halfHV, stride, 16, 16);\
   1.635 +}\
   1.636 +static void OPNAME ## qpel16_mc33_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.637 +    uint64_t half[16*2 + 17*2];\
   1.638 +    uint8_t * const halfH= ((uint8_t*)half) + 256;\
   1.639 +    uint8_t * const halfHV= ((uint8_t*)half);\
   1.640 +    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
   1.641 +    put ## RND ## pixels16_l2_ ## MMX(halfH, src+1, halfH, 16, stride, 17);\
   1.642 +    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
   1.643 +    OPNAME ## pixels16_l2_ ## MMX(dst, halfH+16, halfHV, stride, 16, 16);\
   1.644 +}\
   1.645 +static void OPNAME ## qpel16_mc21_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.646 +    uint64_t half[16*2 + 17*2];\
   1.647 +    uint8_t * const halfH= ((uint8_t*)half) + 256;\
   1.648 +    uint8_t * const halfHV= ((uint8_t*)half);\
   1.649 +    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
   1.650 +    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
   1.651 +    OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, stride, 16, 16);\
   1.652 +}\
   1.653 +static void OPNAME ## qpel16_mc23_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.654 +    uint64_t half[16*2 + 17*2];\
   1.655 +    uint8_t * const halfH= ((uint8_t*)half) + 256;\
   1.656 +    uint8_t * const halfHV= ((uint8_t*)half);\
   1.657 +    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
   1.658 +    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
   1.659 +    OPNAME ## pixels16_l2_ ## MMX(dst, halfH+16, halfHV, stride, 16, 16);\
   1.660 +}\
   1.661 +static void OPNAME ## qpel16_mc12_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.662 +    uint64_t half[17*2];\
   1.663 +    uint8_t * const halfH= ((uint8_t*)half);\
   1.664 +    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
   1.665 +    put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, stride, 17);\
   1.666 +    OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);\
   1.667 +}\
   1.668 +static void OPNAME ## qpel16_mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.669 +    uint64_t half[17*2];\
   1.670 +    uint8_t * const halfH= ((uint8_t*)half);\
   1.671 +    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
   1.672 +    put ## RND ## pixels16_l2_ ## MMX(halfH, src+1, halfH, 16, stride, 17);\
   1.673 +    OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);\
   1.674 +}\
   1.675 +static void OPNAME ## qpel16_mc22_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
   1.676 +    uint64_t half[17*2];\
   1.677 +    uint8_t * const halfH= ((uint8_t*)half);\
   1.678 +    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
   1.679 +    OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);\
   1.680 +}
   1.681 +
   1.682 +#define PUT_OP(a,b,temp, size) "mov" #size " " #a ", " #b "        \n\t"
   1.683 +#define AVG_3DNOW_OP(a,b,temp, size) \
   1.684 +"mov" #size " " #b ", " #temp "   \n\t"\
   1.685 +"pavgusb " #temp ", " #a "        \n\t"\
   1.686 +"mov" #size " " #a ", " #b "      \n\t"
   1.687 +#define AVG_MMX2_OP(a,b,temp, size) \
   1.688 +"mov" #size " " #b ", " #temp "   \n\t"\
   1.689 +"pavgb " #temp ", " #a "          \n\t"\
   1.690 +"mov" #size " " #a ", " #b "      \n\t"
   1.691 +
   1.692 +#define PREFETCH(name, op) \
   1.693 +static void name(void *mem, int stride, int h){\
   1.694 +    const uint8_t *p= mem;\
   1.695 +    do{\
   1.696 +        __asm__ volatile(#op" %0" :: "m"(*p));\
   1.697 +        p+= stride;\
   1.698 +    }while(--h);\
   1.699 +}
   1.700 +PREFETCH(prefetch_mmx2,  prefetcht0)
   1.701 +#undef PREFETCH 
   1.702 +
   1.703 +#include "h264dsp_mmx.c"
   1.704 +
   1.705 +void ff_x264_deblock_v_luma_sse2(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0);
   1.706 +void ff_x264_deblock_h_luma_sse2(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0);
   1.707 +void ff_x264_deblock_h_luma_intra_mmxext(uint8_t *pix, int stride, int alpha, int beta);
   1.708 +void ff_x264_deblock_v_luma_intra_sse2(uint8_t *pix, int stride, int alpha, int beta);
   1.709 +void ff_x264_deblock_h_luma_intra_sse2(uint8_t *pix, int stride, int alpha, int beta);
   1.710 +
   1.711 +void dsputil_init_mmx(DSPContext* c)
   1.712 +{
   1.713 +    mm_flags = mm_support();
   1.714 +
   1.715 +    if (mm_flags & FF_MM_MMX) {
   1.716 +        c->clear_block  = clear_block_sse;
   1.717 +        c->clear_blocks = clear_blocks_sse;
   1.718 +        c->prefetch = prefetch_mmx2;
   1.719 +
   1.720 +
   1.721 +#define H264_QPEL_FUNCS(x, y, CPU)\
   1.722 +            c->put_h264_qpel_pixels_tab[0][x+y*4] = put_h264_qpel16_mc##x##y##_##CPU;\
   1.723 +            c->put_h264_qpel_pixels_tab[1][x+y*4] = put_h264_qpel8_mc##x##y##_##CPU;\
   1.724 +            c->avg_h264_qpel_pixels_tab[0][x+y*4] = avg_h264_qpel16_mc##x##y##_##CPU;\
   1.725 +            c->avg_h264_qpel_pixels_tab[1][x+y*4] = avg_h264_qpel8_mc##x##y##_##CPU;
   1.726 +
   1.727 +        if((mm_flags & FF_MM_SSE2)){
   1.728 +            c->put_pixels_tab[0][0] = put_pixels16_sse2;
   1.729 +            c->avg_pixels_tab[0][0] = avg_pixels16_sse2;
   1.730 +
   1.731 +        }
   1.732 +        if(mm_flags & FF_MM_SSE2){
   1.733 +            H264_QPEL_FUNCS(0, 1, sse2);
   1.734 +            H264_QPEL_FUNCS(0, 2, sse2);
   1.735 +            H264_QPEL_FUNCS(0, 3, sse2);
   1.736 +            H264_QPEL_FUNCS(1, 1, sse2);
   1.737 +            H264_QPEL_FUNCS(1, 2, sse2);
   1.738 +            H264_QPEL_FUNCS(1, 3, sse2);
   1.739 +            H264_QPEL_FUNCS(2, 1, sse2);
   1.740 +            H264_QPEL_FUNCS(2, 2, sse2);
   1.741 +            H264_QPEL_FUNCS(2, 3, sse2);
   1.742 +            H264_QPEL_FUNCS(3, 1, sse2);
   1.743 +            H264_QPEL_FUNCS(3, 2, sse2);
   1.744 +            H264_QPEL_FUNCS(3, 3, sse2);
   1.745 +        }
   1.746 +#if HAVE_SSSE3
   1.747 +        if(mm_flags & FF_MM_SSSE3){
   1.748 +            H264_QPEL_FUNCS(1, 0, ssse3);
   1.749 +            H264_QPEL_FUNCS(1, 1, ssse3);
   1.750 +            H264_QPEL_FUNCS(1, 2, ssse3);
   1.751 +            H264_QPEL_FUNCS(1, 3, ssse3);
   1.752 +            H264_QPEL_FUNCS(2, 0, ssse3);
   1.753 +            H264_QPEL_FUNCS(2, 1, ssse3);
   1.754 +            H264_QPEL_FUNCS(2, 2, ssse3);
   1.755 +            H264_QPEL_FUNCS(2, 3, ssse3);
   1.756 +            H264_QPEL_FUNCS(3, 0, ssse3);
   1.757 +            H264_QPEL_FUNCS(3, 1, ssse3);
   1.758 +            H264_QPEL_FUNCS(3, 2, ssse3);
   1.759 +            H264_QPEL_FUNCS(3, 3, ssse3);
   1.760 +
   1.761 +            c->put_h264_chroma_pixels_tab[0]= put_h264_chroma_mc8_ssse3_rnd;
   1.762 +            c->avg_h264_chroma_pixels_tab[0]= avg_h264_chroma_mc8_ssse3_rnd;
   1.763 +            c->put_h264_chroma_pixels_tab[1]= put_h264_chroma_mc4_ssse3;
   1.764 +            c->avg_h264_chroma_pixels_tab[1]= avg_h264_chroma_mc4_ssse3;
   1.765 +        }
   1.766 +#endif
   1.767 +
   1.768 +
   1.769 +    }
   1.770 +}
   1.771 +
   1.772 +void ff_h264dsp_init_x86(H264DSPContext *c)
   1.773 +{
   1.774 +    mm_flags = mm_support();
   1.775 +
   1.776 +    if (mm_flags & FF_MM_MMX) {
   1.777 +        c->h264_idct_dc_add=
   1.778 +        c->h264_idct_add= ff_h264_idct_add_mmx;
   1.779 +        c->h264_idct8_dc_add=
   1.780 +        c->h264_idct8_add= ff_h264_idct8_add_mmx;
   1.781 +
   1.782 +        if (mm_flags & FF_MM_MMX2) {            
   1.783 +            c->h264_idct_dc_add= ff_h264_idct_dc_add_mmx2;
   1.784 +            c->h264_idct_add8      = ff_h264_idct_add8_mmx2;
   1.785 +			c->h264_idct_add16     = ff_h264_idct_add16_mmx2;
   1.786 +            c->h264_idct_add16intra= ff_h264_idct_add16intra_mmx2;
   1.787 +
   1.788 +			c->h264_idct8_dc_add= ff_h264_idct8_dc_add_mmx2;
   1.789 +			c->h264_idct8_add4     = ff_h264_idct8_add4_mmx2;
   1.790 +
   1.791 +			c->h264_v_loop_filter_luma= h264_v_loop_filter_luma_mmx2;
   1.792 +            c->h264_h_loop_filter_luma= h264_h_loop_filter_luma_mmx2;
   1.793 +            c->h264_v_loop_filter_chroma= h264_v_loop_filter_chroma_mmx2;
   1.794 +            c->h264_h_loop_filter_chroma= h264_h_loop_filter_chroma_mmx2;
   1.795 +            c->h264_v_loop_filter_chroma_intra= h264_v_loop_filter_chroma_intra_mmx2;
   1.796 +            c->h264_h_loop_filter_chroma_intra= h264_h_loop_filter_chroma_intra_mmx2;
   1.797 +            c->h264_loop_filter_strength= h264_loop_filter_strength_mmx2;
   1.798 +
   1.799 +            c->weight_h264_pixels_tab[0]= ff_h264_weight_16x16_mmx2;
   1.800 +            c->weight_h264_pixels_tab[1]= ff_h264_weight_16x8_mmx2;
   1.801 +            c->weight_h264_pixels_tab[2]= ff_h264_weight_8x16_mmx2;
   1.802 +            c->weight_h264_pixels_tab[3]= ff_h264_weight_8x8_mmx2;
   1.803 +            c->weight_h264_pixels_tab[4]= ff_h264_weight_8x4_mmx2;
   1.804 +            c->weight_h264_pixels_tab[5]= ff_h264_weight_4x8_mmx2;
   1.805 +            c->weight_h264_pixels_tab[6]= ff_h264_weight_4x4_mmx2;
   1.806 +            c->weight_h264_pixels_tab[7]= ff_h264_weight_4x2_mmx2;
   1.807 +
   1.808 +            c->biweight_h264_pixels_tab[0]= ff_h264_biweight_16x16_mmx2;
   1.809 +            c->biweight_h264_pixels_tab[1]= ff_h264_biweight_16x8_mmx2;
   1.810 +            c->biweight_h264_pixels_tab[2]= ff_h264_biweight_8x16_mmx2;
   1.811 +            c->biweight_h264_pixels_tab[3]= ff_h264_biweight_8x8_mmx2;
   1.812 +            c->biweight_h264_pixels_tab[4]= ff_h264_biweight_8x4_mmx2;
   1.813 +            c->biweight_h264_pixels_tab[5]= ff_h264_biweight_4x8_mmx2;
   1.814 +            c->biweight_h264_pixels_tab[6]= ff_h264_biweight_4x4_mmx2;
   1.815 +            c->biweight_h264_pixels_tab[7]= ff_h264_biweight_4x2_mmx2;
   1.816 +        }
   1.817 +        if(mm_flags & FF_MM_SSE2){
   1.818 +            c->h264_idct8_add = ff_h264_idct8_add_sse2;
   1.819 +            c->h264_idct8_add4= ff_h264_idct8_add4_sse2;
   1.820 +        }
   1.821 +
   1.822 +    }
   1.823 +}
   1.824 +