Annotation of 43BSDReno/pgrm/lisp/franz/vax/bigmath.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.