giantPort_PPC.c   [plain text]


/* Copyright (c) 1998 Apple Computer, Inc.  All rights reserved.
 *
 * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
 * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
 * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE
 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER,
 * INC.  ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
 * EXPOSE YOU TO LIABILITY.
 ***************************************************************************
 *
 * giantPort_PPC.c - PPC-dependent giant definitions.
 *
 * Revision History
 * ----------------
 * 10/06/98		ap
 *	Changed to compile with C++.
 * 06 Apr 1998	Doug Mitchell at Apple
 *	Created.
 */

#include "feeDebug.h"
#include "platform.h"
#include "giantPort_PPC.h"

#if	!PPC_GIANT_PORT_INLINE


/*
 * Multiple-precision arithmetic routines/macros.
 */

asm giantDigit giantAddDigits(
	register giantDigit dig1,
	register giantDigit dig2,
	register giantDigit *carry)	/* RETURNED, 0 or 1 */

{
	/*
	 * dig1  : r3
	 * dig2  : r4
	 * carry : r5
	 * sum   : r6
	 */

	/* sum = dig1 + dig2 */
	add	r6, dig1, dig2;

	/* if((sum < dig1) || (sum < dig2)) */
	cmpl	crf0,0,r6,dig1
	bc	12,0,*+12
	cmpl	crf0,0,r6,dig2
	bc	4,0,*+16

	/* *carry = 1; */
	li	r7,1
	stw	r7, 0(r5)
	b	*+12

	/* else *carry = 0; */
	li	r7,0
	stw	r7, 0(r5)

	/* return sum in r3 */
	mr.	r3,r6
	blr
}

/*
 * Add a single digit value to a double digit accumulator in place.
 * Carry out of the MSD of the accumulator is not handled.
 * This should work any size giantDigits up to unsigned int.
 */
asm void giantAddDouble(
 	register giantDigit *accLow,		/* IN/OUT */
	register giantDigit *accHigh,		/* IN/OUT */
	register giantDigit val)
{
	/*
	 * r3 : accLow
	 * r4 : accHi
	 * r5 : val
	 * r6 : sumLo
	 * r7 : *accLow
	 */

	/* giantDigit sumLo = *accLow + val; */
	lwz	r7,0(accLow)
	add	r6,r7,val

	/* if((sumLo < *accLow) || (sumLo < val)) { */
	cmpl     crf0,0,r6,r7
	bc       12,0,*+12
	cmpl     crf0,0,r6,val
	bc       4,0,*+16

	/* (*accHigh)++; */
	lwz	r7, 0(accHigh)
	addi	r7,r7,1
	stw	r7, 0(accHigh)

	/* *accLow = sumLo; */
	stw		r6,0(accLow)
	blr
}

asm giantDigit giantSubDigits(
	register giantDigit a,
	register giantDigit b,
	register giantDigit *borrow)		/* RETURNED, 0 or 1 */

{
	/* a  : r3
	   b  : r4
	   borrow : r5
	   diff   : r6 */

	/* giantDigit diff = a - b; */
	subf	r6, b, a;

	/* if(a < b) */
	cmpl	crf0,0,a,b
	bc	4,0,*+16

	/* *borrow = 1; */
	li       r7,1
	stw      r7, 0(borrow)
	b        *+12

	/* else *borrow = 0; */
	li       r7,0
	stw      r7, 0(borrow)

	/* return diff in r3 */
	mr.      r3,r6
	blr
}

asm void giantMulDigits(
	register giantDigit dig1,
	register giantDigit dig2,
 	register giantDigit *lowProduct,	/* RETURNED, low digit */
	register giantDigit *hiProduct)		/* RETURNED, high digit */
{
	/* r3 : dig1
	   r4 : dig2
	   r5 : lowProduct
	   r6 : hiProduct */

	/* dprod = (unsigned long long)dig1 * (unsigned long long)dig2; */
	mullw	r7, dig1, dig2	/* r7 = low(dig1 * dig2) */
	mulhwu	r8, dig1, dig2	/* r8 - hi(dig1 * dig2) */

	/* *hiProduct = (giantDigit)(dprod >> GIANT_BITS_PER_DIGIT); */
	stw	r8, 0(hiProduct)

	/* *lowProduct = (giantDigit)dprod; */
	stw	r7, 0(lowProduct)
	blr
}

asm giantDigit VectorMultiply(
	register giantDigit plierDigit,		/* r3 */
	register giantDigit *candVector,	/* r4 */
	register unsigned candLength,		/* r5 */
	register giantDigit *prodVector)	/* r6 */
{
	register unsigned candDex; 			/* index into multiplicandVector */
	register giantDigit lastCarry;
	register giantDigit prodLo;
	register giantDigit prodHi;
	register unsigned scr1;
	register unsigned sumLo;

	fralloc

    /* giantDigit lastCarry = 0; */
	li       lastCarry,0


	/* for(candDex=0; candDex<candLength; ++candDex) { */
	li       candDex,0
	b		_endLoop

	    /*
	     * prod = *(candVector++) * plierDigit + *prodVector + lastCarry
	     */
_topLoop:
		lwz      scr1,0(candVector)				/* *candVector --> scr1 */
		addi     candVector,candVector,4		/* candVector++ */

		mullw	prodLo,scr1,plierDigit	/* prodLo = low(*candVector * plierDigit) */
		mulhwu	prodHi,scr1,plierDigit	/* prodHi = high(*candVector * plierDigit) */

	    /* giantAddDouble(&prodLo, &prodHi, *prodVector); */
		lwz     scr1,0(prodVector)		/* *prodVector --> r9 */
		add		sumLo,prodLo,scr1		/* prodLo + *prodVector --> sumLo */
		cmpl	crf0,0,sumLo,prodLo		/* sumLo < prodLo? */
		bc		12,0,_carry1
		cmpl	crf0,0,sumLo,scr1		/* sumLo < *prodVector? */
		bc		4,0,_noCar1
_carry1:
		addi	prodHi,prodHi,1			/* prodHi++ */
_noCar1:
		mr.		prodLo,sumLo			/* prodLo := sumLo */

	    /* giantAddDouble(&prodLo, &prodHi, lastCarry); */
		add		sumLo,sumLo,lastCarry	/* sumLo += lastCarry */
		cmpl	crf0,0,sumLo,prodLo		/* sumLo < prodLo? */
		bc		12,0,_carry2
		cmpl	crf0,0,sumLo,lastCarry	/* sumLo < lastCarry? */
		bc		4,0,_noCar2
_carry2:
		addi	prodHi,prodHi,1			/* prodHi++ */
_noCar2:
		mr.		prodLo,sumLo			/* prodLo := sumLo */

	    /* *(prodVector++) = prodLo; */
		stw      prodLo,0(prodVector)		/* prodLo --> *prodVector */
		addi     prodVector,prodVector,4	/* prodVector++ */

	    /* lastCarry = prodHi; */
		mr.		lastCarry,prodHi

	/* } */
	addi     candDex,candDex,1			/* candDex++ */
_endLoop:
	cmpl     crf0,0,candDex,candLength	/* candDex < candLength? */
	bc       12,0,_topLoop

	/* return lastCarry; */
	mr.      r3,lastCarry				/* return lastCarry in r3 */
	frfree
	blr
}

#endif	// PPC_GIANT_PORT_INLINE