** This is the *BIG* one. Here lies 80% of the work I put into
** "Apfelkiste". Basically this function  does the same as it's
** float counterpart Iter_FLOAT() in Float.c, but it uses a
** fix-point format for real calculations.
** Refer to the revision header of "Apfelkiste.c" for the exact
** definition.
** The conversion of normal floats to my format is quite easy:
**	Multiply the float by 2**24 (doing a 24 bit shift in fact),
**	cast to long and there you are...
**
** This file needs to be assembled separately in order to recompile 
** the whole source. I really think Lattice DOES need an inline
** assembly facility, or at least the workbench interface should
** update and link *.a files the same way it does with *.c and *.o .

	CSECT	DATA,1,,2,2

	XREF	_maxcol
	XREF	_MAXITER

	CSECT	TEXT,0,,1,2

	XDEF	_Iter_FXP

_Iter_FXP:
	movem.l	D3-D7,-(SP)

	move.l	D1,D3		;(r)
	move.l	D2,D4		;(i)
	move.w	_MAXITER(A4),D0
	ext.l	D0		;(count)	 

__while:
	swap	D0
	move.l	D3,A1		;save r
	tst.l	D3		;r < 0?
	bpl.s	__skip1		;no
	neg.l	D3		;yes, negate

__skip1:
	move.w	D3,D5		;rl * rl -> D5
	mulu.w	D3,D5
	clr.w	D5		;24 bit right shift
	swap	D5
	lsr.w	#8,D5

	move.l	D3,D6		;2 * rl * rh -> D6
	swap	D6
	mulu.w	D3,D6
	lsr.l	#7,D6		;7 bit only, because of factor 2!
	add.l	D6,D5		;collect in D5

	swap	D3		;rh * rh -> D3
	mulu.w	D3,D3
	asl.l	#8,D3		;8 bit left shift
	add.l	D3,D5		;collect in D5

	move.l	A1,D3		;fetch r back

	move.l	D4,A0		;save i
	tst.l	D4		;D4 < 0?
	bpl.s	__skip2		;no
	neg.l	D4		;yes, negate

__skip2:
	move.w	D4,D6		;il * il -> D6
	mulu.w	D4,D6
	clr.w	D6		;24 bit right shift
	swap	D6
	lsr.w	#8,D6
	add.l	D6,D5		;collect in D5

	move.l	D4,D6		;2 * il * ih -> D6
	swap	D6
	mulu.w	D4,D6
	lsr.l	#7,D6		;7 bit only because of factor 2!
	add.l	D6,D5		;collect in  D5

	swap	D4		;ih * ih -> D4
	mulu.w	D4,D4
	asl.l	#8,D4
	add.l	D4,D5		;collect in D5

;now D5 contains r * r + i * i

	cmp.l	A2,D5		;test for upper bound
	bge	__done		;exceeded => end

;evaluate ( r + i ) * ( r - i ) + p -> D7

	;No need to save r and i (D3 / D4), beacause they're already
	;in A1 / A0 (well, saved another 4 machine cycles!)
	
	add.l	A0,D3		;r+i -> D3
	move.l	A1,D4		;r-i -> D4
	sub.l	A0,D4

	tst.l	D3		;r < 0?
	bpl.s	__skip3		;no
	neg.l	D3		;yes, negate
	not.w	D0		;remember negative sign

__skip3:
	tst.l	D4		;i < 0?
	bpl.s	__skip4		;no
	neg.l	D4		;yes, negate
	not.w	D0		;remember negative sign

__skip4:
	move.w	D3,D7		;rl * il -> D7
	mulu.w	D4,D7
	clr.w	D7		;24 bit shift
	swap	D7
	lsr.w	#8,D7

	swap	D4		;rl * ih -> D6
	move.w	D4,D6
	mulu.w	D3,D6
	lsr.l	#8,D6		;8 bit shift
	
	add.l	D6,D7		;collect in D7

	swap	D3		;rh * ih -> D6
	move.w	D4,D6
	mulu.w	D3,D6
	asl.l	#8,D6		;8 bit shift
	add.l	D6,D7		;collect in D7

	swap	D4		;rh * il -> D6
	mulu.w	D3,D4
	lsr.l	#8,D4		;8 bit shift
	add.l	D4,D7		;collect in D7

	tst.w	D0		;correct result?
	beq.s	__skip5		;no
	neg.l	D7		;yes
	clr.w	D0		;erase marker

__skip5:
	add.l	D1,D7		;add p

;evaluate 2 * r * i + q -> D5

	move.l	A1,D3		;call r and i back
	move.l	A0,D4
	
	tst.l	D3		;r < 0?
	bpl.s	__skip6		;no
	neg.l	D3		;yes, negate
	not.w	D0		;remember negative sign

__skip6:
	tst.l	D4		;i < 0?
	bpl.s	__skip7		;no
	neg.l	D4		;yes, negate
	not.w	D0		;remember negative sign

__skip7:
	move.w	D3,D5		;2 * rl * il -> D5
	mulu.w	D4,D5
	clr.w	D5		;23 bit shift (instead of 24, because of factor 2)
	swap	D5
	lsr.w	#7,D5

	swap	D4		;2 * rl * ih -> D6
	move.w	D4,D6
	mulu.w	D3,D6
	lsr.l	#7,D6		;7 bit shift (instead of 8, because of factor 2)
	add.l	D6,D5		;collect in D5

	swap	D3		;2 * rh * ih -> D6
	move.w	D4,D6
	mulu.w	D3,D6
	asl.l	#8,D6		;9 bit shift  (instead of 8, because of factor 2)
	add.l	D6,D6		;add.l is 2 cycles faster as asl.l #1  !
	add.l	D6,D5		;collect in D5

	swap	D4		;2 * rh * il -> D6
	mulu.w	D3,D4
	lsr.l	#7,D4		;7 bit shift (instead of 8, because of factor 2)
	add.l	D5,D4		;collect in D4, i = 2 * r * i

	tst.w	D0		;correct result?
	beq.s	__skip8		;no
	neg.l	D4		;yes
	clr.w	D0		;erase marker

__skip8:
	add.l	D2,D4		;add q, i = 2 * r * i + q

	move.l	D7,D3		;r = ( r + i ) * ( r - i ) + p

	swap	D0
	dbra	D0,__while	;to start of loop

	moveq	#0,D0		;return 0, if MAXITER was exceeded

	movem.l	(SP)+,D3-D7
	rts

__done:
	swap	D0
	divu.w	_maxcol(A4),D0	;return ( count % maxcol )
	clr.w	D0
	swap	D0

	movem.l	(SP)+,D3-D7
	rts

	END
