Skip to content
Snippets Groups Projects
postprocess.c 94.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • 		"paddsb (%2, %%ecx, 8), %%mm0			\n\t"\
    
    		"paddb %%mm6, %%mm0				\n\t"\
    		"movq %%mm0, " #d "				\n\t"\
    
    HX1b((%0),(%%eax),(%%eax, %1),(%%eax, %1, 2))
    HX1b((%0, %1, 4),(%%ebx),(%%ebx, %1),(%%ebx, %1, 2))
    
    
    		:
    
    		: "r" (src), "r" (stride), "r" (lut)
    
    		: "%eax", "%ebx", "%ecx"
    	);
    #else
    
    //FIXME (has little in common with the mmx2 version)
    	for(y=0; y<BLOCK_SIZE; y++)
    	{
    		int a= src[1] - src[2];
    		int b= src[3] - src[4];
    		int c= src[5] - src[6];
    
    		int d= MAX(ABS(b) - (ABS(a) + ABS(c))/2, 0);
    
    		if(d < QP)
    		{
    			int v = d * SIGN(-b);
    
    			src[1] +=v/8;
    			src[2] +=v/4;
    			src[3] +=3*v/8;
    			src[4] -=3*v/8;
    			src[5] -=v/4;
    			src[6] -=v/8;
    
    		}
    		src+=stride;
    	}
    #endif
    }
    
    
    static inline void doVertDefFilter(uint8_t src[], int stride, int QP)
    {
    #ifdef HAVE_MMX
    
    	src+= stride*4;
    
    	//FIXME try pmul for *5 stuff
    //	src[0]=0;
    	asm volatile(
    		"pxor %%mm7, %%mm7				\n\t"
    		"leal (%0, %1), %%eax				\n\t"
    		"leal (%%eax, %1, 4), %%ebx			\n\t"
    //	0	1	2	3	4	5	6	7
    //	%0	%0+%1	%0+2%1	eax+2%1	%0+4%1	eax+4%1	ebx+%1	ebx+2%1
    //	%0	eax	eax+%1	eax+2%1	%0+4%1	ebx	ebx+%1	ebx+2%1
    
    		"movq (%0), %%mm0				\n\t"
    		"movq %%mm0, %%mm1				\n\t"
    		"punpcklbw %%mm7, %%mm0				\n\t" // low part of line 0
    		"punpckhbw %%mm7, %%mm1				\n\t" // high part of line 0
    
    		"movq (%%eax), %%mm2				\n\t"
    		"movq %%mm2, %%mm3				\n\t"
    		"punpcklbw %%mm7, %%mm2				\n\t" // low part of line 1
    		"punpckhbw %%mm7, %%mm3				\n\t" // high part of line 1
    
    		"movq (%%eax, %1), %%mm4			\n\t"
    		"movq %%mm4, %%mm5				\n\t"
    		"punpcklbw %%mm7, %%mm4				\n\t" // low part of line 2
    		"punpckhbw %%mm7, %%mm5				\n\t" // high part of line 2
    
    		"paddw %%mm0, %%mm0				\n\t" // 2L0
    		"paddw %%mm1, %%mm1				\n\t" // 2H0
    		"psubw %%mm4, %%mm2				\n\t" // L1 - L2
    		"psubw %%mm5, %%mm3				\n\t" // H1 - H2
    		"psubw %%mm2, %%mm0				\n\t" // 2L0 - L1 + L2
    		"psubw %%mm3, %%mm1				\n\t" // 2H0 - H1 + H2
    
    		"psllw $2, %%mm2				\n\t" // 4L1 - 4L2
    		"psllw $2, %%mm3				\n\t" // 4H1 - 4H2
    		"psubw %%mm2, %%mm0				\n\t" // 2L0 - 5L1 + 5L2
    		"psubw %%mm3, %%mm1				\n\t" // 2H0 - 5H1 + 5H2
    
    		"movq (%%eax, %1, 2), %%mm2			\n\t"
    		"movq %%mm2, %%mm3				\n\t"
    		"punpcklbw %%mm7, %%mm2				\n\t" // L3
    		"punpckhbw %%mm7, %%mm3				\n\t" // H3
    
    		"psubw %%mm2, %%mm0				\n\t" // 2L0 - 5L1 + 5L2 - L3
    		"psubw %%mm3, %%mm1				\n\t" // 2H0 - 5H1 + 5H2 - H3
    		"psubw %%mm2, %%mm0				\n\t" // 2L0 - 5L1 + 5L2 - 2L3
    		"psubw %%mm3, %%mm1				\n\t" // 2H0 - 5H1 + 5H2 - 2H3
    		"movq %%mm0, temp0				\n\t" // 2L0 - 5L1 + 5L2 - 2L3
    		"movq %%mm1, temp1				\n\t" // 2H0 - 5H1 + 5H2 - 2H3
    
    		"movq (%0, %1, 4), %%mm0			\n\t"
    		"movq %%mm0, %%mm1				\n\t"
    		"punpcklbw %%mm7, %%mm0				\n\t" // L4
    		"punpckhbw %%mm7, %%mm1				\n\t" // H4
    
    		"psubw %%mm0, %%mm2				\n\t" // L3 - L4
    		"psubw %%mm1, %%mm3				\n\t" // H3 - H4
    		"movq %%mm2, temp2				\n\t" // L3 - L4
    		"movq %%mm3, temp3				\n\t" // H3 - H4
    		"paddw %%mm4, %%mm4				\n\t" // 2L2
    		"paddw %%mm5, %%mm5				\n\t" // 2H2
    		"psubw %%mm2, %%mm4				\n\t" // 2L2 - L3 + L4
    		"psubw %%mm3, %%mm5				\n\t" // 2H2 - H3 + H4
    
    		"psllw $2, %%mm2				\n\t" // 4L3 - 4L4
    		"psllw $2, %%mm3				\n\t" // 4H3 - 4H4
    		"psubw %%mm2, %%mm4				\n\t" // 2L2 - 5L3 + 5L4
    		"psubw %%mm3, %%mm5				\n\t" // 2H2 - 5H3 + 5H4
    //50 opcodes so far
    		"movq (%%ebx), %%mm2				\n\t"
    		"movq %%mm2, %%mm3				\n\t"
    		"punpcklbw %%mm7, %%mm2				\n\t" // L5
    		"punpckhbw %%mm7, %%mm3				\n\t" // H5
    		"psubw %%mm2, %%mm4				\n\t" // 2L2 - 5L3 + 5L4 - L5
    		"psubw %%mm3, %%mm5				\n\t" // 2H2 - 5H3 + 5H4 - H5
    		"psubw %%mm2, %%mm4				\n\t" // 2L2 - 5L3 + 5L4 - 2L5
    		"psubw %%mm3, %%mm5				\n\t" // 2H2 - 5H3 + 5H4 - 2H5
    
    		"movq (%%ebx, %1), %%mm6			\n\t"
    		"punpcklbw %%mm7, %%mm6				\n\t" // L6
    		"psubw %%mm6, %%mm2				\n\t" // L5 - L6
    		"movq (%%ebx, %1), %%mm6			\n\t"
    		"punpckhbw %%mm7, %%mm6				\n\t" // H6
    		"psubw %%mm6, %%mm3				\n\t" // H5 - H6
    
    		"paddw %%mm0, %%mm0				\n\t" // 2L4
    		"paddw %%mm1, %%mm1				\n\t" // 2H4
    		"psubw %%mm2, %%mm0				\n\t" // 2L4 - L5 + L6
    		"psubw %%mm3, %%mm1				\n\t" // 2H4 - H5 + H6
    
    		"psllw $2, %%mm2				\n\t" // 4L5 - 4L6
    		"psllw $2, %%mm3				\n\t" // 4H5 - 4H6
    		"psubw %%mm2, %%mm0				\n\t" // 2L4 - 5L5 + 5L6
    		"psubw %%mm3, %%mm1				\n\t" // 2H4 - 5H5 + 5H6
    
    		"movq (%%ebx, %1, 2), %%mm2			\n\t"
    		"movq %%mm2, %%mm3				\n\t"
    		"punpcklbw %%mm7, %%mm2				\n\t" // L7
    		"punpckhbw %%mm7, %%mm3				\n\t" // H7
    
    		"paddw %%mm2, %%mm2				\n\t" // 2L7
    		"paddw %%mm3, %%mm3				\n\t" // 2H7
    		"psubw %%mm2, %%mm0				\n\t" // 2L4 - 5L5 + 5L6 - 2L7
    		"psubw %%mm3, %%mm1				\n\t" // 2H4 - 5H5 + 5H6 - 2H7
    
    		"movq temp0, %%mm2				\n\t" // 2L0 - 5L1 + 5L2 - 2L3
    		"movq temp1, %%mm3				\n\t" // 2H0 - 5H1 + 5H2 - 2H3
    //FIXME pxor, psubw, pmax for abs
    		"movq %%mm7, %%mm6				\n\t" // 0
    		"pcmpgtw %%mm0, %%mm6				\n\t"
    		"pxor %%mm6, %%mm0				\n\t"
    		"psubw %%mm6, %%mm0				\n\t" // |2L4 - 5L5 + 5L6 - 2L7|
    		"movq %%mm7, %%mm6				\n\t" // 0
    		"pcmpgtw %%mm1, %%mm6				\n\t"
    		"pxor %%mm6, %%mm1				\n\t"
    		"psubw %%mm6, %%mm1				\n\t" // |2H4 - 5H5 + 5H6 - 2H7|
    
    		"movq %%mm7, %%mm6				\n\t" // 0
    		"pcmpgtw %%mm2, %%mm6				\n\t"
    		"pxor %%mm6, %%mm2				\n\t"
    		"psubw %%mm6, %%mm2				\n\t" // |2L0 - 5L1 + 5L2 - 2L3|
    		"movq %%mm7, %%mm6				\n\t" // 0
    		"pcmpgtw %%mm3, %%mm6				\n\t"
    		"pxor %%mm6, %%mm3				\n\t"
    		"psubw %%mm6, %%mm3				\n\t" // |2H0 - 5H1 + 5H2 - 2H3|
    
    #ifdef HAVE_MMX2
    		"pminsw %%mm2, %%mm0				\n\t"
    		"pminsw %%mm3, %%mm1				\n\t"
    #else
    		"movq %%mm0, %%mm6				\n\t"
    		"psubusw %%mm2, %%mm6				\n\t"
    		"psubw %%mm6, %%mm0				\n\t"
    		"movq %%mm1, %%mm6				\n\t"
    		"psubusw %%mm3, %%mm6				\n\t"
    		"psubw %%mm6, %%mm1				\n\t"
    #endif
    
    		"movq %%mm7, %%mm6				\n\t" // 0
    		"pcmpgtw %%mm4, %%mm6				\n\t" // sign(2L2 - 5L3 + 5L4 - 2L5)
    		"pxor %%mm6, %%mm4				\n\t"
    		"psubw %%mm6, %%mm4				\n\t" // |2L2 - 5L3 + 5L4 - 2L5|
    		"pcmpgtw %%mm5, %%mm7				\n\t" // sign(2H2 - 5H3 + 5H4 - 2H5)
    		"pxor %%mm7, %%mm5				\n\t"
    		"psubw %%mm7, %%mm5				\n\t" // |2H2 - 5H3 + 5H4 - 2H5|
    // 100 opcodes
    		"movd %2, %%mm2					\n\t" // QP
    		"punpcklwd %%mm2, %%mm2				\n\t"
    		"punpcklwd %%mm2, %%mm2				\n\t"
    		"psllw $3, %%mm2				\n\t" // 8QP
    		"movq %%mm2, %%mm3				\n\t" // 8QP
    		"pcmpgtw %%mm4, %%mm2				\n\t"
    		"pcmpgtw %%mm5, %%mm3				\n\t"
    		"pand %%mm2, %%mm4				\n\t"
    		"pand %%mm3, %%mm5				\n\t"
    
    
    		"psubusw %%mm0, %%mm4				\n\t" // hd
    		"psubusw %%mm1, %%mm5				\n\t" // ld
    
    
    		"movq w05, %%mm2				\n\t" // 5
    		"pmullw %%mm2, %%mm4				\n\t"
    		"pmullw %%mm2, %%mm5				\n\t"
    		"movq w20, %%mm2				\n\t" // 32
    		"paddw %%mm2, %%mm4				\n\t"
    		"paddw %%mm2, %%mm5				\n\t"
    		"psrlw $6, %%mm4				\n\t"
    		"psrlw $6, %%mm5				\n\t"
    
    /*
    		"movq w06, %%mm2				\n\t" // 6
    		"paddw %%mm2, %%mm4				\n\t"
    		"paddw %%mm2, %%mm5				\n\t"
    		"movq w1400, %%mm2				\n\t" // 1400h = 5120 = 5/64*2^16
    //FIXME if *5/64 is supposed to be /13 then we should use 5041 instead of 5120
    		"pmulhw %%mm2, %%mm4				\n\t" // hd/13
    		"pmulhw %%mm2, %%mm5				\n\t" // ld/13
    */
    
    		"movq temp2, %%mm0				\n\t" // L3 - L4
    		"movq temp3, %%mm1				\n\t" // H3 - H4
    
    		"pxor %%mm2, %%mm2				\n\t"
    		"pxor %%mm3, %%mm3				\n\t"
    
    		"pcmpgtw %%mm0, %%mm2				\n\t" // sign (L3-L4)
    		"pcmpgtw %%mm1, %%mm3				\n\t" // sign (H3-H4)
    		"pxor %%mm2, %%mm0				\n\t"
    		"pxor %%mm3, %%mm1				\n\t"
    		"psubw %%mm2, %%mm0				\n\t" // |L3-L4|
    		"psubw %%mm3, %%mm1				\n\t" // |H3-H4|
    
    		"psrlw $1, %%mm0				\n\t" // |L3 - L4|/2
    		"psrlw $1, %%mm1				\n\t" // |H3 - H4|/2
    
    
    		"pxor %%mm6, %%mm2				\n\t"
    		"pxor %%mm7, %%mm3				\n\t"
    		"pand %%mm2, %%mm4				\n\t"
    		"pand %%mm3, %%mm5				\n\t"
    
    #ifdef HAVE_MMX2
    		"pminsw %%mm0, %%mm4				\n\t"
    		"pminsw %%mm1, %%mm5				\n\t"
    #else
    		"movq %%mm4, %%mm2				\n\t"
    		"psubusw %%mm0, %%mm2				\n\t"
    		"psubw %%mm2, %%mm4				\n\t"
    		"movq %%mm5, %%mm2				\n\t"
    		"psubusw %%mm1, %%mm2				\n\t"
    		"psubw %%mm2, %%mm5				\n\t"
    #endif
    		"pxor %%mm6, %%mm4				\n\t"
    		"pxor %%mm7, %%mm5				\n\t"
    		"psubw %%mm6, %%mm4				\n\t"
    		"psubw %%mm7, %%mm5				\n\t"
    		"packsswb %%mm5, %%mm4				\n\t"
    		"movq (%%eax, %1, 2), %%mm0			\n\t"
    		"paddb   %%mm4, %%mm0				\n\t"
    		"movq %%mm0, (%%eax, %1, 2) 			\n\t"
    		"movq (%0, %1, 4), %%mm0			\n\t"
    		"psubb %%mm4, %%mm0				\n\t"
    		"movq %%mm0, (%0, %1, 4) 			\n\t"
    
    		:
    		: "r" (src), "r" (stride), "r" (QP)
    		: "%eax", "%ebx"
    	);
    #else
    	const int l1= stride;
    	const int l2= stride + l1;
    	const int l3= stride + l2;
    	const int l4= stride + l3;
    	const int l5= stride + l4;
    	const int l6= stride + l5;
    	const int l7= stride + l6;
    	const int l8= stride + l7;
    //	const int l9= stride + l8;
    
    	src+= stride*3;
    
    	{
    		const int middleEnergy= 5*(src[l5] - src[l4]) + 2*(src[l3] - src[l6]);
    		if(ABS(middleEnergy) < 8*QP)
    		{
    			const int q=(src[l4] - src[l5])/2;
    			const int leftEnergy=  5*(src[l3] - src[l2]) + 2*(src[l1] - src[l4]);
    			const int rightEnergy= 5*(src[l7] - src[l6]) + 2*(src[l5] - src[l8]);
    
    			int d= ABS(middleEnergy) - MIN( ABS(leftEnergy), ABS(rightEnergy) );
    			d= MAX(d, 0);
    
    			d= (5*d + 32) >> 6;
    			d*= SIGN(-middleEnergy);
    
    			if(q>0)
    			{
    				d= d<0 ? 0 : d;
    				d= d>q ? q : d;
    			}
    			else
    			{
    				d= d>0 ? 0 : d;
    				d= d<q ? q : d;
    			}
    
            		src[l4]-= d;
    	        	src[l5]+= d;
    		}
    		src++;
    	}
    #endif
    }
    
    //FIXME?  |255-0| = 1
    /**
    
     * Check if the given 8x8 Block is mostly "flat"
    
    static inline int isHorizDC(uint8_t src[], int stride)
    
    asm volatile (
    //		"int $3 \n\t"
    
    		"leal (%1, %2), %%ecx				\n\t"
    		"leal (%%ecx, %2, 4), %%ebx			\n\t"
    //	0	1	2	3	4	5	6	7	8	9
    //	%1	ecx	ecx+%2	ecx+2%2	%1+4%2	ebx	ebx+%2	ebx+2%2	%1+8%2	ebx+4%2
    
    		"movq b7E, %%mm7				\n\t" // mm7 = 0x7F
    		"movq b7C, %%mm6				\n\t" // mm6 = 0x7D
    		"pxor %%mm0, %%mm0				\n\t"
    
    		"movl %1, %%eax					\n\t"
    		"andl $0x1F, %%eax				\n\t"
    		"cmpl $24, %%eax				\n\t"
    		"leal tempBlock, %%eax				\n\t"
    		"jb 1f						\n\t"
    
    #define HDC_CHECK_AND_CPY(src, dst) \
    		"movd " #src ", %%mm2				\n\t"\
    		"punpckldq 4" #src ", %%mm2				\n\t" /* (%1) */\
    
    		"movq %%mm2, %%mm1				\n\t"\
    		"psrlq $8, %%mm2				\n\t"\
    		"psubb %%mm1, %%mm2				\n\t"\
    		"paddb %%mm7, %%mm2				\n\t"\
    		"pcmpgtb %%mm6, %%mm2				\n\t"\
    		"paddb %%mm2, %%mm0				\n\t"\
    
    		"movq %%mm1," #dst "(%%eax)			\n\t"
    
    		HDC_CHECK_AND_CPY((%1),0)
    		HDC_CHECK_AND_CPY((%%ecx),8)
    		HDC_CHECK_AND_CPY((%%ecx, %2),16)
    		HDC_CHECK_AND_CPY((%%ecx, %2, 2),24)
    		HDC_CHECK_AND_CPY((%1, %2, 4),32)
    		HDC_CHECK_AND_CPY((%%ebx),40)
    		HDC_CHECK_AND_CPY((%%ebx, %2),48)
    		HDC_CHECK_AND_CPY((%%ebx, %2, 2),56)
    		"jmp 2f						\n\t"
    		"1:						\n\t"
    // src does not cross a 32 byte cache line so dont waste time with alignment
    #define HDC_CHECK_AND_CPY2(src, dst) \
    		"movq " #src ", %%mm2				\n\t"\
    		"movq " #src ", %%mm1				\n\t"\
    		"psrlq $8, %%mm2				\n\t"\
    		"psubb %%mm1, %%mm2				\n\t"\
    		"paddb %%mm7, %%mm2				\n\t"\
    		"pcmpgtb %%mm6, %%mm2				\n\t"\
    		"paddb %%mm2, %%mm0				\n\t"\
    		"movq %%mm1," #dst "(%%eax)			\n\t"
    
    		HDC_CHECK_AND_CPY2((%1),0)
    		HDC_CHECK_AND_CPY2((%%ecx),8)
    		HDC_CHECK_AND_CPY2((%%ecx, %2),16)
    		HDC_CHECK_AND_CPY2((%%ecx, %2, 2),24)
    		HDC_CHECK_AND_CPY2((%1, %2, 4),32)
    		HDC_CHECK_AND_CPY2((%%ebx),40)
    		HDC_CHECK_AND_CPY2((%%ebx, %2),48)
    		HDC_CHECK_AND_CPY2((%%ebx, %2, 2),56)
    		"2:						\n\t"
    
    		"psllq $8, %%mm0				\n\t" // remove dummy value
    		"movq %%mm0, %%mm1				\n\t"
    		"psrlw $8, %%mm0				\n\t"
    		"paddb %%mm1, %%mm0				\n\t"
    		"movq %%mm0, %%mm1				\n\t"
    		"psrlq $16, %%mm0				\n\t"
    		"paddb %%mm1, %%mm0				\n\t"
    		"movq %%mm0, %%mm1				\n\t"
    		"psrlq $32, %%mm0				\n\t"
    		"paddb %%mm1, %%mm0				\n\t"
    		"movd %%mm0, %0					\n\t"
    		: "=r" (numEq)
    		: "r" (src), "r" (stride)
    
    		: "%eax", "%ebx", "%ecx"
    
    		);
    //	printf("%d\n", numEq);
    
    	numEq= (256 - numEq) &0xFF;
    
    	int y;
    	for(y=0; y<BLOCK_SIZE; y++)
    
    	{
    		if(((src[0] - src[1] + 1) & 0xFFFF) < 3) numEq++;
    		if(((src[1] - src[2] + 1) & 0xFFFF) < 3) numEq++;
    		if(((src[2] - src[3] + 1) & 0xFFFF) < 3) numEq++;
    		if(((src[3] - src[4] + 1) & 0xFFFF) < 3) numEq++;
    		if(((src[4] - src[5] + 1) & 0xFFFF) < 3) numEq++;
    		if(((src[5] - src[6] + 1) & 0xFFFF) < 3) numEq++;
    		if(((src[6] - src[7] + 1) & 0xFFFF) < 3) numEq++;
    		src+= stride;
    	}
    #endif
    /*	if(abs(numEq - asmEq) > 0)
    	{
    //		printf("\nasm:%d  c:%d\n", asmEq, numEq);
    		for(int y=0; y<8; y++)
    		{
    			for(int x=0; x<8; x++)
    			{
    				printf("%d ", src[x + y*stride]);
    			}
    			printf("\n");
    		}
    	}
    */
    //	printf("%d\n", numEq);
    	return numEq > hFlatnessThreshold;
    }
    
    
    static inline int isHorizMinMaxOk(uint8_t src[], int stride, int QP)
    
    	if(abs(src[0] - src[7]) > 2*QP) return 0;
    
    static inline void doHorizDefFilter(uint8_t dst[], int stride, int QP)
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"leal (%0, %1), %%ecx				\n\t"
    		"leal (%%ecx, %1, 4), %%ebx			\n\t"
    //	0	1	2	3	4	5	6	7	8	9
    //	%0	ecx	ecx+%1	ecx+2%1	%0+4%1	ebx	ebx+%1	ebx+2%1	%0+8%1	ebx+4%1
    
    		"pxor %%mm7, %%mm7				\n\t"
    		"movq bm00001000, %%mm6				\n\t"
    		"movd %2, %%mm5					\n\t" // QP
    		"movq %%mm5, %%mm4				\n\t"
    		"paddusb %%mm5, %%mm5				\n\t" // 2QP
    		"paddusb %%mm5, %%mm4				\n\t" // 3QP
    		"psllq $24, %%mm4				\n\t"
    		"pxor %%mm5, %%mm5				\n\t" // 0
    		"psubb %%mm4, %%mm5				\n\t" // -QP
    		"leal tempBlock, %%eax				\n\t"
    
    //FIXME? "unroll by 2" and mix
    
    #ifdef HAVE_MMX2
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    #define HDF(src, dst)	\
    		"movq " #src "(%%eax), %%mm0			\n\t"\
    		"movq " #src "(%%eax), %%mm1			\n\t"\
    		"movq " #src "(%%eax), %%mm2			\n\t"\
    
    		"psrlq $8, %%mm1				\n\t"\
    		"psubusb %%mm1, %%mm2				\n\t"\
    		"psubusb %%mm0, %%mm1				\n\t"\
    		"por %%mm2, %%mm1				\n\t" /* px = |px - p(x+1)| */\
    		"pcmpeqb %%mm7, %%mm2				\n\t" /* px = sgn[px - p(x+1)] */\
    		"pshufw $0x00, %%mm1, %%mm3			\n\t" /* p5 = |p1 - p2| */\
    		"pminub %%mm1, %%mm3				\n\t" /* p5 = min(|p2-p1|, |p6-p5|)*/\
    		"psrlq $16, %%mm3				\n\t" /* p3 = min(|p2-p1|, |p6-p5|)*/\
    		"psubusb %%mm3, %%mm1			\n\t" /* |p3-p4|-min(|p1-p2|,|p5-p6|) */\
    		"paddb %%mm5, %%mm1				\n\t"\
    		"psubusb %%mm5, %%mm1				\n\t"\
    		"psrlw $2, %%mm1				\n\t"\
    		"pxor %%mm2, %%mm1				\n\t"\
    		"psubb %%mm2, %%mm1				\n\t"\
    		"pand %%mm6, %%mm1				\n\t"\
    		"psubb %%mm1, %%mm0				\n\t"\
    		"psllq $8, %%mm1				\n\t"\
    		"paddb %%mm1, %%mm0				\n\t"\
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"movd %%mm0, " #dst"				\n\t"\
    
    		"psrlq $32, %%mm0				\n\t"\
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"movd %%mm0, 4" #dst"				\n\t"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    #define HDF(src, dst)\
    		"movq " #src "(%%eax), %%mm0			\n\t"\
    
    		"movq %%mm0, %%mm1				\n\t"\
    		"movq %%mm0, %%mm2				\n\t"\
    		"psrlq $8, %%mm1				\n\t"\
    		"psubusb %%mm1, %%mm2				\n\t"\
    		"psubusb %%mm0, %%mm1				\n\t"\
    
    		"por %%mm2, %%mm1				\n\t" /* px = |px - p(x+1)| */\
    		"pcmpeqb %%mm7, %%mm2				\n\t" /* px = sgn[px - p(x+1)] */\
    		"movq %%mm1, %%mm3				\n\t"\
    		"psllq $32, %%mm3				\n\t"\
    		"movq %%mm3, %%mm4				\n\t"\
    		"psubusb %%mm1, %%mm4				\n\t"\
    		"psubb %%mm4, %%mm3				\n\t"\
    		"psrlq $16, %%mm3				\n\t" /* p3 = min(|p2-p1|, |p6-p5|)*/\
    
    		"psubusb %%mm3, %%mm1			\n\t" /* |p3-p4|-min(|p1-p2|,|p5,6|) */\
    		"paddb %%mm5, %%mm1				\n\t"\
    		"psubusb %%mm5, %%mm1				\n\t"\
    		"psrlw $2, %%mm1				\n\t"\
    		"pxor %%mm2, %%mm1				\n\t"\
    		"psubb %%mm2, %%mm1				\n\t"\
    		"pand %%mm6, %%mm1				\n\t"\
    		"psubb %%mm1, %%mm0				\n\t"\
    		"psllq $8, %%mm1				\n\t"\
    		"paddb %%mm1, %%mm0				\n\t"\
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"movd %%mm0, " #dst "				\n\t"\
    
    		"psrlq $32, %%mm0				\n\t"\
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"movd %%mm0, 4" #dst "				\n\t"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		HDF(0,(%0))
    		HDF(8,(%%ecx))
    		HDF(16,(%%ecx, %1))
    		HDF(24,(%%ecx, %1, 2))
    		HDF(32,(%0, %1, 4))
    		HDF(40,(%%ebx))
    		HDF(48,(%%ebx, %1))
    		HDF(56,(%%ebx, %1, 2))
    
    		:
    		: "r" (dst), "r" (stride), "r" (QP)
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		: "%eax", "%ebx", "%ecx"
    
    	int y;
    	for(y=0; y<BLOCK_SIZE; y++)
    
    		const int middleEnergy= 5*(dst[4] - dst[5]) + 2*(dst[2] - dst[5]);
    
    			const int q=(dst[3] - dst[4])/2;
    			const int leftEnergy=  5*(dst[2] - dst[1]) + 2*(dst[0] - dst[3]);
    			const int rightEnergy= 5*(dst[6] - dst[5]) + 2*(dst[4] - dst[7]);
    
    
    			int d= ABS(middleEnergy) - MIN( ABS(leftEnergy), ABS(rightEnergy) );
    			d= MAX(d, 0);
    
    			d= (5*d + 32) >> 6;
    			d*= SIGN(-middleEnergy);
    
    			if(q>0)
    			{
    				d= d<0 ? 0 : d;
    				d= d>q ? q : d;
    			}
    			else
    			{
    				d= d>0 ? 0 : d;
    				d= d<q ? q : d;
    			}
    
            		dst[3]-= d;
    	        	dst[4]+= d;
    		}
    		dst+= stride;
    	}
    #endif
    }
    
    /**
    
     * Do a horizontal low pass filter on the 10x8 block (dst points to middle 8x8 Block)
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
     * using the 9-Tap Filter (1,1,2,2,4,2,2,1,1)/16 (C version)
     * using the 7-Tap Filter   (2,2,2,4,2,2,2)/16 (MMX2/3DNOW version)
    
    static inline void doHorizLowPass(uint8_t dst[], int stride, int QP)
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    	asm volatile(
    		"leal (%0, %1), %%ecx				\n\t"
    		"leal (%%ecx, %1, 4), %%ebx			\n\t"
    //	0	1	2	3	4	5	6	7	8	9
    //	%0	ecx	ecx+%1	ecx+2%1	%0+4%1	ebx	ebx+%1	ebx+2%1	%0+8%1	ebx+4%1
    
    		"pxor %%mm7, %%mm7					\n\t"
    		"leal tempBlock, %%eax					\n\t"
    
    #define HLP1	"movq (%0), %%mm0					\n\t"\
    		"movq %%mm0, %%mm1					\n\t"\
    		"psllq $8, %%mm0					\n\t"\
    
    		PAVGB(%%mm1, %%mm0)\
    
    		"psrlw $8, %%mm0					\n\t"\
    		"pxor %%mm1, %%mm1					\n\t"\
    		"packuswb %%mm1, %%mm0					\n\t"\
    		"movq %%mm0, %%mm1					\n\t"\
    		"movq %%mm0, %%mm2					\n\t"\
    		"psllq $32, %%mm0					\n\t"\
    		"paddb %%mm0, %%mm1					\n\t"\
    		"psllq $16, %%mm2					\n\t"\
    
    		PAVGB(%%mm2, %%mm0)\
    
    		"movq %%mm0, %%mm3					\n\t"\
    		"pand bm11001100, %%mm0					\n\t"\
    		"paddusb %%mm0, %%mm3					\n\t"\
    		"psrlq $8, %%mm3					\n\t"\
    
    		PAVGB(%%mm1, %%mm4)\
    		PAVGB(%%mm3, %%mm2)\
    
    		"psrlq $16, %%mm2					\n\t"\
    		"punpcklbw %%mm2, %%mm2					\n\t"\
    		"movq %%mm2, (%0)					\n\t"\
    
    #define HLP2	"movq (%0), %%mm0					\n\t"\
    		"movq %%mm0, %%mm1					\n\t"\
    		"psllq $8, %%mm0					\n\t"\
    
    		PAVGB(%%mm1, %%mm0)\
    
    		"psrlw $8, %%mm0					\n\t"\
    		"pxor %%mm1, %%mm1					\n\t"\
    		"packuswb %%mm1, %%mm0					\n\t"\
    		"movq %%mm0, %%mm2					\n\t"\
    		"psllq $32, %%mm0					\n\t"\
    		"psllq $16, %%mm2					\n\t"\
    
    		PAVGB(%%mm2, %%mm0)\
    
    		"movq %%mm0, %%mm3					\n\t"\
    		"pand bm11001100, %%mm0					\n\t"\
    		"paddusb %%mm0, %%mm3					\n\t"\
    		"psrlq $8, %%mm3					\n\t"\
    
    		PAVGB(%%mm3, %%mm2)\
    
    		"psrlq $16, %%mm2					\n\t"\
    		"punpcklbw %%mm2, %%mm2					\n\t"\
    		"movq %%mm2, (%0)					\n\t"\
    
    // approximately a 7-Tap Filter with Vector (1,2,3,4,3,2,1)/16
    /*
    Implemented	Exact 7-Tap
     9421		A321
     36421		64321
     334321		=
     1234321	=
      1234321	=
       123433	=
        12463	  12346
         1249	   123A
    
    */
    
    #ifdef HAVE_MMX2
    
    #define HLP3(i)	"movq " #i "(%%eax), %%mm0				\n\t"\
    		"movq %%mm0, %%mm1					\n\t"\
    		"movq %%mm0, %%mm2					\n\t"\
    		"movq %%mm0, %%mm3					\n\t"\
    		"movq %%mm0, %%mm4					\n\t"\
    		"psllq $8, %%mm1					\n\t"\
    		"psrlq $8, %%mm2					\n\t"\
    		"pand bm00000001, %%mm3					\n\t"\
    		"pand bm10000000, %%mm4					\n\t"\
    		"por %%mm3, %%mm1					\n\t"\
    		"por %%mm4, %%mm2					\n\t"\
    
    		PAVGB(%%mm2, %%mm1)\
    		PAVGB(%%mm1, %%mm0)\
    
    \
    		"pshufw $0xF9, %%mm0, %%mm3				\n\t"\
    		"pshufw $0x90, %%mm0, %%mm4				\n\t"\
    
    		PAVGB(%%mm3, %%mm4)\
    		PAVGB(%%mm4, %%mm0)\
    
    		"movd %%mm0, (%0)					\n\t"\
    		"psrlq $32, %%mm0					\n\t"\
    
    		"movd %%mm0, 4(%0)					\n\t"
    #else
    #define HLP3(i)	"movq " #i "(%%eax), %%mm0				\n\t"\
    		"movq %%mm0, %%mm1					\n\t"\
    		"movq %%mm0, %%mm2					\n\t"\
    
    		"movd -4(%0), %%mm3					\n\t" /*0001000*/\
    		"movd 8(%0), %%mm4					\n\t" /*0001000*/\
    
    		"psllq $8, %%mm1					\n\t"\
    		"psrlq $8, %%mm2					\n\t"\
    
    		"psrlq $24, %%mm3					\n\t"\
    		"psllq $56, %%mm4					\n\t"\
    
    		"por %%mm3, %%mm1					\n\t"\
    		"por %%mm4, %%mm2					\n\t"\
    		PAVGB(%%mm2, %%mm1)\
    		PAVGB(%%mm1, %%mm0)\
    \
    		"movq %%mm0, %%mm3					\n\t"\
    		"movq %%mm0, %%mm4					\n\t"\
    		"movq %%mm0, %%mm5					\n\t"\
    		"psrlq $16, %%mm3					\n\t"\
    		"psllq $16, %%mm4					\n\t"\
    		"pand bm11000000, %%mm5					\n\t"\
    		"por %%mm5, %%mm3					\n\t"\
    		"movq %%mm0, %%mm5					\n\t"\
    		"pand bm00000011, %%mm5					\n\t"\
    		"por %%mm5, %%mm4					\n\t"\
    		PAVGB(%%mm3, %%mm4)\
    		PAVGB(%%mm4, %%mm0)\
    		"movd %%mm0, (%0)					\n\t"\
    		"psrlq $32, %%mm0					\n\t"\
    		"movd %%mm0, 4(%0)					\n\t"
    #endif
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    #define NEW_HLP(src, dst)\
    		"movq " #src "(%%eax), %%mm1				\n\t"\
    		"movq " #src "(%%eax), %%mm2				\n\t"\
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"movd -4" #dst ", %%mm3					\n\t" /*0001000*/\
    		"movd 8" #dst ", %%mm4					\n\t" /*0001000*/\
    
    		"psrlq $24, %%mm3					\n\t"\
    		"psllq $56, %%mm4					\n\t"\
    		"por %%mm3, %%mm1					\n\t"\
    		"por %%mm4, %%mm2					\n\t"\
    		"movq %%mm1, %%mm5					\n\t"\
    		PAVGB(%%mm2, %%mm1)\
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"movq " #src "(%%eax), %%mm0				\n\t"\
    
    		PAVGB(%%mm1, %%mm0)\
    		"psllq $8, %%mm5					\n\t"\
    		"psrlq $8, %%mm2					\n\t"\
    		"por %%mm3, %%mm5					\n\t"\
    		"por %%mm4, %%mm2					\n\t"\
    		"movq %%mm5, %%mm1					\n\t"\
    		PAVGB(%%mm2, %%mm5)\
    		"psllq $8, %%mm1					\n\t"\
    		"psrlq $8, %%mm2					\n\t"\
    		"por %%mm3, %%mm1					\n\t"\
    		"por %%mm4, %%mm2					\n\t"\
    		PAVGB(%%mm2, %%mm1)\
    		PAVGB(%%mm1, %%mm5)\
    		PAVGB(%%mm5, %%mm0)\
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"movd %%mm0, " #dst "					\n\t"\
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"movd %%mm0, 4" #dst "					\n\t"
    
    
    /* uses the 9-Tap Filter: 112242211 */
    #define NEW_HLP2(i)\
    		"movq " #i "(%%eax), %%mm0				\n\t" /*0001000*/\
    		"movq %%mm0, %%mm1					\n\t" /*0001000*/\
    		"movq %%mm0, %%mm2					\n\t" /*0001000*/\
    		"movd -4(%0), %%mm3					\n\t" /*0001000*/\
    		"movd 8(%0), %%mm4					\n\t" /*0001000*/\
    		"psllq $8, %%mm1					\n\t"\
    		"psrlq $8, %%mm2					\n\t"\
    		"psrlq $24, %%mm3					\n\t"\
    		"psllq $56, %%mm4					\n\t"\
    		"por %%mm3, %%mm1					\n\t" /*0010000*/\
    		"por %%mm4, %%mm2					\n\t" /*0000100*/\
    		"movq %%mm1, %%mm5					\n\t" /*0010000*/\
    		PAVGB(%%mm2, %%mm1)					      /*0010100*/\
    		PAVGB(%%mm1, %%mm0)					      /*0012100*/\
    		"psllq $8, %%mm5					\n\t"\
    		"psrlq $8, %%mm2					\n\t"\
    		"por %%mm3, %%mm5					\n\t" /*0100000*/\
    		"por %%mm4, %%mm2					\n\t" /*0000010*/\
    		"movq %%mm5, %%mm1					\n\t" /*0100000*/\
    		PAVGB(%%mm2, %%mm5)					      /*0100010*/\
    		"psllq $8, %%mm1					\n\t"\
    		"psrlq $8, %%mm2					\n\t"\
    		"por %%mm3, %%mm1					\n\t" /*1000000*/\
    		"por %%mm4, %%mm2					\n\t" /*0000001*/\
    		"movq %%mm1, %%mm6					\n\t" /*1000000*/\
    		PAVGB(%%mm2, %%mm1)					      /*1000001*/\
    		"psllq $8, %%mm6					\n\t"\
    		"psrlq $8, %%mm2					\n\t"\
    		"por %%mm3, %%mm6					\n\t"/*100000000*/\
    		"por %%mm4, %%mm2					\n\t"/*000000001*/\
    		PAVGB(%%mm2, %%mm6)					     /*100000001*/\
    		PAVGB(%%mm6, %%mm1)					     /*110000011*/\
    		PAVGB(%%mm1, %%mm5)					     /*112000211*/\
    		PAVGB(%%mm5, %%mm0)					     /*112242211*/\
    		"movd %%mm0, (%0)					\n\t"\
    		"psrlq $32, %%mm0					\n\t"\
    		"movd %%mm0, 4(%0)					\n\t"
    
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    #define HLP(src, dst) NEW_HLP(src, dst)
    
    		HLP(0, (%0))
    		HLP(8, (%%ecx))
    		HLP(16, (%%ecx, %1))
    		HLP(24, (%%ecx, %1, 2))
    		HLP(32, (%0, %1, 4))
    		HLP(40, (%%ebx))
    		HLP(48, (%%ebx, %1))
    		HLP(56, (%%ebx, %1, 2))
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		: "%eax", "%ebx", "%ecx"
    
    	int y;
    	for(y=0; y<BLOCK_SIZE; y++)
    
    	{
    		const int first= ABS(dst[-1] - dst[0]) < QP ? dst[-1] : dst[0];
    		const int last= ABS(dst[8] - dst[7]) < QP ? dst[8] : dst[7];
    
    		int sums[9];
    
    		sums[0] = first + dst[0];
    		sums[1] = dst[0] + dst[1];
    		sums[2] = dst[1] + dst[2];
    		sums[3] = dst[2] + dst[3];
    		sums[4] = dst[3] + dst[4];
    		sums[5] = dst[4] + dst[5];
    		sums[6] = dst[5] + dst[6];
    		sums[7] = dst[6] + dst[7];
    		sums[8] = dst[7] + last;
    
    
    		dst[0]= ((sums[0]<<2) + ((first + sums[2])<<1) + sums[4] + 8)>>4;
    
    		dst[1]= ((dst[1]<<2) + ((first + sums[0] + sums[3])<<1) + sums[5] + 8)>>4;
    		dst[2]= ((dst[2]<<2) + ((first + sums[1] + sums[4])<<1) + sums[6] + 8)>>4;
    		dst[3]= ((dst[3]<<2) + ((sums[2] + sums[5])<<1) + sums[0] + sums[7] + 8)>>4;
    		dst[4]= ((dst[4]<<2) + ((sums[3] + sums[6])<<1) + sums[1] + sums[8] + 8)>>4;
    		dst[5]= ((dst[5]<<2) + ((last + sums[7] + sums[4])<<1) + sums[2] + 8)>>4;
    		dst[6]= (((last + dst[6])<<2) + ((dst[7] + sums[5])<<1) + sums[3] + 8)>>4;
    		dst[7]= ((sums[8]<<2) + ((last + sums[6])<<1) + sums[4] + 8)>>4;
    
    
    		dst+= stride;
    	}
    #endif
    }
    
    static inline void dering(uint8_t src[], int stride, int QP)
    {
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"movq pQPb, %%mm0				\n\t"
    		"paddusb %%mm0, %%mm0				\n\t"
    		"movq %%mm0, pQPb2				\n\t"
    
    
    		"leal (%0, %1), %%eax				\n\t"
    		"leal (%%eax, %1, 4), %%ebx			\n\t"
    //	0	1	2	3	4	5	6	7	8	9
    //	%0	eax	eax+%1	eax+2%1	%0+4%1	ebx	ebx+%1	ebx+2%1	%0+8%1	ebx+4%1
    
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"pcmpeqb %%mm6, %%mm6				\n\t"
    
    		"pxor %%mm7, %%mm7				\n\t"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    #ifdef HAVE_MMX2
    
    #define FIND_MIN_MAX(addr)\
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"movq " #addr ", %%mm0				\n\t"\
    
    		"pminub %%mm0, %%mm6				\n\t"\
    		"pmaxub %%mm0, %%mm7				\n\t"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    #else
    #define FIND_MIN_MAX(addr)\
    		"movq " #addr ", %%mm0				\n\t"\
    		"movq %%mm6, %%mm1				\n\t"\
    		"psubusb %%mm0, %%mm7				\n\t"\
    		"paddb %%mm0, %%mm7				\n\t"\
    		"psubusb %%mm0, %%mm1				\n\t"\
    		"psubb %%mm1, %%mm6				\n\t"
    #endif
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    FIND_MIN_MAX((%%eax))
    FIND_MIN_MAX((%%eax, %1))
    FIND_MIN_MAX((%%eax, %1, 2))
    FIND_MIN_MAX((%0, %1, 4))
    FIND_MIN_MAX((%%ebx))
    FIND_MIN_MAX((%%ebx, %1))
    FIND_MIN_MAX((%%ebx, %1, 2))
    FIND_MIN_MAX((%0, %1, 8))
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"pminub %%mm4, %%mm6				\n\t" // min of pixels
    
    		"pshufw $0xF9, %%mm6, %%mm4			\n\t"
    		"pminub %%mm4, %%mm6				\n\t" // min of pixels
    		"pshufw $0xFE, %%mm6, %%mm4			\n\t"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"pminub %%mm4, %%mm6				\n\t"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"movq %%mm6, %%mm1				\n\t"
    		"psubusb %%mm4, %%mm1				\n\t"
    		"psubb %%mm1, %%mm6				\n\t"
    
    		"movq %%mm6, %%mm4				\n\t"
    		"psrlq $16, %%mm6				\n\t"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"movq %%mm6, %%mm1				\n\t"
    		"psubusb %%mm4, %%mm1				\n\t"
    		"psubb %%mm1, %%mm6				\n\t"
    
    		"movq %%mm6, %%mm4				\n\t"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"movq %%mm6, %%mm1				\n\t"
    		"psubusb %%mm4, %%mm1				\n\t"
    		"psubb %%mm1, %%mm6				\n\t"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"pmaxub %%mm4, %%mm7				\n\t" // max of pixels
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"pmaxub %%mm4, %%mm7				\n\t"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"pmaxub %%mm4, %%mm7				\n\t"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"psubusb %%mm4, %%mm7				\n\t"
    		"paddb %%mm4, %%mm7				\n\t"
    
    		"movq %%mm7, %%mm4				\n\t"
    		"psrlq $16, %%mm7				\n\t"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"psubusb %%mm4, %%mm7				\n\t"
    		"paddb %%mm4, %%mm7				\n\t"
    
    		"movq %%mm7, %%mm4				\n\t"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"psubusb %%mm4, %%mm7				\n\t"
    		"paddb %%mm4, %%mm7				\n\t"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		PAVGB(%%mm6, %%mm7)				      // a=(max + min)/2
    
    		"punpcklbw %%mm7, %%mm7				\n\t"
    		"punpcklbw %%mm7, %%mm7				\n\t"
    		"punpcklbw %%mm7, %%mm7				\n\t"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    		"movq %%mm7, temp0				\n\t"
    
    		"movq (%0), %%mm0				\n\t" // L10
    		"movq %%mm0, %%mm1				\n\t" // L10
    		"movq %%mm0, %%mm2				\n\t" // L10
    		"psllq $8, %%mm1				\n\t"
    		"psrlq $8, %%mm2				\n\t"
    		"movd -4(%0), %%mm3				\n\t"
    		"movd 8(%0), %%mm4				\n\t"
    		"psrlq $24, %%mm3				\n\t"
    		"psllq $56, %%mm4				\n\t"
    		"por %%mm3, %%mm1				\n\t" // L00
    		"por %%mm4, %%mm2				\n\t" // L20
    		"movq %%mm1, %%mm3				\n\t" // L00
    		PAVGB(%%mm2, %%mm1)				      // (L20 + L00)/2
    		PAVGB(%%mm0, %%mm1)				      // (L20 + L00 + 2L10)/4
    		"psubusb %%mm7, %%mm0				\n\t"
    		"psubusb %%mm7, %%mm2				\n\t"
    		"psubusb %%mm7, %%mm3				\n\t"
    		"pcmpeqb b00, %%mm0				\n\t" // L10 > a ? 0 : -1
    		"pcmpeqb b00, %%mm2				\n\t" // L20 > a ? 0 : -1
    		"pcmpeqb b00, %%mm3				\n\t" // L00 > a ? 0 : -1
    		"paddb %%mm2, %%mm0				\n\t"
    		"paddb %%mm3, %%mm0				\n\t"
    
    		"movq (%%eax), %%mm2				\n\t" // L11
    		"movq %%mm2, %%mm3				\n\t" // L11
    		"movq %%mm2, %%mm4				\n\t" // L11
    		"psllq $8, %%mm3				\n\t"
    		"psrlq $8, %%mm4				\n\t"
    		"movd -4(%%eax), %%mm5				\n\t"
    		"movd 8(%%eax), %%mm6				\n\t"
    		"psrlq $24, %%mm5				\n\t"
    		"psllq $56, %%mm6				\n\t"
    		"por %%mm5, %%mm3				\n\t" // L01
    		"por %%mm6, %%mm4				\n\t" // L21
    		"movq %%mm3, %%mm5				\n\t" // L01
    		PAVGB(%%mm4, %%mm3)				      // (L21 + L01)/2
    		PAVGB(%%mm2, %%mm3)				      // (L21 + L01 + 2L11)/4
    		"psubusb %%mm7, %%mm2				\n\t"
    		"psubusb %%mm7, %%mm4				\n\t"
    		"psubusb %%mm7, %%mm5				\n\t"
    		"pcmpeqb b00, %%mm2				\n\t" // L11 > a ? 0 : -1
    		"pcmpeqb b00, %%mm4				\n\t" // L21 > a ? 0 : -1
    		"pcmpeqb b00, %%mm5				\n\t" // L01 > a ? 0 : -1
    		"paddb %%mm4, %%mm2				\n\t"
    		"paddb %%mm5, %%mm2				\n\t"
    // 0, 2, 3, 1
    #define DERING_CORE(dst,src,ppsx,psx,sx,pplx,plx,lx,t0,t1) \
    		"movq " #src ", " #sx "				\n\t" /* src[0] */\
    		"movq " #sx ", " #lx "				\n\t" /* src[0] */\
    		"movq " #sx ", " #t0 "				\n\t" /* src[0] */\
    		"psllq $8, " #lx "				\n\t"\
    		"psrlq $8, " #t0 "				\n\t"\
    		"movd -4" #src ", " #t1 "			\n\t"\
    		"psrlq $24, " #t1 "				\n\t"\
    		"por " #t1 ", " #lx "				\n\t" /* src[-1] */\
    		"movd 8" #src ", " #t1 "			\n\t"\
    		"psllq $56, " #t1 "				\n\t"\
    		"por " #t1 ", " #t0 "				\n\t" /* src[+1] */\
    		"movq " #lx ", " #t1 "				\n\t" /* src[-1] */\
    		PAVGB(t0, lx)				              /* (src[-1] + src[+1])/2 */\
    		PAVGB(sx, lx)				      /* (src[-1] + 2src[0] + src[+1])/4 */\
    		"psubusb temp0, " #t1 "				\n\t"\
    		"psubusb temp0, " #t0 "				\n\t"\
    		"psubusb temp0, " #sx "				\n\t"\
    		"pcmpeqb b00, " #t1 "				\n\t" /* src[-1] > a ? 0 : -1*/\
    		"pcmpeqb b00, " #t0 "				\n\t" /* src[+1] > a ? 0 : -1*/\
    		"pcmpeqb b00, " #sx "				\n\t" /* src[0]  > a ? 0 : -1*/\
    		"paddb " #t1 ", " #t0 "				\n\t"\
    		"paddb " #t0 ", " #sx "				\n\t"\
    \
    		PAVGB(lx, pplx)					     \
    		PAVGB(plx, pplx)				      /* filtered */\
    		"movq " #dst ", " #t0 "				\n\t" /* dst */\
    		"movq " #pplx ", " #t1 "			\n\t"\
    		"psubusb " #t0 ", " #pplx "			\n\t"\
    		"psubusb " #t1 ", " #t0 "			\n\t"\
    		"por " #t0 ", " #pplx "				\n\t" /* |filtered - dst| */\
    		"psubusb pQPb2, " #pplx "			\n\t"\
    		"pcmpeqb b00, " #pplx "				\n\t"\
    		"paddb " #sx ", " #ppsx "			\n\t"\
    		"paddb " #psx ", " #ppsx "			\n\t"\
    	"#paddb b02, " #ppsx "				\n\t"\
    		"pand b08, " #ppsx "				\n\t"\
    		"pcmpeqb b00, " #ppsx "				\n\t"\
    		"pand " #pplx ", " #ppsx "			\n\t"\
    		"pand " #ppsx ", " #t1 "			\n\t"\
    		"pandn " #dst ", " #ppsx "			\n\t"\
    		"por " #t1 ", " #ppsx "				\n\t"\
    		"movq " #ppsx ", " #dst "			\n\t"
    /*
    0000000
    1111111
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    1111110
    1111101
    1111100
    1111011
    1111010
    1111001