view i386/dsputil_mmx_avg.h @ 6693:6f13852a9161 libavcodec

Skip blocks in B-frames reuse motion vectors from next reference frame. So if referenced blocks is 16x8, 8x16 or 8x8 partitions, skip block will have them too.
author kostya
date Sat, 26 Apr 2008 13:09:36 +0000
parents 745d65881f5c
children 33896780c612
line wrap: on
line source

/*
 * DSP utils : average functions are compiled twice for 3dnow/mmx2
 * Copyright (c) 2000, 2001 Fabrice Bellard.
 * Copyright (c) 2002-2004 Michael Niedermayer
 *
 * MMX optimization by Nick Kurshev <nickols_k@mail.ru>
 * mostly rewritten by Michael Niedermayer <michaelni@gmx.at>
 * and improved by Zdenek Kabelac <kabi@users.sf.net>
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* This header intentionally has no multiple inclusion guards. It is meant to
 * be included multiple times and generates different code depending on the
 * value of certain #defines. */

/* XXX: we use explicit registers to avoid a gcc 2.95.2 register asm
   clobber bug - now it will work with 2.95.2 and also with -fPIC
 */
static void DEF(put_pixels8_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
{
    asm volatile(
        "lea (%3, %3), %%"REG_a"        \n\t"
        "1:                             \n\t"
        "movq (%1), %%mm0               \n\t"
        "movq (%1, %3), %%mm1           \n\t"
        PAVGB" 1(%1), %%mm0             \n\t"
        PAVGB" 1(%1, %3), %%mm1         \n\t"
        "movq %%mm0, (%2)               \n\t"
        "movq %%mm1, (%2, %3)           \n\t"
        "add %%"REG_a", %1              \n\t"
        "add %%"REG_a", %2              \n\t"
        "movq (%1), %%mm0               \n\t"
        "movq (%1, %3), %%mm1           \n\t"
        PAVGB" 1(%1), %%mm0             \n\t"
        PAVGB" 1(%1, %3), %%mm1         \n\t"
        "add %%"REG_a", %1              \n\t"
        "movq %%mm0, (%2)               \n\t"
        "movq %%mm1, (%2, %3)           \n\t"
        "add %%"REG_a", %2              \n\t"
        "subl $4, %0                    \n\t"
        "jnz 1b                         \n\t"
        :"+g"(h), "+S"(pixels), "+D"(block)
        :"r" ((long)line_size)
        :"%"REG_a, "memory");
}

static void DEF(put_pixels4_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
{
    asm volatile(
        "testl $1, %0                   \n\t"
            " jz 1f                     \n\t"
        "movd   (%1), %%mm0             \n\t"
        "movd   (%2), %%mm1             \n\t"
        "add    %4, %1                  \n\t"
        "add    $4, %2                  \n\t"
        PAVGB" %%mm1, %%mm0             \n\t"
        "movd   %%mm0, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "decl   %0                      \n\t"
        "1:                             \n\t"
        "movd   (%1), %%mm0             \n\t"
        "add    %4, %1                  \n\t"
        "movd   (%1), %%mm1             \n\t"
        "movd   (%2), %%mm2             \n\t"
        "movd   4(%2), %%mm3            \n\t"
        "add    %4, %1                  \n\t"
        PAVGB" %%mm2, %%mm0             \n\t"
        PAVGB" %%mm3, %%mm1             \n\t"
        "movd   %%mm0, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "movd   %%mm1, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "movd   (%1), %%mm0             \n\t"
        "add    %4, %1                  \n\t"
        "movd   (%1), %%mm1             \n\t"
        "movd   8(%2), %%mm2            \n\t"
        "movd   12(%2), %%mm3           \n\t"
        "add    %4, %1                  \n\t"
        PAVGB" %%mm2, %%mm0             \n\t"
        PAVGB" %%mm3, %%mm1             \n\t"
        "movd   %%mm0, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "movd   %%mm1, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "add    $16, %2                 \n\t"
        "subl   $4, %0                  \n\t"
        "jnz    1b                      \n\t"
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
        :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#else
        :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#endif
        :"S"((long)src1Stride), "D"((long)dstStride)
        :"memory");
}


static void DEF(put_pixels8_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
{
    asm volatile(
        "testl $1, %0                   \n\t"
            " jz 1f                     \n\t"
        "movq   (%1), %%mm0             \n\t"
        "movq   (%2), %%mm1             \n\t"
        "add    %4, %1                  \n\t"
        "add    $8, %2                  \n\t"
        PAVGB" %%mm1, %%mm0             \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "decl   %0                      \n\t"
        "1:                             \n\t"
        "movq   (%1), %%mm0             \n\t"
        "add    %4, %1                  \n\t"
        "movq   (%1), %%mm1             \n\t"
        "add    %4, %1                  \n\t"
        PAVGB" (%2), %%mm0              \n\t"
        PAVGB" 8(%2), %%mm1             \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "movq   %%mm1, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "movq   (%1), %%mm0             \n\t"
        "add    %4, %1                  \n\t"
        "movq   (%1), %%mm1             \n\t"
        "add    %4, %1                  \n\t"
        PAVGB" 16(%2), %%mm0            \n\t"
        PAVGB" 24(%2), %%mm1            \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "movq   %%mm1, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "add    $32, %2                 \n\t"
        "subl   $4, %0                  \n\t"
        "jnz    1b                      \n\t"
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
        :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#else
        :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#endif
        :"S"((long)src1Stride), "D"((long)dstStride)
        :"memory");
//the following should be used, though better not with gcc ...
/*        :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
        :"r"(src1Stride), "r"(dstStride)
        :"memory");*/
}

static void DEF(put_no_rnd_pixels8_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
{
    asm volatile(
        "pcmpeqb %%mm6, %%mm6           \n\t"
        "testl $1, %0                   \n\t"
            " jz 1f                     \n\t"
        "movq   (%1), %%mm0             \n\t"
        "movq   (%2), %%mm1             \n\t"
        "add    %4, %1                  \n\t"
        "add    $8, %2                  \n\t"
        "pxor %%mm6, %%mm0              \n\t"
        "pxor %%mm6, %%mm1              \n\t"
        PAVGB" %%mm1, %%mm0             \n\t"
        "pxor %%mm6, %%mm0              \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "decl   %0                      \n\t"
        "1:                             \n\t"
        "movq   (%1), %%mm0             \n\t"
        "add    %4, %1                  \n\t"
        "movq   (%1), %%mm1             \n\t"
        "add    %4, %1                  \n\t"
        "movq   (%2), %%mm2             \n\t"
        "movq   8(%2), %%mm3            \n\t"
        "pxor %%mm6, %%mm0              \n\t"
        "pxor %%mm6, %%mm1              \n\t"
        "pxor %%mm6, %%mm2              \n\t"
        "pxor %%mm6, %%mm3              \n\t"
        PAVGB" %%mm2, %%mm0             \n\t"
        PAVGB" %%mm3, %%mm1             \n\t"
        "pxor %%mm6, %%mm0              \n\t"
        "pxor %%mm6, %%mm1              \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "movq   %%mm1, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "movq   (%1), %%mm0             \n\t"
        "add    %4, %1                  \n\t"
        "movq   (%1), %%mm1             \n\t"
        "add    %4, %1                  \n\t"
        "movq   16(%2), %%mm2           \n\t"
        "movq   24(%2), %%mm3           \n\t"
        "pxor %%mm6, %%mm0              \n\t"
        "pxor %%mm6, %%mm1              \n\t"
        "pxor %%mm6, %%mm2              \n\t"
        "pxor %%mm6, %%mm3              \n\t"
        PAVGB" %%mm2, %%mm0             \n\t"
        PAVGB" %%mm3, %%mm1             \n\t"
        "pxor %%mm6, %%mm0              \n\t"
        "pxor %%mm6, %%mm1              \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "movq   %%mm1, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "add    $32, %2                 \n\t"
        "subl   $4, %0                  \n\t"
        "jnz    1b                      \n\t"
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
        :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#else
        :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#endif
        :"S"((long)src1Stride), "D"((long)dstStride)
        :"memory");
//the following should be used, though better not with gcc ...
/*        :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
        :"r"(src1Stride), "r"(dstStride)
        :"memory");*/
}

static void DEF(avg_pixels4_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
{
    asm volatile(
        "testl $1, %0                   \n\t"
            " jz 1f                     \n\t"
        "movd   (%1), %%mm0             \n\t"
        "movd   (%2), %%mm1             \n\t"
        "add    %4, %1                  \n\t"
        "add    $4, %2                  \n\t"
        PAVGB" %%mm1, %%mm0             \n\t"
        PAVGB" (%3), %%mm0              \n\t"
        "movd   %%mm0, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "decl   %0                      \n\t"
        "1:                             \n\t"
        "movd   (%1), %%mm0             \n\t"
        "add    %4, %1                  \n\t"
        "movd   (%1), %%mm1             \n\t"
        "add    %4, %1                  \n\t"
        PAVGB" (%2), %%mm0              \n\t"
        PAVGB" 4(%2), %%mm1             \n\t"
        PAVGB" (%3), %%mm0              \n\t"
        "movd   %%mm0, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        PAVGB" (%3), %%mm1              \n\t"
        "movd   %%mm1, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "movd   (%1), %%mm0             \n\t"
        "add    %4, %1                  \n\t"
        "movd   (%1), %%mm1             \n\t"
        "add    %4, %1                  \n\t"
        PAVGB" 8(%2), %%mm0             \n\t"
        PAVGB" 12(%2), %%mm1            \n\t"
        PAVGB" (%3), %%mm0              \n\t"
        "movd   %%mm0, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        PAVGB" (%3), %%mm1              \n\t"
        "movd   %%mm1, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "add    $16, %2                 \n\t"
        "subl   $4, %0                  \n\t"
        "jnz    1b                      \n\t"
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
        :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#else
        :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#endif
        :"S"((long)src1Stride), "D"((long)dstStride)
        :"memory");
}


static void DEF(avg_pixels8_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
{
    asm volatile(
        "testl $1, %0                   \n\t"
            " jz 1f                     \n\t"
        "movq   (%1), %%mm0             \n\t"
        "movq   (%2), %%mm1             \n\t"
        "add    %4, %1                  \n\t"
        "add    $8, %2                  \n\t"
        PAVGB" %%mm1, %%mm0             \n\t"
        PAVGB" (%3), %%mm0              \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "decl   %0                      \n\t"
        "1:                             \n\t"
        "movq   (%1), %%mm0             \n\t"
        "add    %4, %1                  \n\t"
        "movq   (%1), %%mm1             \n\t"
        "add    %4, %1                  \n\t"
        PAVGB" (%2), %%mm0              \n\t"
        PAVGB" 8(%2), %%mm1             \n\t"
        PAVGB" (%3), %%mm0              \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        PAVGB" (%3), %%mm1              \n\t"
        "movq   %%mm1, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "movq   (%1), %%mm0             \n\t"
        "add    %4, %1                  \n\t"
        "movq   (%1), %%mm1             \n\t"
        "add    %4, %1                  \n\t"
        PAVGB" 16(%2), %%mm0            \n\t"
        PAVGB" 24(%2), %%mm1            \n\t"
        PAVGB" (%3), %%mm0              \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        PAVGB" (%3), %%mm1              \n\t"
        "movq   %%mm1, (%3)             \n\t"
        "add    %5, %3                  \n\t"
        "add    $32, %2                 \n\t"
        "subl   $4, %0                  \n\t"
        "jnz    1b                      \n\t"
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
        :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#else
        :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#endif
        :"S"((long)src1Stride), "D"((long)dstStride)
        :"memory");
//the following should be used, though better not with gcc ...
/*        :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
        :"r"(src1Stride), "r"(dstStride)
        :"memory");*/
}

static void DEF(put_pixels16_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
{
    asm volatile(
        "lea (%3, %3), %%"REG_a"        \n\t"
        "1:                             \n\t"
        "movq (%1), %%mm0               \n\t"
        "movq (%1, %3), %%mm1           \n\t"
        "movq 8(%1), %%mm2              \n\t"
        "movq 8(%1, %3), %%mm3          \n\t"
        PAVGB" 1(%1), %%mm0             \n\t"
        PAVGB" 1(%1, %3), %%mm1         \n\t"
        PAVGB" 9(%1), %%mm2             \n\t"
        PAVGB" 9(%1, %3), %%mm3         \n\t"
        "movq %%mm0, (%2)               \n\t"
        "movq %%mm1, (%2, %3)           \n\t"
        "movq %%mm2, 8(%2)              \n\t"
        "movq %%mm3, 8(%2, %3)          \n\t"
        "add %%"REG_a", %1              \n\t"
        "add %%"REG_a", %2              \n\t"
        "movq (%1), %%mm0               \n\t"
        "movq (%1, %3), %%mm1           \n\t"
        "movq 8(%1), %%mm2              \n\t"
        "movq 8(%1, %3), %%mm3          \n\t"
        PAVGB" 1(%1), %%mm0             \n\t"
        PAVGB" 1(%1, %3), %%mm1         \n\t"
        PAVGB" 9(%1), %%mm2             \n\t"
        PAVGB" 9(%1, %3), %%mm3         \n\t"
        "add %%"REG_a", %1              \n\t"
        "movq %%mm0, (%2)               \n\t"
        "movq %%mm1, (%2, %3)           \n\t"
        "movq %%mm2, 8(%2)              \n\t"
        "movq %%mm3, 8(%2, %3)          \n\t"
        "add %%"REG_a", %2              \n\t"
        "subl $4, %0                    \n\t"
        "jnz 1b                         \n\t"
        :"+g"(h), "+S"(pixels), "+D"(block)
        :"r" ((long)line_size)
        :"%"REG_a, "memory");
}

static void DEF(put_pixels16_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
{
    asm volatile(
        "testl $1, %0                   \n\t"
            " jz 1f                     \n\t"
        "movq   (%1), %%mm0             \n\t"
        "movq   8(%1), %%mm1            \n\t"
        PAVGB" (%2), %%mm0              \n\t"
        PAVGB" 8(%2), %%mm1             \n\t"
        "add    %4, %1                  \n\t"
        "add    $16, %2                 \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "movq   %%mm1, 8(%3)            \n\t"
        "add    %5, %3                  \n\t"
        "decl   %0                      \n\t"
        "1:                             \n\t"
        "movq   (%1), %%mm0             \n\t"
        "movq   8(%1), %%mm1            \n\t"
        "add    %4, %1                  \n\t"
        PAVGB" (%2), %%mm0              \n\t"
        PAVGB" 8(%2), %%mm1             \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "movq   %%mm1, 8(%3)            \n\t"
        "add    %5, %3                  \n\t"
        "movq   (%1), %%mm0             \n\t"
        "movq   8(%1), %%mm1            \n\t"
        "add    %4, %1                  \n\t"
        PAVGB" 16(%2), %%mm0            \n\t"
        PAVGB" 24(%2), %%mm1            \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "movq   %%mm1, 8(%3)            \n\t"
        "add    %5, %3                  \n\t"
        "add    $32, %2                 \n\t"
        "subl   $2, %0                  \n\t"
        "jnz    1b                      \n\t"
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
        :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#else
        :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#endif
        :"S"((long)src1Stride), "D"((long)dstStride)
        :"memory");
//the following should be used, though better not with gcc ...
/*        :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
        :"r"(src1Stride), "r"(dstStride)
        :"memory");*/
}

static void DEF(avg_pixels16_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
{
    asm volatile(
        "testl $1, %0                   \n\t"
            " jz 1f                     \n\t"
        "movq   (%1), %%mm0             \n\t"
        "movq   8(%1), %%mm1            \n\t"
        PAVGB" (%2), %%mm0              \n\t"
        PAVGB" 8(%2), %%mm1             \n\t"
        "add    %4, %1                  \n\t"
        "add    $16, %2                 \n\t"
        PAVGB" (%3), %%mm0              \n\t"
        PAVGB" 8(%3), %%mm1             \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "movq   %%mm1, 8(%3)            \n\t"
        "add    %5, %3                  \n\t"
        "decl   %0                      \n\t"
        "1:                             \n\t"
        "movq   (%1), %%mm0             \n\t"
        "movq   8(%1), %%mm1            \n\t"
        "add    %4, %1                  \n\t"
        PAVGB" (%2), %%mm0              \n\t"
        PAVGB" 8(%2), %%mm1             \n\t"
        PAVGB" (%3), %%mm0              \n\t"
        PAVGB" 8(%3), %%mm1             \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "movq   %%mm1, 8(%3)            \n\t"
        "add    %5, %3                  \n\t"
        "movq   (%1), %%mm0             \n\t"
        "movq   8(%1), %%mm1            \n\t"
        "add    %4, %1                  \n\t"
        PAVGB" 16(%2), %%mm0            \n\t"
        PAVGB" 24(%2), %%mm1            \n\t"
        PAVGB" (%3), %%mm0              \n\t"
        PAVGB" 8(%3), %%mm1             \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "movq   %%mm1, 8(%3)            \n\t"
        "add    %5, %3                  \n\t"
        "add    $32, %2                 \n\t"
        "subl   $2, %0                  \n\t"
        "jnz    1b                      \n\t"
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
        :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#else
        :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#endif
        :"S"((long)src1Stride), "D"((long)dstStride)
        :"memory");
//the following should be used, though better not with gcc ...
/*        :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
        :"r"(src1Stride), "r"(dstStride)
        :"memory");*/
}

static void DEF(put_no_rnd_pixels16_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
{
    asm volatile(
        "pcmpeqb %%mm6, %%mm6           \n\t"
        "testl $1, %0                   \n\t"
            " jz 1f                     \n\t"
        "movq   (%1), %%mm0             \n\t"
        "movq   8(%1), %%mm1            \n\t"
        "movq   (%2), %%mm2             \n\t"
        "movq   8(%2), %%mm3            \n\t"
        "pxor %%mm6, %%mm0              \n\t"
        "pxor %%mm6, %%mm1              \n\t"
        "pxor %%mm6, %%mm2              \n\t"
        "pxor %%mm6, %%mm3              \n\t"
        PAVGB" %%mm2, %%mm0             \n\t"
        PAVGB" %%mm3, %%mm1             \n\t"
        "pxor %%mm6, %%mm0              \n\t"
        "pxor %%mm6, %%mm1              \n\t"
        "add    %4, %1                  \n\t"
        "add    $16, %2                 \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "movq   %%mm1, 8(%3)            \n\t"
        "add    %5, %3                  \n\t"
        "decl   %0                      \n\t"
        "1:                             \n\t"
        "movq   (%1), %%mm0             \n\t"
        "movq   8(%1), %%mm1            \n\t"
        "add    %4, %1                  \n\t"
        "movq   (%2), %%mm2             \n\t"
        "movq   8(%2), %%mm3            \n\t"
        "pxor %%mm6, %%mm0              \n\t"
        "pxor %%mm6, %%mm1              \n\t"
        "pxor %%mm6, %%mm2              \n\t"
        "pxor %%mm6, %%mm3              \n\t"
        PAVGB" %%mm2, %%mm0             \n\t"
        PAVGB" %%mm3, %%mm1             \n\t"
        "pxor %%mm6, %%mm0              \n\t"
        "pxor %%mm6, %%mm1              \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "movq   %%mm1, 8(%3)            \n\t"
        "add    %5, %3                  \n\t"
        "movq   (%1), %%mm0             \n\t"
        "movq   8(%1), %%mm1            \n\t"
        "add    %4, %1                  \n\t"
        "movq   16(%2), %%mm2           \n\t"
        "movq   24(%2), %%mm3           \n\t"
        "pxor %%mm6, %%mm0              \n\t"
        "pxor %%mm6, %%mm1              \n\t"
        "pxor %%mm6, %%mm2              \n\t"
        "pxor %%mm6, %%mm3              \n\t"
        PAVGB" %%mm2, %%mm0             \n\t"
        PAVGB" %%mm3, %%mm1             \n\t"
        "pxor %%mm6, %%mm0              \n\t"
        "pxor %%mm6, %%mm1              \n\t"
        "movq   %%mm0, (%3)             \n\t"
        "movq   %%mm1, 8(%3)            \n\t"
        "add    %5, %3                  \n\t"
        "add    $32, %2                 \n\t"
        "subl   $2, %0                  \n\t"
        "jnz    1b                      \n\t"
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
        :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#else
        :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
#endif
        :"S"((long)src1Stride), "D"((long)dstStride)
        :"memory");
//the following should be used, though better not with gcc ...
/*        :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
        :"r"(src1Stride), "r"(dstStride)
        :"memory");*/
}

/* GL: this function does incorrect rounding if overflow */
static void DEF(put_no_rnd_pixels8_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
{
    MOVQ_BONE(mm6);
    asm volatile(
        "lea (%3, %3), %%"REG_a"        \n\t"
        "1:                             \n\t"
        "movq (%1), %%mm0               \n\t"
        "movq (%1, %3), %%mm2           \n\t"
        "movq 1(%1), %%mm1              \n\t"
        "movq 1(%1, %3), %%mm3          \n\t"
        "add %%"REG_a", %1              \n\t"
        "psubusb %%mm6, %%mm0           \n\t"
        "psubusb %%mm6, %%mm2           \n\t"
        PAVGB" %%mm1, %%mm0             \n\t"
        PAVGB" %%mm3, %%mm2             \n\t"
        "movq %%mm0, (%2)               \n\t"
        "movq %%mm2, (%2, %3)           \n\t"
        "movq (%1), %%mm0               \n\t"
        "movq 1(%1), %%mm1              \n\t"
        "movq (%1, %3), %%mm2           \n\t"
        "movq 1(%1, %3), %%mm3          \n\t"
        "add %%"REG_a", %2              \n\t"
        "add %%"REG_a", %1              \n\t"
        "psubusb %%mm6, %%mm0           \n\t"
        "psubusb %%mm6, %%mm2           \n\t"
        PAVGB" %%mm1, %%mm0             \n\t"
        PAVGB" %%mm3, %%mm2             \n\t"
        "movq %%mm0, (%2)               \n\t"
        "movq %%mm2, (%2, %3)           \n\t"
        "add %%"REG_a", %2              \n\t"
        "subl $4, %0                    \n\t"
        "jnz 1b                         \n\t"
        :"+g"(h), "+S"(pixels), "+D"(block)
        :"r" ((long)line_size)
        :"%"REG_a, "memory");
}

static void DEF(put_pixels8_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
{
    asm volatile(
        "lea (%3, %3), %%"REG_a"        \n\t"
        "movq (%1), %%mm0               \n\t"
        "sub %3, %2                     \n\t"
        "1:                             \n\t"
        "movq (%1, %3), %%mm1           \n\t"
        "movq (%1, %%"REG_a"), %%mm2    \n\t"
        "add %%"REG_a", %1              \n\t"
        PAVGB" %%mm1, %%mm0             \n\t"
        PAVGB" %%mm2, %%mm1             \n\t"
        "movq %%mm0, (%2, %3)           \n\t"
        "movq %%mm1, (%2, %%"REG_a")    \n\t"
        "movq (%1, %3), %%mm1           \n\t"
        "movq (%1, %%"REG_a"), %%mm0    \n\t"
        "add %%"REG_a", %2              \n\t"
        "add %%"REG_a", %1              \n\t"
        PAVGB" %%mm1, %%mm2             \n\t"
        PAVGB" %%mm0, %%mm1             \n\t"
        "movq %%mm2, (%2, %3)           \n\t"
        "movq %%mm1, (%2, %%"REG_a")    \n\t"
        "add %%"REG_a", %2              \n\t"
        "subl $4, %0                    \n\t"
        "jnz 1b                         \n\t"
        :"+g"(h), "+S"(pixels), "+D" (block)
        :"r" ((long)line_size)
        :"%"REG_a, "memory");
}

/* GL: this function does incorrect rounding if overflow */
static void DEF(put_no_rnd_pixels8_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
{
    MOVQ_BONE(mm6);
    asm volatile(
        "lea (%3, %3), %%"REG_a"        \n\t"
        "movq (%1), %%mm0               \n\t"
        "sub %3, %2                     \n\t"
        "1:                             \n\t"
        "movq (%1, %3), %%mm1           \n\t"
        "movq (%1, %%"REG_a"), %%mm2    \n\t"
        "add %%"REG_a", %1              \n\t"
        "psubusb %%mm6, %%mm1           \n\t"
        PAVGB" %%mm1, %%mm0             \n\t"
        PAVGB" %%mm2, %%mm1             \n\t"
        "movq %%mm0, (%2, %3)           \n\t"
        "movq %%mm1, (%2, %%"REG_a")    \n\t"
        "movq (%1, %3), %%mm1           \n\t"
        "movq (%1, %%"REG_a"), %%mm0    \n\t"
        "add %%"REG_a", %2              \n\t"
        "add %%"REG_a", %1              \n\t"
        "psubusb %%mm6, %%mm1           \n\t"
        PAVGB" %%mm1, %%mm2             \n\t"
        PAVGB" %%mm0, %%mm1             \n\t"
        "movq %%mm2, (%2, %3)           \n\t"
        "movq %%mm1, (%2, %%"REG_a")    \n\t"
        "add %%"REG_a", %2              \n\t"
        "subl $4, %0                    \n\t"
        "jnz 1b                         \n\t"
        :"+g"(h), "+S"(pixels), "+D" (block)
        :"r" ((long)line_size)
        :"%"REG_a, "memory");
}

static void DEF(avg_pixels8)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
{
    asm volatile(
        "lea (%3, %3), %%"REG_a"        \n\t"
        "1:                             \n\t"
        "movq (%2), %%mm0               \n\t"
        "movq (%2, %3), %%mm1           \n\t"
        PAVGB" (%1), %%mm0              \n\t"
        PAVGB" (%1, %3), %%mm1          \n\t"
        "movq %%mm0, (%2)               \n\t"
        "movq %%mm1, (%2, %3)           \n\t"
        "add %%"REG_a", %1              \n\t"
        "add %%"REG_a", %2              \n\t"
        "movq (%2), %%mm0               \n\t"
        "movq (%2, %3), %%mm1           \n\t"
        PAVGB" (%1), %%mm0              \n\t"
        PAVGB" (%1, %3), %%mm1          \n\t"
        "add %%"REG_a", %1              \n\t"
        "movq %%mm0, (%2)               \n\t"
        "movq %%mm1, (%2, %3)           \n\t"
        "add %%"REG_a", %2              \n\t"
        "subl $4, %0                    \n\t"
        "jnz 1b                         \n\t"
        :"+g"(h), "+S"(pixels), "+D"(block)
        :"r" ((long)line_size)
        :"%"REG_a, "memory");
}

static void DEF(avg_pixels8_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
{
    asm volatile(
        "lea (%3, %3), %%"REG_a"        \n\t"
        "1:                             \n\t"
        "movq (%1), %%mm0               \n\t"
        "movq (%1, %3), %%mm2           \n\t"
        PAVGB" 1(%1), %%mm0             \n\t"
        PAVGB" 1(%1, %3), %%mm2         \n\t"
        PAVGB" (%2), %%mm0              \n\t"
        PAVGB" (%2, %3), %%mm2          \n\t"
        "add %%"REG_a", %1              \n\t"
        "movq %%mm0, (%2)               \n\t"
        "movq %%mm2, (%2, %3)           \n\t"
        "movq (%1), %%mm0               \n\t"
        "movq (%1, %3), %%mm2           \n\t"
        PAVGB" 1(%1), %%mm0             \n\t"
        PAVGB" 1(%1, %3), %%mm2         \n\t"
        "add %%"REG_a", %2              \n\t"
        "add %%"REG_a", %1              \n\t"
        PAVGB" (%2), %%mm0              \n\t"
        PAVGB" (%2, %3), %%mm2          \n\t"
        "movq %%mm0, (%2)               \n\t"
        "movq %%mm2, (%2, %3)           \n\t"
        "add %%"REG_a", %2              \n\t"
        "subl $4, %0                    \n\t"
        "jnz 1b                         \n\t"
        :"+g"(h), "+S"(pixels), "+D"(block)
        :"r" ((long)line_size)
        :"%"REG_a, "memory");
}

static void DEF(avg_pixels8_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
{
    asm volatile(
        "lea (%3, %3), %%"REG_a"        \n\t"
        "movq (%1), %%mm0               \n\t"
        "sub %3, %2                     \n\t"
        "1:                             \n\t"
        "movq (%1, %3), %%mm1           \n\t"
        "movq (%1, %%"REG_a"), %%mm2    \n\t"
        "add %%"REG_a", %1              \n\t"
        PAVGB" %%mm1, %%mm0             \n\t"
        PAVGB" %%mm2, %%mm1             \n\t"
        "movq (%2, %3), %%mm3           \n\t"
        "movq (%2, %%"REG_a"), %%mm4    \n\t"
        PAVGB" %%mm3, %%mm0             \n\t"
        PAVGB" %%mm4, %%mm1             \n\t"
        "movq %%mm0, (%2, %3)           \n\t"
        "movq %%mm1, (%2, %%"REG_a")    \n\t"
        "movq (%1, %3), %%mm1           \n\t"
        "movq (%1, %%"REG_a"), %%mm0    \n\t"
        PAVGB" %%mm1, %%mm2             \n\t"
        PAVGB" %%mm0, %%mm1             \n\t"
        "add %%"REG_a", %2              \n\t"
        "add %%"REG_a", %1              \n\t"
        "movq (%2, %3), %%mm3           \n\t"
        "movq (%2, %%"REG_a"), %%mm4    \n\t"
        PAVGB" %%mm3, %%mm2             \n\t"
        PAVGB" %%mm4, %%mm1             \n\t"
        "movq %%mm2, (%2, %3)           \n\t"
        "movq %%mm1, (%2, %%"REG_a")    \n\t"
        "add %%"REG_a", %2              \n\t"
        "subl $4, %0                    \n\t"
        "jnz 1b                         \n\t"
        :"+g"(h), "+S"(pixels), "+D"(block)
        :"r" ((long)line_size)
        :"%"REG_a, "memory");
}

/* Note this is not correctly rounded, but this function is only
 * used for B-frames so it does not matter. */
static void DEF(avg_pixels8_xy2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
{
    MOVQ_BONE(mm6);
    asm volatile(
        "lea (%3, %3), %%"REG_a"        \n\t"
        "movq (%1), %%mm0               \n\t"
        PAVGB" 1(%1), %%mm0             \n\t"
         ASMALIGN(3)
        "1:                             \n\t"
        "movq (%1, %%"REG_a"), %%mm2    \n\t"
        "movq (%1, %3), %%mm1           \n\t"
        "psubusb %%mm6, %%mm2           \n\t"
        PAVGB" 1(%1, %3), %%mm1         \n\t"
        PAVGB" 1(%1, %%"REG_a"), %%mm2  \n\t"
        "add %%"REG_a", %1              \n\t"
        PAVGB" %%mm1, %%mm0             \n\t"
        PAVGB" %%mm2, %%mm1             \n\t"
        PAVGB" (%2), %%mm0              \n\t"
        PAVGB" (%2, %3), %%mm1          \n\t"
        "movq %%mm0, (%2)               \n\t"
        "movq %%mm1, (%2, %3)           \n\t"
        "movq (%1, %3), %%mm1           \n\t"
        "movq (%1, %%"REG_a"), %%mm0    \n\t"
        PAVGB" 1(%1, %3), %%mm1         \n\t"
        PAVGB" 1(%1, %%"REG_a"), %%mm0  \n\t"
        "add %%"REG_a", %2              \n\t"
        "add %%"REG_a", %1              \n\t"
        PAVGB" %%mm1, %%mm2             \n\t"
        PAVGB" %%mm0, %%mm1             \n\t"
        PAVGB" (%2), %%mm2              \n\t"
        PAVGB" (%2, %3), %%mm1          \n\t"
        "movq %%mm2, (%2)               \n\t"
        "movq %%mm1, (%2, %3)           \n\t"
        "add %%"REG_a", %2              \n\t"
        "subl $4, %0                    \n\t"
        "jnz 1b                         \n\t"
        :"+g"(h), "+S"(pixels), "+D"(block)
        :"r" ((long)line_size)
        :"%"REG_a,  "memory");
}

static void DEF(avg_pixels4)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
{
    do {
        asm volatile(
            "movd (%1), %%mm0               \n\t"
            "movd (%1, %2), %%mm1           \n\t"
            "movd (%1, %2, 2), %%mm2        \n\t"
            "movd (%1, %3), %%mm3           \n\t"
            PAVGB" (%0), %%mm0              \n\t"
            PAVGB" (%0, %2), %%mm1          \n\t"
            PAVGB" (%0, %2, 2), %%mm2       \n\t"
            PAVGB" (%0, %3), %%mm3          \n\t"
            "movd %%mm0, (%1)               \n\t"
            "movd %%mm1, (%1, %2)           \n\t"
            "movd %%mm2, (%1, %2, 2)        \n\t"
            "movd %%mm3, (%1, %3)           \n\t"
            ::"S"(pixels), "D"(block),
             "r" ((long)line_size), "r"(3L*line_size)
            :"memory");
        block += 4*line_size;
        pixels += 4*line_size;
        h -= 4;
    } while(h > 0);
}

//FIXME the following could be optimized too ...
static void DEF(put_no_rnd_pixels16_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
    DEF(put_no_rnd_pixels8_x2)(block  , pixels  , line_size, h);
    DEF(put_no_rnd_pixels8_x2)(block+8, pixels+8, line_size, h);
}
static void DEF(put_pixels16_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
    DEF(put_pixels8_y2)(block  , pixels  , line_size, h);
    DEF(put_pixels8_y2)(block+8, pixels+8, line_size, h);
}
static void DEF(put_no_rnd_pixels16_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
    DEF(put_no_rnd_pixels8_y2)(block  , pixels  , line_size, h);
    DEF(put_no_rnd_pixels8_y2)(block+8, pixels+8, line_size, h);
}
static void DEF(avg_pixels16)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
    DEF(avg_pixels8)(block  , pixels  , line_size, h);
    DEF(avg_pixels8)(block+8, pixels+8, line_size, h);
}
static void DEF(avg_pixels16_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
    DEF(avg_pixels8_x2)(block  , pixels  , line_size, h);
    DEF(avg_pixels8_x2)(block+8, pixels+8, line_size, h);
}
static void DEF(avg_pixels16_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
    DEF(avg_pixels8_y2)(block  , pixels  , line_size, h);
    DEF(avg_pixels8_y2)(block+8, pixels+8, line_size, h);
}
static void DEF(avg_pixels16_xy2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
    DEF(avg_pixels8_xy2)(block  , pixels  , line_size, h);
    DEF(avg_pixels8_xy2)(block+8, pixels+8, line_size, h);
}

#define QPEL_2TAP_L3(OPNAME) \
static void DEF(OPNAME ## 2tap_qpel16_l3)(uint8_t *dst, uint8_t *src, int stride, int h, int off1, int off2){\
    asm volatile(\
        "1:                    \n\t"\
        "movq   (%1,%2), %%mm0 \n\t"\
        "movq  8(%1,%2), %%mm1 \n\t"\
        PAVGB"  (%1,%3), %%mm0 \n\t"\
        PAVGB" 8(%1,%3), %%mm1 \n\t"\
        PAVGB"  (%1),    %%mm0 \n\t"\
        PAVGB" 8(%1),    %%mm1 \n\t"\
        STORE_OP( (%1,%4),%%mm0)\
        STORE_OP(8(%1,%4),%%mm1)\
        "movq  %%mm0,  (%1,%4) \n\t"\
        "movq  %%mm1, 8(%1,%4) \n\t"\
        "add   %5, %1          \n\t"\
        "decl  %0              \n\t"\
        "jnz   1b              \n\t"\
        :"+g"(h), "+r"(src)\
        :"r"((long)off1), "r"((long)off2),\
         "r"((long)(dst-src)), "r"((long)stride)\
        :"memory"\
    );\
}\
static void DEF(OPNAME ## 2tap_qpel8_l3)(uint8_t *dst, uint8_t *src, int stride, int h, int off1, int off2){\
    asm volatile(\
        "1:                    \n\t"\
        "movq   (%1,%2), %%mm0 \n\t"\
        PAVGB"  (%1,%3), %%mm0 \n\t"\
        PAVGB"  (%1),    %%mm0 \n\t"\
        STORE_OP((%1,%4),%%mm0)\
        "movq  %%mm0,  (%1,%4) \n\t"\
        "add   %5, %1          \n\t"\
        "decl  %0              \n\t"\
        "jnz   1b              \n\t"\
        :"+g"(h), "+r"(src)\
        :"r"((long)off1), "r"((long)off2),\
         "r"((long)(dst-src)), "r"((long)stride)\
        :"memory"\
    );\
}

#define STORE_OP(a,b) PAVGB" "#a","#b" \n\t"
QPEL_2TAP_L3(avg_)
#undef STORE_OP
#define STORE_OP(a,b)
QPEL_2TAP_L3(put_)
#undef STORE_OP
#undef QPEL_2TAP_L3