1
0
mirror of https://github.com/golang/go synced 2024-11-20 10:54:49 -07:00

Implement divWW_g in Go.

R=gri
DELTA=105  (77 added, 23 deleted, 5 changed)
OCL=33890
CL=33910
This commit is contained in:
Ian Lance Taylor 2009-08-26 16:14:17 -07:00
parent 396b47bbbd
commit 06cac23d28
3 changed files with 82 additions and 28 deletions

View File

@ -138,8 +138,55 @@ func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
}
// TODO(gri) get rid of this eventually
func divWWW_s(x1, x0, y Word) (q, r Word)
// q = (x1<<_W + x0 - r)/y
// The most significant bit of y must be 1.
func divStep(x1, x0, y Word) (q, r Word) {
d1, d0 := y>>_W2, y&_M2;
q1, r1 := x1/d1, x1%d1;
m := q1*d0;
r1 = r1*_B2 | x0>>_W2;
if r1 < m {
q1--;
r1 += y;
if r1 >= y && r1 < m {
q1--;
r1 += y;
}
}
r1 -= m;
r0 := r1%d1;
q0 := r1/d1;
m = q0*d0;
r0 = r0*_B2 | x0&_M2;
if r0 < m {
q0--;
r0 += y;
if r0 >= y && r0 < m {
q0--;
r0 += y;
}
}
r0 -= m;
q = q1*_B2 | q0;
r = r0;
return;
}
// Number of leading zeros in x.
func leadingZeros(x Word) (n uint) {
if x == 0 {
return uint(_W);
}
for x & (1<<(_W-1)) == 0 {
n++;
x <<= 1;
}
return;
}
// q = (x1<<_W + x0 - r)/y
func divWW_g(x1, x0, y Word) (q, r Word) {
@ -148,9 +195,39 @@ func divWW_g(x1, x0, y Word) (q, r Word) {
return;
}
// TODO(gri) implement general case w/o assembly code
q, r = divWWW_s(x1, x0, y);
return;
var q0, q1 Word;
z := leadingZeros(y);
if y > x1 {
if z != 0 {
y <<= z;
x1 = (x1 << z) | (x0 >> (uint(_W) - z));
x0 <<= z;
}
q0, x0 = divStep(x1, x0, y);
q1 = 0;
} else {
if z == 0 {
x1 -= y;
q1 = 1;
} else {
z1 := uint(_W) - z;
y <<= z;
x2 := x1 >> z1;
x1 = (x1 << z) | (x0 >> z1);
x0 <<= z;
q1, x1 = divStep(x2, x1, y);
}
q0, x0 = divStep(x1, x0, y);
}
r = x0 >> z;
if q1 != 0 {
panic("div out of range");
}
return q0, r;
}

View File

@ -19,15 +19,3 @@ TEXT big·mulAddVWW_s(SB),7,$0
TEXT big·addMulVVW_s(SB),7,$0
TEXT big·divWVW_s(SB),7,$0
RET
// func divWWW_s(x1, x0, y Word) (q, r Word)
// TODO(gri) Implement this routine completely in Go.
// At the moment we need this assembly version.
TEXT big·divWWW_s(SB),7,$0
MOVL x1+0(FP), DX
MOVL x0+4(FP), AX
DIVL y+8(FP)
MOVL AX, q+12(FP)
MOVL DX, r+16(FP)
RET

View File

@ -176,14 +176,3 @@ E7: SUBL $1, BX // i--
MOVQ DX, r+40(FP)
RET
// TODO(gri) Implement this routine completely in Go.
// At the moment we need this assembly version.
TEXT big·divWWW_s(SB),7,$0
MOVQ x1+0(FP), DX
MOVQ x0+8(FP), AX
DIVQ y+16(FP)
MOVQ AX, q+24(FP)
MOVQ DX, r+32(FP)
RET