]>
Commit | Line | Data |
---|---|---|
ceb2fc49 | 1 | /* QImode div/mod functions for the GCC support library for the Renesas RL78 processors. |
a945c346 | 2 | Copyright (C) 2012-2024 Free Software Foundation, Inc. |
ceb2fc49 DD |
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 | ||
ceb2fc49 DD |
26 | #include "vregs.h" |
27 | ||
52a1ff8b | 28 | .macro MAKE_GENERIC which,need_result |
ceb2fc49 DD |
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 | ||
ceb2fc49 DD |
42 | #define bit b |
43 | #define den c | |
44 | #define bitden bc | |
52a1ff8b NC |
45 | |
46 | START_FUNC __generic_qidivmod\which | |
ceb2fc49 DD |
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: | |
793aa938 | 66 | mov r8, #0x00 |
ceb2fc49 DD |
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 | |
52a1ff8b NC |
73 | .global __generic_qidiv |
74 | __generic_qidiv: | |
ceb2fc49 DD |
75 | |
76 | .else | |
77 | ||
52a1ff8b NC |
78 | .global __generic_qimod |
79 | __generic_qimod: | |
ceb2fc49 DD |
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: | |
52a1ff8b NC |
113 | |
114 | .macro SDB_ONE\which | |
ceb2fc49 DD |
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 | |
52a1ff8b | 128 | .endm |
ceb2fc49 | 129 | |
52a1ff8b NC |
130 | SDB_ONE\which |
131 | SDB_ONE\which | |
ceb2fc49 DD |
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 | |
52a1ff8b NC |
167 | END_FUNC __generic_qidivmod\which |
168 | .endm | |
ceb2fc49 | 169 | |
52a1ff8b NC |
170 | ;---------------------------------------------------------------------- |
171 | ||
172 | MAKE_GENERIC _d 1 | |
173 | MAKE_GENERIC _m 0 | |
ceb2fc49 DD |
174 | |
175 | ;---------------------------------------------------------------------- | |
176 | ||
52a1ff8b | 177 | START_FUNC ___udivqi3 |
ceb2fc49 DD |
178 | ;; r8 = 4[sp] / 6[sp] |
179 | movw hl, sp | |
52a1ff8b NC |
180 | br $!__generic_qidiv |
181 | END_FUNC ___udivqi3 | |
ceb2fc49 DD |
182 | |
183 | ||
52a1ff8b | 184 | START_FUNC ___umodqi3 |
ceb2fc49 DD |
185 | ;; r8 = 4[sp] % 6[sp] |
186 | movw hl, sp | |
52a1ff8b NC |
187 | br $!__generic_qimod |
188 | END_FUNC ___umodqi3 | |
ceb2fc49 DD |
189 | |
190 | ;---------------------------------------------------------------------- | |
191 | ||
52a1ff8b | 192 | .macro NEG_AX |
ceb2fc49 DD |
193 | movw hl, ax |
194 | mov a, #0 | |
195 | sub a, [hl] | |
196 | mov [hl], a | |
52a1ff8b NC |
197 | .endm |
198 | ||
199 | ;---------------------------------------------------------------------- | |
ceb2fc49 | 200 | |
52a1ff8b | 201 | START_FUNC ___divqi3 |
ceb2fc49 DD |
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 | |
52a1ff8b | 211 | br $!__generic_qidiv |
ceb2fc49 DD |
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: | |
52a1ff8b | 229 | call $!__generic_qidiv |
ceb2fc49 DD |
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 | |
52a1ff8b | 237 | NEG_AX |
ceb2fc49 DD |
238 | mov a, d |
239 | div_skip_restore_num: | |
240 | xor a, e | |
241 | bz $div_no_neg | |
242 | movw ax, #r8 | |
52a1ff8b | 243 | NEG_AX |
ceb2fc49 DD |
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 | |
52a1ff8b | 250 | NEG_AX |
ceb2fc49 DD |
251 | div_skip_restore_den: |
252 | ret | |
52a1ff8b | 253 | END_FUNC ___divqi3 |
ceb2fc49 DD |
254 | |
255 | ||
52a1ff8b | 256 | START_FUNC ___modqi3 |
ceb2fc49 DD |
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 | |
52a1ff8b | 266 | br $!__generic_qimod |
ceb2fc49 DD |
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: | |
52a1ff8b | 284 | call $!__generic_qimod |
ceb2fc49 DD |
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 | |
52a1ff8b | 295 | NEG_AX |
ceb2fc49 DD |
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 | |
52a1ff8b | 302 | NEG_AX |
ceb2fc49 DD |
303 | mod_skip_restore_den: |
304 | ret | |
52a1ff8b | 305 | END_FUNC ___modqi3 |