|
|
1.1 ! root 1: /* $Header: bigmath.c 1.4 83/06/09 00:50:06 sklower Exp $ */ ! 2: ! 3: #include "config.h" ! 4: ! 5: .globl _dmlad ! 6: /* ! 7: routine for destructive multiplication and addition to a bignum by ! 8: two fixnums. ! 9: ! 10: from C, the invocation is dmlad(sdot,mul,add); ! 11: where sdot is the address of the first special cell of the bignum ! 12: mul is the multiplier, add is the fixnum to be added (The latter ! 13: being passed by value, as is the usual case. ! 14: ! 15: ! 16: Register assignments: ! 17: ! 18: r11 = current sdot ! 19: r10 = carry ! 20: r9 = previous sdot, for relinking. ! 21: */ ! 22: _dmlad: .word 0x0e00 ! 23: movl 4(ap),r11 #initialize cell pointer ! 24: movl 12(ap),r10 #initialize carry ! 25: loop: emul 8(ap),(r11),r10,r0 #r0 gets cell->car times mul + carry ! 26: /* ediv $0x40000000,r0,r10,(r11)#cell->car gets prod % 2**30 ! 27: #carry gets quotient ! 28: */ ! 29: extzv $0,$30,r0,(r11) ! 30: extv $30,$32,r0,r10 ! 31: movl r11,r9 #save last cell for fixup at end. ! 32: movl 4(r11),r11 #move to next cell ! 33: bneq loop #done indicated by 0 for next sdot ! 34: tstl r10 #if carry zero no need to allocate ! 35: beql done #new bigit ! 36: mcoml r10,r3 #test to see if neg 1. ! 37: bneq alloc #if not must allocate new cell. ! 38: tstl (r9) #make sure product isn't -2**30 ! 39: beql alloc ! 40: movl r0,(r9) #save old lower half of product. ! 41: brb done ! 42: alloc: jsb _qnewdot #otherwise allocate new bigit ! 43: movl r10,(r0) #store carry ! 44: movl r0,4(r9) #save new link cell ! 45: done: movl 4(ap),r0 ! 46: ret ! 47: .globl _dodiv ! 48: /* ! 49: routine to destructively divide array representation of a bignum by ! 50: 1000000000 ! 51: ! 52: invocation: ! 53: remainder = dodiv(top,bottom) ! 54: int *top, *bottom; ! 55: where *bottom is the address of the biggning of the array, *top is ! 56: the top of the array. ! 57: ! 58: register assignments: ! 59: r0 = carry ! 60: r1 & r2 = 64bit temporary ! 61: r3 = pointer ! 62: */ ! 63: _dodiv: .word 0 ! 64: clrl r0 #no carry to begin. ! 65: movl 8(ap),r3 #get pointer to array. ! 66: loop2: emul $0x40000000,r0,(r3),r1 ! 67: ediv $1000000000,r1,(r3),r0 ! 68: acbl 4(ap),$4,r3,loop2 ! 69: ret ! 70: .globl _dsneg ! 71: /* ! 72: dsneg(top, bot); ! 73: int *top, *bot; ! 74: ! 75: routine to destructively negate a bignum stored in array format ! 76: lower order stuff at higher addresses. It is assume that the ! 77: result will be positive. ! 78: */ ! 79: _dsneg: .word 0 ! 80: movl 4(ap),r1 #load up address. ! 81: clrl r2 #set carry ! 82: loop3: mnegl (r1),r0 #negate and take carry into account. ! 83: addl2 r2,r0 ! 84: extzv $0,$30,r0,(r1) ! 85: extv $30,$2,r0,r2 ! 86: acbl 8(ap),$-4,r1,loop3 ! 87: #decrease r1, and branch back if appropriate. ! 88: ret ! 89: ! 90: /* ! 91: bignum add routine ! 92: basic data representation is each bigit is a positive number ! 93: less than 2^30, except for the leading bigit, which is in ! 94: the range -2^30 < x < 2^30. ! 95: */ ! 96: ! 97: .globl _adbig ! 98: .globl Bexport ! 99: .globl backfr ! 100: /* ! 101: Initialization section ! 102: */ ! 103: _adbig: .word 0x0fc0 #save registers 6-11 ! 104: movl 4(ap),r1 #arg1 = addr of 1st bignum ! 105: movl 8(ap),r2 #arg2 = addr of 2nd bignum ! 106: clrl r5 #r5 = carry ! 107: movl $0xC0000000,r4 #r4 = clear constant. ! 108: movl sp,r10 #save start address of bignum on stack. ! 109: #note well that this is 4 above the actual ! 110: #low order word. ! 111: /* ! 112: first loop is to waltz through both bignums adding ! 113: bigits, pushing them onto stack. ! 114: */ ! 115: loop4: addl3 (r1),(r2),r0 #add bigits ! 116: addl2 r5,r0 #add carry ! 117: bicl3 r4,r0,-(sp) #save sum, no overflow possible ! 118: extv $30,$2,r0,r5 #sign extend two high order bits ! 119: #to be next carry. ! 120: movl 4(r1),r1 #get cdr ! 121: bleq out1 #negative indicates end of list. ! 122: movl 4(r2),r2 #get cdr of second bignum ! 123: bgtr loop4 #if neither list at end, do it again ! 124: /* ! 125: second loop propagates carries through higher order words. ! 126: It assumes remaining list in r1. ! 127: */ ! 128: loop5: addl3 (r1),r5,r0 #add bigits and carry ! 129: bicl3 r4,r0,-(sp) #save sum, no overflow possible ! 130: extv $30,$2,r0,r5 #sign extend two high order bits ! 131: #to be next carry. ! 132: movl 4(r1),r1 #get cdr ! 133: out2: bgtr loop5 #negative indicates end of list. ! 134: out2a: pushl r5 ! 135: /* ! 136: suppress unnecessary leading zeroes and -1's ! 137: ! 138: WARNING: this code is duplicated in C in divbig.c ! 139: */ ! 140: iexport:movl sp,r11 #more set up for output routine ! 141: ckloop: ! 142: Bexport:tstl (r11) #look at leading bigit ! 143: bgtr copyit #if positive, can allocate storage etc. ! 144: blss negchk #if neg, still a chance we can get by ! 145: cmpl r11,r10 #check to see that ! 146: bgeq copyit #we don't pop everything off of stack ! 147: tstl (r11)+ #incr r11 ! 148: brb ckloop #examine next ! 149: negchk: ! 150: mcoml (r11),r3 #r3 is junk register ! 151: bneq copyit #short test for -1 ! 152: tstl 4(r11) #examine next bigit ! 153: beql copyit #if zero must must leave as is. ! 154: cmpl r11,r10 #check to see that ! 155: bgeq copyit #we don't pop everything off of stack ! 156: tstl (r11)+ #incr r11 ! 157: bisl2 r4,(r11) #set high order two bits ! 158: brb negchk #try to supress more leading -1's ! 159: /* ! 160: The following code is an error exit from the first loop ! 161: and is out of place to avoid a jump around a jump. ! 162: */ ! 163: out1: movl 4(r2),r1 #get next addr of list to continue. ! 164: brb out2 #if second list simult. exhausted, do ! 165: #right thing. ! 166: /* ! 167: loop6 is a faster version of loop5 when carries are no ! 168: longer necessary. ! 169: */ ! 170: loop6a: pushl (r1) #get datum ! 171: loop6: movl 4(r1),r1 #get cdr ! 172: bgtr loop6a #if not at end get next cell ! 173: brb out2a ! 174: ! 175: /* ! 176: create linked list representation of bignum ! 177: */ ! 178: copyit: subl3 r11,r10,r2 #see if we can get away with allocating an int ! 179: bneq on1 #test for having popped everything ! 180: subl3 $4,r10,r11 #if so, fix up pointer to bottom ! 181: brb intout #and allocate int. ! 182: on1: cmpl r2,$4 #if = 4, then can do ! 183: beql intout ! 184: calls $0,_newsdot #get new cell for new bignum ! 185: backfr: ! 186: #ifdef PORTABLE ! 187: movl r0,*_np ! 188: addl2 $4,_np ! 189: #else ! 190: movl r0,(r6)+ #push address of cell on ! 191: #arg stack to save from garbage collection. ! 192: #There is guaranteed to be slop for a least 1 ! 193: #push without checking. ! 194: #endif ! 195: loop7: movl -(r10),(r0) #save bigit ! 196: movl r0,r9 #r9 = old cell, to link ! 197: cmpl r10,r11 #have we copy'ed all the bigits? ! 198: bleq Edone ! 199: jsb _qnewdot #get new cell for new bignum ! 200: movl r0,4(r9) #link new cell to old ! 201: brb loop7 ! 202: Edone: ! 203: clrl 4(r9) #indicate end of list with 0 ! 204: #ifdef PORTABLE ! 205: subl2 $4,_np ! 206: movl *_np,r0 ! 207: #else ! 208: movl -(r6),r0 #give resultant address. ! 209: #endif ! 210: ret ! 211: /* ! 212: export integer ! 213: */ ! 214: intout: pushl (r11) ! 215: calls $1,_inewint ! 216: ret ! 217: .globl _mulbig ! 218: /* ! 219: bignum multiplication routine ! 220: ! 221: Initialization section ! 222: */ ! 223: _mulbig:.word 0x0fc0 #save regs 6-11 ! 224: movl 4(ap),r1 #get address of first bignum ! 225: movl sp,r11 #save top of 1st bignum ! 226: mloop1: pushl (r1) #get bigit ! 227: movl 4(r1),r1 #get cdr ! 228: bgtr mloop1 #repeat if not done ! 229: movl sp,r10 #save bottom of 1st bignum, top of 2nd bignum ! 230: ! 231: movl 8(ap),r1 #get address of 2nd bignum ! 232: mloop2: pushl (r1) #get bigit ! 233: movl 4(r1),r1 #get cdr ! 234: bgtr mloop2 #repeat if not done ! 235: movl sp,r9 #save bottom of 2nd bignum ! 236: subl3 r9,r11,r6 #r6 contains sum of lengths of bignums ! 237: subl2 r6,sp ! 238: movl sp,r8 #save bottom of product bignum ! 239: /* ! 240: Actual multiplication ! 241: */ ! 242: m1: movc5 $0,(r8),$0,r6,(r8)#zap out stack space ! 243: movl r9,r7 #r7 = &w[j +n] (+4 for a.d.) through calculation ! 244: subl3 $4,r10,r4 #r4 = &v[j] ! 245: ! 246: m3: movl r7,r5 #r7 = &w[j+n] ! 247: subl3 $4,r11,r3 #r3 = &u[i] ! 248: clrl r2 #clear carry. ! 249: ! 250: m4: addl2 -(r5),r2 #add w[i + j] to carry (no ofl poss) ! 251: emul (r3),(r4),r2,r0 #r0 = u[i] * v[j] + sext(carry) ! 252: extzv $0,$30,r0,(r5) #get new bigit ! 253: extv $30,$32,r0,r2 #get new carry ! 254: ! 255: m5: acbl r10,$-4,r3,m4 #r3 =- 4; if(r3 >= r10) goto m4; r10 = &[u1]; ! 256: movl r2,-(r5) #save w[j] = carry ! 257: ! 258: m6: subl2 $4,r7 #add just &w[j+n] (+4 for autodec) ! 259: acbl r9,$-4,r4,m3 #r4 =- 4; if(r4>=r9) goto m5; r9 = &v[1] ! 260: ! 261: movl r9,r10 #set up for output routine ! 262: movl $0xC0000000,r4 #r4 = clear constant. ! 263: movq 20(fp),r6 #restor _np and _lbot ! ! 264: brw iexport #do it! ! 265: /* ! 266: The remainder of this file are routines used in bignum division. ! 267: Interested parties should consult Knuth, Vol 2, and divbig.c. ! 268: These files are here only due to an optimizer bug. ! 269: */ ! 270: .align 1 ! 271: .globl _calqhat ! 272: _calqhat: ! 273: .word 0xf00 ! 274: movl 4(ap),r11 # &u[j] into r11 ! 275: movl 8(ap),r10 # &v[1] into r10 ! 276: cmpl (r10),(r11) # v[1] == u[j] ?? ! 277: beql L102 ! 278: # calculate qhat and rhat simultaneously, ! 279: # qhat in r0 ! 280: # rhat in r1 ! 281: emul (r11),$0x40000000,4(r11),r4 # u[j]b+u[j+1] into r4,r5 ! 282: ediv (r10),r4,r0,r1 # qhat = ((u[j]b+u[j+1])/v[1]) into r0 ! 283: # (u[j]b+u[j+1] -qhat*v[1]) into r1 ! 284: # called rhat ! 285: L101: ! 286: # check if v[2]*qhat > rhat*b+u[j+2] ! 287: emul r0,4(r10),$0,r2 # qhat*v[2] into r3,r2 ! 288: emul r1,$0x40000000,8(r11),r8 #rhat*b + u[j+2] into r9,r8 ! 289: # give up if r3,r2 <= r9,r8, otherwise iterate ! 290: subl2 r8,r2 # perform r3,r2 - r9,r8 ! 291: sbwc r9,r3 ! 292: bleq L103 # give up if negative or equal ! 293: decl r0 # otherwise, qhat = qhat - 1 ! 294: addl2 (r10),r1 # since dec'ed qhat, inc rhat by v[1] ! 295: jbr L101 ! 296: L102: ! 297: # get here if v[1]==u[j] ! 298: # set qhat to b-1 ! 299: # rhat is easily calculated since if we substitute b-1 for qhat in ! 300: # the formula, then it simplifies to (u[j+1] + v[1]) ! 301: # ! 302: addl3 4(r11),(r10),r1 # rhat = u[j+1] + v[1] ! 303: movl $0x3fffffff,r0 # qhat = b-1 ! 304: jbr L101 ! 305: ! 306: L103: ! 307: ret ! 308: ! 309: .align 1 ! 310: .globl _mlsb ! 311: _mlsb: ! 312: .word .R2 ! 313: movl 4(ap),r11 ! 314: movl 8(ap),r10 ! 315: movl 12(ap),r9 ! 316: movl 16(ap),r8 ! 317: clrl r0 ! 318: loop8: addl2 (r11),r0 ! 319: emul r8,-(r9),r0,r2 ! 320: extzv $0,$30,r2,(r11) ! 321: extv $30,$32,r2,r0 ! 322: acbl r10,$-4,r11,loop8 ! 323: ret ! 324: .set .R2,0xf00 ! 325: .align 1 ! 326: .globl _adback ! 327: _adback: ! 328: .word .R3 ! 329: movl 4(ap),r11 ! 330: movl 8(ap),r10 ! 331: movl 12(ap),r9 ! 332: clrl r0 ! 333: loop9: addl2 -(r9),r0 ! 334: addl2 (r11),r0 ! 335: extzv $0,$30,r0,(r11) ! 336: extv $30,$2,r0,r0 ! 337: acbl r10,$-4,r11,loop9 ! 338: ret ! 339: .set .R3,0xe00 ! 340: .align 1 ! 341: .globl _dsdiv ! 342: _dsdiv: ! 343: .word .R4 ! 344: movl 8(ap),r11 ! 345: clrl r0 ! 346: loopa: emul r0,$0x40000000,(r11),r1 ! 347: ediv 12(ap),r1,(r11),r0 ! 348: acbl 4(ap),$4,r11,loopa ! 349: ret ! 350: .set .R4,0x800 ! 351: .align 1 ! 352: .globl _dsmult ! 353: _dsmult: ! 354: .word .R5 ! 355: movl 4(ap),r11 ! 356: clrl r0 ! 357: loopb: emul 12(ap),(r11),r0,r1 ! 358: extzv $0,$30,r1,(r11) ! 359: extv $30,$32,r1,r0 ! 360: acbl 8(ap),$-4,r11,loopb ! 361: movl r1,4(r11) ! 362: ret ! 363: .set .R5,0x800 ! 364: .align 1 ! 365: .globl _dsrsh ! 366: _dsrsh: ! 367: .word .R7 ! 368: movl 8(ap),r11 # bot ! 369: movl 16(ap),r5 # mask ! 370: movl 12(ap),r4 # shift count ! 371: clrl r0 ! 372: L201: emul r0,$0x40000000,(r11),r1 ! 373: bicl3 r5,r1,r0 ! 374: ashq r4,r1,r1 ! 375: movl r1,(r11) ! 376: acbl 4(ap),$4,r11,L201 ! 377: ret ! 378: .set .R7,0x800 ! 379: .align 1 ! 380: .globl _dsadd1 ! 381: _dsadd1: ! 382: .word .R8 ! 383: movl 4(ap),r11 ! 384: movl $1,r0 ! 385: L501: emul $1,(r11),r0,r1 ! 386: extzv $0,$30,r1,(r11) ! 387: extv $30,$32,r1,r0 ! 388: acbl 8(ap),$-4,r11,L501 ! 389: movl r1,4(r11) ! 390: ret ! 391: .set .R8,0x800 ! 392: /* ! 393: myfrexp (value, exp, hi, lo) ! 394: double value; ! 395: int *exp, *hi, *lo; ! 396: ! 397: myfrexp returns three values, exp, hi, lo, ! 398: Such that value = 2**exp*tmp, where tmp = (hi*2**-23+lo*2**-53) ! 399: is uniquely determined subect to .5< abs(tmp) <= 1.0 ! 400: ! 401: ! 402: Entry point ! 403: */ ! 404: .text ! 405: .globl _myfrexp ! 406: _myfrexp: ! 407: .word 0x0000 # We use r2, but do not save it ! 408: ! 409: clrl *12(ap) # Make for easy exit later ! 410: clrl *16(ap) # ! 411: clrl *20(ap) # ! 412: movd 4(ap),r0 # Fetch "value" ! 413: bneq L301 # if zero return zero exponent + mantissa ! 414: ret ! 415: L301: ! 416: extzv $7,$8,r0,r2 # r2 := biased exponent ! 417: movab -129(r2),*12(ap)# subtract bias, store exp ! 418: insv $154,$7,$8,r0 # lie about exponent to get out ! 419: # high 24 bits easily with emodd. ! 420: /* ! 421: This instruction does the following: ! 422: ! 423: Extend the long floating value in r0 with 0, and ! 424: multiply it by 1.0. Store the integer part of the result ! 425: in hi, and the fractional part of the result in r0-r1. ! 426: */ ! 427: emodd r0,$0,$0f1.0,*16(ap),r0 # How did you like ! 428: # THAT, sports fans? [jfr's comment] ! 429: ! 430: tstd r0 # if zero, exit; ! 431: bneq L401 ! 432: ret ! 433: L401: ! 434: insv $158,$7,$8,r0 # lie about exponent to get out ! 435: # next 30 bits easily with emodd. ! 436: # (2^29 takes 30 bits). ! 437: emodd r0,$0,$0f1.0,*20(ap),r0 # Get last bits out likewise! ! 438: ret # (r0 should be zero by now!) ! 439: .globl _inewint ! 440: _inewint:.word 0 ! 441: movl 4(ap),r0 ! 442: cmpl r0,$1024 ! 443: jgeq Ialloc ! 444: cmpl r0,$-1024 ! 445: jlss Ialloc ! 446: moval _Fixzero[r0],r0 ! 447: ret ! 448: Ialloc: ! 449: calls $0,_newint ! 450: movl 4(ap),0(r0) ! 451: ret ! 452: .globl _blzero ! 453: _blzero: # blzero(where,howmuch) ! 454: # char *where; ! 455: # zeroes a block of length howmuch ! 456: # beginning at where. ! 457: .word 0 ! 458: movc5 $0,*4(ap),$0,8(ap),*4(ap) ! 459: ret
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.