]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgcc/config/rl78/divmodqi.S
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / rl78 / divmodqi.S
1 /* QImode div/mod functions for the GCC support library for the Renesas RL78 processors.
2 Copyright (C) 2012-2024 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
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.
11
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.
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 = r10
33 den = r12
34 bit = r14
35 .else
36 num = r8
37 quot = r10
38 den = r12
39 bit = r14
40 .endif
41
42 #define bit b
43 #define den c
44 #define bitden bc
45
46 START_FUNC __generic_qidivmod\which
47
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
56
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
68
69 ;; These routines leave DE alone - the signed functions use DE
70 ;; to store sign information that must remain intact
71
72 .if \need_result
73 .global __generic_qidiv
74 __generic_qidiv:
75
76 .else
77
78 .global __generic_qimod
79 __generic_qimod:
80
81 .endif
82
83 ;; (quot,rem) = 4[hl] /% 6[hl]
84
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
93
94 ;; copy denomonator
95 mov a, [hl+6]
96 mov den, a
97
98 cmp0 den
99 bz $den_is_zero\which
100
101 den_not_zero\which:
102 .if \need_result
103 ;; zero out quot
104 mov quot, #0
105 .endif
106
107 ;; initialize bit to 1
108 mov bit, #1
109
110 ; while (den < num && !(den & (1L << BITS_MINUS_1)))
111
112 shift_den_bit\which:
113
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
120
121 ;; den <<= 1
122 ; mov a, den ; already has it from the cmpw above
123 shl a, 1
124 mov den, a
125
126 ;; bit <<= 1
127 shl bit, 1
128 .endm
129
130 SDB_ONE\which
131 SDB_ONE\which
132
133 br $shift_den_bit\which
134
135 main_loop\which:
136
137 ;; if (num >= den) (cmp den > num)
138 mov a, den
139 cmp a, num
140 bh $next_loop\which
141
142 ;; num -= den
143 mov a, num
144 sub a, den
145 mov num, a
146
147 .if \need_result
148 ;; res |= bit
149 mov a, quot
150 or a, bit
151 mov quot, a
152 .endif
153
154 next_loop\which:
155
156 ;; den, bit >>= 1
157 movw ax, bitden
158 shrw ax, 1
159 movw bitden, ax
160
161 enter_main_loop\which:
162 cmp0 bit
163 bnz $main_loop\which
164
165 main_loop_done\which:
166 ret
167 END_FUNC __generic_qidivmod\which
168 .endm
169
170 ;----------------------------------------------------------------------
171
172 MAKE_GENERIC _d 1
173 MAKE_GENERIC _m 0
174
175 ;----------------------------------------------------------------------
176
177 START_FUNC ___udivqi3
178 ;; r8 = 4[sp] / 6[sp]
179 movw hl, sp
180 br $!__generic_qidiv
181 END_FUNC ___udivqi3
182
183
184 START_FUNC ___umodqi3
185 ;; r8 = 4[sp] % 6[sp]
186 movw hl, sp
187 br $!__generic_qimod
188 END_FUNC ___umodqi3
189
190 ;----------------------------------------------------------------------
191
192 .macro NEG_AX
193 movw hl, ax
194 mov a, #0
195 sub a, [hl]
196 mov [hl], a
197 .endm
198
199 ;----------------------------------------------------------------------
200
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
230
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
255
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
285
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