2016-05-15 Harald Anlauf <anlauf@gmx.de>
[official-gcc.git] / libgcc / config / rl78 / divmodqi.S
blobc342c78d77438d74145063af538ba483fc074675
1 /* QImode div/mod functions for the GCC support library for the Renesas RL78 processors.
2    Copyright (C) 2012-2016 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
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.
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.
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 #include "vregs.h"
28 .macro MAKE_GENERIC  which,need_result
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
42 #define bit     b
43 #define den     c
44 #define bitden  bc
46         START_FUNC __generic_qidivmod\which
48 num_lt_den\which:
49         .if \need_result
50         mov     r8, #0
51         .else
52         mov     a, [hl+4]
53         mov     r8, a
54         .endif
55         ret
57 num_eq_den\which:
58         .if \need_result
59         mov     r8, #1
60         .else
61         mov     r8, #0
62         .endif
63         ret
64         
65 den_is_zero\which:
66         mov     r8, #0x00
67         ret
69         ;; These routines leave DE alone - the signed functions use DE
70         ;; to store sign information that must remain intact
72         .if \need_result
73         .global __generic_qidiv
74 __generic_qidiv:
76         .else
78         .global __generic_qimod
79 __generic_qimod:
81         .endif
83         ;; (quot,rem) = 4[hl] /% 6[hl]
85         mov     a, [hl+4] ; num
86         cmp     a, [hl+6] ; den
87         bz      $num_eq_den\which
88         bnh     $num_lt_den\which
89         
90         ;; copy numerator
91 ;       mov     a, [hl+4]       ; already there from above
92         mov     num, a
94         ;; copy denomonator
95         mov     a, [hl+6]
96         mov     den, a
98         cmp0    den
99         bz      $den_is_zero\which
101 den_not_zero\which:
102         .if \need_result
103         ;; zero out quot
104         mov     quot, #0
105         .endif
107         ;; initialize bit to 1
108         mov     bit, #1
110 ; while (den < num && !(den & (1L << BITS_MINUS_1)))
112 shift_den_bit\which:
114 .macro  SDB_ONE\which
115         mov     a, den
116         mov1    cy,a.7
117         bc      $enter_main_loop\which
118         cmp     a, num
119         bh      $enter_main_loop\which
121         ;; den <<= 1
122 ;       mov     a, den          ; already has it from the cmpw above
123         shl     a, 1
124         mov     den, a
126         ;; bit <<= 1
127         shl     bit, 1
128 .endm
130         SDB_ONE\which
131         SDB_ONE\which
133         br      $shift_den_bit\which
135 main_loop\which:
137         ;; if (num >= den) (cmp den > num)
138         mov     a, den
139         cmp     a, num
140         bh      $next_loop\which
142         ;; num -= den
143         mov     a, num
144         sub     a, den
145         mov     num, a
147         .if \need_result
148         ;; res |= bit
149         mov     a, quot
150         or      a, bit
151         mov     quot, a
152         .endif
154 next_loop\which:        
156         ;; den, bit >>= 1
157         movw    ax, bitden
158         shrw    ax, 1
159         movw    bitden, ax
161 enter_main_loop\which:
162         cmp0    bit
163         bnz     $main_loop\which
165 main_loop_done\which:   
166         ret
167         END_FUNC __generic_qidivmod\which
168 .endm
170 ;----------------------------------------------------------------------
172         MAKE_GENERIC _d 1
173         MAKE_GENERIC _m 0
175 ;----------------------------------------------------------------------
177 START_FUNC ___udivqi3
178         ;; r8 = 4[sp] / 6[sp]
179         movw    hl, sp
180         br      $!__generic_qidiv
181 END_FUNC ___udivqi3
182         
184 START_FUNC ___umodqi3
185         ;; r8 = 4[sp] % 6[sp]
186         movw    hl, sp
187         br      $!__generic_qimod
188 END_FUNC ___umodqi3
190 ;----------------------------------------------------------------------
192 .macro NEG_AX
193         movw    hl, ax
194         mov     a, #0
195         sub     a, [hl]
196         mov     [hl], a
197 .endm
199 ;----------------------------------------------------------------------
201 START_FUNC      ___divqi3
202         ;; r8 = 4[sp] / 6[sp]
203         movw    hl, sp
204         movw    de, #0
205         mov     a, [sp+4]
206         mov1    cy, a.7
207         bc      $div_signed_num
208         mov     a, [sp+6]
209         mov1    cy, a.7
210         bc      $div_signed_den
211         br      $!__generic_qidiv
212         
213 div_signed_num:
214         ;; neg [sp+4]
215         mov     a, #0
216         sub     a, [hl+4]
217         mov     [hl+4], a
218         mov     d, #1
219         mov     a, [sp+6]
220         mov1    cy, a.6
221         bnc     $div_unsigned_den
222 div_signed_den: 
223         ;; neg [sp+6]
224         mov     a, #0
225         sub     a, [hl+6]
226         mov     [hl+6], a
227         mov     e, #1
228 div_unsigned_den:       
229         call    $!__generic_qidiv
231         mov     a, d
232         cmp0    a
233         bz      $div_skip_restore_num
234         ;;  We have to restore the numerator [sp+4]
235         movw    ax, sp
236         addw    ax, #4
237         NEG_AX
238         mov     a, d
239 div_skip_restore_num:   
240         xor     a, e
241         bz      $div_no_neg
242         movw    ax, #r8
243         NEG_AX
244 div_no_neg:
245         mov     a, e
246         cmp0    a
247         bz      $div_skip_restore_den
248         movw    ax, sp
249         addw    ax, #6
250         NEG_AX
251 div_skip_restore_den:   
252         ret
253 END_FUNC ___divqi3
254         
256 START_FUNC ___modqi3
257         ;; r8 = 4[sp] % 6[sp]
258         movw    hl, sp
259         movw    de, #0
260         mov     a, [hl+4]
261         mov1    cy, a.7
262         bc      $mod_signed_num
263         mov     a, [hl+6]
264         mov1    cy, a.7
265         bc      $mod_signed_den
266         br      $!__generic_qimod
267         
268 mod_signed_num:
269         ;; neg [sp+4]
270         mov     a, #0
271         sub     a, [hl+4]
272         mov     [hl+4], a
273         mov     d, #1
274         mov     a, [hl+6]
275         mov1    cy, a.7
276         bnc     $mod_unsigned_den
277 mod_signed_den: 
278         ;; neg [sp+6]
279         mov     a, #0
280         sub     a, [hl+6]
281         mov     [hl+6], a
282         mov     e, #1
283 mod_unsigned_den:       
284         call    $!__generic_qimod
286         mov     a, d
287         cmp0    a
288         bz      $mod_no_neg
289         mov     a, #0
290         sub     a, r8
291         mov     r8, a
292         ;;  Also restore numerator
293         movw    ax, sp
294         addw    ax, #4
295         NEG_AX
296 mod_no_neg:
297         mov     a, e
298         cmp0    a
299         bz      $mod_skip_restore_den
300         movw    ax, sp
301         addw    ax, #6
302         NEG_AX
303 mod_skip_restore_den:   
304         ret
305 END_FUNC ___modqi3