xref: /inferno-os/libkern/div-arm.s (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1Q	= 0
2N	= 1
3D	= 2
4CC	= 3
5TMP	= 11
6
7TEXT	save<>(SB), 1, $0
8	MOVW	R(Q), 0(FP)
9	MOVW	R(N), 4(FP)
10	MOVW	R(D), 8(FP)
11	MOVW	R(CC), 12(FP)
12
13	MOVW	R(TMP), R(Q)		/* numerator */
14	MOVW	20(FP), R(D)		/* denominator */
15	CMP	$0, R(D)
16	BNE	s1
17	SWI		0
18/*	MOVW	-1(R(D)), R(TMP)	/* divide by zero fault */
19s1:	RET
20
21TEXT	rest<>(SB), 1, $0
22	MOVW	0(FP), R(Q)
23	MOVW	4(FP), R(N)
24	MOVW	8(FP), R(D)
25	MOVW	12(FP), R(CC)
26/*
27 * return to caller
28 * of rest<>
29 */
30	MOVW	0(R13), R14
31	ADD	$20, R13
32	B	(R14)
33
34TEXT	div<>(SB), 1, $0
35	MOVW	$32, R(CC)
36/*
37 * skip zeros 8-at-a-time
38 */
39e1:
40	AND.S	$(0xff<<24),R(Q), R(N)
41	BNE	e2
42	SLL	$8, R(Q)
43	SUB.S	$8, R(CC)
44	BNE	e1
45	RET
46e2:
47	MOVW	$0, R(N)
48
49loop:
50/*
51 * shift R(N||Q) left one
52 */
53	SLL	$1, R(N)
54	CMP	$0, R(Q)
55	ORR.LT	$1, R(N)
56	SLL	$1, R(Q)
57
58/*
59 * compare numerator to denominator
60 * if less, subtract and set quotent bit
61 */
62	CMP	R(D), R(N)
63	ORR.HS	$1, R(Q)
64	SUB.HS	R(D), R(N)
65	SUB.S	$1, R(CC)
66	BNE	loop
67	RET
68
69TEXT	_div(SB), 1, $16
70	BL	save<>(SB)
71	CMP	$0, R(Q)
72	BGE	d1
73	RSB	$0, R(Q), R(Q)
74	CMP	$0, R(D)
75	BGE	d2
76	RSB	$0, R(D), R(D)
77d0:
78	BL	div<>(SB)		/* none/both neg */
79	MOVW	R(Q), R(TMP)
80	B	out
81d1:
82	CMP	$0, R(D)
83	BGE	d0
84	RSB	$0, R(D), R(D)
85d2:
86	BL	div<>(SB)		/* one neg */
87	RSB	$0, R(Q), R(TMP)
88	B	out
89
90TEXT	_mod(SB), 1, $16
91	BL	save<>(SB)
92	CMP	$0, R(D)
93	RSB.LT	$0, R(D), R(D)
94	CMP	$0, R(Q)
95	BGE	m1
96	RSB	$0, R(Q), R(Q)
97	BL	div<>(SB)		/* neg numerator */
98	RSB	$0, R(N), R(TMP)
99	B	out
100m1:
101	BL	div<>(SB)		/* pos numerator */
102	MOVW	R(N), R(TMP)
103	B	out
104
105TEXT	_divu(SB), 1, $16
106	BL	save<>(SB)
107	BL	div<>(SB)
108	MOVW	R(Q), R(TMP)
109	B	out
110
111TEXT	_modu(SB), 1, $16
112	BL	save<>(SB)
113	BL	div<>(SB)
114	MOVW	R(N), R(TMP)
115	B	out
116
117out:
118	BL	rest<>(SB)
119	B	out
120