1/* 2 * Copyright (c) 2001,2011,2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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 11 * file. 12 * 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25/* 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. 33 */ 34 35#if defined(__ppc__) && defined(__MACH__) 36 37/********************************************* 38 39Add two digits, return sum. Carry bit returned as an out parameter. 40 41giantDigit giantAddDigits( 42 register giantDigit dig1, 43 register giantDigit dig2, 44 register giantDigit *carry) ...RETURNED, 0 or 1 45**********************************************/ 46 .text 47 .align 2 48.globl _giantAddDigits 49_giantAddDigits: 50 /* 51 * dig1 : r3 52 * dig2 : r4 53 * carry : r5 54 * sum : r6 55 */ 56 57 /* sum = dig1 + dig2 */ 58 add r6, r3, r4; 59 60 /* if((sum < dig1) || (sum < dig2)) */ 61 cmplw cr0,r6,r3 62 blt L1 63 cmplw cr0,r6,r4 64 bge L2 65 66L1: 67 /* *carry = 1; */ 68 li r7,1 69 stw r7, 0(r5) 70 b L3 71 72L2: 73 /* else *carry = 0; */ 74 li r7,0 75 stw r7, 0(r5) 76 77L3: 78 /* return sum in r3 */ 79 mr. r3,r6 80 blr 81 82/********************************************* 83 84Add a single digit value to a double digit accumulator in place. 85Carry out of the MSD of the accumulator is not handled. 86 87void giantAddDouble( 88 giantDigit *accLow, -- IN/OUT 89 giantDigit *accHigh, -- IN/OUT 90 giantDigit val); 91**********************************************/ 92 93 .align 2 94.globl _giantAddDouble 95_giantAddDouble: 96 /* 97 * r3 : accLow 98 * r4 : accHi 99 * r5 : val 100 * r6 : sumLo 101 * r7 : *accLow 102 */ 103 104 /* giantDigit sumLo = *accLow + val; */ 105 lwz r7,0(r3) 106 add r6,r7,r5 107 108 /* if((sumLo < *accLow) || (sumLo < val)) { */ 109 cmplw cr0,r6,r7 110 blt L10 111 cmplw cr0,r6,r5 112 bge L11 113 114L10: 115 /* (*accHigh)++; */ 116 lwz r7, 0(r4) 117 addi r7,r7,1 118 stw r7, 0(r4) 119 120L11: 121 /* *accLow = sumLo; */ 122 stw r6,0(r3) 123 blr 124 125/***************************************************************************** 126 127Subtract a - b, return difference. Borrow bit returned as an out parameter. 128 129giantDigit giantSubDigits( 130 giantDigit a, 131 giantDigit b, 132 giantDigit *borrow) -- RETURNED, 0 or 1 133 134******************************************************************************/ 135 136 .align 2 137.globl _giantSubDigits 138_giantSubDigits: 139 140 /* a : r3 141 b : r4 142 borrow : r5 143 diff : r6 */ 144 145 /* giantDigit diff = a - b; */ 146 subf r6, r4, r3; 147 148 /* if(a < b) */ 149 cmplw cr0,r3,r4 150 bge L20 151 152 /* *borrow = 1; */ 153 li r7,1 154 stw r7, 0(r5) 155 b L21 156 157L20: 158 /* else *borrow = 0; */ 159 li r7,0 160 stw r7, 0(r5) 161 162L21: 163 /* return diff in r3 */ 164 mr. r3,r6 165 blr 166 167/***************************************************************************** 168 169Multiply two digits, return two digits. 170 171void giantMulDigits( 172 giantDigit dig1, 173 giantDigit dig2, 174 giantDigit *lowProduct, -- RETURNED, low digit 175 giantDigit *hiProduct) -- RETURNED, high digit 176 177******************************************************************************/ 178 179 .align 2 180.globl _giantMulDigits 181_giantMulDigits: 182 183 /* r3 : dig1 184 r4 : dig2 185 r5 : lowProduct 186 r6 : hiProduct */ 187 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) */ 191 192 /* *hiProduct = (giantDigit)(dprod >> GIANT_BITS_PER_DIGIT); */ 193 stw r8, 0(r6) 194 195 /* *lowProduct = (giantDigit)dprod; */ 196 stw r7, 0(r5) 197 blr 198 199 200/***************************************************************************** 201 202Multiply a vector of giantDigits, candVector, by a single giantDigit, 203plierDigit, adding results into prodVector. Returns m.s. digit from 204final multiply; only candLength digits of *prodVector will be written. 205 206giantDigit VectorMultiply( 207 giantDigit plierDigit, 208 giantDigit *candVector, 209 unsigned candLength, 210 giantDigit *prodVector) 211 212******************************************************************************/ 213 214/* 215 * Register definitions 216 * Input paramters: 217 */ 218#define plierDigit r3 219#define candVector r4 220#define candLength r5 221#define prodVector r6 222 223/* 224 * PPC ABI specifies: 225 * r3..r10 for parameter passing 226 * r11, r12 volatile (caller saved, we can write) 227 * 228 * We'll use the remainder of the registers normally used for parameter passing 229 * and also the other volatile register for local variables. 230 */ 231#define candDex r7 232#define lastCarry r8 233#define prodLo r9 234#define prodHi r10 235#define scr1 r11 236#define sumLo r12 237 238 .align 2 239.globl _VectorMultiply 240_VectorMultiply: 241 242 /* giantDigit lastCarry = 0; */ 243 li lastCarry,0 244 245 246 /* for(candDex=0; candDex<candLength; ++candDex) { */ 247 li candDex,0 248 b L_endLoop 249 250 /* 251 * prod = *(candVector++) * plierDigit + *prodVector + lastCarry 252 */ 253L_topLoop: 254 lwz scr1,0(candVector) /* *candVector --> scr1 */ 255 addi candVector,candVector,4 /* candVector++ */ 256 257 mullw prodLo,scr1,plierDigit /* prodLo = low(*candVector * plierDigit) */ 258 mulhwu prodHi,scr1,plierDigit /* prodHi = high(*candVector * plierDigit) */ 259 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? */ 264 blt L_carry1 265 cmplw cr0,sumLo,scr1 /* sumLo < *prodVector? */ 266 bge L_noCar1 267L_carry1: 268 addi prodHi,prodHi,1 /* prodHi++ */ 269L_noCar1: 270 mr. prodLo,sumLo /* prodLo := sumLo */ 271 272 /* giantAddDouble(&prodLo, &prodHi, lastCarry); */ 273 add sumLo,sumLo,lastCarry /* sumLo += lastCarry */ 274 cmplw cr0,sumLo,prodLo /* sumLo < prodLo? */ 275 blt L_carry2 276 cmplw cr0,sumLo,lastCarry /* sumLo < lastCarry? */ 277 bge L_noCar2 278L_carry2: 279 addi prodHi,prodHi,1 /* prodHi++ */ 280L_noCar2: 281 mr. prodLo,sumLo /* prodLo := sumLo */ 282 283 /* *(prodVector++) = prodLo; */ 284 stw prodLo,0(prodVector) /* prodLo --> *prodVector */ 285 addi prodVector,prodVector,4 /* prodVector++ */ 286 287 /* lastCarry = prodHi; */ 288 mr. lastCarry,prodHi 289 290 /* } */ 291 addi candDex,candDex,1 /* candDex++ */ 292L_endLoop: 293 cmplw cr0,candDex,candLength /* candDex < candLength? */ 294 blt L_topLoop 295 296 /* return lastCarry; */ 297 mr. r3,lastCarry /* return lastCarry in r3 */ 298 blr 299 300#endif /* defined(__ppc__) && defined(__MACH__) */ 301