1/* Copyright (c) 1998,2011,2014 Apple Inc.  All Rights Reserved.
2 *
3 * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
4 * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
5 * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE
6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE,
7 * INC.  ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
8 * EXPOSE YOU TO LIABILITY.
9 ***************************************************************************
10 *
11 * giantPort_PPC.c - PPC-dependent giant definitions.
12 *
13 * Revision History
14 * ----------------
15 * 10/06/98		ap
16 *	Changed to compile with C++.
17 * 06 Apr 1998 at Apple
18 *	Created.
19 */
20
21#include "feeDebug.h"
22#include "platform.h"
23#include "giantPort_PPC.h"
24
25#if	!PPC_GIANT_PORT_INLINE
26
27
28/*
29 * Multiple-precision arithmetic routines/macros.
30 */
31
32asm giantDigit giantAddDigits(
33	register giantDigit dig1,
34	register giantDigit dig2,
35	register giantDigit *carry)	/* RETURNED, 0 or 1 */
36
37{
38	/*
39	 * dig1  : r3
40	 * dig2  : r4
41	 * carry : r5
42	 * sum   : r6
43	 */
44
45	/* sum = dig1 + dig2 */
46	add	r6, dig1, dig2;
47
48	/* if((sum < dig1) || (sum < dig2)) */
49	cmpl	crf0,0,r6,dig1
50	bc	12,0,*+12
51	cmpl	crf0,0,r6,dig2
52	bc	4,0,*+16
53
54	/* *carry = 1; */
55	li	r7,1
56	stw	r7, 0(r5)
57	b	*+12
58
59	/* else *carry = 0; */
60	li	r7,0
61	stw	r7, 0(r5)
62
63	/* return sum in r3 */
64	mr.	r3,r6
65	blr
66}
67
68/*
69 * Add a single digit value to a double digit accumulator in place.
70 * Carry out of the MSD of the accumulator is not handled.
71 * This should work any size giantDigits up to unsigned int.
72 */
73asm void giantAddDouble(
74 	register giantDigit *accLow,		/* IN/OUT */
75	register giantDigit *accHigh,		/* IN/OUT */
76	register giantDigit val)
77{
78	/*
79	 * r3 : accLow
80	 * r4 : accHi
81	 * r5 : val
82	 * r6 : sumLo
83	 * r7 : *accLow
84	 */
85
86	/* giantDigit sumLo = *accLow + val; */
87	lwz	r7,0(accLow)
88	add	r6,r7,val
89
90	/* if((sumLo < *accLow) || (sumLo < val)) { */
91	cmpl     crf0,0,r6,r7
92	bc       12,0,*+12
93	cmpl     crf0,0,r6,val
94	bc       4,0,*+16
95
96	/* (*accHigh)++; */
97	lwz	r7, 0(accHigh)
98	addi	r7,r7,1
99	stw	r7, 0(accHigh)
100
101	/* *accLow = sumLo; */
102	stw		r6,0(accLow)
103	blr
104}
105
106asm giantDigit giantSubDigits(
107	register giantDigit a,
108	register giantDigit b,
109	register giantDigit *borrow)		/* RETURNED, 0 or 1 */
110
111{
112	/* a  : r3
113	   b  : r4
114	   borrow : r5
115	   diff   : r6 */
116
117	/* giantDigit diff = a - b; */
118	subf	r6, b, a;
119
120	/* if(a < b) */
121	cmpl	crf0,0,a,b
122	bc	4,0,*+16
123
124	/* *borrow = 1; */
125	li       r7,1
126	stw      r7, 0(borrow)
127	b        *+12
128
129	/* else *borrow = 0; */
130	li       r7,0
131	stw      r7, 0(borrow)
132
133	/* return diff in r3 */
134	mr.      r3,r6
135	blr
136}
137
138asm void giantMulDigits(
139	register giantDigit dig1,
140	register giantDigit dig2,
141 	register giantDigit *lowProduct,	/* RETURNED, low digit */
142	register giantDigit *hiProduct)		/* RETURNED, high digit */
143{
144	/* r3 : dig1
145	   r4 : dig2
146	   r5 : lowProduct
147	   r6 : hiProduct */
148
149	/* dprod = (unsigned long long)dig1 * (unsigned long long)dig2; */
150	mullw	r7, dig1, dig2	/* r7 = low(dig1 * dig2) */
151	mulhwu	r8, dig1, dig2	/* r8 - hi(dig1 * dig2) */
152
153	/* *hiProduct = (giantDigit)(dprod >> GIANT_BITS_PER_DIGIT); */
154	stw	r8, 0(hiProduct)
155
156	/* *lowProduct = (giantDigit)dprod; */
157	stw	r7, 0(lowProduct)
158	blr
159}
160
161asm giantDigit VectorMultiply(
162	register giantDigit plierDigit,		/* r3 */
163	register giantDigit *candVector,	/* r4 */
164	register unsigned candLength,		/* r5 */
165	register giantDigit *prodVector)	/* r6 */
166{
167	register unsigned candDex; 			/* index into multiplicandVector */
168	register giantDigit lastCarry;
169	register giantDigit prodLo;
170	register giantDigit prodHi;
171	register unsigned scr1;
172	register unsigned sumLo;
173
174	fralloc
175
176    /* giantDigit lastCarry = 0; */
177	li       lastCarry,0
178
179
180	/* for(candDex=0; candDex<candLength; ++candDex) { */
181	li       candDex,0
182	b		_endLoop
183
184	    /*
185	     * prod = *(candVector++) * plierDigit + *prodVector + lastCarry
186	     */
187_topLoop:
188		lwz      scr1,0(candVector)				/* *candVector --> scr1 */
189		addi     candVector,candVector,4		/* candVector++ */
190
191		mullw	prodLo,scr1,plierDigit	/* prodLo = low(*candVector * plierDigit) */
192		mulhwu	prodHi,scr1,plierDigit	/* prodHi = high(*candVector * plierDigit) */
193
194	    /* giantAddDouble(&prodLo, &prodHi, *prodVector); */
195		lwz     scr1,0(prodVector)		/* *prodVector --> r9 */
196		add		sumLo,prodLo,scr1		/* prodLo + *prodVector --> sumLo */
197		cmpl	crf0,0,sumLo,prodLo		/* sumLo < prodLo? */
198		bc		12,0,_carry1
199		cmpl	crf0,0,sumLo,scr1		/* sumLo < *prodVector? */
200		bc		4,0,_noCar1
201_carry1:
202		addi	prodHi,prodHi,1			/* prodHi++ */
203_noCar1:
204		mr.		prodLo,sumLo			/* prodLo := sumLo */
205
206	    /* giantAddDouble(&prodLo, &prodHi, lastCarry); */
207		add		sumLo,sumLo,lastCarry	/* sumLo += lastCarry */
208		cmpl	crf0,0,sumLo,prodLo		/* sumLo < prodLo? */
209		bc		12,0,_carry2
210		cmpl	crf0,0,sumLo,lastCarry	/* sumLo < lastCarry? */
211		bc		4,0,_noCar2
212_carry2:
213		addi	prodHi,prodHi,1			/* prodHi++ */
214_noCar2:
215		mr.		prodLo,sumLo			/* prodLo := sumLo */
216
217	    /* *(prodVector++) = prodLo; */
218		stw      prodLo,0(prodVector)		/* prodLo --> *prodVector */
219		addi     prodVector,prodVector,4	/* prodVector++ */
220
221	    /* lastCarry = prodHi; */
222		mr.		lastCarry,prodHi
223
224	/* } */
225	addi     candDex,candDex,1			/* candDex++ */
226_endLoop:
227	cmpl     crf0,0,candDex,candLength	/* candDex < candLength? */
228	bc       12,0,_topLoop
229
230	/* return lastCarry; */
231	mr.      r3,lastCarry				/* return lastCarry in r3 */
232	frfree
233	blr
234}
235
236#endif	// PPC_GIANT_PORT_INLINE
237