divmodsi.S revision 1.1.1.1.4.1 1 1.1 mrg /* SImode div/mod functions for the GCC support library for the Renesas RL78 processors.
2 1.1.1.1.4.1 christos Copyright (C) 2012-2016 Free Software Foundation, Inc.
3 1.1 mrg Contributed by Red Hat.
4 1.1 mrg
5 1.1 mrg This file is part of GCC.
6 1.1 mrg
7 1.1 mrg GCC is free software; you can redistribute it and/or modify it
8 1.1 mrg under the terms of the GNU General Public License as published
9 1.1 mrg by the Free Software Foundation; either version 3, or (at your
10 1.1 mrg option) any later version.
11 1.1 mrg
12 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT
13 1.1 mrg ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 1.1 mrg License for more details.
16 1.1 mrg
17 1.1 mrg Under Section 7 of GPL version 3, you are granted additional
18 1.1 mrg permissions described in the GCC Runtime Library Exception, version
19 1.1 mrg 3.1, as published by the Free Software Foundation.
20 1.1 mrg
21 1.1 mrg You should have received a copy of the GNU General Public License and
22 1.1 mrg a copy of the GCC Runtime Library Exception along with this program;
23 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 1.1 mrg <http://www.gnu.org/licenses/>. */
25 1.1 mrg
26 1.1 mrg #include "vregs.h"
27 1.1 mrg
28 1.1.1.1.4.1 christos #if defined __RL78_MUL_G14__
29 1.1.1.1.4.1 christos
30 1.1.1.1.4.1 christos START_FUNC ___divsi3
31 1.1.1.1.4.1 christos ;; r8,r10 = 4[sp],6[sp] / 8[sp],10[sp]
32 1.1.1.1.4.1 christos
33 1.1.1.1.4.1 christos ;; Load and test for a negative denumerator.
34 1.1.1.1.4.1 christos movw ax, [sp+8]
35 1.1.1.1.4.1 christos movw de, ax
36 1.1.1.1.4.1 christos movw ax, [sp+10]
37 1.1.1.1.4.1 christos mov1 cy, a.7
38 1.1.1.1.4.1 christos movw hl, ax
39 1.1.1.1.4.1 christos bc $__div_neg_den
40 1.1.1.1.4.1 christos
41 1.1.1.1.4.1 christos ;; Load and test for a negative numerator.
42 1.1.1.1.4.1 christos movw ax, [sp+6]
43 1.1.1.1.4.1 christos mov1 cy, a.7
44 1.1.1.1.4.1 christos movw bc, ax
45 1.1.1.1.4.1 christos movw ax, [sp+4]
46 1.1.1.1.4.1 christos bc $__div_neg_num
47 1.1.1.1.4.1 christos
48 1.1.1.1.4.1 christos ;; Neither are negative - we can use the unsigned divide instruction.
49 1.1.1.1.4.1 christos __div_no_convert:
50 1.1.1.1.4.1 christos push psw
51 1.1.1.1.4.1 christos di
52 1.1.1.1.4.1 christos divwu
53 1.1.1.1.4.1 christos pop psw
54 1.1.1.1.4.1 christos
55 1.1.1.1.4.1 christos movw r8, ax
56 1.1.1.1.4.1 christos movw ax, bc
57 1.1.1.1.4.1 christos movw r10, ax
58 1.1.1.1.4.1 christos ret
59 1.1.1.1.4.1 christos
60 1.1.1.1.4.1 christos __div_neg_den:
61 1.1.1.1.4.1 christos ;; Negate the denumerator (which is in HLDE)
62 1.1.1.1.4.1 christos clrw ax
63 1.1.1.1.4.1 christos subw ax, de
64 1.1.1.1.4.1 christos movw de, ax
65 1.1.1.1.4.1 christos clrw ax
66 1.1.1.1.4.1 christos sknc
67 1.1.1.1.4.1 christos decw ax
68 1.1.1.1.4.1 christos subw ax, hl
69 1.1.1.1.4.1 christos movw hl, ax
70 1.1.1.1.4.1 christos
71 1.1.1.1.4.1 christos ;; Load and test for a negative numerator.
72 1.1.1.1.4.1 christos movw ax, [sp+6]
73 1.1.1.1.4.1 christos mov1 cy, a.7
74 1.1.1.1.4.1 christos movw bc, ax
75 1.1.1.1.4.1 christos movw ax, [sp+4]
76 1.1.1.1.4.1 christos ;; If it is not negative then we perform the division and then negate the result.
77 1.1.1.1.4.1 christos bnc $__div_then_convert
78 1.1.1.1.4.1 christos
79 1.1.1.1.4.1 christos ;; Otherwise we negate the numerator and then go with a straightforward unsigned division.
80 1.1.1.1.4.1 christos ;; The negation is complicated because AX, BC, DE and HL are already in use.
81 1.1.1.1.4.1 christos ;; ax: numL bc: numH r8: r10:
82 1.1.1.1.4.1 christos xchw ax, bc
83 1.1.1.1.4.1 christos ;; ax: numH bc: numL r8: r10:
84 1.1.1.1.4.1 christos movw r8, ax
85 1.1.1.1.4.1 christos ;; ax: bc: numL r8: numH r10:
86 1.1.1.1.4.1 christos clrw ax
87 1.1.1.1.4.1 christos ;; ax: 0 bc: numL r8: numH r10:
88 1.1.1.1.4.1 christos subw ax, bc
89 1.1.1.1.4.1 christos ;; ax: -numL bc: r8: numH r10:
90 1.1.1.1.4.1 christos movw r10, ax
91 1.1.1.1.4.1 christos ;; ax: bc: r8: numH r10: -numL
92 1.1.1.1.4.1 christos movw ax, r8
93 1.1.1.1.4.1 christos ;; ax: numH bc: r8: r10: -numL
94 1.1.1.1.4.1 christos movw bc, ax
95 1.1.1.1.4.1 christos ;; ax: bc: numH r8: r10: -numL
96 1.1.1.1.4.1 christos clrw ax
97 1.1.1.1.4.1 christos ;; ax: 0 bc: numH r8: r10: -numL
98 1.1.1.1.4.1 christos sknc
99 1.1.1.1.4.1 christos decw ax
100 1.1.1.1.4.1 christos ;; ax: -1 bc: numH r8: r10: -numL
101 1.1.1.1.4.1 christos subw ax, bc
102 1.1.1.1.4.1 christos ;; ax: -numH bc: r8: r10: -numL
103 1.1.1.1.4.1 christos movw bc, ax
104 1.1.1.1.4.1 christos ;; ax: bc: -numH r8: r10: -numL
105 1.1.1.1.4.1 christos movw ax, r10
106 1.1.1.1.4.1 christos ;; ax: -numL bc: -numH r8: r10:
107 1.1.1.1.4.1 christos br $!__div_no_convert
108 1.1.1.1.4.1 christos
109 1.1.1.1.4.1 christos __div_neg_num:
110 1.1.1.1.4.1 christos ;; Negate the numerator (which is in BCAX)
111 1.1.1.1.4.1 christos ;; We know that the denumerator is positive.
112 1.1.1.1.4.1 christos ;; Note - we temporarily overwrite DE. We know that we can safely load it again off the stack again.
113 1.1.1.1.4.1 christos movw de, ax
114 1.1.1.1.4.1 christos clrw ax
115 1.1.1.1.4.1 christos subw ax, de
116 1.1.1.1.4.1 christos movw de, ax
117 1.1.1.1.4.1 christos clrw ax
118 1.1.1.1.4.1 christos sknc
119 1.1.1.1.4.1 christos decw ax
120 1.1.1.1.4.1 christos subw ax, bc
121 1.1.1.1.4.1 christos movw bc, ax
122 1.1.1.1.4.1 christos
123 1.1.1.1.4.1 christos movw ax, [sp+8]
124 1.1.1.1.4.1 christos xchw ax, de
125 1.1.1.1.4.1 christos
126 1.1.1.1.4.1 christos __div_then_convert:
127 1.1.1.1.4.1 christos push psw
128 1.1.1.1.4.1 christos di
129 1.1.1.1.4.1 christos divwu
130 1.1.1.1.4.1 christos pop psw
131 1.1.1.1.4.1 christos
132 1.1.1.1.4.1 christos ;; Negate result (in BCAX) and transfer into r8,r10
133 1.1.1.1.4.1 christos movw de, ax
134 1.1.1.1.4.1 christos clrw ax
135 1.1.1.1.4.1 christos subw ax, de
136 1.1.1.1.4.1 christos movw r8, ax
137 1.1.1.1.4.1 christos clrw ax
138 1.1.1.1.4.1 christos sknc
139 1.1.1.1.4.1 christos decw ax
140 1.1.1.1.4.1 christos subw ax, bc
141 1.1.1.1.4.1 christos movw r10, ax
142 1.1.1.1.4.1 christos ret
143 1.1.1.1.4.1 christos
144 1.1.1.1.4.1 christos END_FUNC ___divsi3
145 1.1.1.1.4.1 christos
146 1.1.1.1.4.1 christos ;----------------------------------------------------------------------
147 1.1.1.1.4.1 christos
148 1.1.1.1.4.1 christos START_FUNC ___udivsi3
149 1.1.1.1.4.1 christos ;; r8,r10 = 4[sp],6[sp] / 8[sp],10[sp]
150 1.1.1.1.4.1 christos ;; Used when compiling with -Os specified.
151 1.1.1.1.4.1 christos
152 1.1.1.1.4.1 christos movw ax, [sp+10]
153 1.1.1.1.4.1 christos movw hl, ax
154 1.1.1.1.4.1 christos movw ax, [sp+8]
155 1.1.1.1.4.1 christos movw de, ax
156 1.1.1.1.4.1 christos movw ax, [sp+6]
157 1.1.1.1.4.1 christos movw bc, ax
158 1.1.1.1.4.1 christos movw ax, [sp+4]
159 1.1.1.1.4.1 christos push psw ; Save the current interrupt status
160 1.1.1.1.4.1 christos di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E
161 1.1.1.1.4.1 christos divwu ; bcax = bcax / hlde
162 1.1.1.1.4.1 christos pop psw ; Restore saved interrupt status
163 1.1.1.1.4.1 christos movw r8, ax
164 1.1.1.1.4.1 christos movw ax, bc
165 1.1.1.1.4.1 christos movw r10, ax
166 1.1.1.1.4.1 christos ret
167 1.1.1.1.4.1 christos
168 1.1.1.1.4.1 christos END_FUNC ___udivsi3
169 1.1.1.1.4.1 christos
170 1.1.1.1.4.1 christos ;----------------------------------------------------------------------
171 1.1.1.1.4.1 christos
172 1.1.1.1.4.1 christos START_FUNC ___modsi3
173 1.1.1.1.4.1 christos ;; r8,r10 = 4[sp],6[sp] % 8[sp],10[sp]
174 1.1.1.1.4.1 christos
175 1.1.1.1.4.1 christos ;; Load and test for a negative denumerator.
176 1.1.1.1.4.1 christos movw ax, [sp+8]
177 1.1.1.1.4.1 christos movw de, ax
178 1.1.1.1.4.1 christos movw ax, [sp+10]
179 1.1.1.1.4.1 christos mov1 cy, a.7
180 1.1.1.1.4.1 christos movw hl, ax
181 1.1.1.1.4.1 christos bc $__mod_neg_den
182 1.1.1.1.4.1 christos
183 1.1.1.1.4.1 christos ;; Load and test for a negative numerator.
184 1.1.1.1.4.1 christos movw ax, [sp+6]
185 1.1.1.1.4.1 christos mov1 cy, a.7
186 1.1.1.1.4.1 christos movw bc, ax
187 1.1.1.1.4.1 christos movw ax, [sp+4]
188 1.1.1.1.4.1 christos bc $__mod_neg_num
189 1.1.1.1.4.1 christos
190 1.1.1.1.4.1 christos ;; Neither are negative - we can use the unsigned divide instruction.
191 1.1.1.1.4.1 christos __mod_no_convert:
192 1.1.1.1.4.1 christos push psw
193 1.1.1.1.4.1 christos di
194 1.1.1.1.4.1 christos divwu
195 1.1.1.1.4.1 christos pop psw
196 1.1.1.1.4.1 christos
197 1.1.1.1.4.1 christos movw ax, de
198 1.1.1.1.4.1 christos movw r8, ax
199 1.1.1.1.4.1 christos movw ax, hl
200 1.1.1.1.4.1 christos movw r10, ax
201 1.1.1.1.4.1 christos ret
202 1.1.1.1.4.1 christos
203 1.1.1.1.4.1 christos __mod_neg_den:
204 1.1.1.1.4.1 christos ;; Negate the denumerator (which is in HLDE)
205 1.1.1.1.4.1 christos clrw ax
206 1.1.1.1.4.1 christos subw ax, de
207 1.1.1.1.4.1 christos movw de, ax
208 1.1.1.1.4.1 christos clrw ax
209 1.1.1.1.4.1 christos sknc
210 1.1.1.1.4.1 christos decw ax
211 1.1.1.1.4.1 christos subw ax, hl
212 1.1.1.1.4.1 christos movw hl, ax
213 1.1.1.1.4.1 christos
214 1.1.1.1.4.1 christos ;; Load and test for a negative numerator.
215 1.1.1.1.4.1 christos movw ax, [sp+6]
216 1.1.1.1.4.1 christos mov1 cy, a.7
217 1.1.1.1.4.1 christos movw bc, ax
218 1.1.1.1.4.1 christos movw ax, [sp+4]
219 1.1.1.1.4.1 christos ;; If it is not negative then we perform the modulo operation without conversion
220 1.1.1.1.4.1 christos bnc $__mod_no_convert
221 1.1.1.1.4.1 christos
222 1.1.1.1.4.1 christos ;; Otherwise we negate the numerator and then go with a modulo followed by negation.
223 1.1.1.1.4.1 christos ;; The negation is complicated because AX, BC, DE and HL are already in use.
224 1.1.1.1.4.1 christos xchw ax, bc
225 1.1.1.1.4.1 christos movw r8, ax
226 1.1.1.1.4.1 christos clrw ax
227 1.1.1.1.4.1 christos subw ax, bc
228 1.1.1.1.4.1 christos movw r10, ax
229 1.1.1.1.4.1 christos movw ax, r8
230 1.1.1.1.4.1 christos movw bc, ax
231 1.1.1.1.4.1 christos clrw ax
232 1.1.1.1.4.1 christos sknc
233 1.1.1.1.4.1 christos decw ax
234 1.1.1.1.4.1 christos subw ax, bc
235 1.1.1.1.4.1 christos movw bc, ax
236 1.1.1.1.4.1 christos movw ax, r10
237 1.1.1.1.4.1 christos br $!__mod_then_convert
238 1.1.1.1.4.1 christos
239 1.1.1.1.4.1 christos __mod_neg_num:
240 1.1.1.1.4.1 christos ;; Negate the numerator (which is in BCAX)
241 1.1.1.1.4.1 christos ;; We know that the denumerator is positive.
242 1.1.1.1.4.1 christos ;; Note - we temporarily overwrite DE. We know that we can safely load it again off the stack again.
243 1.1.1.1.4.1 christos movw de, ax
244 1.1.1.1.4.1 christos clrw ax
245 1.1.1.1.4.1 christos subw ax, de
246 1.1.1.1.4.1 christos movw de, ax
247 1.1.1.1.4.1 christos clrw ax
248 1.1.1.1.4.1 christos sknc
249 1.1.1.1.4.1 christos decw ax
250 1.1.1.1.4.1 christos subw ax, bc
251 1.1.1.1.4.1 christos movw bc, ax
252 1.1.1.1.4.1 christos
253 1.1.1.1.4.1 christos movw ax, [sp+8]
254 1.1.1.1.4.1 christos xchw ax, de
255 1.1.1.1.4.1 christos
256 1.1.1.1.4.1 christos __mod_then_convert:
257 1.1.1.1.4.1 christos push psw
258 1.1.1.1.4.1 christos di
259 1.1.1.1.4.1 christos divwu
260 1.1.1.1.4.1 christos pop psw
261 1.1.1.1.4.1 christos
262 1.1.1.1.4.1 christos ;; Negate result (in HLDE) and transfer into r8,r10
263 1.1.1.1.4.1 christos clrw ax
264 1.1.1.1.4.1 christos subw ax, de
265 1.1.1.1.4.1 christos movw r8, ax
266 1.1.1.1.4.1 christos clrw ax
267 1.1.1.1.4.1 christos sknc
268 1.1.1.1.4.1 christos decw ax
269 1.1.1.1.4.1 christos subw ax, hl
270 1.1.1.1.4.1 christos movw r10, ax
271 1.1.1.1.4.1 christos ret
272 1.1.1.1.4.1 christos
273 1.1.1.1.4.1 christos END_FUNC ___modsi3
274 1.1.1.1.4.1 christos
275 1.1.1.1.4.1 christos ;----------------------------------------------------------------------
276 1.1.1.1.4.1 christos
277 1.1.1.1.4.1 christos START_FUNC ___umodsi3
278 1.1.1.1.4.1 christos ;; r8,r10 = 4[sp],6[sp] % 8[sp],10[sp]
279 1.1.1.1.4.1 christos ;; Used when compiling with -Os specified.
280 1.1.1.1.4.1 christos
281 1.1.1.1.4.1 christos movw ax, [sp+10]
282 1.1.1.1.4.1 christos movw hl, ax
283 1.1.1.1.4.1 christos movw ax, [sp+8]
284 1.1.1.1.4.1 christos movw de, ax
285 1.1.1.1.4.1 christos movw ax, [sp+6]
286 1.1.1.1.4.1 christos movw bc, ax
287 1.1.1.1.4.1 christos movw ax, [sp+4]
288 1.1.1.1.4.1 christos push psw ; Save the current interrupt status
289 1.1.1.1.4.1 christos di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E
290 1.1.1.1.4.1 christos divwu ; hlde = bcax %% hlde
291 1.1.1.1.4.1 christos pop psw ; Restore saved interrupt status
292 1.1.1.1.4.1 christos movw ax, de
293 1.1.1.1.4.1 christos movw r8, ax
294 1.1.1.1.4.1 christos movw ax, hl
295 1.1.1.1.4.1 christos movw r10, ax
296 1.1.1.1.4.1 christos ret
297 1.1.1.1.4.1 christos
298 1.1.1.1.4.1 christos END_FUNC ___umodsi3
299 1.1.1.1.4.1 christos
300 1.1.1.1.4.1 christos ;----------------------------------------------------------------------
301 1.1.1.1.4.1 christos
302 1.1.1.1.4.1 christos #elif defined __RL78_MUL_G13__
303 1.1.1.1.4.1 christos
304 1.1.1.1.4.1 christos ;----------------------------------------------------------------------
305 1.1.1.1.4.1 christos
306 1.1.1.1.4.1 christos ;; Hardware registers. Note - these values match the silicon, not the documentation.
307 1.1.1.1.4.1 christos MDAL = 0xffff0
308 1.1.1.1.4.1 christos MDAH = 0xffff2
309 1.1.1.1.4.1 christos MDBL = 0xffff6
310 1.1.1.1.4.1 christos MDBH = 0xffff4
311 1.1.1.1.4.1 christos MDCL = 0xf00e0
312 1.1.1.1.4.1 christos MDCH = 0xf00e2
313 1.1.1.1.4.1 christos MDUC = 0xf00e8
314 1.1.1.1.4.1 christos
315 1.1.1.1.4.1 christos .macro _Negate low, high
316 1.1.1.1.4.1 christos movw ax, \low
317 1.1.1.1.4.1 christos movw bc, ax
318 1.1.1.1.4.1 christos clrw ax
319 1.1.1.1.4.1 christos subw ax, bc
320 1.1.1.1.4.1 christos movw \low, ax
321 1.1.1.1.4.1 christos movw ax, \high
322 1.1.1.1.4.1 christos movw bc, ax
323 1.1.1.1.4.1 christos clrw ax
324 1.1.1.1.4.1 christos sknc
325 1.1.1.1.4.1 christos decw ax
326 1.1.1.1.4.1 christos subw ax, bc
327 1.1.1.1.4.1 christos movw \high, ax
328 1.1.1.1.4.1 christos .endm
329 1.1.1.1.4.1 christos
330 1.1.1.1.4.1 christos ;----------------------------------------------------------------------
331 1.1.1.1.4.1 christos
332 1.1.1.1.4.1 christos START_FUNC ___divsi3
333 1.1.1.1.4.1 christos ;; r8,r10 = 4[sp],6[sp] / 8[sp],10[sp]
334 1.1.1.1.4.1 christos
335 1.1.1.1.4.1 christos mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1
336 1.1.1.1.4.1 christos mov !MDUC, a ; This preps the peripheral for division without interrupt generation
337 1.1.1.1.4.1 christos
338 1.1.1.1.4.1 christos ;; Load and test for a negative denumerator.
339 1.1.1.1.4.1 christos movw ax, [sp+8]
340 1.1.1.1.4.1 christos movw MDBL, ax
341 1.1.1.1.4.1 christos movw ax, [sp+10]
342 1.1.1.1.4.1 christos mov1 cy, a.7
343 1.1.1.1.4.1 christos movw MDBH, ax
344 1.1.1.1.4.1 christos bc $__div_neg_den
345 1.1.1.1.4.1 christos
346 1.1.1.1.4.1 christos ;; Load and test for a negative numerator.
347 1.1.1.1.4.1 christos movw ax, [sp+6]
348 1.1.1.1.4.1 christos mov1 cy, a.7
349 1.1.1.1.4.1 christos movw MDAH, ax
350 1.1.1.1.4.1 christos movw ax, [sp+4]
351 1.1.1.1.4.1 christos movw MDAL, ax
352 1.1.1.1.4.1 christos bc $__div_neg_num
353 1.1.1.1.4.1 christos
354 1.1.1.1.4.1 christos ;; Neither are negative - we can use the unsigned divide hardware.
355 1.1.1.1.4.1 christos __div_no_convert:
356 1.1.1.1.4.1 christos mov a, #0xC1 ; Set the DIVST bit in MDUC
357 1.1.1.1.4.1 christos mov !MDUC, a ; This starts the division op
358 1.1.1.1.4.1 christos
359 1.1.1.1.4.1 christos 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
360 1.1.1.1.4.1 christos bt a.0, $1b
361 1.1.1.1.4.1 christos
362 1.1.1.1.4.1 christos movw ax, MDAL ; Read the result
363 1.1.1.1.4.1 christos movw r8, ax
364 1.1.1.1.4.1 christos movw ax, MDAH
365 1.1.1.1.4.1 christos movw r10, ax
366 1.1.1.1.4.1 christos ret
367 1.1.1.1.4.1 christos
368 1.1.1.1.4.1 christos __div_neg_den:
369 1.1.1.1.4.1 christos ;; Negate the denumerator (which is in MDBL/MDBH)
370 1.1.1.1.4.1 christos _Negate MDBL MDBH
371 1.1.1.1.4.1 christos
372 1.1.1.1.4.1 christos ;; Load and test for a negative numerator.
373 1.1.1.1.4.1 christos movw ax, [sp+6]
374 1.1.1.1.4.1 christos mov1 cy, a.7
375 1.1.1.1.4.1 christos movw MDAH, ax
376 1.1.1.1.4.1 christos movw ax, [sp+4]
377 1.1.1.1.4.1 christos movw MDAL, ax
378 1.1.1.1.4.1 christos ;; If it is not negative then we perform the division and then negate the result.
379 1.1.1.1.4.1 christos bnc $__div_then_convert
380 1.1.1.1.4.1 christos
381 1.1.1.1.4.1 christos ;; Otherwise we negate the numerator and then go with a straightforward unsigned division.
382 1.1.1.1.4.1 christos _Negate MDAL MDAH
383 1.1.1.1.4.1 christos br $!__div_no_convert
384 1.1.1.1.4.1 christos
385 1.1.1.1.4.1 christos __div_neg_num:
386 1.1.1.1.4.1 christos ;; Negate the numerator (which is in MDAL/MDAH)
387 1.1.1.1.4.1 christos ;; We know that the denumerator is positive.
388 1.1.1.1.4.1 christos _Negate MDAL MDAH
389 1.1.1.1.4.1 christos
390 1.1.1.1.4.1 christos __div_then_convert:
391 1.1.1.1.4.1 christos mov a, #0xC1 ; Set the DIVST bit in MDUC
392 1.1.1.1.4.1 christos mov !MDUC, a ; This starts the division op
393 1.1.1.1.4.1 christos
394 1.1.1.1.4.1 christos 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
395 1.1.1.1.4.1 christos bt a.0, $1b
396 1.1.1.1.4.1 christos
397 1.1.1.1.4.1 christos ;; Negate result and transfer into r8,r10
398 1.1.1.1.4.1 christos _Negate MDAL MDAH ; FIXME: This could be coded more efficiently.
399 1.1.1.1.4.1 christos movw r10, ax
400 1.1.1.1.4.1 christos movw ax, MDAL
401 1.1.1.1.4.1 christos movw r8, ax
402 1.1.1.1.4.1 christos
403 1.1.1.1.4.1 christos ret
404 1.1.1.1.4.1 christos
405 1.1.1.1.4.1 christos END_FUNC ___divsi3
406 1.1.1.1.4.1 christos
407 1.1.1.1.4.1 christos ;----------------------------------------------------------------------
408 1.1.1.1.4.1 christos
409 1.1.1.1.4.1 christos START_FUNC ___modsi3
410 1.1.1.1.4.1 christos ;; r8,r10 = 4[sp],6[sp] % 8[sp],10[sp]
411 1.1.1.1.4.1 christos
412 1.1.1.1.4.1 christos mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1
413 1.1.1.1.4.1 christos mov !MDUC, a ; This preps the peripheral for division without interrupt generation
414 1.1.1.1.4.1 christos
415 1.1.1.1.4.1 christos ;; Load and test for a negative denumerator.
416 1.1.1.1.4.1 christos movw ax, [sp+8]
417 1.1.1.1.4.1 christos movw MDBL, ax
418 1.1.1.1.4.1 christos movw ax, [sp+10]
419 1.1.1.1.4.1 christos mov1 cy, a.7
420 1.1.1.1.4.1 christos movw MDBH, ax
421 1.1.1.1.4.1 christos bc $__mod_neg_den
422 1.1.1.1.4.1 christos
423 1.1.1.1.4.1 christos ;; Load and test for a negative numerator.
424 1.1.1.1.4.1 christos movw ax, [sp+6]
425 1.1.1.1.4.1 christos mov1 cy, a.7
426 1.1.1.1.4.1 christos movw MDAH, ax
427 1.1.1.1.4.1 christos movw ax, [sp+4]
428 1.1.1.1.4.1 christos movw MDAL, ax
429 1.1.1.1.4.1 christos bc $__mod_neg_num
430 1.1.1.1.4.1 christos
431 1.1.1.1.4.1 christos ;; Neither are negative - we can use the unsigned divide hardware
432 1.1.1.1.4.1 christos __mod_no_convert:
433 1.1.1.1.4.1 christos mov a, #0xC1 ; Set the DIVST bit in MDUC
434 1.1.1.1.4.1 christos mov !MDUC, a ; This starts the division op
435 1.1.1.1.4.1 christos
436 1.1.1.1.4.1 christos 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
437 1.1.1.1.4.1 christos bt a.0, $1b
438 1.1.1.1.4.1 christos
439 1.1.1.1.4.1 christos movw ax, !MDCL ; Read the remainder
440 1.1.1.1.4.1 christos movw r8, ax
441 1.1.1.1.4.1 christos movw ax, !MDCH
442 1.1.1.1.4.1 christos movw r10, ax
443 1.1.1.1.4.1 christos ret
444 1.1.1.1.4.1 christos
445 1.1.1.1.4.1 christos __mod_neg_den:
446 1.1.1.1.4.1 christos ;; Negate the denumerator (which is in MDBL/MDBH)
447 1.1.1.1.4.1 christos _Negate MDBL MDBH
448 1.1.1.1.4.1 christos
449 1.1.1.1.4.1 christos ;; Load and test for a negative numerator.
450 1.1.1.1.4.1 christos movw ax, [sp+6]
451 1.1.1.1.4.1 christos mov1 cy, a.7
452 1.1.1.1.4.1 christos movw MDAH, ax
453 1.1.1.1.4.1 christos movw ax, [sp+4]
454 1.1.1.1.4.1 christos movw MDAL, ax
455 1.1.1.1.4.1 christos ;; If it is not negative then we perform the modulo operation without conversion
456 1.1.1.1.4.1 christos bnc $__mod_no_convert
457 1.1.1.1.4.1 christos
458 1.1.1.1.4.1 christos ;; Otherwise we negate the numerator and then go with a modulo followed by negation.
459 1.1.1.1.4.1 christos _Negate MDAL MDAH
460 1.1.1.1.4.1 christos br $!__mod_then_convert
461 1.1.1.1.4.1 christos
462 1.1.1.1.4.1 christos __mod_neg_num:
463 1.1.1.1.4.1 christos ;; Negate the numerator (which is in MDAL/MDAH)
464 1.1.1.1.4.1 christos ;; We know that the denumerator is positive.
465 1.1.1.1.4.1 christos _Negate MDAL MDAH
466 1.1.1.1.4.1 christos
467 1.1.1.1.4.1 christos __mod_then_convert:
468 1.1.1.1.4.1 christos mov a, #0xC1 ; Set the DIVST bit in MDUC
469 1.1.1.1.4.1 christos mov !MDUC, a ; This starts the division op
470 1.1.1.1.4.1 christos
471 1.1.1.1.4.1 christos 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
472 1.1.1.1.4.1 christos bt a.0, $1b
473 1.1.1.1.4.1 christos
474 1.1.1.1.4.1 christos movw ax, !MDCL
475 1.1.1.1.4.1 christos movw bc, ax
476 1.1.1.1.4.1 christos clrw ax
477 1.1.1.1.4.1 christos subw ax, bc
478 1.1.1.1.4.1 christos movw r8, ax
479 1.1.1.1.4.1 christos movw ax, !MDCH
480 1.1.1.1.4.1 christos movw bc, ax
481 1.1.1.1.4.1 christos clrw ax
482 1.1.1.1.4.1 christos sknc
483 1.1.1.1.4.1 christos decw ax
484 1.1.1.1.4.1 christos subw ax, bc
485 1.1.1.1.4.1 christos movw r10, ax
486 1.1.1.1.4.1 christos ret
487 1.1.1.1.4.1 christos
488 1.1.1.1.4.1 christos END_FUNC ___modsi3
489 1.1.1.1.4.1 christos
490 1.1.1.1.4.1 christos ;----------------------------------------------------------------------
491 1.1.1.1.4.1 christos
492 1.1.1.1.4.1 christos START_FUNC ___udivsi3
493 1.1.1.1.4.1 christos ;; r8,r10 = 4[sp],6[sp] / 8[sp],10[sp]
494 1.1.1.1.4.1 christos ;; Used when compilng with -Os specified.
495 1.1.1.1.4.1 christos
496 1.1.1.1.4.1 christos mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1
497 1.1.1.1.4.1 christos mov !MDUC, a ; This preps the peripheral for division without interrupt generation
498 1.1.1.1.4.1 christos
499 1.1.1.1.4.1 christos movw ax, [sp+4] ; Load the divisor
500 1.1.1.1.4.1 christos movw MDAL, ax
501 1.1.1.1.4.1 christos movw ax, [sp+6]
502 1.1.1.1.4.1 christos movw MDAH, ax
503 1.1.1.1.4.1 christos movw ax, [sp+8] ; Load the dividend
504 1.1.1.1.4.1 christos movw MDBL, ax
505 1.1.1.1.4.1 christos movw ax, [sp+10]
506 1.1.1.1.4.1 christos movw MDBH, ax
507 1.1.1.1.4.1 christos
508 1.1.1.1.4.1 christos mov a, #0xC1 ; Set the DIVST bit in MDUC
509 1.1.1.1.4.1 christos mov !MDUC, a ; This starts the division op
510 1.1.1.1.4.1 christos
511 1.1.1.1.4.1 christos 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
512 1.1.1.1.4.1 christos bt a.0, $1b
513 1.1.1.1.4.1 christos
514 1.1.1.1.4.1 christos movw ax, !MDAL ; Read the result
515 1.1.1.1.4.1 christos movw r8, ax
516 1.1.1.1.4.1 christos movw ax, !MDAH
517 1.1.1.1.4.1 christos movw r10, ax
518 1.1.1.1.4.1 christos ret
519 1.1.1.1.4.1 christos
520 1.1.1.1.4.1 christos END_FUNC ___udivsi3
521 1.1.1.1.4.1 christos
522 1.1.1.1.4.1 christos ;----------------------------------------------------------------------
523 1.1.1.1.4.1 christos
524 1.1.1.1.4.1 christos START_FUNC ___umodsi3
525 1.1.1.1.4.1 christos ;; r8,r10 = 4[sp],6[sp] % 8[sp],10[sp]
526 1.1.1.1.4.1 christos ;; Used when compilng with -Os specified.
527 1.1.1.1.4.1 christos ;; Note - hardware address match the silicon, not the documentation
528 1.1.1.1.4.1 christos
529 1.1.1.1.4.1 christos mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1
530 1.1.1.1.4.1 christos mov !MDUC, a ; This preps the peripheral for division without interrupt generation
531 1.1.1.1.4.1 christos
532 1.1.1.1.4.1 christos movw ax, [sp+4] ; Load the divisor
533 1.1.1.1.4.1 christos movw MDAL, ax
534 1.1.1.1.4.1 christos movw ax, [sp+6]
535 1.1.1.1.4.1 christos movw MDAH, ax
536 1.1.1.1.4.1 christos movw ax, [sp+8] ; Load the dividend
537 1.1.1.1.4.1 christos movw MDBL, ax
538 1.1.1.1.4.1 christos movw ax, [sp+10]
539 1.1.1.1.4.1 christos movw MDBH, ax
540 1.1.1.1.4.1 christos
541 1.1.1.1.4.1 christos mov a, #0xC1 ; Set the DIVST bit in MDUC
542 1.1.1.1.4.1 christos mov !MDUC, a ; This starts the division op
543 1.1.1.1.4.1 christos
544 1.1.1.1.4.1 christos 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
545 1.1.1.1.4.1 christos bt a.0, $1b
546 1.1.1.1.4.1 christos
547 1.1.1.1.4.1 christos movw ax, !MDCL ; Read the remainder
548 1.1.1.1.4.1 christos movw r8, ax
549 1.1.1.1.4.1 christos movw ax, !MDCH
550 1.1.1.1.4.1 christos movw r10, ax
551 1.1.1.1.4.1 christos ret
552 1.1.1.1.4.1 christos
553 1.1.1.1.4.1 christos END_FUNC ___umodsi3
554 1.1.1.1.4.1 christos
555 1.1.1.1.4.1 christos ;----------------------------------------------------------------------
556 1.1.1.1.4.1 christos
557 1.1.1.1.4.1 christos #elif defined __RL78_MUL_NONE__
558 1.1.1.1.4.1 christos
559 1.1 mrg .macro MAKE_GENERIC which,need_result
560 1.1 mrg
561 1.1 mrg .if \need_result
562 1.1 mrg quot = r8
563 1.1 mrg num = r12
564 1.1 mrg den = r16
565 1.1 mrg bit = r20
566 1.1 mrg .else
567 1.1 mrg num = r8
568 1.1 mrg quot = r12
569 1.1 mrg den = r16
570 1.1 mrg bit = r20
571 1.1 mrg .endif
572 1.1 mrg
573 1.1 mrg quotH = quot+2
574 1.1 mrg quotL = quot
575 1.1 mrg quotB0 = quot
576 1.1 mrg quotB1 = quot+1
577 1.1 mrg quotB2 = quot+2
578 1.1 mrg quotB3 = quot+3
579 1.1 mrg
580 1.1 mrg numH = num+2
581 1.1 mrg numL = num
582 1.1 mrg numB0 = num
583 1.1 mrg numB1 = num+1
584 1.1 mrg numB2 = num+2
585 1.1 mrg numB3 = num+3
586 1.1 mrg
587 1.1 mrg #define denH bc
588 1.1 mrg denL = den
589 1.1 mrg denB0 = den
590 1.1 mrg denB1 = den+1
591 1.1 mrg #define denB2 c
592 1.1 mrg #define denB3 b
593 1.1 mrg
594 1.1 mrg bitH = bit+2
595 1.1 mrg bitL = bit
596 1.1 mrg bitB0 = bit
597 1.1 mrg bitB1 = bit+1
598 1.1 mrg bitB2 = bit+2
599 1.1 mrg bitB3 = bit+3
600 1.1 mrg
601 1.1.1.1.4.1 christos ;----------------------------------------------------------------------
602 1.1.1.1.4.1 christos
603 1.1 mrg START_FUNC __generic_sidivmod\which
604 1.1 mrg
605 1.1 mrg num_lt_den\which:
606 1.1 mrg .if \need_result
607 1.1 mrg movw r8, #0
608 1.1 mrg movw r10, #0
609 1.1 mrg .else
610 1.1 mrg movw ax, [sp+8]
611 1.1 mrg movw r8, ax
612 1.1 mrg movw ax, [sp+10]
613 1.1 mrg movw r10, ax
614 1.1 mrg .endif
615 1.1 mrg ret
616 1.1 mrg
617 1.1 mrg shift_den_bit16\which:
618 1.1 mrg movw ax, denL
619 1.1 mrg movw denH, ax
620 1.1 mrg movw denL, #0
621 1.1 mrg .if \need_result
622 1.1 mrg movw ax, bitL
623 1.1 mrg movw bitH, ax
624 1.1 mrg movw bitL, #0
625 1.1 mrg .else
626 1.1 mrg mov a, bit
627 1.1 mrg add a, #16
628 1.1 mrg mov bit, a
629 1.1 mrg .endif
630 1.1 mrg br $shift_den_bit\which
631 1.1 mrg
632 1.1 mrg ;; These routines leave DE alone - the signed functions use DE
633 1.1 mrg ;; to store sign information that must remain intact
634 1.1 mrg
635 1.1 mrg .if \need_result
636 1.1 mrg .global __generic_sidiv
637 1.1 mrg __generic_sidiv:
638 1.1 mrg
639 1.1 mrg .else
640 1.1 mrg
641 1.1 mrg .global __generic_simod
642 1.1 mrg __generic_simod:
643 1.1 mrg
644 1.1 mrg .endif
645 1.1 mrg
646 1.1 mrg ;; (quot,rem) = 8[sp] /% 12[sp]
647 1.1 mrg
648 1.1 mrg movw hl, sp
649 1.1 mrg movw ax, [hl+14] ; denH
650 1.1 mrg cmpw ax, [hl+10] ; numH
651 1.1 mrg movw ax, [hl+12] ; denL
652 1.1 mrg sknz
653 1.1 mrg cmpw ax, [hl+8] ; numL
654 1.1 mrg bh $num_lt_den\which
655 1.1 mrg
656 1.1 mrg #ifdef __RL78_G10__
657 1.1 mrg movw ax, denL
658 1.1 mrg push ax
659 1.1 mrg movw ax, bitL
660 1.1 mrg push ax
661 1.1 mrg movw ax, bitH
662 1.1 mrg push ax
663 1.1 mrg #else
664 1.1 mrg sel rb2
665 1.1 mrg push ax ; denL
666 1.1 mrg ; push bc ; denH
667 1.1 mrg push de ; bitL
668 1.1 mrg push hl ; bitH - stored in BC
669 1.1 mrg sel rb0
670 1.1 mrg #endif
671 1.1 mrg
672 1.1 mrg ;; (quot,rem) = 16[sp] /% 20[sp]
673 1.1 mrg
674 1.1 mrg ;; copy numerator
675 1.1 mrg movw ax, [hl+8]
676 1.1 mrg movw numL, ax
677 1.1 mrg movw ax, [hl+10]
678 1.1 mrg movw numH, ax
679 1.1 mrg
680 1.1 mrg ;; copy denomonator
681 1.1 mrg movw ax, [hl+12]
682 1.1 mrg movw denL, ax
683 1.1 mrg movw ax, [hl+14]
684 1.1 mrg movw denH, ax
685 1.1 mrg
686 1.1 mrg movw ax, denL
687 1.1 mrg or a, denB2
688 1.1 mrg or a, denB3 ; not x
689 1.1 mrg cmpw ax, #0
690 1.1 mrg bnz $den_not_zero\which
691 1.1.1.1.4.1 christos .if \need_result
692 1.1.1.1.4.1 christos movw quotL, #0
693 1.1.1.1.4.1 christos movw quotH, #0
694 1.1.1.1.4.1 christos .else
695 1.1 mrg movw numL, #0
696 1.1 mrg movw numH, #0
697 1.1.1.1.4.1 christos .endif
698 1.1.1.1.4.1 christos br $!main_loop_done_himode\which
699 1.1 mrg
700 1.1 mrg den_not_zero\which:
701 1.1 mrg .if \need_result
702 1.1 mrg ;; zero out quot
703 1.1 mrg movw quotL, #0
704 1.1 mrg movw quotH, #0
705 1.1 mrg .endif
706 1.1 mrg
707 1.1 mrg ;; initialize bit to 1
708 1.1 mrg movw bitL, #1
709 1.1 mrg movw bitH, #0
710 1.1 mrg
711 1.1 mrg ; while (den < num && !(den & (1L << BITS_MINUS_1)))
712 1.1 mrg
713 1.1 mrg .if 1
714 1.1 mrg ;; see if we can short-circuit a bunch of shifts
715 1.1 mrg movw ax, denH
716 1.1 mrg cmpw ax, #0
717 1.1 mrg bnz $shift_den_bit\which
718 1.1 mrg movw ax, denL
719 1.1 mrg cmpw ax, numH
720 1.1 mrg bnh $shift_den_bit16\which
721 1.1 mrg .endif
722 1.1 mrg
723 1.1 mrg shift_den_bit\which:
724 1.1 mrg movw ax, denH
725 1.1 mrg mov1 cy,a.7
726 1.1 mrg bc $enter_main_loop\which
727 1.1 mrg cmpw ax, numH
728 1.1 mrg movw ax, denL ; we re-use this below
729 1.1 mrg sknz
730 1.1 mrg cmpw ax, numL
731 1.1 mrg bh $enter_main_loop\which
732 1.1 mrg
733 1.1 mrg ;; den <<= 1
734 1.1 mrg ; movw ax, denL ; already has it from the cmpw above
735 1.1 mrg shlw ax, 1
736 1.1 mrg movw denL, ax
737 1.1 mrg ; movw ax, denH
738 1.1 mrg rolwc denH, 1
739 1.1 mrg ; movw denH, ax
740 1.1 mrg
741 1.1 mrg ;; bit <<= 1
742 1.1 mrg .if \need_result
743 1.1 mrg movw ax, bitL
744 1.1 mrg shlw ax, 1
745 1.1 mrg movw bitL, ax
746 1.1 mrg movw ax, bitH
747 1.1 mrg rolwc ax, 1
748 1.1 mrg movw bitH, ax
749 1.1 mrg .else
750 1.1 mrg ;; if we don't need to compute the quotent, we don't need an
751 1.1 mrg ;; actual bit *mask*, we just need to keep track of which bit
752 1.1 mrg inc bitB0
753 1.1 mrg .endif
754 1.1 mrg
755 1.1 mrg br $shift_den_bit\which
756 1.1 mrg
757 1.1 mrg ;; while (bit)
758 1.1 mrg main_loop\which:
759 1.1 mrg
760 1.1 mrg ;; if (num >= den) (cmp den > num)
761 1.1 mrg movw ax, numH
762 1.1 mrg cmpw ax, denH
763 1.1 mrg movw ax, numL
764 1.1 mrg sknz
765 1.1 mrg cmpw ax, denL
766 1.1 mrg skz
767 1.1 mrg bnh $next_loop\which
768 1.1 mrg
769 1.1 mrg ;; num -= den
770 1.1 mrg ; movw ax, numL ; already has it from the cmpw above
771 1.1 mrg subw ax, denL
772 1.1 mrg movw numL, ax
773 1.1 mrg movw ax, numH
774 1.1 mrg sknc
775 1.1 mrg decw ax
776 1.1 mrg subw ax, denH
777 1.1 mrg movw numH, ax
778 1.1 mrg
779 1.1 mrg .if \need_result
780 1.1 mrg ;; res |= bit
781 1.1 mrg mov a, quotB0
782 1.1 mrg or a, bitB0
783 1.1 mrg mov quotB0, a
784 1.1 mrg mov a, quotB1
785 1.1 mrg or a, bitB1
786 1.1 mrg mov quotB1, a
787 1.1 mrg mov a, quotB2
788 1.1 mrg or a, bitB2
789 1.1 mrg mov quotB2, a
790 1.1 mrg mov a, quotB3
791 1.1 mrg or a, bitB3
792 1.1 mrg mov quotB3, a
793 1.1 mrg .endif
794 1.1 mrg
795 1.1 mrg next_loop\which:
796 1.1 mrg
797 1.1 mrg ;; den >>= 1
798 1.1 mrg movw ax, denH
799 1.1 mrg shrw ax, 1
800 1.1 mrg movw denH, ax
801 1.1 mrg mov a, denB1
802 1.1 mrg rorc a, 1
803 1.1 mrg mov denB1, a
804 1.1 mrg mov a, denB0
805 1.1 mrg rorc a, 1
806 1.1 mrg mov denB0, a
807 1.1 mrg
808 1.1 mrg ;; bit >>= 1
809 1.1 mrg .if \need_result
810 1.1 mrg movw ax, bitH
811 1.1 mrg shrw ax, 1
812 1.1 mrg movw bitH, ax
813 1.1 mrg mov a, bitB1
814 1.1 mrg rorc a, 1
815 1.1 mrg mov bitB1, a
816 1.1 mrg mov a, bitB0
817 1.1 mrg rorc a, 1
818 1.1 mrg mov bitB0, a
819 1.1 mrg .else
820 1.1 mrg dec bitB0
821 1.1 mrg .endif
822 1.1 mrg
823 1.1 mrg enter_main_loop\which:
824 1.1 mrg .if \need_result
825 1.1 mrg movw ax, bitH
826 1.1 mrg cmpw ax, #0
827 1.1 mrg bnz $main_loop\which
828 1.1 mrg .else
829 1.1 mrg cmp bitB0, #15
830 1.1 mrg bh $main_loop\which
831 1.1 mrg .endif
832 1.1 mrg ;; bit is HImode now; check others
833 1.1 mrg movw ax, numH ; numerator
834 1.1 mrg cmpw ax, #0
835 1.1 mrg bnz $bit_high_set\which
836 1.1 mrg movw ax, denH ; denominator
837 1.1 mrg cmpw ax, #0
838 1.1 mrg bz $switch_to_himode\which
839 1.1 mrg bit_high_set\which:
840 1.1 mrg .if \need_result
841 1.1 mrg movw ax, bitL
842 1.1 mrg cmpw ax, #0
843 1.1 mrg .else
844 1.1 mrg cmp0 bitB0
845 1.1 mrg .endif
846 1.1 mrg bnz $main_loop\which
847 1.1 mrg
848 1.1 mrg switch_to_himode\which:
849 1.1 mrg .if \need_result
850 1.1 mrg movw ax, bitL
851 1.1 mrg cmpw ax, #0
852 1.1 mrg .else
853 1.1 mrg cmp0 bitB0
854 1.1 mrg .endif
855 1.1 mrg bz $main_loop_done_himode\which
856 1.1 mrg
857 1.1 mrg ;; From here on in, r22, r14, and r18 are all zero
858 1.1 mrg ;; while (bit)
859 1.1 mrg main_loop_himode\which:
860 1.1 mrg
861 1.1 mrg ;; if (num >= den) (cmp den > num)
862 1.1 mrg movw ax, denL
863 1.1 mrg cmpw ax, numL
864 1.1 mrg bh $next_loop_himode\which
865 1.1 mrg
866 1.1 mrg ;; num -= den
867 1.1 mrg movw ax, numL
868 1.1 mrg subw ax, denL
869 1.1 mrg movw numL, ax
870 1.1 mrg movw ax, numH
871 1.1 mrg sknc
872 1.1 mrg decw ax
873 1.1 mrg subw ax, denH
874 1.1 mrg movw numH, ax
875 1.1 mrg
876 1.1 mrg .if \need_result
877 1.1 mrg ;; res |= bit
878 1.1 mrg mov a, quotB0
879 1.1 mrg or a, bitB0
880 1.1 mrg mov quotB0, a
881 1.1 mrg mov a, quotB1
882 1.1 mrg or a, bitB1
883 1.1 mrg mov quotB1, a
884 1.1 mrg .endif
885 1.1 mrg
886 1.1 mrg next_loop_himode\which:
887 1.1 mrg
888 1.1 mrg ;; den >>= 1
889 1.1 mrg movw ax, denL
890 1.1 mrg shrw ax, 1
891 1.1 mrg movw denL, ax
892 1.1 mrg
893 1.1 mrg .if \need_result
894 1.1 mrg ;; bit >>= 1
895 1.1 mrg movw ax, bitL
896 1.1 mrg shrw ax, 1
897 1.1 mrg movw bitL, ax
898 1.1 mrg .else
899 1.1 mrg dec bitB0
900 1.1 mrg .endif
901 1.1 mrg
902 1.1 mrg .if \need_result
903 1.1 mrg movw ax, bitL
904 1.1 mrg cmpw ax, #0
905 1.1 mrg .else
906 1.1 mrg cmp0 bitB0
907 1.1 mrg .endif
908 1.1 mrg bnz $main_loop_himode\which
909 1.1 mrg
910 1.1 mrg main_loop_done_himode\which:
911 1.1 mrg #ifdef __RL78_G10__
912 1.1 mrg pop ax
913 1.1 mrg movw bitH, ax
914 1.1 mrg pop ax
915 1.1 mrg movw bitL, ax
916 1.1 mrg pop ax
917 1.1 mrg movw denL, ax
918 1.1 mrg #else
919 1.1 mrg sel rb2
920 1.1 mrg pop hl ; bitH - stored in BC
921 1.1 mrg pop de ; bitL
922 1.1 mrg ; pop bc ; denH
923 1.1 mrg pop ax ; denL
924 1.1 mrg sel rb0
925 1.1 mrg #endif
926 1.1 mrg
927 1.1 mrg ret
928 1.1 mrg END_FUNC __generic_sidivmod\which
929 1.1 mrg .endm
930 1.1 mrg
931 1.1 mrg ;----------------------------------------------------------------------
932 1.1 mrg
933 1.1 mrg MAKE_GENERIC _d 1
934 1.1 mrg MAKE_GENERIC _m 0
935 1.1 mrg
936 1.1 mrg ;----------------------------------------------------------------------
937 1.1 mrg
938 1.1 mrg START_FUNC ___udivsi3
939 1.1 mrg ;; r8 = 4[sp] / 8[sp]
940 1.1 mrg call $!__generic_sidiv
941 1.1 mrg ret
942 1.1 mrg END_FUNC ___udivsi3
943 1.1 mrg
944 1.1 mrg
945 1.1 mrg START_FUNC ___umodsi3
946 1.1 mrg ;; r8 = 4[sp] % 8[sp]
947 1.1 mrg call $!__generic_simod
948 1.1 mrg ret
949 1.1 mrg END_FUNC ___umodsi3
950 1.1 mrg
951 1.1 mrg ;----------------------------------------------------------------------
952 1.1 mrg
953 1.1 mrg .macro NEG_AX
954 1.1 mrg movw hl, ax
955 1.1 mrg movw ax, #0
956 1.1 mrg subw ax, [hl]
957 1.1 mrg movw [hl], ax
958 1.1 mrg movw ax, #0
959 1.1 mrg sknc
960 1.1 mrg decw ax
961 1.1 mrg subw ax, [hl+2]
962 1.1 mrg movw [hl+2], ax
963 1.1 mrg .endm
964 1.1 mrg
965 1.1 mrg ;----------------------------------------------------------------------
966 1.1 mrg
967 1.1 mrg START_FUNC ___divsi3
968 1.1 mrg ;; r8 = 4[sp] / 8[sp]
969 1.1 mrg movw de, #0
970 1.1 mrg mov a, [sp+7]
971 1.1 mrg mov1 cy, a.7
972 1.1 mrg bc $div_signed_num
973 1.1 mrg mov a, [sp+11]
974 1.1 mrg mov1 cy, a.7
975 1.1 mrg bc $div_signed_den
976 1.1 mrg call $!__generic_sidiv
977 1.1 mrg ret
978 1.1 mrg
979 1.1 mrg div_signed_num:
980 1.1 mrg ;; neg [sp+4]
981 1.1 mrg movw ax, sp
982 1.1 mrg addw ax, #4
983 1.1 mrg NEG_AX
984 1.1 mrg mov d, #1
985 1.1 mrg mov a, [sp+11]
986 1.1 mrg mov1 cy, a.7
987 1.1 mrg bnc $div_unsigned_den
988 1.1 mrg div_signed_den:
989 1.1 mrg ;; neg [sp+8]
990 1.1 mrg movw ax, sp
991 1.1 mrg addw ax, #8
992 1.1 mrg NEG_AX
993 1.1 mrg mov e, #1
994 1.1 mrg div_unsigned_den:
995 1.1 mrg call $!__generic_sidiv
996 1.1 mrg
997 1.1 mrg mov a, d
998 1.1 mrg cmp0 a
999 1.1 mrg bz $div_skip_restore_num
1000 1.1 mrg ;; We have to restore the numerator [sp+4]
1001 1.1 mrg movw ax, sp
1002 1.1 mrg addw ax, #4
1003 1.1 mrg NEG_AX
1004 1.1 mrg mov a, d
1005 1.1 mrg div_skip_restore_num:
1006 1.1 mrg xor a, e
1007 1.1 mrg bz $div_no_neg
1008 1.1 mrg movw ax, #r8
1009 1.1 mrg NEG_AX
1010 1.1 mrg div_no_neg:
1011 1.1 mrg mov a, e
1012 1.1 mrg cmp0 a
1013 1.1 mrg bz $div_skip_restore_den
1014 1.1 mrg ;; We have to restore the denominator [sp+8]
1015 1.1 mrg movw ax, sp
1016 1.1 mrg addw ax, #8
1017 1.1 mrg NEG_AX
1018 1.1 mrg div_skip_restore_den:
1019 1.1 mrg ret
1020 1.1 mrg END_FUNC ___divsi3
1021 1.1 mrg
1022 1.1 mrg
1023 1.1 mrg START_FUNC ___modsi3
1024 1.1 mrg ;; r8 = 4[sp] % 8[sp]
1025 1.1 mrg movw de, #0
1026 1.1 mrg mov a, [sp+7]
1027 1.1 mrg mov1 cy, a.7
1028 1.1 mrg bc $mod_signed_num
1029 1.1 mrg mov a, [sp+11]
1030 1.1 mrg mov1 cy, a.7
1031 1.1 mrg bc $mod_signed_den
1032 1.1 mrg call $!__generic_simod
1033 1.1 mrg ret
1034 1.1 mrg
1035 1.1 mrg mod_signed_num:
1036 1.1 mrg ;; neg [sp+4]
1037 1.1 mrg movw ax, sp
1038 1.1 mrg addw ax, #4
1039 1.1 mrg NEG_AX
1040 1.1 mrg mov d, #1
1041 1.1 mrg mov a, [sp+11]
1042 1.1 mrg mov1 cy, a.7
1043 1.1 mrg bnc $mod_unsigned_den
1044 1.1 mrg mod_signed_den:
1045 1.1 mrg ;; neg [sp+8]
1046 1.1 mrg movw ax, sp
1047 1.1 mrg addw ax, #8
1048 1.1 mrg NEG_AX
1049 1.1 mrg mov e, #1
1050 1.1 mrg mod_unsigned_den:
1051 1.1 mrg call $!__generic_simod
1052 1.1 mrg
1053 1.1 mrg mov a, d
1054 1.1 mrg cmp0 a
1055 1.1 mrg bz $mod_no_neg
1056 1.1 mrg movw ax, #r8
1057 1.1 mrg NEG_AX
1058 1.1 mrg ;; We have to restore [sp+4] as well.
1059 1.1 mrg movw ax, sp
1060 1.1 mrg addw ax, #4
1061 1.1 mrg NEG_AX
1062 1.1 mrg mod_no_neg:
1063 1.1 mrg .if 1
1064 1.1 mrg mov a, e
1065 1.1 mrg cmp0 a
1066 1.1 mrg bz $mod_skip_restore_den
1067 1.1 mrg movw ax, sp
1068 1.1 mrg addw ax, #8
1069 1.1 mrg NEG_AX
1070 1.1 mrg mod_skip_restore_den:
1071 1.1 mrg .endif
1072 1.1 mrg ret
1073 1.1 mrg END_FUNC ___modsi3
1074 1.1.1.1.4.1 christos
1075 1.1.1.1.4.1 christos ;----------------------------------------------------------------------
1076 1.1.1.1.4.1 christos
1077 1.1.1.1.4.1 christos #else
1078 1.1.1.1.4.1 christos
1079 1.1.1.1.4.1 christos #error "Unknown RL78 hardware multiply/divide support"
1080 1.1.1.1.4.1 christos
1081 1.1.1.1.4.1 christos #endif
1082