Reverting merge from trunk
[official-gcc.git] / libgcc / config / rl78 / divmodsi.S
blobe22b5ba56e850f890c5f4ae8ed299c053de036b9
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.
5    This file is part of GCC.
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.
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.
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.
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/>.  */
26 #ifndef __RL78_G10__
28 #include "vregs.h"
30         .macro make_generic  which,need_result
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
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
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
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
99         ;; These routines leave DE alone - the signed functions use DE
100         ;; to store sign information that must remain intact
102         .if \need_result
104 generic_div:
106         .else
108 generic_mod:
110         .endif
112         ;; (quot,rem) = 8[sp] /% 12[sp]
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
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
129         ;; (quot,rem) = 16[sp] /% 20[sp]
131         ;; copy numerator
132         movw    ax, [hl+8]
133         movw    numL, ax
134         movw    ax, [hl+10]
135         movw    numH, ax
137         ;; copy denomonator
138         movw    ax, [hl+12]
139         movw    denL, ax
140         movw    ax, [hl+14]
141         movw    denH, ax
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
152 den_not_zero\which:
153         .if \need_result
154         ;; zero out quot
155         movw    quotL, #0
156         movw    quotH, #0
157         .endif
159         ;; initialize bit to 1
160         movw    bitL, #1
161         movw    bitH, #0
163 ; while (den < num && !(den & (1L << BITS_MINUS_1)))
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
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
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
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
207         br      $shift_den_bit\which
209         ;; while (bit)
210 main_loop\which:
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
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
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
247 next_loop\which:        
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
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
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
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
309         ;; From here on in, r22, r14, and r18 are all zero
310         ;; while (bit)
311 main_loop_himode\which:
313         ;; if (num >= den) (cmp den > num)
314         movw    ax, denL
315         cmpw    ax, numL
316         bh      $next_loop_himode\which
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
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
338 next_loop_himode\which: 
340         ;; den >>= 1
341         movw    ax, denL
342         shrw    ax, 1
343         movw    denL, ax
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
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
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
370         ret
371         .endm
373         make_generic _d 1
374         make_generic _m 0
376 ;----------------------------------------------------------------------
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         
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
395 ;----------------------------------------------------------------------
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
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
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         
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
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
521 #endif