1/* SPDX-License-Identifier: GPL-2.0 */
2#include "libgcc.h"
3
4	;; This function also computes the remainder and stores it in er3.
5	.global	__udivsi3
6__udivsi3:
7	mov.w	A1E,A1E		; denominator top word 0?
8	bne	DenHighNonZero
9
10	; do it the easy way, see page 107 in manual
11	mov.w	A0E,A2
12	extu.l	A2P
13	divxu.w	A1,A2P
14	mov.w	A2E,A0E
15	divxu.w	A1,A0P
16	mov.w	A0E,A3
17	mov.w	A2,A0E
18	extu.l	A3P
19	rts
20
21	; er0 = er0 / er1
22	; er3 = er0 % er1
23	; trashes er1 er2
24	; expects er1 >= 2^16
25DenHighNonZero:
26	mov.l	er0,er3
27	mov.l	er1,er2
28#ifdef CONFIG_CPU_H8300H
29divmod_L21:
30	shlr.l	er0
31	shlr.l	er2		; make divisor < 2^16
32	mov.w	e2,e2
33	bne	divmod_L21
34#else
35	shlr.l	#2,er2		; make divisor < 2^16
36	mov.w	e2,e2
37	beq	divmod_L22A
38divmod_L21:
39	shlr.l	#2,er0
40divmod_L22:
41	shlr.l	#2,er2		; make divisor < 2^16
42	mov.w	e2,e2
43	bne	divmod_L21
44divmod_L22A:
45	rotxl.w	r2
46	bcs	divmod_L23
47	shlr.l	er0
48	bra	divmod_L24
49divmod_L23:
50	rotxr.w	r2
51	shlr.l	#2,er0
52divmod_L24:
53#endif
54	;; At this point,
55	;;  er0 contains shifted dividend
56	;;  er1 contains divisor
57	;;  er2 contains shifted divisor
58	;;  er3 contains dividend, later remainder
59	divxu.w	r2,er0		; r0 now contains the approximate quotient (AQ)
60	extu.l	er0
61	beq	divmod_L25
62	subs	#1,er0		; er0 = AQ - 1
63	mov.w	e1,r2
64	mulxu.w	r0,er2		; er2 = upper (AQ - 1) * divisor
65	sub.w	r2,e3		; dividend - 65536 * er2
66	mov.w	r1,r2
67	mulxu.w	r0,er2		; compute er3 = remainder (tentative)
68	sub.l	er2,er3		; er3 = dividend - (AQ - 1) * divisor
69divmod_L25:
70	cmp.l	er1,er3		; is divisor < remainder?
71	blo	divmod_L26
72	adds	#1,er0
73	sub.l	er1,er3		; correct the remainder
74divmod_L26:
75	rts
76
77	.end
78