
		include	"exec/types.i"

;********************************************************************
;
;	form_component_prediction
;
;	1.0 - 29.7.98 (bifat)	written in assembler
;	1.1 - 5.8.98 (bifat)	code restructured
;	1.2 - 1.6		(buggy)
;	1.7 - 2.10.98 (bifat)	loops unrolled
;	1.8 - 2.10.98 (bifat)	inlined to the calling function
;				form_prediction, using a structure
;				instead of registers
;	1.9 - 3.10.98 (bifat)	removed lots of overhead
;
;********************************************************************

		section text

		XDEF	_form_prediction

		XREF	_chroma_format
		XREF	_opts


OPT_GREY	EQU	1

CHROMA420 	EQU	1
CHROMA422 	EQU	2
CHROMA444 	EQU	3


	STRUCTURE fpdata,0
		WORD	fp_h
		WORD	fp_w
		WORD	fp_lx2
		WORD	fp_y
		WORD	fp_x
		WORD	fp_lx
		WORD	fp_dx
		WORD	fp_dy

		APTR	fp_src
		APTR	fp_dst
		WORD	fp_sfield
		WORD	fp_dfield
	LABEL	fp_sizeof			
		

;********************************************************************

		cnop	0,16

	;	a3	fpdata
	;	d1	average_flag

_form_prediction:

		movem.l	d2-d7/a2-a5,-(a7)

		lea	_form_component_prediction_noaverage(pc),a4

		and.w	#1,d1
		beq.b	.noav

		lea	_form_component_prediction_average(pc),a4
		
.noav

;-- - -- -  -  -   - -

		movem.w	(a3),d0-d7


	;	src[0] + (sfield ? lx2 >> 1 : 0)
	;	dst[0] + (dfield ? lx2 >> 1 : 0)

		ror.l	#1,d2

		move.l	fp_src(a3),a0
		move.l	(a0),a0
		
		tst.w	fp_sfield(a3)
		beq.b	.nosf1

		add.w	d2,a0
		
.nosf1		move.l	fp_dst(a3),a1
		move.l	(a1),a1

		tst.w	fp_dfield(a3)
		beq.b	.nodf1
		
		add.w	d2,a1
.nodf1		
		rol.l	#1,d2


		jsr	(a4)

;-- - -- -  -   -   - - 

		tst.l	_opts+4*OPT_GREY
		bne	.raus


;-- - -- -  -   -   - - 

		movem.w	(a3),d0-d7

		cmp.l	#CHROMA444,_chroma_format
		beq.b	.skip444

		asr.w	#1,d5
		asr.w	#1,d2
		asr.w	#1,d1
		asr.w	#1,d4
		asr.w	#1,d6

.skip444
		cmp.l	#CHROMA420,_chroma_format
		bne.b	.skip420

		asr.w	#1,d0
		asr.w	#1,d3
		asr.w	#1,d7
		
.skip420
		movem.w	d0-d7,-(a7)


	;	src[1] + (sfield ? lx2 >> 1 : 0)
	;	dst[1] + (dfield ? lx2 >> 1 : 0)

		ror.l	#1,d2

		move.l	fp_src(a3),a0
		move.l	4(a0),a0
		
		tst.w	fp_sfield(a3)
		beq.b	.nosf2

		add.w	d2,a0
		
.nosf2		move.l	fp_dst(a3),a1
		move.l	4(a1),a1

		tst.w	fp_dfield(a3)
		beq.b	.nodf2

		add.w	d2,a1

.nodf2		rol.l	#1,d2


		jsr	(a4)


		movem.w	(a7)+,d0-d7


	;	src[2] + (sfield ? lx2 >> 1 : 0)
	;	dst[2] + (dfield ? lx2 >> 1 : 0)

		ror.l	#1,d2

		move.l	fp_src(a3),a0
		move.l	8(a0),a0
		
		tst.w	fp_sfield(a3)
		beq.b	.nosf3
		
		add.w	d2,a0
		
.nosf3
		move.l	fp_dst(a3),a1
		move.l	8(a1),a1

		tst.w	fp_dfield(a3)
		beq.b	.nodf3

		add.w	d2,a1

.nodf3		rol.l	#1,d2


		jsr	(a4)

;-- - -- -  -   -   - - 

.raus		
		movem.l	(a7)+,d2-d7/a2-a5
		rts
		
				
;********************************************************************

		cnop	0,16

_form_component_prediction_noaverage:

	;	a0	uchar *src
	;	a1	uchar *dst

		add.w	d4,a0		; src + x

		ror.l	#1,d7		; yint = dy >> 1

		add.w	d4,a1		; d + x

		ror.l	#1,d6		; xint = dx >> 1

		move.l	d7,d4

		sub.w	d1,d2		; modulo

		add.w	d3,d7		; y + yint

		add.w	d6,a0		; src + x + xint

		muls.w	d5,d7		; lx * (y + yint)

		move.w	d1,a5

		muls.w	d5,d3		; lx * y

		add.l	d7,a0		; s = src + x + lx * (y + yint)

		add.l	d3,a1		; d = dst + x + lx * y 


		tst.l	d6
		bmi.b	.xh1

		tst.l	d4
		bmi.b	.xh0_yh1
		

.xh0_yh0

.xh0_yh0_notav	; - - - - - - - - - - - - - - - - - - - - - - - -

.xh0_yh0_notavjl
		move.w	a5,d1

.xh0_yh0_notavil
		;        {
		;          d[i] = s[i];
		;        }

		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+

		subq.w	#8,d1
		bne.b	.xh0_yh0_notavil

		add.w	d2,a0
		add.w	d2,a1

		subq.w	#1,d0
		bne.b	.xh0_yh0_notavjl
		bra	.raus

		cnop	0,4

		; - - - - - - - - - - - - - - - - - - - - - - - -
.xh0_yh1		

		lea	(a0,d5.w),a2

.xh0_yh1_notavjl
		move.w	a5,d1
		moveq	#0,d4
		moveq	#0,d6

.xh0_yh1_notavil ;       {
		 ;         d[i] = (unsigned int)(s[i]+s[i+lx]+1)>>1;
		 ;       }

		rept	2

		moveq	#0,d3
		move.b	(a0)+,d4
			move.b	(a0)+,d6
			moveq	#0,d7
		move.b	(a2)+,d3
		add.w	d4,d3
			move.b	(a2)+,d7
		addq.w	#1,d3
			add.w	d6,d7
		asr.w	#1,d3
			addq.w	#1,d7
		move.b	d3,(a1)+
			asr.w	#1,d7
			move.b	d7,(a1)+

		endr

		subq.w	#4,d1
		bne.b	.xh0_yh1_notavil

		add.w	d2,a0
		add.w	d2,a1
		add.w	d2,a2

		subq.w	#1,d0
		bne	.xh0_yh1_notavjl
		bra	.raus

		cnop	0,4

		; - - - - - - - - - - - - - - - - - - - - - - - -

.xh1		tst.l	d4
		bmi.b	.xh1_yh1

.xh1_yh0

.xh1_yh0_notavjl
		moveq	#0,d7
		moveq	#0,d4
		move.b	(a0)+,d7
		move.w	a5,d1

.xh1_yh0_notavil
		;        {
		;          d[i] = (unsigned int)(s[i]+s[i+1]+1)>>1;
		;        }

		rept	4
		move.b	(a0)+,d4
		move.w	d4,d3
		add.w	d7,d3
		asr.w	#1,d3
		move.b	d3,(a1)+
		move.w	d4,d7
		endr

		subq.w	#4,d1

		bne.b	.xh1_yh0_notavil

		add.w	d2,a0
		subq.w	#1,a0
		add.w	d2,a1

		subq.w	#1,d0
		bne.b	.xh1_yh0_notavjl

		bra.b	.raus

		cnop	0,4

		; - - - - - - - - - - - - - - - - - - - - - - - -

.xh1_yh1

.xh1_yh1_notav
		lea	(a0,d5.w),a2
		subq.w	#1,d2

.xh1_yh1_notavjl
		moveq	#0,d6
		moveq	#0,d7
		move.b	(a0)+,d6
		moveq	#0,d4
		move.b	(a2)+,d7
		move.w	a5,d1

.xh1_yh1_notavil
		;        {
		;          d[i] = (unsigned int)(s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2;
		;        }

	rept	2
		move.b	(a0)+,d4
		move.w	d4,d3
		add.w	d6,d3
		move.w	d4,d6
		move.b	(a2)+,d4
		add.w	d4,d3
		add.w	d7,d3
	;	addq.w	#2,d3
		move.w	d4,d7
		asr.w	#2,d3
		move.b	d3,(a1)+
	endr

		subq.w	#2,d1
		bne.b	.xh1_yh1_notavil

		add.w	d2,a0
		add.w	d2,a1
		add.w	d2,a2
		addq.w	#1,a1

		subq.w	#1,d0
		bne.b	.xh1_yh1_notavjl

		; - - - - - - - - - - - - - - - - - - - - - - - -

.raus
	
;		movem.l	(a7)+,d1-d7/a2-d2

		rts


;********************************************************************


		cnop	0,16

_form_component_prediction_average:

	;	a0	uchar *src
	;	a1	uchar *dst


		add.w	d4,a0		; src + x

		ror.l	#1,d7		; yint = dy >> 1

		add.w	d4,a1		; d + x

		ror.l	#1,d6		; xint = dx >> 1

		move.l	d7,d4

		sub.w	d1,d2		; modulo

		add.w	d3,d7		; y + yint

		add.w	d6,a0		; src + x + xint

		muls.w	d5,d7		; lx * (y + yint)

		move.w	d1,a5

		muls.w	d5,d3		; lx * y

		add.l	d7,a0		; s = src + x + lx * (y + yint)

		add.l	d3,a1		; d = dst + x + lx * y 


		tst.l	d6
		bmi	.xh1
		
		tst.l	d4
		bmi.b	.xh0_yh1
.xh0_yh0
		
.xh0_yh0_av	; - - - - - - - - - - - - - - - - - - - - - - - -

.xh0_yh0_avjl	
		move.w	a5,d1
		moveq	#0,d4
		moveq	#0,d6

.xh0_yh0_avil	;        {
		;          v = d[i]+s[i];
		;          d[i] = (v + (v >= 0 ? 1 : 0 )) >>1;
		;        }

		rept	2

		moveq	#0,d3
		move.b	(a0)+,d4
			move.b	(a0)+,d6
		move.b	(a1),d3
			moveq	#0,d7
		add.w	d4,d3
			move.b	1(a1),d7
		addq.w	#1,d3
			add.w	d6,d7
		asr.w	#1,d3
			addq.w	#1,d7
		move.b	d3,(a1)+
			asr.w	#1,d7
			move.b	d7,(a1)+
		endr

		subq.w	#4,d1
		bne.b	.xh0_yh0_avil

		add.w	d2,a0
		add.w	d2,a1

		subq.w	#1,d0
		bne.b	.xh0_yh0_avjl
		bra	.raus


		cnop	0,4

		; - - - - - - - - - - - - - - - - - - - - - - - -
.xh0_yh1		

.xh0_yh1_av
		lea	(a0,d5.w),a2

.xh0_yh1_avjl
		move.w	a5,d1
		moveq	#0,d4
		moveq	#0,d6

.xh0_yh1_avil	 ;       {
		 ;         v = d[i] + ((unsigned int)(s[i]+s[i+lx]+1)>>1);
		 ;         d[i]=(v+(v>=0?1:0))>>1;
		 ;       }


		rept	2

		moveq	#0,d3
		move.b	(a0)+,d4
			move.b	(a0)+,d6
			moveq	#0,d7
		move.b	(a2)+,d3
		add.w	d4,d3
			move.b	(a2)+,d7
		addq.w	#1,d3
			add.w	d6,d7
		asr.w	#1,d3
	;		addq.w	#1,d7
		move.b	(a1),d4
			asr.w	#1,d7
			move.b	1(a1),d6
		add.w	d4,d3
			add.w	d6,d7
	;	addq.w	#1,d3
	;		addq.w	#1,d7
		asr.w	#1,d3
		move.b	d3,(a1)+
			asr.w	#1,d7
			move.b	d7,(a1)+
		
		endr
		
		subq.w	#4,d1
		bne	.xh0_yh1_avil

		add.w	d2,a0
		add.w	d2,a1
		add.w	d2,a2

		subq.w	#1,d0
		bne	.xh0_yh1_avjl
		bra	.raus


		cnop	0,4

		; - - - - - - - - - - - - - - - - - - - - - - - -

.xh1
		tst.l	d4
		bmi.b	.xh1_yh1

.xh1_yh0

.xh1_yh0_av	; - - - - - - - - - - - - - - - - - - - - - - - -

.xh1_yh0_avjl	moveq	#0,d7
		move.w	a5,d1
		move.b	(a0)+,d7
		moveq	#0,d4

.xh1_yh0_avil
		;        {
		;          v = d[i] + ((unsigned int)(s[i]+s[i+1]+1)>>1);
		;          d[i] = (v+(v>=0?1:0))>>1;
		;        }

	rept	4
		move.b	(a0)+,d4
		move.w	d4,d3
		add.w	d7,d3
		move.w	d4,d7
		asr.w	#1,d3
		move.b	(a1),d4
		add.w	d4,d3
		asr.w	#1,d3
		move.b	d3,(a1)+
	endr

		subq.w	#4,d1
		bne	.xh1_yh0_avil

		add.w	d2,a0
		subq.w	#1,a0
		add.w	d2,a1

		subq.w	#1,d0
		bne	.xh1_yh0_avjl
		bra.b	.raus

		cnop	0,4


		; - - - - - - - - - - - - - - - - - - - - - - - -

.xh1_yh1	lea	(a0,d5.w),a2
		subq.w	#1,d2

.xh1_yh1_avjl	moveq	#0,d6
		moveq	#0,d7
		move.b	(a0)+,d6
		move.w	a5,d1
		move.b	(a2)+,d7
		moveq	#0,d4
		
.xh1_yh1_avil
		;        {
		;          v = d[i] + ((unsigned int)(s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2);
		;          d[i] = (v+(v>=0?1:0))>>1;
		;        }

	rept	2
		move.b	(a0)+,d4
		move.w	d4,d3
		add.w	d6,d3
		move.w	d4,d6
		move.b	(a2)+,d4
		add.w	d4,d3
		add.w	d7,d3
	;	addq.w	#2,d3
		move.w	d4,d7
		asr.w	#2,d3
		move.b	(a1),d4
		add.w	d4,d3
	;	addq.w	#1,d3
		asr.w	#1,d3
		move.b	d3,(a1)+
	endr

		subq.w	#2,d1
		bne.b	.xh1_yh1_avil

		add.w	d2,a0
		add.w	d2,a1
		add.w	d2,a2
		addq.w	#1,a1

		subq.w	#1,d0
		bne.b	.xh1_yh1_avjl
		
.raus
		rts


;********************************************************************

		END

