]> gcc.gnu.org Git - gcc.git/blob - libgcc/config/rl78/divmodsi.S
Update copyright years.
[gcc.git] / libgcc / config / rl78 / divmodsi.S
1 /* SImode 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 it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 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 = r12
33 den = r16
34 bit = r20
35 .else
36 num = r8
37 quot = r12
38 den = r16
39 bit = r20
40 .endif
41
42 quotH = quot+2
43 quotL = quot
44 quotB0 = quot
45 quotB1 = quot+1
46 quotB2 = quot+2
47 quotB3 = quot+3
48
49 numH = num+2
50 numL = num
51 numB0 = num
52 numB1 = num+1
53 numB2 = num+2
54 numB3 = num+3
55
56 #define denH bc
57 denL = den
58 denB0 = den
59 denB1 = den+1
60 #define denB2 c
61 #define denB3 b
62
63 bitH = bit+2
64 bitL = bit
65 bitB0 = bit
66 bitB1 = bit+1
67 bitB2 = bit+2
68 bitB3 = bit+3
69
70 START_FUNC __generic_sidivmod\which
71
72 num_lt_den\which:
73 .if \need_result
74 movw r8, #0
75 movw r10, #0
76 .else
77 movw ax, [sp+8]
78 movw r8, ax
79 movw ax, [sp+10]
80 movw r10, ax
81 .endif
82 ret
83
84 shift_den_bit16\which:
85 movw ax, denL
86 movw denH, ax
87 movw denL, #0
88 .if \need_result
89 movw ax, bitL
90 movw bitH, ax
91 movw bitL, #0
92 .else
93 mov a, bit
94 add a, #16
95 mov bit, a
96 .endif
97 br $shift_den_bit\which
98
99 ;; These routines leave DE alone - the signed functions use DE
100 ;; to store sign information that must remain intact
101
102 .if \need_result
103 .global __generic_sidiv
104 __generic_sidiv:
105
106 .else
107
108 .global __generic_simod
109 __generic_simod:
110
111 .endif
112
113 ;; (quot,rem) = 8[sp] /% 12[sp]
114
115 movw hl, sp
116 movw ax, [hl+14] ; denH
117 cmpw ax, [hl+10] ; numH
118 movw ax, [hl+12] ; denL
119 sknz
120 cmpw ax, [hl+8] ; numL
121 bh $num_lt_den\which
122
123 #ifdef __RL78_G10__
124 movw ax, denL
125 push ax
126 movw ax, bitL
127 push ax
128 movw ax, bitH
129 push ax
130 #else
131 sel rb2
132 push ax ; denL
133 ; push bc ; denH
134 push de ; bitL
135 push hl ; bitH - stored in BC
136 sel rb0
137 #endif
138
139 ;; (quot,rem) = 16[sp] /% 20[sp]
140
141 ;; copy numerator
142 movw ax, [hl+8]
143 movw numL, ax
144 movw ax, [hl+10]
145 movw numH, ax
146
147 ;; copy denomonator
148 movw ax, [hl+12]
149 movw denL, ax
150 movw ax, [hl+14]
151 movw denH, ax
152
153 movw ax, denL
154 or a, denB2
155 or a, denB3 ; not x
156 cmpw ax, #0
157 bnz $den_not_zero\which
158 movw numL, #0
159 movw numH, #0
160 ret
161
162 den_not_zero\which:
163 .if \need_result
164 ;; zero out quot
165 movw quotL, #0
166 movw quotH, #0
167 .endif
168
169 ;; initialize bit to 1
170 movw bitL, #1
171 movw bitH, #0
172
173 ; while (den < num && !(den & (1L << BITS_MINUS_1)))
174
175 .if 1
176 ;; see if we can short-circuit a bunch of shifts
177 movw ax, denH
178 cmpw ax, #0
179 bnz $shift_den_bit\which
180 movw ax, denL
181 cmpw ax, numH
182 bnh $shift_den_bit16\which
183 .endif
184
185 shift_den_bit\which:
186 movw ax, denH
187 mov1 cy,a.7
188 bc $enter_main_loop\which
189 cmpw ax, numH
190 movw ax, denL ; we re-use this below
191 sknz
192 cmpw ax, numL
193 bh $enter_main_loop\which
194
195 ;; den <<= 1
196 ; movw ax, denL ; already has it from the cmpw above
197 shlw ax, 1
198 movw denL, ax
199 ; movw ax, denH
200 rolwc denH, 1
201 ; movw denH, ax
202
203 ;; bit <<= 1
204 .if \need_result
205 movw ax, bitL
206 shlw ax, 1
207 movw bitL, ax
208 movw ax, bitH
209 rolwc ax, 1
210 movw bitH, ax
211 .else
212 ;; if we don't need to compute the quotent, we don't need an
213 ;; actual bit *mask*, we just need to keep track of which bit
214 inc bitB0
215 .endif
216
217 br $shift_den_bit\which
218
219 ;; while (bit)
220 main_loop\which:
221
222 ;; if (num >= den) (cmp den > num)
223 movw ax, numH
224 cmpw ax, denH
225 movw ax, numL
226 sknz
227 cmpw ax, denL
228 skz
229 bnh $next_loop\which
230
231 ;; num -= den
232 ; movw ax, numL ; already has it from the cmpw above
233 subw ax, denL
234 movw numL, ax
235 movw ax, numH
236 sknc
237 decw ax
238 subw ax, denH
239 movw numH, ax
240
241 .if \need_result
242 ;; res |= bit
243 mov a, quotB0
244 or a, bitB0
245 mov quotB0, a
246 mov a, quotB1
247 or a, bitB1
248 mov quotB1, a
249 mov a, quotB2
250 or a, bitB2
251 mov quotB2, a
252 mov a, quotB3
253 or a, bitB3
254 mov quotB3, a
255 .endif
256
257 next_loop\which:
258
259 ;; den >>= 1
260 movw ax, denH
261 shrw ax, 1
262 movw denH, ax
263 mov a, denB1
264 rorc a, 1
265 mov denB1, a
266 mov a, denB0
267 rorc a, 1
268 mov denB0, a
269
270 ;; bit >>= 1
271 .if \need_result
272 movw ax, bitH
273 shrw ax, 1
274 movw bitH, ax
275 mov a, bitB1
276 rorc a, 1
277 mov bitB1, a
278 mov a, bitB0
279 rorc a, 1
280 mov bitB0, a
281 .else
282 dec bitB0
283 .endif
284
285 enter_main_loop\which:
286 .if \need_result
287 movw ax, bitH
288 cmpw ax, #0
289 bnz $main_loop\which
290 .else
291 cmp bitB0, #15
292 bh $main_loop\which
293 .endif
294 ;; bit is HImode now; check others
295 movw ax, numH ; numerator
296 cmpw ax, #0
297 bnz $bit_high_set\which
298 movw ax, denH ; denominator
299 cmpw ax, #0
300 bz $switch_to_himode\which
301 bit_high_set\which:
302 .if \need_result
303 movw ax, bitL
304 cmpw ax, #0
305 .else
306 cmp0 bitB0
307 .endif
308 bnz $main_loop\which
309
310 switch_to_himode\which:
311 .if \need_result
312 movw ax, bitL
313 cmpw ax, #0
314 .else
315 cmp0 bitB0
316 .endif
317 bz $main_loop_done_himode\which
318
319 ;; From here on in, r22, r14, and r18 are all zero
320 ;; while (bit)
321 main_loop_himode\which:
322
323 ;; if (num >= den) (cmp den > num)
324 movw ax, denL
325 cmpw ax, numL
326 bh $next_loop_himode\which
327
328 ;; num -= den
329 movw ax, numL
330 subw ax, denL
331 movw numL, ax
332 movw ax, numH
333 sknc
334 decw ax
335 subw ax, denH
336 movw numH, ax
337
338 .if \need_result
339 ;; res |= bit
340 mov a, quotB0
341 or a, bitB0
342 mov quotB0, a
343 mov a, quotB1
344 or a, bitB1
345 mov quotB1, a
346 .endif
347
348 next_loop_himode\which:
349
350 ;; den >>= 1
351 movw ax, denL
352 shrw ax, 1
353 movw denL, ax
354
355 .if \need_result
356 ;; bit >>= 1
357 movw ax, bitL
358 shrw ax, 1
359 movw bitL, ax
360 .else
361 dec bitB0
362 .endif
363
364 .if \need_result
365 movw ax, bitL
366 cmpw ax, #0
367 .else
368 cmp0 bitB0
369 .endif
370 bnz $main_loop_himode\which
371
372 main_loop_done_himode\which:
373 #ifdef __RL78_G10__
374 pop ax
375 movw bitH, ax
376 pop ax
377 movw bitL, ax
378 pop ax
379 movw denL, ax
380 #else
381 sel rb2
382 pop hl ; bitH - stored in BC
383 pop de ; bitL
384 ; pop bc ; denH
385 pop ax ; denL
386 sel rb0
387 #endif
388
389 ret
390 END_FUNC __generic_sidivmod\which
391 .endm
392
393 ;----------------------------------------------------------------------
394
395 MAKE_GENERIC _d 1
396 MAKE_GENERIC _m 0
397
398 ;----------------------------------------------------------------------
399
400 START_FUNC ___udivsi3
401 ;; r8 = 4[sp] / 8[sp]
402 call $!__generic_sidiv
403 ret
404 END_FUNC ___udivsi3
405
406
407 START_FUNC ___umodsi3
408 ;; r8 = 4[sp] % 8[sp]
409 call $!__generic_simod
410 ret
411 END_FUNC ___umodsi3
412
413 ;----------------------------------------------------------------------
414
415 .macro NEG_AX
416 movw hl, ax
417 movw ax, #0
418 subw ax, [hl]
419 movw [hl], ax
420 movw ax, #0
421 sknc
422 decw ax
423 subw ax, [hl+2]
424 movw [hl+2], ax
425 .endm
426
427 ;----------------------------------------------------------------------
428
429 START_FUNC ___divsi3
430 ;; r8 = 4[sp] / 8[sp]
431 movw de, #0
432 mov a, [sp+7]
433 mov1 cy, a.7
434 bc $div_signed_num
435 mov a, [sp+11]
436 mov1 cy, a.7
437 bc $div_signed_den
438 call $!__generic_sidiv
439 ret
440
441 div_signed_num:
442 ;; neg [sp+4]
443 movw ax, sp
444 addw ax, #4
445 NEG_AX
446 mov d, #1
447 mov a, [sp+11]
448 mov1 cy, a.7
449 bnc $div_unsigned_den
450 div_signed_den:
451 ;; neg [sp+8]
452 movw ax, sp
453 addw ax, #8
454 NEG_AX
455 mov e, #1
456 div_unsigned_den:
457 call $!__generic_sidiv
458
459 mov a, d
460 cmp0 a
461 bz $div_skip_restore_num
462 ;; We have to restore the numerator [sp+4]
463 movw ax, sp
464 addw ax, #4
465 NEG_AX
466 mov a, d
467 div_skip_restore_num:
468 xor a, e
469 bz $div_no_neg
470 movw ax, #r8
471 NEG_AX
472 div_no_neg:
473 mov a, e
474 cmp0 a
475 bz $div_skip_restore_den
476 ;; We have to restore the denominator [sp+8]
477 movw ax, sp
478 addw ax, #8
479 NEG_AX
480 div_skip_restore_den:
481 ret
482 END_FUNC ___divsi3
483
484
485 START_FUNC ___modsi3
486 ;; r8 = 4[sp] % 8[sp]
487 movw de, #0
488 mov a, [sp+7]
489 mov1 cy, a.7
490 bc $mod_signed_num
491 mov a, [sp+11]
492 mov1 cy, a.7
493 bc $mod_signed_den
494 call $!__generic_simod
495 ret
496
497 mod_signed_num:
498 ;; neg [sp+4]
499 movw ax, sp
500 addw ax, #4
501 NEG_AX
502 mov d, #1
503 mov a, [sp+11]
504 mov1 cy, a.7
505 bnc $mod_unsigned_den
506 mod_signed_den:
507 ;; neg [sp+8]
508 movw ax, sp
509 addw ax, #8
510 NEG_AX
511 mov e, #1
512 mod_unsigned_den:
513 call $!__generic_simod
514
515 mov a, d
516 cmp0 a
517 bz $mod_no_neg
518 movw ax, #r8
519 NEG_AX
520 ;; We have to restore [sp+4] as well.
521 movw ax, sp
522 addw ax, #4
523 NEG_AX
524 mod_no_neg:
525 .if 1
526 mov a, e
527 cmp0 a
528 bz $mod_skip_restore_den
529 movw ax, sp
530 addw ax, #8
531 NEG_AX
532 mod_skip_restore_den:
533 .endif
534 ret
535 END_FUNC ___modsi3
This page took 0.059855 seconds and 5 git commands to generate.