divmodhi.S revision 1.7 1 1.1 mrg /* HImode div/mod functions for the GCC support library for the Renesas RL78 processors.
2 1.7 mrg Copyright (C) 2012-2022 Free Software Foundation, Inc.
3 1.1 mrg Contributed by Red Hat.
4 1.1 mrg
5 1.1 mrg This file is part of GCC.
6 1.1 mrg
7 1.1 mrg GCC is free software; you can redistribute it and/or modify
8 1.1 mrg it under the terms of the GNU General Public License as published by
9 1.1 mrg the Free Software Foundation; either version 3, or (at your option)
10 1.1 mrg any later version.
11 1.1 mrg
12 1.1 mrg GCC is distributed in the hope that it will be useful,
13 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 mrg GNU General Public License for more details.
16 1.1 mrg
17 1.1 mrg Under Section 7 of GPL version 3, you are granted additional
18 1.1 mrg permissions described in the GCC Runtime Library Exception, version
19 1.1 mrg 3.1, as published by the Free Software Foundation.
20 1.1 mrg
21 1.1 mrg You should have received a copy of the GNU General Public License and
22 1.1 mrg a copy of the GCC Runtime Library Exception along with this program;
23 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 1.1 mrg <http://www.gnu.org/licenses/>. */
25 1.1 mrg
26 1.1 mrg #include "vregs.h"
27 1.1 mrg
28 1.3 mrg #if defined __RL78_MUL_G14__
29 1.3 mrg
30 1.3 mrg START_FUNC ___divhi3
31 1.3 mrg ;; r8 = 4[sp] / 6[sp]
32 1.3 mrg
33 1.3 mrg ;; Test for a negative denumerator.
34 1.3 mrg movw ax, [sp+6]
35 1.3 mrg mov1 cy, a.7
36 1.3 mrg movw de, ax
37 1.3 mrg bc $__div_neg_den
38 1.3 mrg
39 1.3 mrg ;; Test for a negative numerator.
40 1.3 mrg movw ax, [sp+4]
41 1.3 mrg mov1 cy, a.7
42 1.3 mrg bc $__div_neg_num
43 1.3 mrg
44 1.3 mrg ;; Neither are negative - we can use the unsigned divide instruction.
45 1.3 mrg __div_no_convert:
46 1.3 mrg push psw
47 1.3 mrg di
48 1.3 mrg divhu
49 1.3 mrg pop psw
50 1.3 mrg
51 1.3 mrg movw r8, ax
52 1.3 mrg ret
53 1.3 mrg
54 1.3 mrg __div_neg_den:
55 1.3 mrg ;; Negate the denumerator (which is in DE)
56 1.3 mrg clrw ax
57 1.3 mrg subw ax, de
58 1.3 mrg movw de, ax
59 1.3 mrg
60 1.3 mrg ;; Test for a negative numerator.
61 1.3 mrg movw ax, [sp+4]
62 1.3 mrg mov1 cy, a.7
63 1.3 mrg ;; If it is not negative then we perform the division and then negate the result.
64 1.3 mrg bnc $__div_then_convert
65 1.3 mrg
66 1.3 mrg ;; Otherwise we negate the numerator and then go with an unsigned division.
67 1.3 mrg movw bc, ax
68 1.3 mrg clrw ax
69 1.3 mrg subw ax, bc
70 1.3 mrg br $__div_no_convert
71 1.3 mrg
72 1.3 mrg __div_neg_num:
73 1.3 mrg ;; Negate the numerator (which is in AX)
74 1.3 mrg ;; We know that the denumerator is positive.
75 1.3 mrg movw bc, ax
76 1.3 mrg clrw ax
77 1.3 mrg subw ax, bc
78 1.3 mrg
79 1.3 mrg __div_then_convert:
80 1.3 mrg push psw
81 1.3 mrg di
82 1.3 mrg divhu
83 1.3 mrg pop psw
84 1.3 mrg
85 1.3 mrg ;; Negate result and transfer into r8
86 1.3 mrg movw bc, ax
87 1.3 mrg clrw ax
88 1.3 mrg subw ax, bc
89 1.3 mrg movw r8, ax
90 1.3 mrg ret
91 1.3 mrg
92 1.3 mrg END_FUNC ___divhi3
93 1.3 mrg
94 1.3 mrg ;----------------------------------------------------------------------
95 1.3 mrg
96 1.3 mrg START_FUNC ___modhi3
97 1.3 mrg ;; r8 = 4[sp] % 6[sp]
98 1.3 mrg
99 1.3 mrg ;; Test for a negative denumerator.
100 1.3 mrg movw ax, [sp+6]
101 1.3 mrg mov1 cy, a.7
102 1.3 mrg movw de, ax
103 1.3 mrg bc $__mod_neg_den
104 1.3 mrg
105 1.3 mrg ;; Test for a negative numerator.
106 1.3 mrg movw ax, [sp+4]
107 1.3 mrg mov1 cy, a.7
108 1.3 mrg bc $__mod_neg_num
109 1.3 mrg
110 1.3 mrg ;; Neither are negative - we can use the unsigned divide instruction.
111 1.3 mrg __mod_no_convert:
112 1.3 mrg push psw
113 1.3 mrg di
114 1.3 mrg divhu
115 1.3 mrg pop psw
116 1.3 mrg
117 1.3 mrg movw ax, de
118 1.3 mrg movw r8, ax
119 1.3 mrg ret
120 1.3 mrg
121 1.3 mrg __mod_neg_den:
122 1.3 mrg ;; Negate the denumerator (which is in DE)
123 1.3 mrg clrw ax
124 1.3 mrg subw ax, de
125 1.3 mrg movw de, ax
126 1.3 mrg
127 1.3 mrg ;; Test for a negative numerator.
128 1.3 mrg movw ax, [sp+4]
129 1.3 mrg mov1 cy, a.7
130 1.3 mrg ;; If it is not negative then we perform the modulo operation without conversion.
131 1.3 mrg bnc $__mod_no_convert
132 1.3 mrg
133 1.3 mrg ;; Otherwise we negate the numerator and then go with an unsigned modulo operation.
134 1.3 mrg movw bc, ax
135 1.3 mrg clrw ax
136 1.3 mrg subw ax, bc
137 1.3 mrg br $__mod_then_convert
138 1.3 mrg
139 1.3 mrg __mod_neg_num:
140 1.3 mrg ;; Negate the numerator (which is in AX)
141 1.3 mrg ;; We know that the denumerator is positive.
142 1.3 mrg movw bc, ax
143 1.3 mrg clrw ax
144 1.3 mrg subw ax, bc
145 1.3 mrg
146 1.3 mrg __mod_then_convert:
147 1.3 mrg push psw
148 1.3 mrg di
149 1.3 mrg divhu
150 1.3 mrg pop psw
151 1.3 mrg
152 1.3 mrg ;; Negate result and transfer into r8
153 1.3 mrg clrw ax
154 1.3 mrg subw ax, de
155 1.3 mrg movw r8, ax
156 1.3 mrg ret
157 1.3 mrg
158 1.3 mrg END_FUNC ___modhi3
159 1.3 mrg
160 1.3 mrg ;----------------------------------------------------------------------
161 1.3 mrg
162 1.3 mrg #elif defined __RL78_MUL_G13__
163 1.3 mrg
164 1.3 mrg ;; The G13 S2 core does not have a 16 bit divide peripheral.
165 1.3 mrg ;; So instead we perform a 32-bit divide and twiddle the inputs
166 1.3 mrg ;; as necessary.
167 1.3 mrg
168 1.3 mrg ;; Hardware registers. Note - these values match the silicon, not the documentation.
169 1.3 mrg MDAL = 0xffff0
170 1.3 mrg MDAH = 0xffff2
171 1.3 mrg MDBL = 0xffff6
172 1.3 mrg MDBH = 0xffff4
173 1.3 mrg MDCL = 0xf00e0
174 1.3 mrg MDCH = 0xf00e2
175 1.3 mrg MDUC = 0xf00e8
176 1.3 mrg
177 1.3 mrg .macro _Negate src, dest
178 1.3 mrg movw ax, !\src
179 1.3 mrg movw bc, ax
180 1.3 mrg clrw ax
181 1.3 mrg subw ax, bc
182 1.3 mrg movw \dest, ax
183 1.3 mrg .endm
184 1.3 mrg
185 1.3 mrg ;----------------------------------------------------------------------
186 1.3 mrg
187 1.3 mrg START_FUNC ___divhi3
188 1.3 mrg ;; r8 = 4[sp] / 6[sp] (signed division)
189 1.3 mrg
190 1.3 mrg mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1
191 1.3 mrg mov !MDUC, a ; This preps the peripheral for division without interrupt generation
192 1.3 mrg
193 1.3 mrg clrw ax ; Clear the top 16-bits of the divisor and dividend
194 1.3 mrg movw MDBH, ax
195 1.3 mrg movw MDAH, ax
196 1.3 mrg
197 1.3 mrg ;; Load and test for a negative denumerator.
198 1.3 mrg movw ax, [sp+6]
199 1.3 mrg movw MDBL, ax
200 1.3 mrg mov1 cy, a.7
201 1.3 mrg bc $__div_neg_den
202 1.3 mrg
203 1.3 mrg ;; Load and test for a negative numerator.
204 1.3 mrg movw ax, [sp+4]
205 1.3 mrg mov1 cy, a.7
206 1.3 mrg movw MDAL, ax
207 1.3 mrg bc $__div_neg_num
208 1.3 mrg
209 1.3 mrg ;; Neither are negative - we can use the unsigned divide hardware.
210 1.3 mrg __div_no_convert:
211 1.3 mrg mov a, #0xC1 ; Set the DIVST bit in MDUC
212 1.3 mrg mov !MDUC, a ; This starts the division op
213 1.3 mrg
214 1.3 mrg 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
215 1.3 mrg bt a.0, $1b
216 1.3 mrg
217 1.3 mrg movw ax, MDAL ; Read the result
218 1.3 mrg movw r8, ax
219 1.3 mrg ret
220 1.3 mrg
221 1.3 mrg __div_neg_den:
222 1.3 mrg ;; Negate the denumerator (which is in MDBL)
223 1.3 mrg _Negate MDBL MDBL
224 1.3 mrg
225 1.3 mrg ;; Load and test for a negative numerator.
226 1.3 mrg movw ax, [sp+4]
227 1.3 mrg mov1 cy, a.7
228 1.3 mrg movw MDAL, ax
229 1.3 mrg ;; If it is not negative then we perform the division and then negate the result.
230 1.3 mrg bnc $__div_then_convert
231 1.3 mrg
232 1.3 mrg ;; Otherwise we negate the numerator and then go with a straightforward unsigned division.
233 1.3 mrg _Negate MDAL MDAL
234 1.3 mrg br $!__div_no_convert
235 1.3 mrg
236 1.3 mrg __div_neg_num:
237 1.3 mrg ;; Negate the numerator (which is in MDAL)
238 1.3 mrg ;; We know that the denumerator is positive.
239 1.3 mrg _Negate MDAL MDAL
240 1.3 mrg
241 1.3 mrg __div_then_convert:
242 1.3 mrg mov a, #0xC1 ; Set the DIVST bit in MDUC
243 1.3 mrg mov !MDUC, a ; This starts the division op
244 1.3 mrg
245 1.3 mrg 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
246 1.3 mrg bt a.0, $1b
247 1.3 mrg
248 1.3 mrg ;; Negate result and transfer into r8
249 1.3 mrg _Negate MDAL r8
250 1.3 mrg ret
251 1.3 mrg
252 1.3 mrg END_FUNC ___divhi3
253 1.3 mrg
254 1.3 mrg ;----------------------------------------------------------------------
255 1.3 mrg
256 1.3 mrg START_FUNC ___modhi3
257 1.3 mrg ;; r8 = 4[sp] % 6[sp] (signed modulus)
258 1.3 mrg
259 1.3 mrg mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1
260 1.3 mrg mov !MDUC, a ; This preps the peripheral for division without interrupt generation
261 1.3 mrg
262 1.3 mrg clrw ax ; Clear the top 16-bits of the divisor and dividend
263 1.3 mrg movw MDBH, ax
264 1.3 mrg movw MDAH, ax
265 1.3 mrg
266 1.3 mrg ;; Load and test for a negative denumerator.
267 1.3 mrg movw ax, [sp+6]
268 1.3 mrg movw MDBL, ax
269 1.3 mrg mov1 cy, a.7
270 1.3 mrg bc $__mod_neg_den
271 1.3 mrg
272 1.3 mrg ;; Load and test for a negative numerator.
273 1.3 mrg movw ax, [sp+4]
274 1.3 mrg mov1 cy, a.7
275 1.3 mrg movw MDAL, ax
276 1.3 mrg bc $__mod_neg_num
277 1.3 mrg
278 1.3 mrg ;; Neither are negative - we can use the unsigned divide hardware
279 1.3 mrg __mod_no_convert:
280 1.3 mrg mov a, #0xC1 ; Set the DIVST bit in MDUC
281 1.3 mrg mov !MDUC, a ; This starts the division op
282 1.3 mrg
283 1.3 mrg 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
284 1.3 mrg bt a.0, $1b
285 1.3 mrg
286 1.3 mrg movw ax, !MDCL ; Read the remainder
287 1.3 mrg movw r8, ax
288 1.3 mrg ret
289 1.3 mrg
290 1.3 mrg __mod_neg_den:
291 1.3 mrg ;; Negate the denumerator (which is in MDBL)
292 1.3 mrg _Negate MDBL MDBL
293 1.3 mrg
294 1.3 mrg ;; Load and test for a negative numerator.
295 1.3 mrg movw ax, [sp+4]
296 1.3 mrg mov1 cy, a.7
297 1.3 mrg movw MDAL, ax
298 1.3 mrg ;; If it is not negative then we perform the modulo operation without conversion.
299 1.3 mrg bnc $__mod_no_convert
300 1.3 mrg
301 1.3 mrg ;; Otherwise we negate the numerator and then go with a modulo followed by negation.
302 1.3 mrg _Negate MDAL MDAL
303 1.3 mrg br $!__mod_then_convert
304 1.3 mrg
305 1.3 mrg __mod_neg_num:
306 1.3 mrg ;; Negate the numerator (which is in MDAL)
307 1.3 mrg ;; We know that the denumerator is positive.
308 1.3 mrg _Negate MDAL MDAL
309 1.3 mrg
310 1.3 mrg __mod_then_convert:
311 1.3 mrg mov a, #0xC1 ; Set the DIVST bit in MDUC
312 1.3 mrg mov !MDUC, a ; This starts the division op
313 1.3 mrg
314 1.3 mrg 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
315 1.3 mrg bt a.0, $1b
316 1.3 mrg
317 1.3 mrg _Negate MDCL r8
318 1.3 mrg ret
319 1.3 mrg
320 1.3 mrg END_FUNC ___modhi3
321 1.3 mrg
322 1.3 mrg ;----------------------------------------------------------------------
323 1.3 mrg
324 1.3 mrg START_FUNC ___udivhi3
325 1.3 mrg ;; r8 = 4[sp] / 6[sp] (unsigned division)
326 1.3 mrg
327 1.3 mrg mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1
328 1.3 mrg mov !MDUC, a ; This preps the peripheral for division without interrupt generation
329 1.3 mrg
330 1.3 mrg movw ax, [sp+4] ; Load the divisor
331 1.3 mrg movw MDAL, ax
332 1.3 mrg movw ax, [sp+6] ; Load the dividend
333 1.3 mrg movw MDBL, ax
334 1.3 mrg clrw ax
335 1.3 mrg movw MDAH, ax
336 1.3 mrg movw MDBH, ax
337 1.3 mrg
338 1.3 mrg mov a, #0xC1 ; Set the DIVST bit in MDUC
339 1.3 mrg mov !MDUC, a ; This starts the division op
340 1.3 mrg
341 1.3 mrg 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
342 1.3 mrg bt a.0, $1b
343 1.3 mrg
344 1.3 mrg movw ax, !MDAL ; Read the remainder
345 1.3 mrg movw r8, ax
346 1.3 mrg ret
347 1.3 mrg
348 1.3 mrg END_FUNC ___udivhi3
349 1.3 mrg
350 1.3 mrg ;----------------------------------------------------------------------
351 1.3 mrg
352 1.3 mrg START_FUNC ___umodhi3
353 1.3 mrg ;; r8 = 4[sp] % 6[sp] (unsigned modulus)
354 1.3 mrg
355 1.3 mrg mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1
356 1.3 mrg mov !MDUC, a ; This preps the peripheral for division without interrupt generation
357 1.3 mrg
358 1.3 mrg movw ax, [sp+4] ; Load the divisor
359 1.3 mrg movw MDAL, ax
360 1.3 mrg movw ax, [sp+6] ; Load the dividend
361 1.3 mrg movw MDBL, ax
362 1.3 mrg clrw ax
363 1.3 mrg movw MDAH, ax
364 1.3 mrg movw MDBH, ax
365 1.3 mrg
366 1.3 mrg mov a, #0xC1 ; Set the DIVST bit in MDUC
367 1.3 mrg mov !MDUC, a ; This starts the division op
368 1.3 mrg
369 1.3 mrg 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
370 1.3 mrg bt a.0, $1b
371 1.3 mrg
372 1.3 mrg movw ax, !MDCL ; Read the remainder
373 1.3 mrg movw r8, ax
374 1.3 mrg ret
375 1.3 mrg
376 1.3 mrg END_FUNC ___umodhi3
377 1.3 mrg
378 1.3 mrg ;----------------------------------------------------------------------
379 1.3 mrg
380 1.3 mrg #elif defined __RL78_MUL_NONE__
381 1.3 mrg
382 1.1 mrg .macro MAKE_GENERIC which,need_result
383 1.1 mrg
384 1.1 mrg .if \need_result
385 1.1 mrg quot = r8
386 1.1 mrg num = r10
387 1.1 mrg den = r12
388 1.1 mrg bit = r14
389 1.1 mrg .else
390 1.1 mrg num = r8
391 1.1 mrg quot = r10
392 1.1 mrg den = r12
393 1.1 mrg bit = r14
394 1.1 mrg .endif
395 1.1 mrg
396 1.1 mrg quotB0 = quot
397 1.1 mrg quotB1 = quot+1
398 1.1 mrg
399 1.1 mrg numB0 = num
400 1.1 mrg numB1 = num+1
401 1.1 mrg
402 1.1 mrg denB0 = den
403 1.1 mrg denB1 = den+1
404 1.1 mrg
405 1.1 mrg bitB0 = bit
406 1.1 mrg bitB1 = bit+1
407 1.1 mrg
408 1.1 mrg #define bit bc
409 1.1 mrg #define bitB0 c
410 1.1 mrg #define bitB1 b
411 1.1 mrg
412 1.1 mrg START_FUNC __generic_hidivmod\which
413 1.1 mrg
414 1.1 mrg num_lt_den\which:
415 1.1 mrg .if \need_result
416 1.1 mrg movw r8, #0
417 1.1 mrg .else
418 1.1 mrg movw ax, [sp+8]
419 1.1 mrg movw r8, ax
420 1.1 mrg .endif
421 1.1 mrg ret
422 1.1 mrg
423 1.1 mrg ;; These routines leave DE alone - the signed functions use DE
424 1.1 mrg ;; to store sign information that must remain intact
425 1.1 mrg
426 1.1 mrg .if \need_result
427 1.1 mrg .global __generic_hidiv
428 1.1 mrg __generic_hidiv:
429 1.1 mrg
430 1.1 mrg .else
431 1.1 mrg
432 1.1 mrg .global __generic_himod
433 1.1 mrg __generic_himod:
434 1.1 mrg
435 1.1 mrg .endif
436 1.1 mrg
437 1.1 mrg ;; (quot,rem) = 8[sp] /% 10[sp]
438 1.1 mrg
439 1.1 mrg movw hl, sp
440 1.1 mrg movw ax, [hl+10] ; denH
441 1.1 mrg cmpw ax, [hl+8] ; numH
442 1.1 mrg bh $num_lt_den\which
443 1.1 mrg
444 1.1 mrg ;; (quot,rem) = 16[sp] /% 20[sp]
445 1.1 mrg
446 1.1 mrg ;; copy numerator
447 1.1 mrg movw ax, [hl+8]
448 1.1 mrg movw num, ax
449 1.1 mrg
450 1.1 mrg ;; copy denomonator
451 1.1 mrg movw ax, [hl+10]
452 1.1 mrg movw den, ax
453 1.1 mrg
454 1.1 mrg movw ax, den
455 1.1 mrg cmpw ax, #0
456 1.1 mrg bnz $den_not_zero\which
457 1.3 mrg .if \need_result
458 1.3 mrg movw quot, #0
459 1.3 mrg .else
460 1.1 mrg movw num, #0
461 1.3 mrg .endif
462 1.1 mrg ret
463 1.1 mrg
464 1.1 mrg den_not_zero\which:
465 1.1 mrg .if \need_result
466 1.1 mrg ;; zero out quot
467 1.1 mrg movw quot, #0
468 1.1 mrg .endif
469 1.1 mrg
470 1.1 mrg ;; initialize bit to 1
471 1.1 mrg movw bit, #1
472 1.1 mrg
473 1.1 mrg ; while (den < num && !(den & (1L << BITS_MINUS_1)))
474 1.1 mrg
475 1.1 mrg shift_den_bit\which:
476 1.1 mrg movw ax, den
477 1.1 mrg mov1 cy,a.7
478 1.1 mrg bc $enter_main_loop\which
479 1.1 mrg cmpw ax, num
480 1.1 mrg bh $enter_main_loop\which
481 1.1 mrg
482 1.1 mrg ;; den <<= 1
483 1.1 mrg ; movw ax, den ; already has it from the cmpw above
484 1.1 mrg shlw ax, 1
485 1.1 mrg movw den, ax
486 1.1 mrg
487 1.1 mrg ;; bit <<= 1
488 1.1 mrg .if \need_result
489 1.1 mrg #ifdef bit
490 1.1 mrg shlw bit, 1
491 1.1 mrg #else
492 1.1 mrg movw ax, bit
493 1.1 mrg shlw ax, 1
494 1.1 mrg movw bit, ax
495 1.1 mrg #endif
496 1.1 mrg .else
497 1.1 mrg ;; if we don't need to compute the quotent, we don't need an
498 1.1 mrg ;; actual bit *mask*, we just need to keep track of which bit
499 1.1 mrg inc bitB0
500 1.1 mrg .endif
501 1.1 mrg
502 1.1 mrg br $shift_den_bit\which
503 1.1 mrg
504 1.1 mrg main_loop\which:
505 1.1 mrg
506 1.1 mrg ;; if (num >= den) (cmp den > num)
507 1.1 mrg movw ax, den
508 1.1 mrg cmpw ax, num
509 1.1 mrg bh $next_loop\which
510 1.1 mrg
511 1.1 mrg ;; num -= den
512 1.1 mrg movw ax, num
513 1.1 mrg subw ax, den
514 1.1 mrg movw num, ax
515 1.1 mrg
516 1.1 mrg .if \need_result
517 1.1 mrg ;; res |= bit
518 1.1 mrg mov a, quotB0
519 1.1 mrg or a, bitB0
520 1.1 mrg mov quotB0, a
521 1.1 mrg mov a, quotB1
522 1.1 mrg or a, bitB1
523 1.1 mrg mov quotB1, a
524 1.1 mrg .endif
525 1.1 mrg
526 1.1 mrg next_loop\which:
527 1.1 mrg
528 1.1 mrg ;; den >>= 1
529 1.1 mrg movw ax, den
530 1.1 mrg shrw ax, 1
531 1.1 mrg movw den, ax
532 1.1 mrg
533 1.1 mrg .if \need_result
534 1.1 mrg ;; bit >>= 1
535 1.1 mrg movw ax, bit
536 1.1 mrg shrw ax, 1
537 1.1 mrg movw bit, ax
538 1.1 mrg .else
539 1.1 mrg dec bitB0
540 1.1 mrg .endif
541 1.1 mrg
542 1.1 mrg enter_main_loop\which:
543 1.1 mrg .if \need_result
544 1.1 mrg movw ax, bit
545 1.1 mrg cmpw ax, #0
546 1.1 mrg .else
547 1.1 mrg cmp0 bitB0
548 1.1 mrg .endif
549 1.1 mrg bnz $main_loop\which
550 1.1 mrg
551 1.1 mrg main_loop_done\which:
552 1.1 mrg ret
553 1.1 mrg END_FUNC __generic_hidivmod\which
554 1.1 mrg .endm
555 1.1 mrg ;----------------------------------------------------------------------
556 1.1 mrg
557 1.1 mrg MAKE_GENERIC _d 1
558 1.1 mrg MAKE_GENERIC _m 0
559 1.1 mrg
560 1.1 mrg ;----------------------------------------------------------------------
561 1.1 mrg
562 1.1 mrg START_FUNC ___udivhi3
563 1.1 mrg ;; r8 = 4[sp] / 6[sp]
564 1.1 mrg call $!__generic_hidiv
565 1.1 mrg ret
566 1.1 mrg END_FUNC ___udivhi3
567 1.1 mrg
568 1.1 mrg
569 1.1 mrg START_FUNC ___umodhi3
570 1.1 mrg ;; r8 = 4[sp] % 6[sp]
571 1.1 mrg call $!__generic_himod
572 1.1 mrg ret
573 1.1 mrg END_FUNC ___umodhi3
574 1.1 mrg
575 1.1 mrg ;----------------------------------------------------------------------
576 1.1 mrg
577 1.1 mrg .macro NEG_AX
578 1.1 mrg movw hl, ax
579 1.1 mrg movw ax, #0
580 1.1 mrg subw ax, [hl]
581 1.1 mrg movw [hl], ax
582 1.1 mrg .endm
583 1.1 mrg
584 1.1 mrg ;----------------------------------------------------------------------
585 1.1 mrg
586 1.1 mrg START_FUNC ___divhi3
587 1.1 mrg ;; r8 = 4[sp] / 6[sp]
588 1.1 mrg movw de, #0
589 1.1 mrg mov a, [sp+5]
590 1.1 mrg mov1 cy, a.7
591 1.1 mrg bc $div_signed_num
592 1.1 mrg mov a, [sp+7]
593 1.1 mrg mov1 cy, a.7
594 1.1 mrg bc $div_signed_den
595 1.1 mrg call $!__generic_hidiv
596 1.1 mrg ret
597 1.1 mrg
598 1.1 mrg div_signed_num:
599 1.1 mrg ;; neg [sp+4]
600 1.1 mrg movw ax, sp
601 1.1 mrg addw ax, #4
602 1.1 mrg NEG_AX
603 1.1 mrg mov d, #1
604 1.1 mrg mov a, [sp+7]
605 1.1 mrg mov1 cy, a.7
606 1.1 mrg bnc $div_unsigned_den
607 1.1 mrg div_signed_den:
608 1.1 mrg ;; neg [sp+6]
609 1.1 mrg movw ax, sp
610 1.1 mrg addw ax, #6
611 1.1 mrg NEG_AX
612 1.1 mrg mov e, #1
613 1.1 mrg div_unsigned_den:
614 1.1 mrg call $!__generic_hidiv
615 1.1 mrg
616 1.1 mrg mov a, d
617 1.1 mrg cmp0 a
618 1.1 mrg bz $div_skip_restore_num
619 1.1 mrg ;; We have to restore the numerator [sp+4]
620 1.1 mrg movw ax, sp
621 1.1 mrg addw ax, #4
622 1.1 mrg NEG_AX
623 1.1 mrg mov a, d
624 1.1 mrg div_skip_restore_num:
625 1.1 mrg xor a, e
626 1.1 mrg bz $div_no_neg
627 1.1 mrg movw ax, #r8
628 1.1 mrg NEG_AX
629 1.1 mrg div_no_neg:
630 1.1 mrg mov a, e
631 1.1 mrg cmp0 a
632 1.1 mrg bz $div_skip_restore_den
633 1.1 mrg movw ax, sp
634 1.1 mrg addw ax, #6
635 1.1 mrg NEG_AX
636 1.1 mrg div_skip_restore_den:
637 1.1 mrg ret
638 1.1 mrg END_FUNC ___divhi3
639 1.1 mrg
640 1.1 mrg
641 1.1 mrg START_FUNC ___modhi3
642 1.1 mrg ;; r8 = 4[sp] % 6[sp]
643 1.1 mrg movw de, #0
644 1.1 mrg mov a, [sp+5]
645 1.1 mrg mov1 cy, a.7
646 1.1 mrg bc $mod_signed_num
647 1.1 mrg mov a, [sp+7]
648 1.1 mrg mov1 cy, a.7
649 1.1 mrg bc $mod_signed_den
650 1.1 mrg call $!__generic_himod
651 1.1 mrg ret
652 1.1 mrg
653 1.1 mrg mod_signed_num:
654 1.1 mrg ;; neg [sp+4]
655 1.1 mrg movw ax, sp
656 1.1 mrg addw ax, #4
657 1.1 mrg NEG_AX
658 1.1 mrg mov d, #1
659 1.1 mrg mov a, [sp+7]
660 1.1 mrg mov1 cy, a.7
661 1.1 mrg bnc $mod_unsigned_den
662 1.1 mrg mod_signed_den:
663 1.1 mrg ;; neg [sp+6]
664 1.1 mrg movw ax, sp
665 1.1 mrg addw ax, #6
666 1.1 mrg NEG_AX
667 1.1 mrg mod_unsigned_den:
668 1.1 mrg call $!__generic_himod
669 1.1 mrg
670 1.1 mrg mov a, d
671 1.1 mrg cmp0 a
672 1.1 mrg bz $mod_no_neg
673 1.1 mrg movw ax, #r8
674 1.1 mrg NEG_AX
675 1.1 mrg ;; Also restore numerator
676 1.1 mrg movw ax, sp
677 1.1 mrg addw ax, #4
678 1.1 mrg NEG_AX
679 1.1 mrg mod_no_neg:
680 1.1 mrg mov a, e
681 1.1 mrg cmp0 a
682 1.1 mrg bz $mod_skip_restore_den
683 1.1 mrg movw ax, sp
684 1.1 mrg addw ax, #6
685 1.1 mrg NEG_AX
686 1.1 mrg mod_skip_restore_den:
687 1.1 mrg ret
688 1.1 mrg END_FUNC ___modhi3
689 1.3 mrg
690 1.3 mrg ;----------------------------------------------------------------------
691 1.3 mrg
692 1.3 mrg #else
693 1.3 mrg
694 1.3 mrg #error "Unknown RL78 hardware multiply/divide support"
695 1.3 mrg
696 1.3 mrg #endif
697