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
25 DenHighNonZero:
26 	mov.l	er0,er3
27 	mov.l	er1,er2
28 #ifdef CONFIG_CPU_H8300H
29 divmod_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
38 divmod_L21:
39 	shlr.l	#2,er0
40 divmod_L22:
41 	shlr.l	#2,er2		; make divisor < 2^16
42 	mov.w	e2,e2
43 	bne	divmod_L21
44 divmod_L22A:
45 	rotxl.w	r2
46 	bcs	divmod_L23
47 	shlr.l	er0
48 	bra	divmod_L24
49 divmod_L23:
50 	rotxr.w	r2
51 	shlr.l	#2,er0
52 divmod_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
69 divmod_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
74 divmod_L26:
75 	rts
76 
77 	.end
78