From: Russ Cox Date: Mon, 16 Sep 2013 19:11:32 +0000 (-0400) Subject: runtime: fix uint64 division on 386 X-Git-Tag: go1.2rc2~196 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=70138a2108d81a771a180af93edbc007d2a5c8b2;p=gostls13.git runtime: fix uint64 division on 386 The uint64 divide function calls _mul64x32 to do a 64x32-bit multiply and then compares the result against the 64-bit numerator. If the result is bigger than the numerator, must use the slow path. Unfortunately, the 64x32 produces a 96-bit product, and only the low 64 bits were being used in the comparison. Return all 96 bits, the bottom 64 via the original uint64* pointer, and the top 32 as the function's return value. Fixes 386 build (broken by ARM division tests). R=golang-dev, iant CC=golang-dev https://golang.org/cl/13722044 --- diff --git a/src/pkg/runtime/vlop_386.s b/src/pkg/runtime/vlop_386.s index edc659b848..9783fdc936 100644 --- a/src/pkg/runtime/vlop_386.s +++ b/src/pkg/runtime/vlop_386.s @@ -29,6 +29,8 @@ * C runtime for 64-bit divide. */ +// _mul64x32(r *uint64, a uint64, b uint32) +// sets *r = low 64 bits of 96-bit product a*b; returns high 32 bits. TEXT _mul64by32(SB), NOSPLIT, $0 MOVL r+0(FP), CX MOVL a+4(FP), AX @@ -38,7 +40,9 @@ TEXT _mul64by32(SB), NOSPLIT, $0 MOVL a+8(FP), AX MULL b+12(FP) ADDL AX, BX + ADCL $0, DX MOVL BX, 4(CX) + MOVL DX, AX RET TEXT _div64by32(SB), NOSPLIT, $0 diff --git a/src/pkg/runtime/vlrt_386.c b/src/pkg/runtime/vlrt_386.c index d8bc94bd94..8d965c086e 100644 --- a/src/pkg/runtime/vlrt_386.c +++ b/src/pkg/runtime/vlrt_386.c @@ -147,7 +147,7 @@ _v2f(Vlong x) } ulong _div64by32(Vlong, ulong, ulong*); -void _mul64by32(Vlong*, Vlong, ulong); +int _mul64by32(Vlong*, Vlong, ulong); static void slowdodiv(Vlong num, Vlong den, Vlong *q, Vlong *r) @@ -232,8 +232,7 @@ dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp) if(den.hi != 0){ q.hi = 0; n = num.hi/den.hi; - _mul64by32(&x, den, n); - if(x.hi > num.hi || (x.hi == num.hi && x.lo > num.lo)) + if(_mul64by32(&x, den, n) || x.hi > num.hi || (x.hi == num.hi && x.lo > num.lo)) slowdodiv(num, den, &q, &r); else { q.lo = n;