Skip to content

Commit d993ecc

Browse files
committed
Improved timesplit arm64 assembly without UDIV
1 parent 1a4f82c commit d993ecc

File tree

1 file changed

+33
-18
lines changed

1 file changed

+33
-18
lines changed

src/runtime/sys_plan9_arm64.s

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -143,23 +143,39 @@ TEXT runtime·plan9_tsemacquire(SB),NOSPLIT,$0-20
143143
RET
144144

145145
// func timesplit(u uint64) (sec int64, nsec int32)
146-
TEXT runtime·timesplit(SB),NOSPLIT,$0-16
147-
// load u (nanoseconds)
148-
MOVD u+0(FP), R0
149-
150-
// compute sec = u / 1e9
151-
MOVD R0, R1
152-
MOVD $1000000000, R2
153-
UDIV R2, R1 // R1 = R1 / R2 -> seconds
154-
155-
// compute rem = u - sec * 1e9
156-
MOVD R1, R3
157-
MUL R3, R2 // R2 = sec * 1e9
158-
SUB R2, R0 // R0 = u - (sec*1e9) -> remainder (nsec)
159-
160-
// store results
161-
MOVD R1, sec+0(FP)
162-
MOVWU R0, nsec+8(FP)
146+
TEXT runtime·timesplit(SB), NOSPLIT, $0
147+
// R1 = u (nanoseconds)
148+
MOVD u+0(FP), R1
149+
150+
// --- reciprocal multiply to get seconds ---
151+
MOVW $0x89705f41, R2 // reciprocal constant ≈ 2^61 / 1e9
152+
UMULH R1, R2, R3 // high 64 bits of (u * constant)
153+
LSR $29, R3, R4 // R4 = seconds (int64)
154+
155+
// --- compute remainder = u - sec*1e9 ---
156+
MOVD $1000000000, R5
157+
MUL R4, R5, R6
158+
SUB R6, R1, R1 // R1 = remainder
159+
160+
// --- branchless correction ---
161+
// if remainder >= 1e9:
162+
// remainder -= 1e9
163+
// sec += 1
164+
165+
SUB R5, R1, R7 // R7 = remainder - 1e9
166+
LSR $63, R7, R8 // R8 = 1 if remainder < 1e9, else 0
167+
EOR $1, R8 // invert: R8 = 1 if remainder >= 1e9, else 0
168+
169+
// remainder -= R8 * 1e9
170+
NEG R8, R9 // R9 = -R8 (0 or -1)
171+
MADD R9, R5, R1, R1 // R1 = R1 + R9*R5 → subtract 1e9 if flag=1
172+
173+
// sec += R8
174+
ADD R8, R4, R4
175+
176+
// --- store results ---
177+
MOVD R4, sec+0(FP)
178+
MOVW R1, nsec+8(FP)
163179
RET
164180

165181
//func nsec(*int64) int64
@@ -172,7 +188,6 @@ TEXT runtime·nsec(SB),NOSPLIT|NOFRAME,$0-16
172188
// func walltime() (sec int64, nsec int32)
173189
TEXT runtime·walltime(SB),NOSPLIT,$16-12
174190
// use nsec system call to get current time in nanoseconds
175-
176191
MOVD $SYS_NSEC, R0
177192
SVC $0
178193

0 commit comments

Comments
 (0)