ocaml/otherlibs/num/bignum/s/RS6000KerN.s

469 lines
12 KiB
ArmAsm

# Copyright Digital Equipment Corporation & INRIA 1988, 1989
#
# KerN for the RS6000
# [Bepaul]
#
# La plupart du code est celui ge'ne're' par le compilo C (Cha^peau!)
#
.set RES,3
.set CA1,3
.set CA2,4
.set CA3,5
.set CA4,6
.set CA5,7
.set X4,7
.set X3,8
.set X2,9
.set X1,10
.set NN1,CA1
.set MM1,CA1
.set D1,CA1
.set NN2,CA2
.set NL2,CA2
.set ML2,CA2
.set D2,CA2
.set NN3,CA3
.set NL3,CA3
.set NL4,CA4
.toc
T.bignum_dat: .tc bignum_dat[TC],bignum_dat[RW]
.csect bignum_dat[RW]
.csect bignum_txt[PR]
.globl .BnnSetToZero # BnnSetToZero(nn, nl)
.BnnSetToZero: cmpi 0,NL2,0 # if(nl <= 0) return;
bler
mtctr NL2 # ctr = nl;
lil X1,0 # cte = 0;
ai NN1,NN1,-4 # nn--;
BSTZ1: stu X1,4(NN1) # *(++nn) = cte;
bdn BSTZ1 # if(--ctr != 0) goto BSTZ1;
br # return;
.globl .BnnAssign # BnnAssign(mm, nn, nl)
.BnnAssign: cmpi 0,NL3,0 # if(nl <= 0) return;
bler
mtctr NL3 # ctr = nl;
cmpl 0,MM1,NN2 # if(mm >= nn) goto BAG2;
bge BAG2
ai MM1,MM1,-4 # mm--;
ai NN2,NN2,-4 # nn--;
BAG1: lu X1,4(NN2) # X = *(++nn);
stu X1,4(MM1) # *(++mm) = X;
bdn BAG1 # if(--ctr != 0) goto BAG1;
br
BAG2: beqr # if(mm == nn) return;
sli X1,NL3,2
a NN2,NN2,X1 # nn += nl;
a MM1,MM1,X1 # mm += nl;
BAG3: lu X1,-4(NN2) # X = *(--nn);
stu X1,-4(MM1) # *(--mm) = X;
bdn BAG3 # (if(--ctr != 0) goto BAG3;
br # return;
.globl .BnnSetDigit # BnnSetDigit(nn, d)
.BnnSetDigit: st D2,0(NN1)
br
.globl .BnnGetDigit # BnnGetDigit(nn)
.BnnGetDigit: l RES,0(NN1)
br
.globl .BnnNumDigits # BnnNumDigits(nn, nl)
.BnnNumDigits: cmpi 0,NL2,0 # if(nl <= 0) return(1);
ble BND2
sli X1,NL2,2
a NN1,NN1,X1 # nn += nl;
mtctr NL2 # ctr = nl;
BND1: lu X1,-4(NN1) # X = *(--nn);
cmpi 0,X1,0 # if(X != 0) goto BND3
bne BND3
bdn BND1 # if(--ctr != 0) goto BND1;
BND2: lil RES,1 # return(1);
br
BND3: mfctr RES # return(ctr);
br
.globl .BnnNumLeadingZeroBitsInDigit # (d)
.BnnNumLeadingZeroBitsInDigit:
cntlz RES,D1 # Yeah!
br
.globl .BnnDoesDigitFitInWord # (d)
.BnnDoesDigitFitInWord:
lil RES,1 # return(1);
br
.globl .BnnIsDigitZero # BnnIsDigitZero(d)
.BnnIsDigitZero: # Use the fact that nabs(d) >=0 <=> d == 0
nabs RES,D1
rlinm RES,RES,1,31,31 # sign in the lowest bit.
xoril RES,RES,1 # get the inverse.
br
.globl .BnnIsDigitNormalized # (d)
.BnnIsDigitNormalized:
rlinm RES,D1,1,31,31 # sign in the lowest bit.
br
.globl .BnnIsDigitOdd # BnnIsDigitOdd(d)
.BnnIsDigitOdd: rlinm RES,D1,0,31,31 # only the lowest bit.
br
.globl .BnnCompareDigits # BnnCompareDigits(d1, d2)
.BnnCompareDigits:
cmpl 0,D1,D2 # if(d1 == d2) return(0);
beq BSD0
bgt BCDsup # if(d1 > d2) return(1);
lil RES,-1 # return(-1);
BSDret: br
BCDsup: lil RES,1 # return(1);
br
BSD0: lil RES,0 # return(0);
br
.globl .BnnComplement #.BnnComplement(nn, nl)
.BnnComplement: cmpi 0,NL2,0 # if(nl <= 0) return;
bler
ai NN1,NN1,-4 # nn--;
mtctr NL2 # ctr = nl;
BCM1: l X1,4(NN1) # X = nn[1];
sfi X1,X1,-1 # X ^= -1;
stu X1,4(NN1) # *++nn = X;
bdn BCM1 # if(--ctr > 0) goto BCM1
br # return;
.globl .BnnAndDigits # BnnAndDigits(nn, d)
.BnnAndDigits: l X1,0(NN1) # X = *nn;
and X1,X1,D2 # X &= d;
st X1,0(NN1) # *nn = X;
br
.globl .BnnOrDigits # BnnOrDigits(nn, d)
.BnnOrDigits: l X1,0(NN1) # X = *nn;
or X1,X1,D2 # X |= d;
st X1,0(NN1) # *nn = X;
br
.globl .BnnXorDigits # BnnXorDigits(nn, d)
.BnnXorDigits: l X1,0(NN1) # X = *nn;
xor X1,X1,D2 # X ^= d;
st X1,0(NN1) # *nn = X;
br
.globl .BnnShiftLeft # BnnShiftLeft(mm, ml, nbits)
# here and in the next funxtion we use the fact that MM1 == RES.
.set NBI,CA3; .set SMM,X1; .set RNB,X2; .set SX,X3; .set SY,ML2
.BnnShiftLeft: oril SMM,MM1,0
lil RES,0 # res = 0;
cmpi 0,NBI,0 # if(nbits == 0) return(res);
beqr
cmpi 0,ML2,0 # if(ml <= 0) return(res);
bler
sfi RNB,NBI,32 # rnbits = 32 - nbits;
ai SMM,SMM,-4 # mm--;
mtctr ML2 # ctr = ml;
BSL1: l SX,4(SMM) # X = mm[1];
sl SY,SX,NBI # Y = X << nbits;
or SY,SY,RES # Y |= res;
stu SY,4(SMM) # *(++mm) = Y;
sr RES,SX,RNB # res = X >> rnbits;
bdn BSL1 # if(--ctr > 0) goto BSL1
br # return(res);
.globl .BnnShiftRight # BnnShiftRight(mm, ml, nbits)
.BnnShiftRight: sli X1,ML2,2 # mm += ml;
a SMM,MM1,X1
lil RES,0 # res = 0;
cmpi 0,NBI,0 # if(nbits == 0) return(res);
beqr
cmpi 0,ML2,0 # if(ml <= 0) return(res);
bler
sfi RNB,NBI,32 # rnbits = 32 - nbits;
mtctr ML2 # ctr = ml;
BSR1: lu SX,-4(SMM) # X = *(--mm);
sr SY,SX,NBI # Y = X >> nbits;
or SY,SY,RES # Y |= res;
st SY,0(SMM) # *(mm) = Y;
sl RES,SX,RNB # res = X << rnbits;
bdn BSR1 # if(--ctr > 0) goto BSR1
br # return(res);
.globl .BnnAddCarry # BnnAddCarry(nn, nl, carryin)
.set CARRY,CA3 # also for BnnSubtractBorrow
.BnnAddCarry: cmpi 0,CARRY,0 # if(carryin == 0) return(0);
beq BAC3
cmpi 0,NL2,0 # if(nl == 0) return(1);
beq BAC2
ai NN1,NN1,-4 # nn--;
mtctr NL2 # ctr = nl;
BAC1: l X1,4(NN1) # X = nn[1];
ai. X1,X1,1 # X++;
stu X1,4(NN1) # *(++nn) = X;
bne BAC3 # if(X != 0) return(0);
bdn BAC1 # if(--ctr > 0) goto BAC1
BAC2: lil RES,1 # return(1);
br
BAC3: lil RES,0 # return(0);
br
.globl .BnnAdd # BnnAdd(mm, ml, nn, nl, carryin)
.set CARRYIN,CA5 # also for BnnSubtract.
.BnnAdd: sf ML2,NL4,ML2 # ml -= nl;
ai NN3,NN3,-4 # nn--;
ai MM1,MM1,-4 # mm--; carry = 1;
cmpi 0,NL4,0 # if(nl == 0) goto BADD2;
beq BADD2
mtctr NL4 # ctr = nl;
cmpi 0,CARRYIN,0 # if(carryin) goto BADD1;
bne BADD1
ai X1,X1,0 # carry = 0;
BADD1: lu X2,4(NN3) # Y = *(++nn);
l X1,4(MM1) # X = mm[1];
ae X1,X1,X2 # X = X + Y + carry; carry = ??
stu X1,4(MM1) # *(++mm) = X;
bdn BADD1 # if(--ctr > 0) goto BADD1
lil X2,0
ae CARRYIN,X2,X2 # carryin = carry;
BADD2: cmpi 0,CARRYIN,0 # if(carryin == 0) return(0);
beq BADD5
cmpi 0,ML2,0 # if(ml == 0) return(1);
beq BADD4
mtctr ML2 # ctr = ml;
BADD3: l X1,4(MM1) # X = mm[1];
ai. X1,X1,1 # X++;
stu X1,4(MM1) # *(++mm) = X;
bne BADD5 # if(X != 0) return(0);
bdn BADD3 # if(--ctr > 0) goto BADD3;
BADD4: lil RES,1 # return(1);
br
BADD5: lil RES,0 # return(0);
br
.globl .BnnSubtractBorrow # (nn, nl, carryin)
.BnnSubtractBorrow:
cmpi 0,CARRY,1 # if(carryin == 1) return(1);
beq BSB3
cmpi 0,NL2,0 # if(nl == 0) return(0);
beq BSB2
ai NN1,NN1,-4 # nn--;
mtctr NL2 # ctr = nl;
BSB1: l X1,4(NN1) # X = nn[1];
si X2,X1,1 # Y= X-1;
stu X2,4(NN1) # *(++nn) = Y;
cmpi 0,X1,0
bne BSB3 # if(X != 0) return(1);
bdn BSB1 # if(--ctr > 0) goto BSB1
BSB2: lil RES,0 # return(0);
br
BSB3: lil RES,1 # return(1);
br
.globl .BnnSubtract # BnnSubtract(mm, ml, nn, nl, carryin)
.BnnSubtract: sf ML2,NL4,ML2 # ml -= nl;
ai NN3,NN3,-4 # nn--;
ai MM1,MM1,-4 # mm--; carry = 1;
cmpi 0,NL4,0 # if(nl == 0) goto BS2
beq BS2
mtctr NL4 # ctr = nl;
cmpi 0,CARRYIN,0 # if(carryin) goto BS1
bne BS1
ai X1,X1,0 # carry = 0;
BS1: lu X2,4(NN3) # Y = *(++nn);
l X1,4(MM1) # X = mm[1];
sfe X1,X2,X1 # X = X - (Y + carry); carry = ??
stu X1,4(MM1) # *(++mm) = X;
bdn BS1 # if(--ctr > 0) goto BS1
lil CA5,0
ae CA5,CA5,CA5 # carryin = carry;
BS2: cmpi 0,CA5,1 # if(carryin == 0) return(1);
beq BS5
cmpi 0,ML2,0 # if(ml == 0) return(0);
beq BS4
mtctr ML2 # ctr = ml;
BS3: l X1,4(MM1) # X = mm[1];
si X2,X1,1 # Y= X-1;
stu X2,4(MM1) # *(++mm) = Y;
cmpi 0,X1,0 # if(X != 0) return(1);
bne BS5
bdn BS3 # if(--ctr > 0) goto BS3
BS4: lil RES,0 # return(0);
br
BS5: lil RES,1 # return(1);
br
.globl .BnnMultiplyDigit # BnnMultiplyDigit(pp, pl, mm, ml, d)
.set PP,CA1; .set PL,CA2; .set MM,CA3; .set ML,CA4; .set D,CA5
.set LOW,X1; .set HIGHT,X2; .set OHIGHT,X3
.BnnMultiplyDigit:
cmpi 0,D,0 # if(d == 0) return(0);
beq BMD7
BMD1: cmpi 0,D,1 # if(d != 1) goto BMD2;
bne BMD2
lil CA5,0 # return(BnnAdd(pp, pl, mm, ml, 0));
b .BnnAdd
BMD2: sf PL,ML,PL # pl -= ml;
ai MM,MM,-4 # mm--;
ai PP,PP,-4 # pp--;
cmpi 0,ML,0 # if(ml == 0) return(0);
beq BMD7
mtctr ML # ctr = ml;
lil OHIGHT,0 # OldHight = 0;
cmpi 0,D,0 # if(D < 0) goto BMD8;
blt BMD8
BMD3: lu LOW,4(MM) # Low = mm[1];
mul HIGHT,LOW,D # Hight:MQ = Low*d
cmpi 0,LOW,0 # if(Low>=0) pas de correction.
bge BMD4
a HIGHT,HIGHT,D # Correction multiplication signe'.
BMD4: mfmq LOW # Low = MQ;
a LOW,LOW,OHIGHT # Low += OldHight;
aze HIGHT,HIGHT # Hight += carry;
l OHIGHT,4(PP) # *++pp += Low;
a LOW,LOW,OHIGHT
stu LOW,4(PP)
aze OHIGHT,HIGHT # OldHight = Hight + carry;
bdn BMD3 # if(--ctr > 0) goto BMD3;
BMD40: l LOW,4(PP) # *(++pp) += OldHight;
a LOW,LOW,OHIGHT
stu LOW,4(PP)
lil LOW,0 # if(carry == 0) return(0);
aze. LOW,LOW
beq BMD7
si. PL,PL,1 # pl--;
ble BMD6 # if(pl <= 0) return(1);
mtctr PL # ctr = pl;
BMD5: l X1,4(PP) # X = pp[1];
ai. X1,X1,1 # X++;
stu X1,4(PP) # *(++pp) = X;
bne BMD7 # if(X != 0) return(0);
bdn BMD5 # if(--ctr > 0) goto BMD5;
BMD6: lil RES,1 # return(1);
br
BMD7: lil RES,0 # return(0);
br
BMD8: lu LOW,4(MM) # Low = mm[1];
mul HIGHT,LOW,D # Hight:MQ = Low*d
a HIGHT,HIGHT,LOW # Correction pour d<0...
cmpi 0,LOW,0 # if(Low>=0) pas de correction.
bge BMD9
a HIGHT,HIGHT,D # Correction multiplication signe'.
BMD9: mfmq LOW # Low = MQ;
a LOW,LOW,OHIGHT # Low += OldHight;
aze HIGHT,HIGHT # Hight += carry;
l OHIGHT,4(PP) # *pp += Low;
a LOW,LOW,OHIGHT
stu LOW,4(PP)
aze OHIGHT,HIGHT # OldHight = Hight + carry;
bdn BMD8 # if(--ctr > 0) goto BMD8;
b BMD40 # goto BMD40;
.globl .BnnDivideDigit # BnnDivideDigit(qq, nn, nl, d)
.set QQ,CA1; .set NN,CA2; .set NL,CA3; .set DD,CA4
.set SQQ,X1; .set R,CA1; .set Q,X2; .set NLOW,X2; .set DQ,X3
.set BITS,X4; .set AUX,CA3
.BnnDivideDigit:
sli X1,NL,2
a NN,NN,X1 # nn = &nn[nl];
a SQQ,QQ,X1 # qq = &qq[nl];
si SQQ,SQQ,4 # qq--;
lu R,-4(NN) # R = *(--nn);
si. NL,NL,1 # nl--;
bler # if(nl <= 0) return(R);
mtctr NL # ctr = nl;
sri DQ,DD,1 # D'= D / 2;
cmpi 0,DD,0 # if(D<0) goto BDDinf;
blt BDDinf
# D > 0
BDDsup: lu NLOW,-4(NN) # Low = *(--nn);
cmpl 0,R,DQ # if (R < D') goto BDDsupinf;
blt BDDsupinf
andil. BITS,NLOW,1 # bits = Low & 1;
sri NLOW,NLOW,1 # Low >>= 1;
andil. AUX,R,1 # aux = R & 1;
sri R,R,1 # R >>= 1;
sli AUX,AUX,31 # Low |= aux << 31;
or NLOW,NLOW,AUX
mtmq NLOW # MQ = Low;
div Q,R,DD # Q=R:MQ/D; MQ=R:MQ%D;
mfmq R # R=MQ;
sli R,R,1 # R <<= 1;
sli Q,Q,1 # Q <<= 1;
a R,R,BITS # R+=bits;
cmpl 0,R,DD # si R<D => ok
blt BDDsup1
ai Q,Q,1 # Q++;
sf R,DD,R # R-=D;
BDDsup1: stu Q,-4(SQQ) # *(--qq)=Q;
bdn BDDsup # if(--ctr > 0) goto BDDsup;
br # return(R);
BDDsupinf: mtmq NLOW # MQ = XL;
div Q,R,DD # Q=R:MQ/D; MQ=R:MQ%D;
mfmq R # R=MQ;
stu Q,-4(SQQ) # *(--qq)=Q;
bdn BDDsup # if(--ctr > 0) goto BDDsup;
br # return(R);
# D < 0
BDDinf: lu NLOW,-4(NN) # Low = *(--nn);
andil. BITS,NLOW,7 # bits = Low & 7;
sri NLOW,NLOW,3 # Low >>= 3;
andil. AUX,R,7 # aux = R & 7;
sri R,R,3 # R >>= 3;
sli AUX,AUX,29 # Low |= aux << 29;
or NLOW,NLOW,AUX
mtmq NLOW # MQ = Low;
div Q,R,DQ # Q=R:MQ/D'; MQ=R:MQ%D';
mfmq R # R=MQ
sli R,R,1 # R *= 2;
andil. AUX,DD,1 # if((D & 1) == 0) rien a retrancher;
cmpli 0,AUX,0
beq BDDi4
# R <- R - Q
cmpl 0,R,Q # On teste avant de faire la diff.
blt BDDi3 # la diff est < 0
sf R,Q,R # la diff est > 0
b BDDi4
BDDi3: sf R,Q,R # On met a` jour
si Q,Q,1 # Q--;
a R,R,DD # R += D;
# R <- 2R; Q <- 2Q;
BDDi4: cmpl 0,R,DQ # On teste avant de faire la mult.
blt BDDi41 # Ca va passer..
bne BDDi40 # Ca va casser...
cmpli 0,AUX,0 # d0 = 1 ca passe...
bne BDDi41
BDDi40: sli Q,Q,1 # Q *= 2;
sli R,R,1 # R *= 2;
ai Q,Q,1 # Q++;
sf R,DD,R # R -= D;
b BDDi5
BDDi41: sli Q,Q,1 # Q *= 2;
sli R,R,1 # R *= 2;
# R <- 2R; Q <- 2Q;
BDDi5: cmpl 0,R,DQ # On teste avant de faire la mult.
blt BDDi51 # Ca va passer..
bne BDDi50 # Ca va casser...
cmpli 0,AUX,0 # d0 = 1 ca passe...
bne BDDi51
BDDi50: sli Q,Q,1 # Q *= 2;
sli R,R,1 # R *= 2;
ai Q,Q,1 # Q++;
sf R,DD,R # R -= D;
b BDDi6
BDDi51: sli Q,Q,1 # Q *= 2;
sli R,R,1 # R *= 2;
# R += bits;
BDDi6: sf AUX,BITS,DD # pour tester sans de'bordement..
cmpl 0,R,AUX
blt BDDi61 # Ca va passer..
ai Q,Q,1 # Q++;
sf R,DD,R # R -= D;
BDDi61: a R,R,BITS # R += bits;
stu Q,-4(SQQ) # *(--qq)=Q;
bdn BDDinf # if(--ctr > 0) goto BDDinf;
br