2 * Copyright (c) 2001,2011,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 * As of 3/19/2001, using this module results in no change in runtime
27 * performance compared to using the inline C functions in
28 * giantPort_Generic.h. Examination of the compiled code shows that
29 * the GNU C compiler, when configured for -O2, generates almost
30 * exactly the same code as we have here.
31 * We'll leave this code in, to protect against changes in gcc, changes
32 * in CFLAGS, and to serve as an example for other PPC implementations.
35 #if defined(__ppc__) && defined(__MACH__)
37 /*********************************************
39 Add two digits, return sum. Carry bit returned as an out parameter.
41 giantDigit giantAddDigits(
42 register giantDigit dig1,
43 register giantDigit dig2,
44 register giantDigit *carry) ...RETURNED, 0 or 1
45 **********************************************/
48 .globl _giantAddDigits
57 /* sum = dig1 + dig2 */
60 /* if((sum < dig1) || (sum < dig2)) */
73 /* else *carry = 0; */
78 /* return sum in r3 */
82 /*********************************************
84 Add a single digit value to a double digit accumulator in place.
85 Carry out of the MSD of the accumulator is not handled.
88 giantDigit *accLow, -- IN/OUT
89 giantDigit *accHigh, -- IN/OUT
91 **********************************************/
94 .globl _giantAddDouble
104 /* giantDigit sumLo = *accLow + val; */
108 /* if((sumLo < *accLow) || (sumLo < val)) { */
121 /* *accLow = sumLo; */
125 /*****************************************************************************
127 Subtract a - b, return difference. Borrow bit returned as an out parameter.
129 giantDigit giantSubDigits(
132 giantDigit *borrow) -- RETURNED, 0 or 1
134 ******************************************************************************/
137 .globl _giantSubDigits
145 /* giantDigit diff = a - b; */
158 /* else *borrow = 0; */
163 /* return diff in r3 */
167 /*****************************************************************************
169 Multiply two digits, return two digits.
174 giantDigit *lowProduct, -- RETURNED, low digit
175 giantDigit *hiProduct) -- RETURNED, high digit
177 ******************************************************************************/
180 .globl _giantMulDigits
188 /* dprod = (unsigned long long)dig1 * (unsigned long long)dig2; */
189 mullw r7, r3, r4 /* r7 = low(dig1 * dig2) */
190 mulhwu r8, r3, r4 /* r8 - hi(dig1 * dig2) */
192 /* *hiProduct = (giantDigit)(dprod >> GIANT_BITS_PER_DIGIT); */
195 /* *lowProduct = (giantDigit)dprod; */
200 /*****************************************************************************
202 Multiply a vector of giantDigits, candVector, by a single giantDigit,
203 plierDigit, adding results into prodVector. Returns m.s. digit from
204 final multiply; only candLength digits of *prodVector will be written.
206 giantDigit VectorMultiply(
207 giantDigit plierDigit,
208 giantDigit *candVector,
210 giantDigit *prodVector)
212 ******************************************************************************/
215 * Register definitions
218 #define plierDigit r3
219 #define candVector r4
220 #define candLength r5
221 #define prodVector r6
225 * r3..r10 for parameter passing
226 * r11, r12 volatile (caller saved, we can write)
228 * We'll use the remainder of the registers normally used for parameter passing
229 * and also the other volatile register for local variables.
239 .globl _VectorMultiply
242 /* giantDigit lastCarry = 0; */
246 /* for(candDex=0; candDex<candLength; ++candDex) { */
251 * prod = *(candVector++) * plierDigit + *prodVector + lastCarry
254 lwz scr1,0(candVector) /* *candVector --> scr1 */
255 addi candVector,candVector,4 /* candVector++ */
257 mullw prodLo,scr1,plierDigit /* prodLo = low(*candVector * plierDigit) */
258 mulhwu prodHi,scr1,plierDigit /* prodHi = high(*candVector * plierDigit) */
260 /* giantAddDouble(&prodLo, &prodHi, *prodVector); */
261 lwz scr1,0(prodVector) /* *prodVector --> r9 */
262 add sumLo,prodLo,scr1 /* prodLo + *prodVector --> sumLo */
263 cmplw cr0,sumLo,prodLo /* sumLo < prodLo? */
265 cmplw cr0,sumLo,scr1 /* sumLo < *prodVector? */
268 addi prodHi,prodHi,1 /* prodHi++ */
270 mr. prodLo,sumLo /* prodLo := sumLo */
272 /* giantAddDouble(&prodLo, &prodHi, lastCarry); */
273 add sumLo,sumLo,lastCarry /* sumLo += lastCarry */
274 cmplw cr0,sumLo,prodLo /* sumLo < prodLo? */
276 cmplw cr0,sumLo,lastCarry /* sumLo < lastCarry? */
279 addi prodHi,prodHi,1 /* prodHi++ */
281 mr. prodLo,sumLo /* prodLo := sumLo */
283 /* *(prodVector++) = prodLo; */
284 stw prodLo,0(prodVector) /* prodLo --> *prodVector */
285 addi prodVector,prodVector,4 /* prodVector++ */
287 /* lastCarry = prodHi; */
291 addi candDex,candDex,1 /* candDex++ */
293 cmplw cr0,candDex,candLength /* candDex < candLength? */
296 /* return lastCarry; */
297 mr. r3,lastCarry /* return lastCarry in r3 */
300 #endif /* defined(__ppc__) && defined(__MACH__) */