Prepare for SDCC 4.5.0 release.
[sdcc.git] / sdcc / device / lib / _modulong.c
blob8901d067aa1fbf949f80c0586726c9b20ba19810
1 /*-------------------------------------------------------------------------
2 _modulong.c - routine for modulus of 32 bit unsigned long
4 Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net
5 Bug fixes by Martijn van Balen, aed@iae.nl
7 This library is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
12 This library 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 You should have received a copy of the GNU General Public License
18 along with this library; see the file COPYING. If not, write to the
19 Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
20 MA 02110-1301, USA.
22 As a special exception, if you link this library with other files,
23 some of which are compiled with SDCC, to produce an executable,
24 this library does not by itself cause the resulting executable to
25 be covered by the GNU General Public License. This exception does
26 not however invalidate any other reasons why the executable file
27 might be covered by the GNU General Public License.
28 -------------------------------------------------------------------------*/
30 /* Assembler-functions are provided for:
31 mcs51 small
32 mcs51 small stack-auto
35 #include <sdcc-lib.h>
37 #if !defined(__SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
38 # if defined(__SDCC_mcs51)
39 # if defined(__SDCC_MODEL_SMALL)
40 # if defined(__SDCC_STACK_AUTO) && !defined (__SDCC_PARMS_IN_BANK1)
41 # define _MODULONG_ASM_SMALL_AUTO
42 # else
43 # define _MODULONG_ASM_SMALL
44 # endif
45 # endif
46 # endif
47 #endif
49 #if defined _MODULONG_ASM_SMALL
51 static void
52 _modlong_dummy (void) __naked
54 __asm
56 .globl __modulong
58 #define a0 dpl
59 #define a1 dph
60 #define a2 b
61 #define a3 r1
62 #define count r0
64 __modulong:
65 #if defined(__SDCC_PARMS_IN_BANK1)
66 #define b0 (b1_0)
67 #define b1 (b1_1)
68 #define b2 (b1_2)
69 #define b3 (b1_3)
70 #else
71 #if defined(__SDCC_NOOVERLAY)
72 .area DSEG (DATA)
73 #else
74 .area OSEG (OVR,DATA)
75 #endif
77 .globl __modulong_PARM_2
78 .globl __modslong_PARM_2
80 __modulong_PARM_2:
81 __modslong_PARM_2:
82 .ds 4
84 .area CSEG (CODE)
86 #define b0 (__modulong_PARM_2)
87 #define b1 (__modulong_PARM_2 + 1)
88 #define b2 (__modulong_PARM_2 + 2)
89 #define b3 (__modulong_PARM_2 + 3)
90 #endif
91 ; parameter a comes in a, b, dph, dpl
92 mov a3,a ; save parameter a3
94 mov a,b0 ; b == 0? avoid endless loop
95 orl a,b1
96 orl a,b2
97 orl a,b3
98 jz div_by_0
100 mov count,#0
101 clr c ; when loop1 jumps immediately to loop2
103 loop1: inc count
105 mov a,b3 ; if (!MSB_SET(b))
106 jb acc.7,loop2
108 mov a,b0 ; b <<= 1
109 add a,acc
110 mov b0,a
111 mov a,b1
112 rlc a
113 mov b1,a
114 mov a,b2
115 rlc a
116 mov b2,a
117 mov a,b3
118 rlc a
119 mov b3,a
121 mov a,a0 ; a - b
122 subb a,b0 ; here carry is always clear
123 mov a,a1
124 subb a,b1
125 mov a,a2
126 subb a,b2
127 mov a,a3
128 subb a,b3
130 jnc loop1
133 clr c
134 mov a,b3 ; b >>= 1;
135 rrc a
136 mov b3,a
137 mov a,b2
138 rrc a
139 mov b2,a
140 mov a,b1
141 rrc a
142 mov b1,a
143 mov a,b0
144 rrc a
145 mov b0,a
147 loop2: ; clr c never set
148 mov a,a0 ; a - b
149 subb a,b0
150 mov r4,a
151 mov a,a1
152 subb a,b1
153 mov r5,a
154 mov a,a2
155 subb a,b2
156 mov r6,a
157 mov a,a3
158 subb a,b3
160 jc smaller ; a >= b?
162 mov a3,a ; -> yes; a = a - b;
163 mov a2,r6
164 mov a1,r5
165 mov a0,r4
166 smaller: ; -> no
167 clr c
168 mov a,b3 ; b >>= 1;
169 rrc a
170 mov b3,a
171 mov a,b2
172 rrc a
173 mov b2,a
174 mov a,b1
175 rrc a
176 mov b1,a
177 mov a,b0
178 rrc a
179 mov b0,a
181 djnz count,loop2
183 mov a,a3 ; prepare the return value
184 div_by_0:
187 __endasm;
190 #elif defined _MODULONG_ASM_SMALL_AUTO
192 static void
193 _modlong_dummy (void) __naked
195 __asm
197 .globl __modulong
199 __modulong:
201 #define count r0
203 #define a0 dpl
204 #define a1 dph
205 #define a2 b
206 #define a3 r1
208 #define b0 r2
209 #define b1 r3
210 #define b2 r4
211 #define b3 r5
213 ar2 = 2 ; BUG register set is not considered
214 ar3 = 3
215 ar4 = 4
216 ar5 = 5
218 .globl __modlong ; entry point for __modslong
220 ; parameter a comes in a, b, dph, dpl
221 mov a3,a ; save parameter a3
223 mov a,sp
224 add a,#-2-3 ; 2 bytes return address, 3 bytes param b
225 mov r0,a ; r1 points to b0
227 mov ar2,@r0 ; load b0
228 inc r0 ; r0 points to b1
229 mov ar3,@r0 ; b1
230 inc r0
231 mov ar4,@r0 ; b2
232 inc r0
233 mov ar5,@r0 ; b3
235 __modlong: ; entry point for __modslong
236 ; a in r1, b, dph, dpl
237 ; b in r5, r4, r3, r2
239 mov count,#0
241 mov a,b0 ; b == 0? avoid endless loop
242 orl a,b1
243 orl a,b2
244 orl a,b3
245 jz div_by_0
247 mov count,#0
248 clr c ; when loop1 jumps immediately to loop2
250 loop1: inc count
252 mov a,b3 ; if (!MSB_SET(b))
253 jb acc.7,loop2
255 mov a,b0 ; b <<= 1
256 add a,acc
257 mov b0,a
258 mov a,b1
259 rlc a
260 mov b1,a
261 mov a,b2
262 rlc a
263 mov b2,a
264 mov a,b3
265 rlc a
266 mov b3,a
268 mov a,a0 ; a - b
269 subb a,b0 ; here carry is always clear
270 mov a,a1
271 subb a,b1
272 mov a,a2
273 subb a,b2
274 mov a,a3
275 subb a,b3
277 jnc loop1
279 clr c
280 mov a,b3 ; b >>= 1;
281 rrc a
282 mov b3,a
283 mov a,b2
284 rrc a
285 mov b2,a
286 mov a,b1
287 rrc a
288 mov b1,a
289 mov a,b0
290 rrc a
291 mov b0,a
293 loop2: ; clr c never set
294 mov a,a0 ; a - b
295 subb a,b0
296 mov a,a1
297 subb a,b1
298 mov r6,a ; d1
299 mov a,a2
300 subb a,b2
301 mov r7,a ; d2
302 mov a,a3
303 subb a,b3
305 jc smaller ; a >= b?
307 mov a3,a ; -> yes; a = a - b;
308 mov a2,r7
309 mov a1,r6
310 mov a,a0
311 subb a,b0
312 mov a0,a
313 smaller: ; -> no
314 clr c
315 mov a,b3 ; b >>= 1;
316 rrc a
317 mov b3,a
318 mov a,b2
319 rrc a
320 mov b2,a
321 mov a,b1
322 rrc a
323 mov b1,a
324 mov a,b0
325 rrc a
326 mov b0,a
328 djnz count,loop2
330 mov a,a3 ; prepare the return value
331 div_by_0:
334 __endasm;
337 #else // _MODULONG_ASM
339 #define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1)
341 unsigned long
342 _modulong (unsigned long a, unsigned long b) __SDCC_NONBANKED
344 unsigned char count = 0;
346 while (!MSB_SET(b))
348 b <<= 1;
349 if (b > a)
351 b >>=1;
352 break;
354 count++;
358 if (a >= b)
359 a -= b;
360 b >>= 1;
362 while (count--);
364 return a;
367 #endif // _MODULONG_ASM