BSD 3 development
[unix-history] / usr / src / cmd / lisp / adbig.s
# bignum add routine
# basic data representation is each bigit is a positive number
# less than 2^30, except for the leading bigit, which is in
# the range -2^30 < x < 2^30.
.globl _adbig
.globl Bexport
.globl backfr
#
# Initialization section
#
_adbig: .word 0x0fc0 #save registers 6-11
movl 4(ap),r1 #arg1 = addr of 1st bignum
movl 8(ap),r2 #arg2 = addr of 2nd bignum
clrl r5 #r5 = carry
movl $0xC0000000,r4 #r4 = clear constant.
movl sp,r10 #save start address of bignum on stack.
#note well that this is 4 above the actual
#low order word.
#
# first loop is to waltz through both bignums adding
# bigits, pushing them onto stack.
#
loop1: addl3 (r1),(r2),r0 #add bigits
addl2 r5,r0 #add carry
bicl3 r4,r0,-(sp) #save sum, no overflow possible
extv $30,$2,r0,r5 #sign extend two high order bits
#to be next carry.
movl 4(r1),r1 #get cdr
bleq out1 #negative indicates end of list.
movl 4(r2),r2 #get cdr of second bignum
bgtr loop1 #if neither list at end, do it again
#
# second loop propagates carries through higher order words.
# It assumes remaining list in r1.
#
loop2: addl3 (r1),r5,r0 #add bigits and carry
bicl3 r4,r0,-(sp) #save sum, no overflow possible
extv $30,$2,r0,r5 #sign extend two high order bits
#to be next carry.
movl 4(r1),r1 #get cdr
out2: bgtr loop2 #negative indicates end of list.
out2a: pushl r5
#
# suppress unnecessary leading zeroes and -1's
#
iexport:movl sp,r11 #more set up for output routine
ckloop:
Bexport:tstl (r11) #look at leading bigit
bgtr copyit #if positive, can allocate storage etc.
blss negchk #if neg, still a chance we can get by
cmpl r11,r10 #check to see that
bgeq copyit #we don't pop everything off of stack
tstl (r11)+ #incr r11
brb ckloop #examine next
negchk:
mcoml (r11),r3 #r3 is junk register
bneq copyit #short test for -1
tstl 4(r11) #examine next bigit
beql copyit #if zero must must leave as is.
cmpl r11,r10 #check to see that
bgeq copyit #we don't pop everything off of stack
tstl (r11)+ #incr r11
bisl2 r4,(r11) #set high order two bits
brb negchk #try to supress more leading -1's
#
# The following code is an error exit from the first loop
# and is out of place to avoid a jump around a jump.
#
out1: movl 4(r2),r1 #get next addr of list to continue.
brb out2 #if second list simult. exhausted, do
#right thing.
#
# loop3 is a faster version of loop2 when carries are no
# longer necessary.
#
loop3a: pushl (r1) #get datum
loop3: movl 4(r1),r1 #get cdr
bgtr loop3a #if not at end get next cell
brb out2a
#
# create linked list representation of bignum
#
copyit: subl3 r11,r10,r2 #see if we can get away with allocating an int
bneq on1 #test for having popped everything
subl3 $4,r10,r11 #if so, fix up pointer to bottom
brb intout #and allocate int.
on1: cmpl r2,$4 #if = 4, then can do
beql intout
calls $0,_newsdot #get new cell for new bignum
backfr: movl r0,(r6)+ #push address of cell on
#arg stack to save from garbage collection.
#There is guaranteed to be slop for a least one
#push without checking.
movl r0,r8 #r8 = result of adbig
loop4: movl -(r10),(r0) #save bigit
movl r0,r9 #r9 = old cell, to link
cmpl r10,r11 #have we copy'ed all the bigits?
bleq done
calls $0,_newsdot #get new cell for new bignum
movl r0,4(r9) #link new cell to old
brb loop4
done:
clrl 4(r9) #indicate end of list with 0
movl -(r6),r0 #give resultant address.
ret
#
# export integer
#
intout: pushl (r11)
calls $1,_inewint
ret
.globl _mulbig
#
# bignum multiplication routine
#
# Initialization section
#
_mulbig:.word 0x0fc0 #save regs 6-11
movl 4(ap),r1 #get address of first bignum
movl sp,r11 #save top of 1st bignum
mloop1: pushl (r1) #get bigit
movl 4(r1),r1 #get cdr
bgtr mloop1 #repeat if not done
movl sp,r10 #save bottom of 1st bignum, top of 2nd bignum
movl 8(ap),r1 #get address of 2nd bignum
mloop2: pushl (r1) #get bigit
movl 4(r1),r1 #get cdr
bgtr mloop2 #repeat if not done
movl sp,r9 #save bottom of 2nd bignum
subl3 r9,r11,r6 #r6 contains sum of lengths of bignums
subl2 r6,sp
movl sp,r8 #save bottom of product bignum
#
# Actual multiplication
#
m1: movc5 $0,(r8),$0,r6,(r8)#zap out stack space
movl r9,r7 #r7 = &w[j +n] (+4 for a.d.) through calculation
subl3 $4,r10,r4 #r4 = &v[j]
m3: movl r7,r5 #r7 = &w[j+n]
subl3 $4,r11,r3 #r3 = &u[i]
clrl r2 #clear carry.
m4: addl2 -(r5),r2 #add w[i + j] to carry (no ofl poss)
emul (r3),(r4),r2,r0 #r0 = u[i] * v[j] + sext(carry)
extzv $0,$30,r0,(r5) #get new bigit
extv $30,$32,r0,r2 #get new carry
m5: acbl r10,$-4,r3,m4 #r3 =- 4; if(r3 >= r10) goto m4; r10 = &[u1];
movl r2,-(r5) #save w[j] = carry
m6: subl2 $4,r7 #add just &w[j+n] (+4 for autodec)
acbl r9,$-4,r4,m3 #r4 =- 4; if(r4>=r9) goto m5; r9 = &v[1]
movl r9,r10 #set up for output routine
movl $0xC0000000,r4 #r4 = clear constant.
movq 20(fp),r6 #restor _np and _lbot !
brw iexport #do it!