;	VirtualDub - Video processing and capture application
;	Copyright (C) 1998-2001 Avery Lee
;
;	This program is free software; you can redistribute it and/or modify
;	it under the terms of the GNU General Public License as published by
;	the Free Software Foundation; either version 2 of the License, or
;	(at your option) any later version.
;
;	This program 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 General Public License for more details.
;
;	You should have received a copy of the GNU General Public License
;	along with this program; if not, write to the Free Software
;	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

	.686
	.mmx
	.xmm
	.model	flat


	.const

	align 16

SSE2_02b		dq	00202020202020202h,00202020202020202h
SSE2_fcb		dq	0fcfcfcfcfcfcfcfch,0fcfcfcfcfcfcfcfch
SSE2_02w		dq	00002000200020002h

predictorsSSE2_Y		dd	predict_Y_normal_SSE2
			dd	predict_Y_halfpelX_SSE2
			dd	predict_Y_halfpelY_SSE2
			dd	predict_Y_quadpel_SSE2
addersSSE2_Y		dd	predict_add_Y_normal_SSE2
			dd	predict_add_Y_halfpelX_SSE2
			dd	predict_add_Y_halfpelY_SSE2
			dd	predict_add_Y_quadpel_SSE2

	.code

src	equ	[esp+4+16]
dst	equ	[esp+8+16]
vx	equ	[esp+12+16]
vy	equ	[esp+16+16]
pitch	equ	[esp+20+16]

	public	_video_copy_prediction_Y_SSE2

	align	16
_video_copy_prediction_Y_SSE2:
	push	ebp
	push	edi
	push	esi
	push	ebx

	mov	esi,pitch
	mov	ecx,src
	mov	eax,vx
	mov	ebx,vy

	mov	edi,eax			;edi = vx
	mov	ebp,ebx			;ebp = vy
	sar	edi,1			;edi = x
	and	eax,1			;eax = x half-pel
	sar	ebp,1			;ebp = y
	add	ecx,edi			;ecx = src + x
	imul	ebp,esi			;ebp = y*pitch
	add	ecx,ebp			;ecx = src + x + y*pitch
	and	ebx,1			;ebx = y half-pel
	shl	eax,2
	mov	edx,dst
	call	dword ptr [predictorsSSE2_Y+eax+ebx*8]

	pop	ebx
	pop	esi
	pop	edi
	pop	ebp
	ret

;*********************************************************
;*
;*	Luminance - quadpel
;*
;*********************************************************

	align 16

predict_Y_quadpel_SSE2:
	movdqa	xmm6,SSE2_02b
	movdqa	xmm7,SSE2_fcb
	mov	edi,16
	
	movdqu	xmm0,[ecx]
	movdqu	xmm1,[ecx+1]
	add	ecx,esi
	
	movdqa	xmm3,xmm7
	pandn	xmm3,xmm0
	movdqa	xmm5,xmm7
	pandn	xmm5,xmm1

	paddb	xmm3,xmm5
	paddb	xmm3,xmm6
	
	pand	xmm0,xmm7
	pand	xmm1,xmm7
	pavgb	xmm0,xmm1
	
	;entry:
	; xmm0: last row high sum
	; xmm3: last row low sum + rounder
	
predict_Y_quadpel_SSE2@loop:
	movdqu	xmm1,[ecx]	;xmm1 = p3
	movdqu	xmm2,[ecx+1]	;xmm2 = p4
	add	ecx,esi
	
	movdqa	xmm4,xmm7
	pandn	xmm4,xmm1	;xmm4 = p3 low bits
	movdqa	xmm5,xmm7
	pandn	xmm5,xmm2	;xmm5 = p4 low bits
	pand	xmm1,xmm7	;xmm1 = p3 high bits
	pand	xmm2,xmm7	;xmm2 = p4 high bits
	pavgb	xmm1,xmm2	;xmm1 = p3+p4 high bits
	paddb	xmm4,xmm5
	
	pavgb	xmm0,xmm1	;xmm0 = pout high bits
	paddb	xmm3,xmm4	;xmm3 = (pout low bits << 2) + rounder
	
	psrlq	xmm3,2
	paddb	xmm4,xmm6	;xmm4 = next loop low sum	

	movdqa	xmm5,xmm7
	pandn	xmm5,xmm3
	paddb	xmm0,xmm5
	movdqa	xmm3,xmm4	;xmm3 = next loop low sum
	movdqa	[edx],xmm0
	movdqa	xmm0,xmm1	;xmm0 = next loop high sum

	add	edx,esi

	dec	edi
	jne	predict_Y_quadpel_SSE2@loop

	ret


;*********************************************************
;*
;*	Luminance - half-pel Y
;*
;*********************************************************

	align 16
predict_Y_halfpelY_SSE2:
	mov	edi,8
	mov	eax,esi
	movdqu	mm0,[ecx]
	add	eax,eax
predict_Y_halfpelY_SSE2@loop:
	prefetcht0 [ecx+eax]
	movdqu	xmm2,[ecx+esi]

	movdqu	xmm4,[ecx+eax]
	pavgb	xmm0,xmm2

	movdqa	[edx],xmm0
	pavgb	xmm2,xmm4

	movdqa	[edx+esi],xmm2
	movdqa	xmm0,xmm4

	add	ecx,eax
	add	edx,eax
	
	dec	edi
	jne	predict_Y_halfpelY_SSE2@loop
	ret

;*********************************************************
;*
;*	Luminance - half-pel X
;*
;*********************************************************

	align 16
predict_Y_halfpelX_SSE2:
	mov	edi,8
	mov	eax,esi
	add	eax,eax

predict_Y_halfpelX_SSE2@loop:
	movdqu	xmm0,[ecx]
	movdqu	xmm1,[ecx+1]
	movdqu	xmm2,[ecx+esi]
	movdqu	xmm3,[ecx+esi+1]
	pavgb	xmm0,xmm1
	pavgb	xmm2,xmm3
	movdqa	[edx],xmm0
	movdqa	[edx+esi],xmm2
	
	add	edx,eax
	add	ecx,eax

	dec	edi
	jne	predict_Y_halfpelX_SSE2@loop

	ret

;*********************************************************
;*
;*	Luminance - normal
;*
;*********************************************************

	align 16
predict_Y_normal_SSE2:
	mov	edi,8
	mov	eax,esi
	add	eax,eax

predict_Y_normal_SSE2@loop:
	movdqu	xmm0,[ecx]
	movdqu	xmm2,[ecx+esi]
	movdqa	[edx],xmm0
	movdqa	[edx+esi],xmm2
	add	ecx,eax
	add	edx,eax
	dec	edi
	jne	predict_Y_normal_SSE2@loop

	ret





;**************************************************************************
;*
;*
;*
;*  Addition predictors
;*
;*
;*
;**************************************************************************

	public	_video_add_prediction_Y_SSE2

	align	16
_video_add_prediction_Y_SSE2:
	push	ebp
	push	edi
	push	esi
	push	ebx

	mov	esi,pitch
	mov	ecx,src
	mov	eax,vx
	mov	ebx,vy

	mov	edi,eax			;edi = vx
	mov	ebp,ebx			;ebp = vy
	sar	edi,1			;edi = x
	and	eax,1			;eax = x half-pel
	sar	ebp,1			;ebp = y
	add	ecx,edi			;ecx = src + x
	imul	ebp,esi			;ebp = y*pitch
	add	ecx,ebp			;ecx = src + x + y*pitch
	and	ebx,1			;ebx = y half-pel
	shl	eax,2
	mov	edx,dst
	call	dword ptr [addersSSE2_Y+eax+ebx*8]

	pop	ebx
	pop	esi
	pop	edi
	pop	ebp
	ret

;*********************************************************
;*
;*	Luminance - quadpel
;*
;*********************************************************

	align 16

	
predict_add_Y_quadpel_SSE2:
	movdqa	xmm6,SSE2_02b
	movdqa	xmm7,SSE2_fcb
	mov	edi,16
	
	movdqu	xmm0,[ecx]
	movdqu	xmm1,[ecx+1]
	add	ecx,esi
	
	movdqa	xmm3,xmm7
	pandn	xmm3,xmm0
	movdqa	xmm5,xmm7
	pandn	xmm5,xmm1

	paddb	xmm3,xmm5
	paddb	xmm3,xmm6
	
	pand	xmm0,xmm7
	pand	xmm1,xmm7
	pavgb	xmm0,xmm1
	
	;entry:
	; xmm0: last row high sum
	; xmm3: last row low sum + rounder
	
add_Y_quadpel_SSE2@loop:
	movdqu	xmm1,[ecx]	;xmm1 = p3
	movdqu	xmm2,[ecx+1]	;xmm2 = p4
	add	ecx,esi
	
	movdqa	xmm4,xmm7
	pandn	xmm4,xmm1	;xmm4 = p3 low bits
	movdqa	xmm5,xmm7
	pandn	xmm5,xmm2	;xmm5 = p4 low bits
	pand	xmm1,xmm7	;xmm1 = p3 high bits
	pand	xmm2,xmm7	;xmm2 = p4 high bits
	pavgb	xmm1,xmm2	;xmm1 = p3+p4 high bits
	paddb	xmm4,xmm5
	
	pavgb	xmm0,xmm1	;xmm0 = pout high bits
	paddb	xmm3,xmm4	;xmm3 = (pout low bits << 2) + rounder
	
	psrlq	xmm3,2
	paddb	xmm4,xmm6	;xmm4 = next loop low sum	

	movdqa	xmm5,xmm7
	pandn	xmm5,xmm3
	paddb	xmm0,xmm5
	pavgb	xmm0,[edx]
	movdqa	xmm3,xmm4	;xmm3 = next loop low sum
	movdqa	[edx],xmm0
	movdqa	xmm0,xmm1	;xmm0 = next loop high sum

	add	edx,esi

	dec	edi
	jne	add_Y_quadpel_SSE2@loop
	
	ret
	
;*********************************************************
;*
;*	Luminance - half-pel Y
;*
;*********************************************************

	align 16
predict_add_Y_halfpelY_SSE2:
	movdqu	xmm0,[ecx]
	add	ecx,esi
	mov	eax,esi
	add	eax,eax
	mov	edi,8
predict_add_Y_halfpelY_SSE2@loop:
	movdqu	xmm1,[ecx]
	movdqu	xmm2,[ecx+esi]
	pavgb	xmm0,xmm1
	pavgb	xmm1,xmm2
	pavgb	xmm0,[edx]
	pavgb	xmm1,[edx+esi]
		
	add	ecx,eax

	movdqa	[edx],xmm0
	movdqa	[edx+esi],xmm1
	add	edx,eax
	movdqa	xmm0,xmm2
	dec	edi
	jne	predict_add_Y_halfpelY_SSE2@loop

	ret

;*********************************************************
;*
;*	Luminance - half-pel X
;*
;*********************************************************

	align 16
predict_add_Y_halfpelX_SSE2:
	mov	edi,8
	mov	eax,esi
	add	eax,eax
predict_add_Y_halfpelX_SSE2@loop:
	movdqu	xmm0,[ecx]
	movdqu	xmm2,[ecx+esi]
	movdqu	xmm1,[ecx+1]
	movdqu	xmm3,[ecx+esi+1]
	pavgb	xmm0,xmm1
	pavgb	xmm2,xmm3
	pavgb	xmm0,[edx]
	pavgb	xmm2,[edx+esi]

	add	ecx,eax
	movdqa	[edx],xmm0
	movdqa	[edx+esi],xmm2
	add	edx,eax
	dec	edi
	jne	predict_add_Y_halfpelX_SSE2@loop

	ret



;*********************************************************
;*
;*	Luminance - normal
;*
;*********************************************************

	align 16
predict_add_Y_normal_SSE2:
	mov	edi,8
	mov	eax,esi
	add	eax,eax

add_Y_normal_SSE2@loop:
	movdqu	xmm0,[ecx]
	movdqu	xmm2,[ecx+esi]
	pavgb	xmm0,[edx]
	pavgb	xmm2,[edx+esi]
	movdqa	[edx],xmm0
	movdqa	[edx+esi],xmm2

	add	ecx,eax
	add	edx,eax

	dec	edi
	jne	add_Y_normal_SSE2@loop

	ret



	end
