xref: /aosp_15_r20/external/coreboot/src/arch/arm/libgcc/ldivmod.S (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1/* SPDX-License-Identifier: ISC OR GPL-2.0-only */
2
3/*
4 * ldivmod.S: signed 64 bit division (quotient and remainder)
5 *
6 * Taken from CrOS EC: third_party/libaeabi-cortexm0/core/cortex-m0/ldivmod.S
7 */
8
9#include <arch/asm.h>
10
11
12@ {long long quotient, long long remainder}
13@ __aeabi_ldivmod(long long numerator, long long denominator)
14@
15@ Divide r1:r0 by r3:r2 and return the quotient in r1:r0 and the remainder in
16@ r3:r2 (all signed)
17@
18
19ENTRY(__aeabi_ldivmod)
20
21	cmp	r1, #0
22	bge	L_num_pos
23
24	push	{r4, lr}
25	movs	r4, #0			@ num = -num
26	rsbs	r0, r0, #0
27	sbcs	r4, r1
28	mov	r1, r4
29
30	cmp	r3, #0
31	bge	L_neg_both
32
33	movs	r4, #0			@ den = -den
34	rsbs	r2, r2, #0
35	sbcs	r4, r3
36	mov	r3, r4
37	bl	__aeabi_uldivmod
38	movs	r4, #0			@ rem = -rem
39	rsbs	r2, r2, #0
40	sbcs	r4, r3
41	mov	r3, r4
42	pop	{r4, pc}
43
44L_neg_both:
45	bl	__aeabi_uldivmod
46	movs	r4, #0			@ quot = -quot
47	rsbs	r0, r0, #0
48	sbcs	r4, r1
49	mov	r1, r4
50	movs	r4, #0			@ rem = -rem
51	rsbs	r2, r2, #0
52	sbcs	r4, r3
53	mov	r3, r4
54	pop	{r4, pc}
55
56L_num_pos:
57	cmp	r3, #0
58	blt	L_den_neg
59	push	{r4, lr}
60	bl	__aeabi_uldivmod	@ offset too big for b / bge
61	pop	{r4, pc}
62
63L_den_neg:
64	push	{r4, lr}
65	movs	r4, #0			@ den = -den
66	rsbs	r2, r2, #0
67	sbcs	r4, r3
68	mov	r3, r4
69	bl	__aeabi_uldivmod
70	movs	r4, #0			@ quot = -quot
71	rsbs	r0, r0, #0
72	sbcs	r4, r1
73	mov	r1, r4
74	pop	{r4, pc}
75