**
**	MandelSquare - AmigaDOS 2.0/3.0 Mandelbrot set explorer
**
**	Iterate.asm, Assembly-language calculation routines
**
**	Copyright © 1991-1992 by Olaf `Olsen' Barthel
**		All Rights Reserved
**

	csect	text,0,0,1,2

	xdef	_Iterate

;	UBYTE Iterate(double RealValue,double ImaginaryValue);
;
;		Fast hand-coded '881 assembly language subroutine.
;	As SAS/C 5.10b and apparently all of its predecessors fail
;	to correctly pass the function arguments in fpu registers
;	SAS/C v6.0 or higher is required to compile the program.
;
;	This is ye olde z²+c algorithm, register usage is a follows:
;
;		d0	= Maximum number of iterations to run
;		d1	= Number of iterations actually run
;
;		fp0	= c (real component, constant)
;		fp1	= c (imaginary component, constant)
;
;		fp2	= Real component
;		fp3	= Imaginary component
;
;		fp4	= z (real component, scratch)
;		fp5	= z (imaginary component, scratch)
;
;		fp6	= Scratch

_Iterate:

	fmovem.x fp2-fp6,-(sp)			; Save registers

	fmove.x	fp0,fp2				; Real = RealValue
	fmove.x	fp1,fp3				; Imaginary = ImaginaryValue

	move.l	_MaxIteration(a4),d0		; Get maximum number of iterations
	moveq	#1,d1				; i = 1

	fmove.x	fp2,fp4				; RealTemp = Real
	fmove.x	fp3,fp5				; ImaginaryTemp = Imaginary

	fmul.x	fp4,fp4				; RealTemp = RealTemp^2
	fmul.x	fp5,fp5				; ImaginaryTemp = ImaginaryTemp^2

	fmove.x	fp4,fp6				; Scratch  = RealTemp
	fadd.x	fp5,fp6				; Scratch += ImaginaryTemp
	fabs.x	fp6,fp6				; Scratch  = fabs(Scratch)

	fcmp.w	#4,fp6				; Scratch > 4?
	fbgt.w	2$				; true -> break

1$	fadd.x	fp3,fp3				; Imaginary *= 2
	fmul.x	fp2,fp3				; Imaginary *= Real
	fadd.x	fp1,fp3				; Imaginary += ImaginaryValue

	fmove.x	fp4,fp2				; Real = RealTemp
	fsub.x	fp5,fp2				; Real -= ImaginaryTemp
	fadd.x	fp0,fp2				; Real += RealValue

	fmove.x	fp2,fp4				; RealTemp = Real
	fmove.x	fp3,fp5				; ImaginaryTemp = Imaginary

	fmul.x	fp4,fp4				; RealTemp = RealTemp^2
	fmul.x	fp5,fp5				; ImaginaryTemp = ImaginaryTemp^2

	fmove.x	fp4,fp6				; Scratch  = RealTemp
	fadd.x	fp5,fp6				; Scratch += ImaginaryTemp
	fabs.x	fp6,fp6				; Scratch  = fabs(Scratch)

	fcmp.w	#4,fp6				; Scratch > 4?
	fbgt.w	2$				; true -> break

	addq	#1,d1				; Iterations++;
	dbf	d0,1$				; false -> Loop;

	moveq	#0,d0

	fmovem.x (sp)+,fp2-fp6			; Restore registers, return 0
	rts

2$	movea.l	_Wave(a4),a0			; Get colour wave table
	move.b	0(a0,d1.w),d0			; Get wave index, always > 0

	fmovem.x (sp)+,fp2-fp6			; Restore registers
	rts

	section	__MERGED,data

	xref	_MaxIteration
	xref	_Wave

	end
