]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: replace divide with multiply in runtime.usleep on arm
authorRuss Cox <rsc@golang.org>
Thu, 30 Jul 2015 14:54:53 +0000 (10:54 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 30 Jul 2015 15:48:29 +0000 (15:48 +0000)
We want to adjust the DIV calling convention to use m,
and usleep can be called without an m, so switch to a
multiplication by the reciprocal (and test).

Step toward a fix for #6699 and #10486.

Change-Id: Iccf76a18432d835e48ec64a2fa34a0e4d6d4b955
Reviewed-on: https://go-review.googlesource.com/12898
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/runtime/asm_arm.s
src/runtime/export_arm_test.go [new file with mode: 0644]
src/runtime/sys_arm.go
src/runtime/sys_darwin_arm.s
src/runtime/sys_freebsd_arm.s
src/runtime/sys_linux_arm.s
src/runtime/sys_netbsd_arm.s
src/runtime/sys_openbsd_arm.s
src/runtime/vlop_arm_test.go

index 661538c02472706aaadb492337fcfa46c98778f2..280a682a7c7ddb3d690fe20d4edcc0799ef0d997 100644 (file)
@@ -1029,3 +1029,24 @@ TEXT runtime·prefetcht2(SB),NOSPLIT,$0-4
 
 TEXT runtime·prefetchnta(SB),NOSPLIT,$0-4
        RET
+
+// x -> x/1000000, x%1000000, called from Go with args, results on stack.
+TEXT runtime·usplit(SB),NOSPLIT,$0-12
+       MOVW    x+0(FP), R0
+       CALL    runtime·usplitR0(SB)
+       MOVW    R0, q+4(FP)
+       MOVW    R1, r+8(FP)
+       RET
+
+// R0, R1 = R0/1000000, R0%1000000
+TEXT runtime·usplitR0(SB),NOSPLIT,$0
+       // magic multiply to avoid software divide without available m.
+       // see output of go tool compile -S for x/1000000.
+       MOVW    R0, R3
+       MOVW    $1125899907, R1
+       MULLU   R1, R0, (R0, R1)
+       MOVW    R0>>18, R0
+       MOVW    $1000000, R1
+       MULU    R0, R1
+       SUB     R1, R3, R1
+       RET
diff --git a/src/runtime/export_arm_test.go b/src/runtime/export_arm_test.go
new file mode 100644 (file)
index 0000000..446d264
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2015 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Export guts for testing.
+
+package runtime
+
+var Usplit = usplit
index 6e50d210988ac109b55b4325239108f9d79863fb..d2e69146af1027371e89933fb852d65f9ce28455 100644 (file)
@@ -33,3 +33,6 @@ func rewindmorestack(buf *gobuf) {
        print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n")
        throw("runtime: misuse of rewindmorestack")
 }
+
+// for testing
+func usplit(x uint32) (q, r uint32)
index be35d37bc81839f3fedf52119483f7ab07b09290..087dec551e24c18e2093b9a31f62dbb3b87fc218 100644 (file)
@@ -283,10 +283,7 @@ TEXT runtime·sigaction(SB),NOSPLIT,$0
 
 TEXT runtime·usleep(SB),NOSPLIT,$12
        MOVW    usec+0(FP), R0
-       MOVW    R0, R1
-       MOVW    $1000000, R2
-       DIV     R2, R0
-       MOD     R2, R1
+       CALL    runtime·usplitR0(SB)
        MOVW    R0, a-12(SP)
        MOVW    R1, b-8(SP)
 
index 0441d81b25c8a2ad6dc00c9a622b2b4e56a2ffa9..bd6ff96f3153ed5aaf5dbce5e1aafd8292ca50b9 100644 (file)
@@ -302,15 +302,12 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
 
 TEXT runtime·usleep(SB),NOSPLIT,$16
        MOVW usec+0(FP), R0
-       MOVW R0, R2
-       MOVW $1000000, R1
-       DIV R1, R0
+       CALL runtime·usplitR0(SB)
        // 0(R13) is the saved LR, don't use it
        MOVW R0, 4(R13) // tv_sec.low
        MOVW $0, R0
        MOVW R0, 8(R13) // tv_sec.high
-       MOD R1, R2
-       MOVW $1000, R1
+       MOVW $1000, R2
        MUL R1, R2
        MOVW R2, 12(R13) // tv_nsec
 
index abdeb93e59a28e7c25a9342f727141bcdcbbd650..29eb8eb077514e005e4947afa21fb44bf6108652 100644 (file)
@@ -378,10 +378,7 @@ TEXT runtime·rt_sigaction(SB),NOSPLIT,$0
 
 TEXT runtime·usleep(SB),NOSPLIT,$12
        MOVW    usec+0(FP), R0
-       MOVW    R0, R1
-       MOVW    $1000000, R2
-       DIV     R2, R0
-       MOD     R2, R1
+       CALL    runtime·usplitR0(SB)
        MOVW    R0, 4(R13)
        MOVW    R1, 8(R13)
        MOVW    $0, R0
index 24c32a61580dc96bfe7c5bb79b4d54ce69084bdc..ae669ce76b6bc789e2623c7f4c2622bd1bb3f1b5 100644 (file)
@@ -104,15 +104,12 @@ TEXT runtime·lwp_tramp(SB),NOSPLIT,$0
 
 TEXT runtime·usleep(SB),NOSPLIT,$16
        MOVW usec+0(FP), R0
-       MOVW R0, R2
-       MOVW $1000000, R1
-       DIV R1, R0
+       CALL runtime·usplitR0(SB)
        // 0(R13) is the saved LR, don't use it
        MOVW R0, 4(R13) // tv_sec.low
        MOVW $0, R0
        MOVW R0, 8(R13) // tv_sec.high
-       MOD R1, R2
-       MOVW $1000, R1
+       MOVW $1000, R2
        MUL R1, R2
        MOVW R2, 12(R13) // tv_nsec
 
index ab7f2ae01fbb111f6250bbecf64c1a36868c1884..60deb8f38a7cc282c636231210d0b1d52c90fc49 100644 (file)
@@ -70,14 +70,11 @@ TEXT runtime·write(SB),NOSPLIT,$-4
 
 TEXT runtime·usleep(SB),NOSPLIT,$16
        MOVW    usec+0(FP), R0
-       MOVW    R0, R2
-       MOVW    $1000000, R1
-       DIV     R1, R0
+       CALL    runtime·usplitR0(SB)
        MOVW    R0, 4(R13)              // tv_sec - l32
        MOVW    $0, R0
        MOVW    R0, 8(R13)              // tv_sec - h32
-       MOD     R1, R2
-       MOVW    $1000, R1
+       MOVW    $1000, R2
        MUL     R1, R2
        MOVW    R2, 12(R13)             // tv_nsec
 
index cd28419adfa05d86ee74dcd54fffbf0b350fd411..1a211196f2f962d0c191519f76a1b0b9169128d9 100644 (file)
@@ -4,7 +4,10 @@
 
 package runtime_test
 
-import "testing"
+import (
+       "runtime"
+       "testing"
+)
 
 // arm soft division benchmarks adapted from
 // http://ridiculousfish.com/files/division_benchmarks.tar.gz
@@ -68,3 +71,14 @@ func BenchmarkUint32Mod13307(b *testing.B)     { bmUint32Mod(13307, b) }
 func BenchmarkUint32Mod52513(b *testing.B)     { bmUint32Mod(52513, b) }
 func BenchmarkUint32Mod60978747(b *testing.B)  { bmUint32Mod(60978747, b) }
 func BenchmarkUint32Mod106956295(b *testing.B) { bmUint32Mod(106956295, b) }
+
+func TestUsplit(t *testing.T) {
+       var den uint32 = 1000000
+       for _, x := range []uint32{0, 1, 999999, 1000000, 1010101, 0xFFFFFFFF} {
+               q1, r1 := runtime.Usplit(x)
+               q2, r2 := x/den, x%den
+               if q1 != q2 || r1 != r2 {
+                       t.Errorf("%d/1e6, %d%%1e6 = %d, %d, want %d, %d", x, x, q1, r1, q2, r2)
+               }
+       }
+}