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