Skip to content

Commit c9d2c7f

Browse files
committed
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/12898 Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent a1e4220 commit c9d2c7f

9 files changed

+56
-24
lines changed

src/runtime/asm_arm.s

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,3 +1029,24 @@ TEXT runtime·prefetcht2(SB),NOSPLIT,$0-4
10291029

10301030
TEXT runtime·prefetchnta(SB),NOSPLIT,$0-4
10311031
RET
1032+
1033+
// x -> x/1000000, x%1000000, called from Go with args, results on stack.
1034+
TEXT runtime·usplit(SB),NOSPLIT,$0-12
1035+
MOVW x+0(FP), R0
1036+
CALL runtime·usplitR0(SB)
1037+
MOVW R0, q+4(FP)
1038+
MOVW R1, r+8(FP)
1039+
RET
1040+
1041+
// R0, R1 = R0/1000000, R0%1000000
1042+
TEXT runtime·usplitR0(SB),NOSPLIT,$0
1043+
// magic multiply to avoid software divide without available m.
1044+
// see output of go tool compile -S for x/1000000.
1045+
MOVW R0, R3
1046+
MOVW $1125899907, R1
1047+
MULLU R1, R0, (R0, R1)
1048+
MOVW R0>>18, R0
1049+
MOVW $1000000, R1
1050+
MULU R0, R1
1051+
SUB R1, R3, R1
1052+
RET

src/runtime/export_arm_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright 2015 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Export guts for testing.
6+
7+
package runtime
8+
9+
var Usplit = usplit

src/runtime/sys_arm.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,6 @@ func rewindmorestack(buf *gobuf) {
3333
print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n")
3434
throw("runtime: misuse of rewindmorestack")
3535
}
36+
37+
// for testing
38+
func usplit(x uint32) (q, r uint32)

src/runtime/sys_darwin_arm.s

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,10 +283,7 @@ TEXT runtime·sigaction(SB),NOSPLIT,$0
283283

284284
TEXT runtime·usleep(SB),NOSPLIT,$12
285285
MOVW usec+0(FP), R0
286-
MOVW R0, R1
287-
MOVW $1000000, R2
288-
DIV R2, R0
289-
MOD R2, R1
286+
CALL runtime·usplitR0(SB)
290287
MOVW R0, a-12(SP)
291288
MOVW R1, b-8(SP)
292289

src/runtime/sys_freebsd_arm.s

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -302,15 +302,12 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
302302

303303
TEXT runtime·usleep(SB),NOSPLIT,$16
304304
MOVW usec+0(FP), R0
305-
MOVW R0, R2
306-
MOVW $1000000, R1
307-
DIV R1, R0
305+
CALL runtime·usplitR0(SB)
308306
// 0(R13) is the saved LR, don't use it
309307
MOVW R0, 4(R13) // tv_sec.low
310308
MOVW $0, R0
311309
MOVW R0, 8(R13) // tv_sec.high
312-
MOD R1, R2
313-
MOVW $1000, R1
310+
MOVW $1000, R2
314311
MUL R1, R2
315312
MOVW R2, 12(R13) // tv_nsec
316313

src/runtime/sys_linux_arm.s

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -378,10 +378,7 @@ TEXT runtime·rt_sigaction(SB),NOSPLIT,$0
378378

379379
TEXT runtime·usleep(SB),NOSPLIT,$12
380380
MOVW usec+0(FP), R0
381-
MOVW R0, R1
382-
MOVW $1000000, R2
383-
DIV R2, R0
384-
MOD R2, R1
381+
CALL runtime·usplitR0(SB)
385382
MOVW R0, 4(R13)
386383
MOVW R1, 8(R13)
387384
MOVW $0, R0

src/runtime/sys_netbsd_arm.s

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,12 @@ TEXT runtime·lwp_tramp(SB),NOSPLIT,$0
104104

105105
TEXT runtime·usleep(SB),NOSPLIT,$16
106106
MOVW usec+0(FP), R0
107-
MOVW R0, R2
108-
MOVW $1000000, R1
109-
DIV R1, R0
107+
CALL runtime·usplitR0(SB)
110108
// 0(R13) is the saved LR, don't use it
111109
MOVW R0, 4(R13) // tv_sec.low
112110
MOVW $0, R0
113111
MOVW R0, 8(R13) // tv_sec.high
114-
MOD R1, R2
115-
MOVW $1000, R1
112+
MOVW $1000, R2
116113
MUL R1, R2
117114
MOVW R2, 12(R13) // tv_nsec
118115

src/runtime/sys_openbsd_arm.s

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,11 @@ TEXT runtime·write(SB),NOSPLIT,$-4
7070

7171
TEXT runtime·usleep(SB),NOSPLIT,$16
7272
MOVW usec+0(FP), R0
73-
MOVW R0, R2
74-
MOVW $1000000, R1
75-
DIV R1, R0
73+
CALL runtime·usplitR0(SB)
7674
MOVW R0, 4(R13) // tv_sec - l32
7775
MOVW $0, R0
7876
MOVW R0, 8(R13) // tv_sec - h32
79-
MOD R1, R2
80-
MOVW $1000, R1
77+
MOVW $1000, R2
8178
MUL R1, R2
8279
MOVW R2, 12(R13) // tv_nsec
8380

src/runtime/vlop_arm_test.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
package runtime_test
66

7-
import "testing"
7+
import (
8+
"runtime"
9+
"testing"
10+
)
811

912
// arm soft division benchmarks adapted from
1013
// http://ridiculousfish.com/files/division_benchmarks.tar.gz
@@ -68,3 +71,14 @@ func BenchmarkUint32Mod13307(b *testing.B) { bmUint32Mod(13307, b) }
6871
func BenchmarkUint32Mod52513(b *testing.B) { bmUint32Mod(52513, b) }
6972
func BenchmarkUint32Mod60978747(b *testing.B) { bmUint32Mod(60978747, b) }
7073
func BenchmarkUint32Mod106956295(b *testing.B) { bmUint32Mod(106956295, b) }
74+
75+
func TestUsplit(t *testing.T) {
76+
var den uint32 = 1000000
77+
for _, x := range []uint32{0, 1, 999999, 1000000, 1010101, 0xFFFFFFFF} {
78+
q1, r1 := runtime.Usplit(x)
79+
q2, r2 := x/den, x%den
80+
if q1 != q2 || r1 != r2 {
81+
t.Errorf("%d/1e6, %d%%1e6 = %d, %d, want %d, %d", x, x, q1, r1, q2, r2)
82+
}
83+
}
84+
}

0 commit comments

Comments
 (0)