gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
gbdk-lib/libc/_divulong.c
1 /*-------------------------------------------------------------------------
2 _divulong.c - routine for division of 32 bit unsigned long
3
4 Ecrit par - Jean-Louis Vern . jlvern@writeme.com (1999)
5
6 This library is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Library General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24
25 /* Assembler-functions are provided for:
26 mcs51 small
27 mcs51 small stack-auto
28 */
29
30 #if !defined(SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
31 # if defined(SDCC_mcs51)
32 # if defined(SDCC_MODEL_SMALL)
33 # if defined(SDCC_STACK_AUTO)
34 # define _DIVULONG_ASM_SMALL_AUTO
35 # else
36 # define _DIVULONG_ASM_SMALL
37 # endif
38 # endif
39 # endif
40 #endif
41
42 #if defined _DIVULONG_ASM_SMALL
43
44 static void
45 _divlong_dummy (void) _naked
46 {
47 _asm
48
49 .globl __divulong
50
51 __divulong:
52
53 #define count r2
54
55 #define a0 dpl
56 #define a1 dph
57 #define a2 b
58 #define a3 r3
59
60 #define reste0 r4
61 #define reste1 r5
62 #define reste2 r6
63 #define reste3 r7
64
65 #if defined(SDCC_NOOVERLAY)
66 .area DSEG (DATA)
67 #else
68 .area OSEG (OVR,DATA)
69 #endif
70
71 .globl __divulong_PARM_2
72 .globl __divslong_PARM_2
73
74 __divulong_PARM_2:
75 __divslong_PARM_2:
76 .ds 4
77
78 .area CSEG (CODE)
79
80 #define b0 (__divulong_PARM_2)
81 #define b1 (__divulong_PARM_2 + 1)
82 #define b2 (__divulong_PARM_2 + 2)
83 #define b3 (__divulong_PARM_2 + 3)
84
85 ; parameter a comes in a, b, dph, dpl
86 mov a3,a ; save parameter a3
87
88 mov count,#32
89 clr a
90 mov reste0,a
91 mov reste1,a
92 mov reste2,a
93 mov reste3,a
94
95 ; optimization loop in lp0 until the first bit is shifted into rest
96
97 lp0: mov a,a0 ; a <<= 1
98 add a,a0
99 mov a0,a
100 mov a,a1
101 rlc a
102 mov a1,a
103 mov a,a2
104 rlc a
105 mov a2,a
106 mov a,a3
107 rlc a
108 mov a3,a
109
110 jc in_lp
111 djnz count,lp0
112
113 sjmp exit
114
115 loop: mov a,a0 ; a <<= 1
116 add a,a0
117 mov a0,a
118 mov a,a1
119 rlc a
120 mov a1,a
121 mov a,a2
122 rlc a
123 mov a2,a
124 mov a,a3
125 rlc a
126 mov a3,a
127
128 in_lp: mov a,reste0 ; reste <<= 1
129 rlc a ; feed in carry
130 mov reste0,a
131 mov a,reste1
132 rlc a
133 mov reste1,a
134 mov a,reste2
135 rlc a
136 mov reste2,a
137 mov a,reste3
138 rlc a
139 mov reste3,a
140
141 mov a,reste0 ; reste - b
142 subb a,b0 ; carry is always clear here, because
143 ; reste <<= 1 never overflows
144 mov a,reste1
145 subb a,b1
146 mov a,reste2
147 subb a,b2
148 mov a,reste3
149 subb a,b3
150
151 jc minus ; reste >= b?
152
153 ; -> yes; reste -= b;
154 mov a,reste0
155 subb a,b0 ; carry is always clear here (jc)
156 mov reste0,a
157 mov a,reste1
158 subb a,b1
159 mov reste1,a
160 mov a,reste2
161 subb a,b2
162 mov reste2,a
163 mov a,reste3
164 subb a,b3
165 mov reste3,a
166
167 orl a0,#1
168
169 minus: djnz count,loop ; -> no
170
171 exit: mov a,a3 ; prepare the return value
172 ret
173
174 _endasm ;
175 }
176
177 #elif defined _DIVULONG_ASM_SMALL_AUTO
178
179 static void
180 _divlong_dummy (void) _naked
181 {
182 _asm
183
184 .globl __divulong
185
186 __divulong:
187
188 #define count r2
189
190 #define a0 dpl
191 #define a1 dph
192 #define a2 b
193 #define a3 r3
194
195 #define reste0 r4
196 #define reste1 r5
197 #define reste2 r6
198 #define reste3 r7
199
200 .globl __divlong ; entry point for __divslong
201
202 #define b0 r1
203
204 ar0 = 0 ; BUG register set is not considered
205 ar1 = 1
206
207 ; parameter a comes in a, b, dph, dpl
208 mov a3,a ; save parameter a3
209
210 mov a,sp
211 add a,#-2-3 ; 2 bytes return address, 3 bytes param b
212 mov r0,a ; r0 points to b0
213
214 __divlong: ; entry point for __divslong
215
216 mov ar1,@r0 ; load b0
217 inc r0 ; r0 points to b1
218
219 mov count,#32
220 clr a
221 mov reste0,a
222 mov reste1,a
223 mov reste2,a
224 mov reste3,a
225
226 ; optimization loop in lp0 until the first bit is shifted into rest
227
228 lp0: mov a,a0 ; a <<= 1
229 add a,a0
230 mov a0,a
231 mov a,a1
232 rlc a
233 mov a1,a
234 mov a,a2
235 rlc a
236 mov a2,a
237 mov a,a3
238 rlc a
239 mov a3,a
240
241 jc in_lp
242 djnz count,lp0
243
244 sjmp exit
245
246 loop: mov a,a0 ; a <<= 1
247 add a,a0
248 mov a0,a
249 mov a,a1
250 rlc a
251 mov a1,a
252 mov a,a2
253 rlc a
254 mov a2,a
255 mov a,a3
256 rlc a
257 mov a3,a
258
259 in_lp: mov a,reste0 ; reste <<= 1
260 rlc a ; feed in carry
261 mov reste0,a
262 mov a,reste1
263 rlc a
264 mov reste1,a
265 mov a,reste2
266 rlc a
267 mov reste2,a
268 mov a,reste3
269 rlc a
270 mov reste3,a
271
272 mov a,reste0 ; reste - b
273 subb a,b0 ; carry is always clear here, because
274 ; reste <<= 1 never overflows
275 mov a,reste1
276 subb a,@r0 ; b1
277 mov a,reste2
278 inc r0
279 subb a,@r0 ; b2
280 mov a,reste3
281 inc r0
282 subb a,@r0 ; b3
283 dec r0
284 dec r0
285
286 jc minus ; reste >= b?
287
288 ; -> yes; reste -= b;
289 mov a,reste0
290 subb a,b0 ; carry is always clear here (jc)
291 mov reste0,a
292 mov a,reste1
293 subb a,@r0 ; b1
294 mov reste1,a
295 mov a,reste2
296 inc r0
297 subb a,@r0 ; b2
298 mov reste2,a
299 mov a,reste3
300 inc r0
301 subb a,@r0 ; b3
302 mov reste3,a
303 dec r0
304 dec r0
305
306 orl a0,#1
307
308 minus: djnz count,loop ; -> no
309
310 exit: mov a,a3 ; prepare the return value
311 ret
312
313 _endasm ;
314 }
315
316 #else // _DIVULONG_ASM
317
318 #define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1)
319
320 unsigned long
321 _divulong (unsigned long a, unsigned long b)
322 {
323 unsigned long reste = 0L;
324 unsigned char count = 32;
325 #if defined(__SDCC_STACK_AUTO) || defined(__SDCC_z80) || defined(__SDCC_sm83) || defined(__SDCC_mos6502)
326 char c;
327 #else
328 bit c;
329 #endif
330
331 do
332 {
333 // reste: a <- 0;
334 c = MSB_SET(a);
335 a <<= 1;
336 reste <<= 1;
337 if (c)
338 reste |= 1L;
339
340 if (reste >= b)
341 {
342 reste -= b;
343 // a <- (result = 1)
344 a |= 1L;
345 }
346 }
347 while (--count);
348 return a;
349 }
350
351 #endif // _DIVULONG_ASM
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.