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
--- /dev/null
+// 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
print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n")
throw("runtime: misuse of rewindmorestack")
}
+
+// for testing
+func usplit(x uint32) (q, r uint32)
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)
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
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
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
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
package runtime_test
-import "testing"
+import (
+ "runtime"
+ "testing"
+)
// arm soft division benchmarks adapted from
// http://ridiculousfish.com/files/division_benchmarks.tar.gz
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)
+ }
+ }
+}