ocaml/otherlibs/num/bignum/s/pyramidKerN.s

455 lines
11 KiB
ArmAsm

# Copyright Digital Equipment Corporation & INRIA 1988, 1989
#
# KerN for Pyramid Architecture
# Bernard Paul Serpette
#
.text 0
.globl _BnnSetToZero
_BnnSetToZero: subw $1,pr1 # nl--;
blt BSTZ2 # if(nl < 0) return;
BSTZ1: movw $0,(pr0) # *nn = 0;
addw $4,pr0 # nn++;
subw $1,pr1 # nl--;
bge BSTZ1 # if(nl >= 0) goto BSTZ1;
BSTZ2: ret # return;
.globl _BnnAssign
_BnnAssign: ucmpw pr1,pr0
bgt BAG3 # if(mm > nn) goto BAG3;
subw $1,pr2 # nl--;
bge BAG2 # if(nl >= 0) goto BAG2;
ret
BAG1: addw $4,pr0 # mm++;
addw $4,pr1 # nn++;
BAG2: movw (pr1),(pr0) # *mm = *nn;
subw $1,pr2 # nl--;
bge BAG1 # if(nl >= 0) goto BAG1;
ret
BAG3: mova (pr1)[pr2*0x4],pr1 # nn += nl;
mova (pr0)[pr2*0x4],pr0 # mm += nl;
subw $1,pr2 # nl--;
blt BAG5 # if(nl < 0) return;
BAG4: subw $4,pr0 # mm--;
subw $4,pr1 # nn--;
movw (pr1),(pr0) # *mm = *nn;
subw $1,pr2 # nl--;
bge BAG4 # if(nl >= 0) goto BAG4;
BAG5: ret
.globl _BnnSetDigit
_BnnSetDigit: movw pr1,(pr0) # *nn = d;
ret
.globl _BnnGetDigit
_BnnGetDigit: movw (pr0),pr0 # return(*nn);
ret
.globl _BnnNumDigits
_BnnNumDigits:
mova (pr0)[pr1*0x4],pr0 # nn += nl;
br BND2
BND1: subw $4,pr0 # nn--;
mtstw (pr0),pr2
bne BND3 # if(*nn) goto BND3
subw $1,pr1 # nl--;
BND2: mtstw pr1,pr2
bne BND1 # if(nl) goto BND1;
movw $1,pr0 # return(1);
ret
BND3: movw pr1,pr0 # return(nl);
ret
.globl _BnnNumLeadingZeroBitsInDigit
_BnnNumLeadingZeroBitsInDigit:
movw $0,pr1 # p = 0;
mtstw pr0,pr0
bne BLZ2 # if(!d) goto BLZ2;
movw $32,pr0 # return(32);
ret
BLZ1: addw $1,pr1 # p++;
lshlw $1,pr0 # d <<= 1;
BLZ2: mtstw pr0,pr0
bgt BLZ1 # if(d > 0) goto BLZ1;
movw pr1,pr0 # return(p);
ret
.globl _BnnDoesDigitFitInWord
_BnnDoesDigitFitInWord:
movw $1,pr0 # return(1);
ret
.globl _BnnIsDigitZero
_BnnIsDigitZero:
mtstw pr0,pr0 # set NZVC flags
mpsw pr0 # mov NZVC flags in register
andw $4,pr0 # return(Z);
ret
.globl _BnnIsDigitNormalized
_BnnIsDigitNormalized:
mtstw pr0,pr0 # set NZVC flags
mpsw pr0 # mov NZVC flags in register
andw $8,pr0 # return(N);
ret
.globl _BnnIsDigitOdd
_BnnIsDigitOdd:
andw $1,pr0 # return(d & 1);
ret
.globl _BnnCompareDigits
_BnnCompareDigits:
ucmpw pr1,pr0
bgt BCDsup
bne BCDinf
movw $0,pr0
ret
BCDinf: movw $-1,pr0
ret
BCDsup: movw $1,pr0
ret
.globl _BnnComplement
_BnnComplement:
subw $1,pr1 # nl--;
blt BCM2 # if(nl < 0) goto BCM2
BCM1: mcomw (pr0),pr2 # tmp = *nn ^ -1;
movw pr2,(pr0) # *nn = tmp;
addw $4,pr0 # nn++;
subw $1,pr1 # nl--;
bge BCM1 # if(nl >= 0) goto BCM1;
BCM2: ret
.globl _BnnAndDigits
_BnnAndDigits: andw (pr0),pr1 # d &= *nn;
movw pr1,(pr0) # *nn = d;
ret
.globl _BnnOrDigits
_BnnOrDigits: orw (pr0),pr1 # d |= *nn;
movw pr1,(pr0) # *nn = d;
ret
.globl _BnnXorDigits
_BnnXorDigits: xorw (pr0),pr1 # d ^= *nn;
movw pr1,(pr0) # *nn = d;
ret
.globl _BnnShiftLeft
_BnnShiftLeft: movw $0,lr1 # res = 0;
mtstw pr2,pr2
beq BSL2 # if(!nbi) return(res);
movw $32,lr2 # rnbi = 32;
subw pr2,lr2 # rnbi -= nbi;
subw $1,pr1 # ml--;
blt BSL2 # if(ml < 0) return(res);
BSL1: movw (pr0),lr0 # save = *mm;
movw lr0,pr3 # X = save;
lshlw pr2,pr3 # X <<= nbi;
orw lr1,pr3 # X |= res;
movw pr3,(pr0) # *mm = X;
addw $4,pr0 # mm++;
movw lr0,lr1 # res = save;
lshrw lr2,lr1 # res >>= rnbi;
subw $1,pr1 # ml--;
bge BSL1 # if(ml >= 0) goto BSL1;
BSL2: movw lr1,pr0 # return(res);
ret
.globl _BnnShiftRight
_BnnShiftRight: movw $0,lr1 # res = 0;
mtstw pr2,pr2
beq BSR2 # if(!nbi) return(res);
mova (pr0)[pr1*0x4],pr0 # mm += ml;
movw $32,lr2 # lnbi = 32;
subw pr2,lr2 # lnbi -= nbi;
subw $1,pr1 # ml--;
blt BSR2 # if(ml < 0) return(res);
BSR1: subw $4,pr0 # mm--;
movw (pr0),lr0 # save = *mm;
movw lr0,pr3 # X = save;
lshrw pr2,pr3 # X >>= nbi;
orw lr1,pr3 # X |= res;
movw pr3,(pr0) # *mm = X;
movw lr0,lr1 # res = save;
lshlw lr2,lr1 # res <<= lnbi;
subw $1,pr1 # ml--;
bge BSR1 # if(ml >= 0) goto BSR1;
BSR2: movw lr1,pr0 # return(res);
ret
.globl _BnnAddCarry
_BnnAddCarry: mtstw pr2,pr2
beq BAC3 # if(!carryin) return(0);
mtstw pr1,pr1
beq BAC2 # if(!nl) return(1);
subw $1,pr1 # nl--;
BAC1: icmpw $0,(pr0) # Z = (++(nn) == 0);
bne BAC3 # if(!Z) goto BAC3;
addw $4,pr0 # nn++;
subw $1,pr1 # nl--
bge BAC1 # if(nl >= 0) goto BAC1;
BAC2: movw $1,pr0 # return(1);
ret
BAC3: movw $0,pr0 # return(0);
ret
.globl _BnnAdd
_BnnAdd: subw pr3,pr1 # ml -= nl;
mtstw pr3,pr3
beq BADD5 # if(!nl) goto BADD5;
BADD1: subw $1,pr3 # nl--;
BADDX: movw (pr0),pr5 # X1 = *mm
bicpsw $1
bispsw pr4 # Set the carry C;
addwc (pr2),pr5 # X1 += *nn + C;
mpsw pr4
andw $1,pr4 # get the carry C;
movw pr5,(pr0) # *mm = X1;
addw $4,pr0 # mm++;
addw $4,pr2 # nn++;
subw $1,pr3 # nl--;
bge BADDX # if(nl >= 0) goto BADDX;
BADD5: mtstw pr4,pr4
bne BADD7 # if(car) goto BADD7;
BADD6: movw $0,pr0 # return(0);
ret
BADD7: mtstw pr1,pr1
beq BADD9 # if(!ml) return(1);
subw $1,pr1 # ml--;
BADD8: icmpw $0,(pr0) # Z = (++(mm) == 0);
bne BADD6 # if(!Z) goto BADD6;
addw $4,pr0 # nn++;
subw $1,pr1 # nl--
bge BADD8 # if(nl >= 0) goto BADD8;
BADD9: movw $1,pr0 # return(1);
ret
.globl _BnnSubtractBorrow
_BnnSubtractBorrow:
mtstw pr2,pr2
bne BSB3 # if(carryin) return(1);
mtstw pr1,pr1
beq BSB2 # if(!nl) return(1);
subw $1,pr1 # nl--;
BSB1: dcmpw $-1,(pr0) # Z = (--(nn) == -1);
bne BSB3 # if(!Z) goto BSB3;
addw $4,pr0 # nn++;
subw $1,pr1 # nl--
bge BSB1 # if(nl >= 0) goto BSB1;
BSB2: movw $0,pr0 # return(0);
ret
BSB3: movw $1,pr0 # return(1);
ret
.globl _BnnSubtract
_BnnSubtract: subw pr3,pr1 # ml -= nl;
mtstw pr3,pr3
beq BS5 # if(!nl) goto BS5;
BS1: subw $1,pr3 # nl--;
BSX: movw (pr0),pr5 # X1 = *mm
bicpsw $1
bispsw pr4 # Set the carry C;
subwb (pr2),pr5 # X1 -= *nn + C;
mpsw pr4
andw $1,pr4 # get the carry C;
movw pr5,(pr0) # *mm = X1;
addw $4,pr0 # mm++;
addw $4,pr2 # nn++;
subw $1,pr3 # nl--;
bge BSX # if(nl >= 0) goto BSX;
BS5: mtstw pr4,pr4
beq BS7 # if(!car) goto BS7;
BS6: movw $1,pr0 # return(1);
ret
BS7: mtstw pr1,pr1
beq BS9 # if(!ml) return(1);
subw $1,pr1 # ml--;
BS8: dcmpw $-1,(pr0) # Z = (--(mm) == -1);
bne BS6 # if(!Z) goto BS6;
addw $4,pr0 # nn++;
subw $1,pr1 # nl--
bge BS8 # if(nl >= 0) goto BS8;
BS9: movw $0,pr0 # return(0);
ret
.globl _BnnMultiplyDigit # (pp, pl, mm, ml, d)
_BnnMultiplyDigit:
mtstw pr4,pr4
bne BMD1 # if(!d) return(0);
movw $0,pr0
ret
BMD1: ucmpw $1,pr4
bne BMD2 # if(d != 1) goto BMD2;
movw $0,pr4
br _BnnAdd # BnnAdd(p,pl,m,ml,0);
BMD2: subw pr3,pr1 # pl -= ml;
movw $0,pr8 # Un zero.
movw pr8,pr7 # low = 0;
br BMD4
BMD3: subw $1,pr3 # pl--;
movw (pr2),pr6 # X = *mm;
addw $4,pr2 # mm++;
uemul pr4,pr5 # X *= d;
addw pr7,pr6 # X += low;
addwc pr8,pr5 # X(hight) += Carry;
addw (pr0),pr6 # X += *pp;
addwc pr8,pr5 # X(hight) += Carry;
movw pr6,(pr0) # *pp = X(low);
addw $4,pr0 # pp++;
movw pr5,pr7 # low = X(Hight);
BMD4: mtstw pr3,pr3
bne BMD3 # if(ml) goto BMD3;
addw (pr0),pr7 # low += *pp;
movw pr7,(pr0) # *pp = low;
bcs BMD7 # if(Carry) goto BMD7;
BMD6: movw $0,pr0 # return(0);
ret
BMD7: addw $4,pr0 # pp++;
subw $1,pr1 # pl--;
beq BMD10 # if(!pl) return(1);
subw $1,pr1 # pl--;
BMD8: icmpw $0,(pr0) # Z = (++(*pp) == 0)
bne BMD6 # if(!!Z) goto BADD6;
addw $4,pr0 # pp++;
subw $1,pr1 # pl--
bge BMD8 # if(pl >= 0) goto BADD8;
BMD10: movw $1,pr0 # return(1);
ret
# The 64 bits/32 bits unsigned division, like in Vaxes, must be simulated
#by a 64/32 signed division:
#
#N = D*Q + R
#D = 2D' + d0
#Cas 1: 0 <= D < 2^31
#------
# Sous-cas 1: N < D'*2^32 -> Calcul direct signe'
# -----------
#
# Sous-cas 2: N >= D'*2^32
# -----------
# N = 2N' + n0
# N' = DQ' + R' (0 <= R' < D)
# N = 2DQ' + 2R' + n0 (0 <= 2R' + n0 < 2D)
# Si 2R' + n0 < D
# Q = 2Q' et R = 2R' + n0
# sinon Q = 2Q' + 1 et R = 2R' + n0 - D
#
#Cas 2: 2^31 <= D < 2^32
#------
# N = 8N' + 4n2 + 2n1 + n0
# N' = D'Q' + R' (0 <= R' <= D' - 1)
# N = 8D'Q' + 8R' + 4n2 + 2n1 + n0
# N = 4DQ' + 8R' + 4n2 + 2n1 + n0 - 4Q'd0
# N = 4DQ' + 2(2(2R' + n2 - Q'd0) + n1) + n0 (0 <= 2R' + n2 < D)
# Q' < 2^31 <= D
# -D <= R1 = 2R' + n2 - Q'd0 < D
# Si d0 = 1 et -D < R1 < 0
# Q1 = Q' - 1; R1 = R1 + D
# N = 4Q1D + 2(2R1 + n1) + n0
# Q0 = 2Q1; R0 = 2R1 + n1
# Si R2 >= D
# Q0 = Q0 + 1; R2 = R2 - D
# N = 2Q0 + 2R0 + n0
# Q = 2Q0; R = 2R0 + n0
# Si R >= d
# Q = Q + 1; R = R - D
.globl _BnnDivideDigit # (qq, nn, nl, d)
_BnnDivideDigit:
subw $1,pr2 # nl--;
mova (pr1)[pr2*0x4],pr1 # nn += nl;
mova (pr0)[pr2*0x4],pr0 # qq += nl;
movw (pr1),pr4 # N(Hight) = *nn;
movw pr3,pr6
lshrw $1,pr6 # D' = D >> 1;
mtstw pr3,pr3
bge BDD2
movw pr3,lr5
andw $1,lr5
movw $1,lr6 # lr6 <- 0x1FFFFFFF
lshlw $29,lr6 # pour le
subw $1,lr6 # shift arithme'tique
br BDD5
BDD1: subw $4,pr1 # nn--;
movw (pr1),pr5 # N(low) = *nn;
ucmpw pr6,pr4
blt BDD11 # if(N < D'*2^32) goto BDD11;
movw pr5,lr0
andw $1,lr0 # n0 = N & 1;
ashrl $1,pr4 # N = N' = N / 2;
ediv pr3,pr4 # Q = N' / D
# R = N' % D
lshlw $1,pr4 # Q = 2Q
lshlw $1,pr5 # R = 2R;
addw lr0,pr5 # R = R + n0
ucmpw pr3,pr5
blt BDD12 # if(R < D) goto BDD12;
addw $1,pr4 # Q = Q + 1;
subw pr3,pr5 # R = R - D;
br BDD12 # goto BDD12
BDD11: ediv pr3,pr4 # N(Hight) = N / d;
# N(low) = N % d;
BDD12: subw $4,pr0 # qq--;
movw pr4,(pr0) # *qq = X(low);
movw pr5,pr4
BDD2: subw $1,pr2
bge BDD1
movw pr4,pr0
ret
BDD3: subw $4,pr1 # nn--;
movw (pr1),pr5 # N(low) = *nn;
movw pr5,lr0
andw $1,lr0 # lr0 = n0 = N & 1;
movw pr5,lr1
andw $2,lr1 # lr1 = 2n1 = N & 2;
movw pr5,lr2
andw $4,lr2 # lr2 = 4n2 = N & 4;
ashrl $3,pr4 # N = N' = N / 8;
andw lr6,pr4 # shift arithme'tique!!
ediv pr6,pr4 # Q' = N' / D';
# R' = N' % D';
addw pr5,pr5 # R1 = 2 * R'; Q1 = Q';
mtstw lr5,lr5
beq BDD33 # if(d0 == 0) goto BDD33;
ucmpw pr4,pr5
bge BDD32 # if(R1 >= Q') goto BDD32;
subw pr4,pr5 # R1 = R1 - Q'
subw $1,pr4 # Q1 = Q1 - 1;
addw pr3,pr5 # R1 = R1 + D;
br BDD33
BDD32: subw pr4,pr5 # R1 = R1 - Q'
BDD33: addw pr4,pr4 # Q0 = 2 * Q1;
addw pr5,pr5 # R0 = 2 * R1;
bcs BDD4
ucmpw pr3,pr5
blt BDD40 # if(R0 < D) goto BDD40;
BDD4: addw $1,pr4 # Q0 = Q0 + 1;
subw pr3,pr5 # R0 = R0 - D
BDD40: addw pr4,pr4 # Q = 2 * Q0;
addw pr5,pr5 # R = 2 * R0;
bcs BDD41
ucmpw pr3,pr5
blt BDD42 # if(R < D) goto BDD42;
BDD41: addw $1,pr4 # Q = Q + 1;
subw pr3,pr5 # R = R - D;
BDD42: addw lr2,pr5
addw lr1,pr5
addw lr0,pr5 # R = R + lr2 + lr1 + lr0;
ucmpw pr3,pr5
blt BDD43 # if(R < D) goto BDD43
addw $1,pr4 # Q = Q + 1;
subw pr3,pr5 # R = R - D;
BDD43: subw $4,pr0 # qq--;
movw pr4,(pr0) # *qq = X(low);
movw pr5,pr4
BDD5: subw $1,pr2
bge BDD3
movw pr4,pr0
ret