xref: /netbsd-src/external/gpl3/gcc/dist/libgcc/config/rl78/divmodhi.S (revision 4d5abbe83f525258eb479e5fca29f25cb943f379)
1/* HImode div/mod functions for the GCC support library for the Renesas RL78 processors.
2   Copyright (C) 2012-2015 Free Software Foundation, Inc.
3   Contributed by Red Hat.
4
5   This file is part of GCC.
6
7   GCC is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 3, or (at your option)
10   any later version.
11
12   GCC is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   Under Section 7 of GPL version 3, you are granted additional
18   permissions described in the GCC Runtime Library Exception, version
19   3.1, as published by the Free Software Foundation.
20
21   You should have received a copy of the GNU General Public License and
22   a copy of the GCC Runtime Library Exception along with this program;
23   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24   <http://www.gnu.org/licenses/>.  */
25
26#include "vregs.h"
27
28.macro MAKE_GENERIC  which,need_result
29
30	.if \need_result
31	quot = r8
32	num = r10
33	den = r12
34	bit = r14
35	.else
36	num = r8
37	quot = r10
38	den = r12
39	bit = r14
40	.endif
41
42	quotB0 = quot
43	quotB1 = quot+1
44
45	numB0 = num
46	numB1 = num+1
47
48	denB0 = den
49	denB1 = den+1
50
51	bitB0 = bit
52	bitB1 = bit+1
53
54#define bit	bc
55#define bitB0	c
56#define bitB1	b
57
58	START_FUNC __generic_hidivmod\which
59
60num_lt_den\which:
61	.if \need_result
62	movw	r8, #0
63	.else
64	movw	ax, [sp+8]
65	movw	r8, ax
66	.endif
67	ret
68
69	;; These routines leave DE alone - the signed functions use DE
70	;; to store sign information that must remain intact
71
72	.if \need_result
73	.global __generic_hidiv
74__generic_hidiv:
75
76	.else
77
78	.global __generic_himod
79__generic_himod:
80
81	.endif
82
83	;; (quot,rem) = 8[sp] /% 10[sp]
84
85	movw	hl, sp
86	movw	ax, [hl+10] ; denH
87	cmpw	ax, [hl+8] ; numH
88	bh	$num_lt_den\which
89
90	;; (quot,rem) = 16[sp] /% 20[sp]
91
92	;; copy numerator
93	movw	ax, [hl+8]
94	movw	num, ax
95
96	;; copy denomonator
97	movw	ax, [hl+10]
98	movw	den, ax
99
100	movw	ax, den
101	cmpw	ax, #0
102	bnz	$den_not_zero\which
103	movw	num, #0
104	ret
105
106den_not_zero\which:
107	.if \need_result
108	;; zero out quot
109	movw	quot, #0
110	.endif
111
112	;; initialize bit to 1
113	movw	bit, #1
114
115; while (den < num && !(den & (1L << BITS_MINUS_1)))
116
117shift_den_bit\which:
118	movw	ax, den
119	mov1	cy,a.7
120	bc	$enter_main_loop\which
121	cmpw	ax, num
122	bh	$enter_main_loop\which
123
124	;; den <<= 1
125;	movw	ax, den		; already has it from the cmpw above
126	shlw	ax, 1
127	movw	den, ax
128
129	;; bit <<= 1
130	.if \need_result
131#ifdef bit
132	shlw	bit, 1
133#else
134	movw	ax, bit
135	shlw	ax, 1
136	movw	bit, ax
137#endif
138	.else
139	;; if we don't need to compute the quotent, we don't need an
140	;; actual bit *mask*, we just need to keep track of which bit
141	inc	bitB0
142	.endif
143
144	br	$shift_den_bit\which
145
146main_loop\which:
147
148	;; if (num >= den) (cmp den > num)
149	movw	ax, den
150	cmpw	ax, num
151	bh	$next_loop\which
152
153	;; num -= den
154	movw	ax, num
155	subw	ax, den
156	movw	num, ax
157
158	.if \need_result
159	;; res |= bit
160	mov	a, quotB0
161	or	a, bitB0
162	mov	quotB0, a
163	mov	a, quotB1
164	or	a, bitB1
165	mov	quotB1, a
166	.endif
167
168next_loop\which:
169
170	;; den >>= 1
171	movw	ax, den
172	shrw	ax, 1
173	movw	den, ax
174
175	.if \need_result
176	;; bit >>= 1
177	movw	ax, bit
178	shrw	ax, 1
179	movw	bit, ax
180	.else
181	dec	bitB0
182	.endif
183
184enter_main_loop\which:
185	.if \need_result
186	movw	ax, bit
187	cmpw	ax, #0
188	.else
189	cmp0	bitB0
190	.endif
191	bnz	$main_loop\which
192
193main_loop_done\which:
194	ret
195	END_FUNC __generic_hidivmod\which
196.endm
197;----------------------------------------------------------------------
198
199	MAKE_GENERIC _d 1
200	MAKE_GENERIC _m 0
201
202;----------------------------------------------------------------------
203
204START_FUNC ___udivhi3
205	;; r8 = 4[sp] / 6[sp]
206	call	$!__generic_hidiv
207	ret
208END_FUNC ___udivhi3
209
210
211START_FUNC ___umodhi3
212	;; r8 = 4[sp] % 6[sp]
213	call	$!__generic_himod
214	ret
215END_FUNC ___umodhi3
216
217;----------------------------------------------------------------------
218
219.macro NEG_AX
220	movw	hl, ax
221	movw	ax, #0
222	subw	ax, [hl]
223	movw	[hl], ax
224.endm
225
226;----------------------------------------------------------------------
227
228START_FUNC ___divhi3
229	;; r8 = 4[sp] / 6[sp]
230	movw	de, #0
231	mov	a, [sp+5]
232	mov1	cy, a.7
233	bc	$div_signed_num
234	mov	a, [sp+7]
235	mov1	cy, a.7
236	bc	$div_signed_den
237	call	$!__generic_hidiv
238	ret
239
240div_signed_num:
241	;; neg [sp+4]
242	movw	ax, sp
243	addw	ax, #4
244	NEG_AX
245	mov	d, #1
246	mov	a, [sp+7]
247	mov1	cy, a.7
248	bnc	$div_unsigned_den
249div_signed_den:
250	;; neg [sp+6]
251	movw	ax, sp
252	addw	ax, #6
253	NEG_AX
254	mov	e, #1
255div_unsigned_den:
256	call	$!__generic_hidiv
257
258	mov	a, d
259	cmp0	a
260	bz	$div_skip_restore_num
261	;;  We have to restore the numerator [sp+4]
262	movw	ax, sp
263	addw	ax, #4
264	NEG_AX
265	mov	a, d
266div_skip_restore_num:
267	xor	a, e
268	bz	$div_no_neg
269	movw	ax, #r8
270	NEG_AX
271div_no_neg:
272	mov	a, e
273	cmp0	a
274	bz	$div_skip_restore_den
275	movw	ax, sp
276	addw	ax, #6
277	NEG_AX
278div_skip_restore_den:
279	ret
280END_FUNC ___divhi3
281
282
283START_FUNC ___modhi3
284	;; r8 = 4[sp] % 6[sp]
285	movw	de, #0
286	mov	a, [sp+5]
287	mov1	cy, a.7
288	bc	$mod_signed_num
289	mov	a, [sp+7]
290	mov1	cy, a.7
291	bc	$mod_signed_den
292	call	$!__generic_himod
293	ret
294
295mod_signed_num:
296	;; neg [sp+4]
297	movw	ax, sp
298	addw	ax, #4
299	NEG_AX
300	mov	d, #1
301	mov	a, [sp+7]
302	mov1	cy, a.7
303	bnc	$mod_unsigned_den
304mod_signed_den:
305	;; neg [sp+6]
306	movw	ax, sp
307	addw	ax, #6
308	NEG_AX
309mod_unsigned_den:
310	call	$!__generic_himod
311
312	mov	a, d
313	cmp0	a
314	bz	$mod_no_neg
315	movw	ax, #r8
316	NEG_AX
317	;;  Also restore numerator
318	movw 	ax, sp
319	addw	ax, #4
320	NEG_AX
321mod_no_neg:
322	mov	a, e
323	cmp0	a
324	bz	$mod_skip_restore_den
325	movw	ax, sp
326	addw	ax, #6
327	NEG_AX
328mod_skip_restore_den:
329	ret
330END_FUNC ___modhi3
331