2 * Copyright 2010, Google Inc.
4 * Brought in from coreboot uldivmod.S
6 * SPDX-License-Identifier: GPL-2.0
9 #include <linux/linkage.h>
10 #include <asm/assembler.h>
12 /* We don't use Thumb instructions for now */
17 * A, Q = r0 + (r1 << 32)
18 * B, R = r2 + (r3 << 32)
40 ENTRY(__aeabi_uldivmod)
41 stmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) lr}
43 orrs ip, B_0, B_1 @ Z set -> B == 0
45 @ Test if B is power of 2: (B & (B - 1)) == 0
51 @ Test if A_1 == B_1 == 0
56 /* CLZ only exists in ARM architecture version 5 and above. */
70 @ if clz B - clz A > 0
73 @ B <<= (clz B - clz A)
76 movmi B_1, B_1, lsl D_0
77 ARM( orrmi B_1, B_1, B_0, lsr ip )
78 THUMB( lsrmi TMP, B_0, ip )
79 THUMB( orrmi B_1, B_1, TMP )
80 movpl B_1, B_0, lsl D_1
82 @ C = 1 << (clz B - clz A)
83 movmi C_1, C_1, lsl D_0
84 ARM( orrmi C_1, C_1, C_0, lsr ip )
85 THUMB( lsrmi TMP, C_0, ip )
86 THUMB( orrmi C_1, C_1, TMP )
87 movpl C_1, C_0, lsl D_1
92 @ C: current bit; D: result
94 @ C: current bit; D: result
106 orr B_1, B_1, B_0, lsr #28
110 orr C_1, C_1, C_0, lsr #28
120 orr B_1, B_1, B_0, lsr #31
124 orr C_1, C_1, C_0, lsr #31
144 movs C_1, C_1, lsr #1
150 movs B_1, B_1, lsr #1
154 @ Note: A, B & Q, R are aliases
159 ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc}
162 @ Note: A_0 & r0 are aliases
169 ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc}
173 @ Note: A, B and Q, R are aliases
178 @ Note: B must not be 0 here!
185 mov A_0, A_1, lsr D_0
188 movpl A_0, A_0, lsr D_0
189 ARM( orrpl A_0, A_0, A_1, lsl D_1 )
190 THUMB( lslpl TMP, A_1, D_1 )
191 THUMB( orrpl A_0, A_0, TMP )
192 mov A_1, A_1, lsr D_0
196 ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc}
198 @ Note: A, B and Q, R are aliases
203 @ Note: B must not be 0 here!
204 @ Count the leading zeroes in B.
207 @ If B is greater than 1 << 31, divide A and B by 1 << 32.
211 @ Count the remaining leading zeroes in B.
212 movs B_1, B_0, lsl #16
214 moveq B_0, B_0, lsr #16
217 moveq B_0, B_0, lsr #8
220 moveq B_0, B_0, lsr #4
223 moveq B_0, B_0, lsr #2
226 @ Shift A to the right by the appropriate amount.
228 mov Q_0, A_0, lsr D_0
229 orr Q_0, A_1, lsl D_1
230 mov Q_1, A_1, lsr D_0
234 ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc}
239 @ As wrong as it could be
244 ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc}
245 ENDPROC(__aeabi_uldivmod)