Commit c9d2c7f0 authored by Russ Cox's avatar Russ Cox

runtime: replace divide with multiply in runtime.usleep on arm

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/12898Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent a1e42207
...@@ -1029,3 +1029,24 @@ TEXT runtime·prefetcht2(SB),NOSPLIT,$0-4 ...@@ -1029,3 +1029,24 @@ TEXT runtime·prefetcht2(SB),NOSPLIT,$0-4
TEXT runtime·prefetchnta(SB),NOSPLIT,$0-4 TEXT runtime·prefetchnta(SB),NOSPLIT,$0-4
RET 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
// 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
...@@ -33,3 +33,6 @@ func rewindmorestack(buf *gobuf) { ...@@ -33,3 +33,6 @@ func rewindmorestack(buf *gobuf) {
print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n") print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n")
throw("runtime: misuse of rewindmorestack") throw("runtime: misuse of rewindmorestack")
} }
// for testing
func usplit(x uint32) (q, r uint32)
...@@ -283,10 +283,7 @@ TEXT runtime·sigaction(SB),NOSPLIT,$0 ...@@ -283,10 +283,7 @@ TEXT runtime·sigaction(SB),NOSPLIT,$0
TEXT runtime·usleep(SB),NOSPLIT,$12 TEXT runtime·usleep(SB),NOSPLIT,$12
MOVW usec+0(FP), R0 MOVW usec+0(FP), R0
MOVW R0, R1 CALL runtime·usplitR0(SB)
MOVW $1000000, R2
DIV R2, R0
MOD R2, R1
MOVW R0, a-12(SP) MOVW R0, a-12(SP)
MOVW R1, b-8(SP) MOVW R1, b-8(SP)
......
...@@ -302,15 +302,12 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$-8 ...@@ -302,15 +302,12 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
TEXT runtime·usleep(SB),NOSPLIT,$16 TEXT runtime·usleep(SB),NOSPLIT,$16
MOVW usec+0(FP), R0 MOVW usec+0(FP), R0
MOVW R0, R2 CALL runtime·usplitR0(SB)
MOVW $1000000, R1
DIV R1, R0
// 0(R13) is the saved LR, don't use it // 0(R13) is the saved LR, don't use it
MOVW R0, 4(R13) // tv_sec.low MOVW R0, 4(R13) // tv_sec.low
MOVW $0, R0 MOVW $0, R0
MOVW R0, 8(R13) // tv_sec.high MOVW R0, 8(R13) // tv_sec.high
MOD R1, R2 MOVW $1000, R2
MOVW $1000, R1
MUL R1, R2 MUL R1, R2
MOVW R2, 12(R13) // tv_nsec MOVW R2, 12(R13) // tv_nsec
......
...@@ -378,10 +378,7 @@ TEXT runtime·rt_sigaction(SB),NOSPLIT,$0 ...@@ -378,10 +378,7 @@ TEXT runtime·rt_sigaction(SB),NOSPLIT,$0
TEXT runtime·usleep(SB),NOSPLIT,$12 TEXT runtime·usleep(SB),NOSPLIT,$12
MOVW usec+0(FP), R0 MOVW usec+0(FP), R0
MOVW R0, R1 CALL runtime·usplitR0(SB)
MOVW $1000000, R2
DIV R2, R0
MOD R2, R1
MOVW R0, 4(R13) MOVW R0, 4(R13)
MOVW R1, 8(R13) MOVW R1, 8(R13)
MOVW $0, R0 MOVW $0, R0
......
...@@ -104,15 +104,12 @@ TEXT runtime·lwp_tramp(SB),NOSPLIT,$0 ...@@ -104,15 +104,12 @@ TEXT runtime·lwp_tramp(SB),NOSPLIT,$0
TEXT runtime·usleep(SB),NOSPLIT,$16 TEXT runtime·usleep(SB),NOSPLIT,$16
MOVW usec+0(FP), R0 MOVW usec+0(FP), R0
MOVW R0, R2 CALL runtime·usplitR0(SB)
MOVW $1000000, R1
DIV R1, R0
// 0(R13) is the saved LR, don't use it // 0(R13) is the saved LR, don't use it
MOVW R0, 4(R13) // tv_sec.low MOVW R0, 4(R13) // tv_sec.low
MOVW $0, R0 MOVW $0, R0
MOVW R0, 8(R13) // tv_sec.high MOVW R0, 8(R13) // tv_sec.high
MOD R1, R2 MOVW $1000, R2
MOVW $1000, R1
MUL R1, R2 MUL R1, R2
MOVW R2, 12(R13) // tv_nsec MOVW R2, 12(R13) // tv_nsec
......
...@@ -70,14 +70,11 @@ TEXT runtime·write(SB),NOSPLIT,$-4 ...@@ -70,14 +70,11 @@ TEXT runtime·write(SB),NOSPLIT,$-4
TEXT runtime·usleep(SB),NOSPLIT,$16 TEXT runtime·usleep(SB),NOSPLIT,$16
MOVW usec+0(FP), R0 MOVW usec+0(FP), R0
MOVW R0, R2 CALL runtime·usplitR0(SB)
MOVW $1000000, R1
DIV R1, R0
MOVW R0, 4(R13) // tv_sec - l32 MOVW R0, 4(R13) // tv_sec - l32
MOVW $0, R0 MOVW $0, R0
MOVW R0, 8(R13) // tv_sec - h32 MOVW R0, 8(R13) // tv_sec - h32
MOD R1, R2 MOVW $1000, R2
MOVW $1000, R1
MUL R1, R2 MUL R1, R2
MOVW R2, 12(R13) // tv_nsec MOVW R2, 12(R13) // tv_nsec
......
...@@ -4,7 +4,10 @@ ...@@ -4,7 +4,10 @@
package runtime_test package runtime_test
import "testing" import (
"runtime"
"testing"
)
// arm soft division benchmarks adapted from // arm soft division benchmarks adapted from
// http://ridiculousfish.com/files/division_benchmarks.tar.gz // http://ridiculousfish.com/files/division_benchmarks.tar.gz
...@@ -68,3 +71,14 @@ func BenchmarkUint32Mod13307(b *testing.B) { bmUint32Mod(13307, b) } ...@@ -68,3 +71,14 @@ func BenchmarkUint32Mod13307(b *testing.B) { bmUint32Mod(13307, b) }
func BenchmarkUint32Mod52513(b *testing.B) { bmUint32Mod(52513, b) } func BenchmarkUint32Mod52513(b *testing.B) { bmUint32Mod(52513, b) }
func BenchmarkUint32Mod60978747(b *testing.B) { bmUint32Mod(60978747, b) } func BenchmarkUint32Mod60978747(b *testing.B) { bmUint32Mod(60978747, b) }
func BenchmarkUint32Mod106956295(b *testing.B) { bmUint32Mod(106956295, 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)
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment