/*

	Name: algebra_881.s

	68K-assembler replacement for algebra.c (written for GNU `as')
	--------------------------------------------------------------

	Hopefully this will make things a bit faster, and the output
	file smaller. This was primarily a test to see if hand-
	optimization is worth the trouble, and to learn a bit more
	about gcc w/ assembler.

	This source should be easy to adapt to other assemblers than
	`as'. You may have to change the '.global' statements, and
	perhaps the comments. Normally I prefer to use PhxAss (on the
	Amiga). For that assembler you would have to add two lines
	with `MACHINE 68020' and `FPU 1'. Other assemblers may require
	other changes/settings.


    This source-code is part of the RayLab 1.1 package, and it is provided
    for your compiling pleasure.  You may use it, change it, re-compile it
    etc., as long as nobody else but you receive the changes/compilations
    that you have made!

    You may not use any part(s) of this source-code for your own productions
    without the permission from the author of RayLab. Please read the legal
    information found in the users documentation for RayLab for more details.

*/


.global _CreateVector
.global _CopyVector
.global _AddVector
.global _SubVector
.global _NegVector
.global _CrossProduct
.global _DotProduct
.global _ScaleVector
.global _NormalizeVector
.global _VectorLength
.global _VectorsAngle
.global _CreatePoint
.global _CopyPoint
.global _MakeLine
.global _Rotate2D
.global _RotatePoint
.global _RotateVector
.global _RevRotatePoint
.global _RevRotateVector



/* --------------------------------------------------------------
   void CreateVector(VECTOR *v, double vx, double vy, double vz);
   void CreatePoint(POINT *p, double px, double py, double pz);
   -------------------------------------------------------------- */

_CreateVector:
_CreatePoint:
	lea.l	4(sp),a0
	move.l	(a0)+,a1
	moveq 	#6-1,d0
loop0:	move.l	(a0)+,(a1)+	/*  Copy 6 longwords <=> 3 doubles  */
	dbf	d0,loop0
	rts


/* --------------------------------------------------------------
   void CopyVector(VECTOR *v2, VECTOR *v1);
   void CopyPoint(POINT *p2, POINT *p1);
   -------------------------------------------------------------- */

_CopyVector:
_CopyPoint:
	move.l	4(sp),a1	/*  a1 = &v2/p2  */
	move.l	8(sp),a0	/*  a0 = &v1/p1  */
	moveq	#6-1,d0
loop1:	move.l	(a0)+,(a1)+	/*  Copy 6 longwords <=> 3 doubles  */
	dbf	d0,loop1
	rts


/* --------------------------------------------------------------
   void AddVector(VECTOR *v3, VECTOR *v1, VECTOR *v2);
   -------------------------------------------------------------- */

_AddVector:
	move.l	a2,-(sp)
	move.l	8(sp),a2	/*  a2 = &v3  */
	move.l	12(sp),a0	/*  a0 = &v1  */
	move.l	16(sp),a1	/*  a1 = &v2  */
	moveq	#3-1,d0
loop2:	fmove.d	(a0)+,fp0
	fadd.d	(a1)+,fp0
	fmove.d	fp0,(a2)+
	dbf	d0,loop2
	move.l	(sp)+,a2
	rts


/* --------------------------------------------------------------
   void SubVector(VECTOR *v3, VECTOR *v1, VECTOR *v2);
   -------------------------------------------------------------- */

_SubVector:
	move.l	a2,-(sp)
	move.l	8(sp),a2	/*  a2 = &v3  */
	move.l	12(sp),a0	/*  a0 = &v1  */
	move.l	16(sp),a1	/*  a1 = &v2  */
	moveq	#3-1,d0
loop3:	fmove.d	(a0)+,fp0
	fsub.d	(a1)+,fp0
	fmove.d	fp0,(a2)+
	dbf	d0,loop3
	move.l	(sp)+,a2
	rts


/* --------------------------------------------------------------
   void NegVector(VECTOR *v2, VECTOR *v1);
   -------------------------------------------------------------- */

_NegVector:
	move.l	4(sp),a1	/*  a1 = &v2  */
	move.l	8(sp),a0	/*  a0 = &v1  */
	fneg.d	(a0)+,fp0
	fmove.d	fp0,(a1)+
	fneg.d	(a0)+,fp0
	fmove.d	fp0,(a1)+
	fneg.d	(a0)+,fp0
	fmove.d	fp0,(a1)+
	rts


/* --------------------------------------------------------------
   void CrossProduct(VECTOR *v3, VECTOR *v1, VECTOR *v2);
   -------------------------------------------------------------- */

_CrossProduct:
	move.l	a2,-(sp)
	move.l	8(sp),a2	/*  a2 = &v3  */
	move.l	12(sp),a0	/*  a0 = &v1  */
	move.l	16(sp),a1	/*  a1 = &v2  */
	fmove.d	8(a0),fp0
	fmul.d	16(a1),fp0
	fmove.d	16(a0),fp1
	fmul.d	8(a1),fp1
	fsub.x	fp1,fp0
	fmove.d	fp0,(a2)+	/*  v3.x = v1.y * v2.z - v1.z * v2.y  */
	fmove.d	16(a0),fp0
	fmul.d	(a1),fp0
	fmove.d	(a0),fp1
	fmul.d	16(a1),fp1
	fsub.x	fp1,fp0
	fmove.d	fp0,(a2)+	/*  v3.y = v1.z * v2.x - v1.x * v2.z  */
	fmove.d	(a0),fp0
	fmul.d	8(a1),fp0
	fmove.d	8(a0),fp1
	fmul.d	(a1),fp1
	fsub.x	fp1,fp0
	fmove.d	fp0,(a2)	/*  v3.z = v1.x * v2.y - v1.y * v2.x  */
	move.l	(sp)+,a2
	rts


/* --------------------------------------------------------------
   double DotProduct(VECTOR *v1, VECTOR *v2);
   -------------------------------------------------------------- */

_DotProduct:
	move.l	4(sp),a0	/*  a0 = &v1  */
	move.l	8(sp),a1	/*  a1 = &v2  */
	fmove.d	(a0)+,fp0
	fmul.d	(a1)+,fp0
	fmove.d	(a0)+,fp1
	fmul.d	(a1)+,fp1
	fadd.x	fp1,fp0
	fmove.d	(a0),fp1
	fmul.d	(a1),fp1
	fadd.x	fp1,fp0
	fmove.d	fp0,-(sp)
	movem.l	(sp)+,d0/d1	/*  Return double in d0:d1  */
	rts


/* --------------------------------------------------------------
   void ScaleVector(VECTOR *v2, double t, VECTOR *v1);
   -------------------------------------------------------------- */

_ScaleVector:
	move.l	4(sp),a1	/*  a1 = &v2  */
	fmove.d	8(sp),fp1	/* fp1 = t    */
	move.l	16(sp),a0	/*  a0 = &v1  */
	moveq	#3-1,d0
loop4:	fmove.d	(a0)+,fp0
	fmul.x	fp1,fp0
	fmove.d	fp0,(a1)+
	dbf	d0,loop4
	rts


/* --------------------------------------------------------------
   void NormalizeVector(VECTOR *v2, VECTOR *v1);
   -------------------------------------------------------------- */

_NormalizeVector:
	move.l	4(sp),a1	/*  a1 = &v2  */
	move.l	8(sp),a0	/*  a0 = &v1  */
	fmove.d	(a0),fp0
	fmul.x	fp0,fp0
	fmove.d	8(a0),fp1
	fmul.x	fp1,fp1
	fadd.x	fp1,fp0
	fmove.d	16(a0),fp1
	fmul.x	fp1,fp1
	fadd.x	fp1,fp0
	fsqrt.x	fp0,fp0		/*  fp0 = | v1 |  */
	fmovecr	#0x32,fp1	/*  fp1 = 1.0  (from FPU ROM)  */
	fdiv.x	fp0,fp1
	moveq	#3-1,d0
loop5:	fmove.d	(a0)+,fp0
	fmul.x	fp1,fp0
	fmove.d	fp0,(a1)+
	dbf	d0,loop5
	rts


/* --------------------------------------------------------------
   double VectorLength(VECTOR *v);
   -------------------------------------------------------------- */

_VectorLength:
	move.l	4(sp),a0	/*  a0 = &v  */
	fmove.d	(a0)+,fp0
	fmul.x	fp0,fp0
	fmove.d	(a0)+,fp1
	fmul.x	fp1,fp1
	fadd.x	fp1,fp0
	fmove.d	(a0),fp1
	fmul.x	fp1,fp1
	fadd.x	fp1,fp0
	fsqrt.x	fp0,fp0		/*  fp0 = | v |  */
	fmove.d	fp0,-(sp)
	movem.l	(sp)+,d0/d1	/*  Return double in d0:d1  */
	rts


/* --------------------------------------------------------------
   double VectorsAngle(VECTOR *v1, VECTOR *v2);
   -------------------------------------------------------------- */

_VectorsAngle:
	move.l	4(sp),a0	/*  a0 = &v1  */
	move.l	8(sp),a1	/*  a1 = &v2  */
	fmove.x	fp2,-(sp)

	fmove.d	(a0),fp0
	fmul.x	fp0,fp0
	fmove.d	8(a0),fp1
	fmul.x	fp1,fp1
	fadd.x	fp1,fp0
	fmove.d	16(a0),fp1
	fmul.x	fp1,fp1
	fadd.x	fp1,fp0		/*  fp0 = | v1 | ^ 2  */

	fmove.d	(a1),fp2
	fmul.x	fp2,fp2
	fmove.d	8(a1),fp1
	fmul.x	fp1,fp1
	fadd.x	fp1,fp2
	fmove.d	16(a1),fp1
	fmul.x	fp1,fp1
	fadd.x	fp1,fp2		/*  fp2 = | v2 | ^ 2  */
	fmul.x	fp0,fp2
	fsqrt.x	fp2,fp2		/*  fp2 = | v1 | * | v2 |  */

	fmove.d	(a0)+,fp0
	fmul.d	(a1)+,fp0
	fmove.d	(a0)+,fp1
	fmul.d	(a1)+,fp1
	fadd.x	fp1,fp0
	fmove.d	(a0)+,fp1
	fmul.d	(a1)+,fp1
	fadd.x	fp1,fp0		/*  fp0 = v1 . v2  */
	fdiv.x	fp2,fp0
	facos.x	fp0,fp0		/*  fp0 = Smallest angle between v1 and v2  */
	fmove.d	fp0,-(sp)
	movem.l	(sp)+,d0/d1	/*  Return double in d0:d1  */
	fmove.x	(sp)+,fp2
	rts


/* --------------------------------------------------------------
   void MakeLine(LINE *l, POINT *p1, POINT *p2);
   -------------------------------------------------------------- */

_MakeLine:
	move.l	a2,-(sp)
	move.l	8(sp),a2	/*  a2 = &l  */
	move.l	12(sp),a0	/*  a0 = &p1  */
	move.l	16(sp),a1	/*  a1 = &p2  */
	fmovem.x fp2-fp5,-(sp)
	fmove.d	(a0)+,fp0
	fmove.d	(a0)+,fp1
	fmove.d	(a0),fp2	/*  fp0-fp2 = p1  */
	fmove.d	fp0,(a2)+
	fmove.d	fp1,(a2)+
	fmove.d	fp2,(a2)+	/*  l.Origin = p1  */
	fmove.d	(a1)+,fp3
	fmove.d	(a1)+,fp4
	fmove.d	(a1),fp5	/*  fp3-fp5 = p2  */
	fsub.x	fp0,fp3
	fsub.x	fp1,fp4
	fsub.x	fp2,fp5
	fmove.d	fp3,(a2)+
	fmove.d	fp4,(a2)+
	fmove.d	fp5,(a2)	/*  l.Direction = p2 - p1  */
	fmovem.x (sp)+,fp2-fp5
	move.l	(sp)+,a2
	rts


/* --------------------------------------------------------------
   void Rotate2D(double *x, double *y, double ar);
   -------------------------------------------------------------- */

_Rotate2D:
	move.l	4(sp),a0	/*  a0 = &x  */
	move.l	8(sp),a1	/*  a1 = &y  */
	fmove.x	fp2,-(sp)
	fmove.d	24(sp),fp2	/*  fp2 = ar  */
	bsr	Rotate2DQuick
	fmove.x	(sp)+,fp2
	rts


/* --------------------------------------------------------------
   void RotatePoint(POINT *p, VECTOR *RotV);
   void RotateVector(VECTOR *v, VECTOR *RotV);
   -------------------------------------------------------------- */

_RotatePoint:
_RotateVector:
	movem.l	a2/a3,-(sp)
	move.l	12(sp),a2	/*  a2 = &p  */
	move.l	16(sp),a3	/*  a3 = &RotV  */
	fmove.x	fp2,-(sp)
	fmove.d	(a3)+,fp2	/*  fp2 = RotV.x  */
	fcmp.s	#0,fp2
	fbeq	no_xrot0
	lea.l	8(a2),a0	/*  a0 = &p.y  */
	lea.l	16(a2),a1	/*  a1 = &p.z  */
	bsr	Rotate2DQuick
no_xrot0:
	fmove.d	(a3)+,fp2	/*  fp2 = RotV.y  */
	fcmp.s	#0,fp2
	fbeq	no_yrot0
	lea.l	16(a2),a0	/*  a0 = &p.z  */
	lea.l	(a2),a1		/*  a1 = &p.x  */
	bsr	Rotate2DQuick
no_yrot0:
	fmove.d	(a3),fp2	/*  fp2 = RotV.z  */
	fcmp.s	#0,fp2
	fbeq	no_zrot0
	lea.l	(a2),a0		/*  a0 = &p.x  */
	lea.l	8(a2),a1	/*  a1 = &p.y  */
	bsr	Rotate2DQuick
no_zrot0:
	fmove.x	(sp)+,fp2
	movem.l	(sp)+,a2/a3
	rts


/* --------------------------------------------------------------
   void Rotate2DQuick(double *x, double *y, double ar);

   a0 = &x,  a1 = &y,  fp2 = ar
   -------------------------------------------------------------- */


Rotate2DQuick:
	fmovem.x fp3-fp5,-(sp)
	fmove.d	(a0),fp0	/*  fp0 = x  */
	fmove.d	(a1),fp1	/*  fp1 = y  */
	fcos.x	fp2,fp3		/*  fp3 = cos(ar)  */
	fsin.x	fp2,fp2		/*  fp2 = sin(ar)  */
	fmove.x	fp0,fp4
	fmul.x	fp3,fp4
	fmove.x	fp1,fp5
	fmul.x	fp2,fp5
	fsub.x	fp5,fp4		/*  fp4 = x cos(ar) - y sin(ar)  */
	fmul.x	fp2,fp0
	fmul.x	fp3,fp1
	fadd.x	fp0,fp1		/*  fp1 = x sin(ar) + y cos(ar)  */
	fmove.d	fp4,(a0)	/*  x1 =  x cos(ar) - y sin(ar)  */
	fmove.d	fp1,(a1)	/*  y1 =  x sin(ar) + y cos(ar)  */
	fmovem.x (sp)+,fp3-fp5
	rts


/* --------------------------------------------------------------
   void RevRotatePoint(POINT *p, VECTOR *RotV);
   void RevRotateVector(VECTOR *v, VECTOR *RotV);
   -------------------------------------------------------------- */

_RevRotatePoint:
_RevRotateVector:
	movem.l	a2/a3,-(sp)
	move.l	12(sp),a2	/*  a2 = *p  */
	move.l	16(sp),a3	/*  a3 = *RotV  */
	fmove.x	fp2,-(sp)
	fmove.d	16(a3),fp2	/*  fp2 = RotV.z  */
	fcmp.s	#0,fp2
	fbeq	no_zrot1
	lea.l	(a2),a0		/*  a0 = &p.x  */
	lea.l	8(a2),a1	/*  a1 = &p.y  */
	bsr	Rotate2DQuick
no_zrot1:
	fmove.d	8(a3),fp2	/*  fp2 = RotV.y  */
	fcmp.s	#0,fp2
	fbeq	no_yrot1
	lea.l	16(a2),a0	/*  a0 = &p.z  */
	lea.l	(a2),a1		/*  a1 = &p.x  */
	bsr	Rotate2DQuick
no_yrot1:
	fmove.d	(a3),fp2	/*  fp2 = RotV.x  */
	fcmp.s	#0,fp2
	fbeq	no_xrot1
	lea.l	8(a2),a0	/*  a0 = &p.y  */
	lea.l	16(a2),a1	/*  a1 = &p.z  */
	bsr	Rotate2DQuick
no_xrot1:
	fmove.x	(sp)+,fp2
	movem.l	(sp)+,a2/a3
	rts

