2 * giantPort_X_PPC.s - PPC/OS X giant port module
4 * Created 3/19/2001 by Doug Mitchell.
8 * As of 3/19/2001, using this module results in no change in runtime
9 * performance compared to using the inline C functions in
10 * giantPort_Generic.h. Examination of the compiled code shows that
11 * the GNU C compiler, when configured for -O2, generates almost
12 * exactly the same code as we have here.
13 * We'll leave this code in, to protect against changes in gcc, changes
14 * in CFLAGS, and to serve as an example for other PPC implementations.
17 #if defined(__ppc__) && defined(__MACH__)
19 /*********************************************
21 Add two digits, return sum. Carry bit returned as an out parameter.
23 giantDigit giantAddDigits(
24 register giantDigit dig1,
25 register giantDigit dig2,
26 register giantDigit *carry) ...RETURNED, 0 or 1
27 **********************************************/
30 .globl _giantAddDigits
39 /* sum = dig1 + dig2 */
42 /* if((sum < dig1) || (sum < dig2)) */
55 /* else *carry = 0; */
60 /* return sum in r3 */
64 /*********************************************
66 Add a single digit value to a double digit accumulator in place.
67 Carry out of the MSD of the accumulator is not handled.
70 giantDigit *accLow, -- IN/OUT
71 giantDigit *accHigh, -- IN/OUT
73 **********************************************/
76 .globl _giantAddDouble
86 /* giantDigit sumLo = *accLow + val; */
90 /* if((sumLo < *accLow) || (sumLo < val)) { */
103 /* *accLow = sumLo; */
107 /*****************************************************************************
109 Subtract a - b, return difference. Borrow bit returned as an out parameter.
111 giantDigit giantSubDigits(
114 giantDigit *borrow) -- RETURNED, 0 or 1
116 ******************************************************************************/
119 .globl _giantSubDigits
127 /* giantDigit diff = a - b; */
140 /* else *borrow = 0; */
145 /* return diff in r3 */
149 /*****************************************************************************
151 Multiply two digits, return two digits.
156 giantDigit *lowProduct, -- RETURNED, low digit
157 giantDigit *hiProduct) -- RETURNED, high digit
159 ******************************************************************************/
162 .globl _giantMulDigits
170 /* dprod = (unsigned long long)dig1 * (unsigned long long)dig2; */
171 mullw r7, r3, r4 /* r7 = low(dig1 * dig2) */
172 mulhwu r8, r3, r4 /* r8 - hi(dig1 * dig2) */
174 /* *hiProduct = (giantDigit)(dprod >> GIANT_BITS_PER_DIGIT); */
177 /* *lowProduct = (giantDigit)dprod; */
182 /*****************************************************************************
184 Multiply a vector of giantDigits, candVector, by a single giantDigit,
185 plierDigit, adding results into prodVector. Returns m.s. digit from
186 final multiply; only candLength digits of *prodVector will be written.
188 giantDigit VectorMultiply(
189 giantDigit plierDigit,
190 giantDigit *candVector,
192 giantDigit *prodVector)
194 ******************************************************************************/
197 * Register definitions
200 #define plierDigit r3
201 #define candVector r4
202 #define candLength r5
203 #define prodVector r6
207 * r3..r10 for parameter passing
208 * r11, r12 volatile (caller saved, we can write)
210 * We'll use the remainder of the registers normally used for parameter passing
211 * and also the other volatile register for local variables.
221 .globl _VectorMultiply
224 /* giantDigit lastCarry = 0; */
228 /* for(candDex=0; candDex<candLength; ++candDex) { */
233 * prod = *(candVector++) * plierDigit + *prodVector + lastCarry
236 lwz scr1,0(candVector) /* *candVector --> scr1 */
237 addi candVector,candVector,4 /* candVector++ */
239 mullw prodLo,scr1,plierDigit /* prodLo = low(*candVector * plierDigit) */
240 mulhwu prodHi,scr1,plierDigit /* prodHi = high(*candVector * plierDigit) */
242 /* giantAddDouble(&prodLo, &prodHi, *prodVector); */
243 lwz scr1,0(prodVector) /* *prodVector --> r9 */
244 add sumLo,prodLo,scr1 /* prodLo + *prodVector --> sumLo */
245 cmplw cr0,sumLo,prodLo /* sumLo < prodLo? */
247 cmplw cr0,sumLo,scr1 /* sumLo < *prodVector? */
250 addi prodHi,prodHi,1 /* prodHi++ */
252 mr. prodLo,sumLo /* prodLo := sumLo */
254 /* giantAddDouble(&prodLo, &prodHi, lastCarry); */
255 add sumLo,sumLo,lastCarry /* sumLo += lastCarry */
256 cmplw cr0,sumLo,prodLo /* sumLo < prodLo? */
258 cmplw cr0,sumLo,lastCarry /* sumLo < lastCarry? */
261 addi prodHi,prodHi,1 /* prodHi++ */
263 mr. prodLo,sumLo /* prodLo := sumLo */
265 /* *(prodVector++) = prodLo; */
266 stw prodLo,0(prodVector) /* prodLo --> *prodVector */
267 addi prodVector,prodVector,4 /* prodVector++ */
269 /* lastCarry = prodHi; */
273 addi candDex,candDex,1 /* candDex++ */
275 cmplw cr0,candDex,candLength /* candDex < candLength? */
278 /* return lastCarry; */
279 mr. r3,lastCarry /* return lastCarry in r3 */
282 #endif /* defined(__ppc__) && defined(__MACH__) */