replaced by _mulint.c and _mullong.c
[fw/sdcc] / device / lib / _modulong.c
1 /*-------------------------------------------------------------------------
2    _modulong.c - routine for modulus of 32 bit unsigned long
3
4              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
5
6              Bug fixes by Martijn van Balen, aed@iae.nl
7
8    This library is free software; you can redistribute it and/or modify it
9    under the terms of the GNU Library General Public License as published by the
10    Free Software Foundation; either version 2, or (at your option) any
11    later version.
12
13    This library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU Library General Public License for more details.
17
18    You should have received a copy of the GNU Library General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22    In other words, you are welcome to use, share and improve this program.
23    You are forbidden to forbid anyone else to use, share and improve
24    what you give them.   Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
26
27 /*   Assembler-functions are provided for:
28      mcs51 small
29      mcs51 small stack-auto
30 */
31
32 #if !defined(SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
33 #  if defined(SDCC_mcs51)
34 #    if defined(SDCC_MODEL_SMALL)
35 #      if defined(SDCC_STACK_AUTO)
36 #        define _MODULONG_ASM_SMALL_AUTO
37 #      else
38 #        define _MODULONG_ASM_SMALL
39 #      endif
40 #    endif
41 #  endif
42 #endif
43
44 #if defined _MODULONG_ASM_SMALL
45
46 static void
47 _modlong_dummy (void) _naked
48 {
49         _asm
50
51                 .globl __modulong
52
53         __modulong:
54
55 #if defined(SDCC_NOOVERLAY)             // BUG SDCC_NOOVERLAY is not set by -no-overlay
56                 .area DSEG    (DATA)
57 #else
58                 .area OSEG    (OVR,DATA)
59 #endif
60
61                 .globl __modulong_PARM_2
62                 .globl __modslong_PARM_2
63
64         __modulong_PARM_2:
65         __modslong_PARM_2:
66                 .ds     4
67
68                 .area CSEG    (CODE)
69
70                 #define count   r0
71
72                 #define a0      dpl
73                 #define a1      dph
74                 #define a2      b
75                 #define a3      r1
76
77                 #define b0      (__modulong_PARM_2)
78                 #define b1      (__modulong_PARM_2 + 1)
79                 #define b2      (__modulong_PARM_2 + 2)
80                 #define b3      (__modulong_PARM_2 + 3)
81
82                                         ; parameter a comes in a, b, dph, dpl
83                 mov     a3,a            ; save parameter a3
84
85                 mov     a,b0            ; b == 0? avoid endless loop
86                 orl     a,b1
87                 orl     a,b2
88                 orl     a,b3
89                 jz      div_by_0
90
91                 mov     count,#0
92                 clr     c               ; when loop1 jumps immediately to loop2
93
94         loop1:  inc     count
95
96                 mov     a,b3            ; if (!MSB_SET(b))
97                 jb      acc.7,loop2
98
99                 mov     a,b0            ; b <<= 1
100                 add     a,acc
101                 mov     b0,a
102                 mov     a,b1
103                 rlc     a
104                 mov     b1,a
105                 mov     a,b2
106                 rlc     a
107                 mov     b2,a
108                 mov     a,b3
109                 rlc     a
110                 mov     b3,a
111
112                 mov     a,a0            ; a - b
113                 subb    a,b0            ; here carry is always clear
114                 mov     a,a1
115                 subb    a,b1
116                 mov     a,a2
117                 subb    a,b2
118                 mov     a,a3
119                 subb    a,b3
120
121                 jnc     loop1
122
123
124                 clr     c
125                 mov     a,b3            ; b >>= 1;
126                 rrc     a
127                 mov     b3,a
128                 mov     a,b2
129                 rrc     a
130                 mov     b2,a
131                 mov     a,b1
132                 rrc     a
133                 mov     b1,a
134                 mov     a,b0
135                 rrc     a
136                 mov     b0,a
137
138         loop2:  ; clr   c                 never set
139                 mov     a,a0            ; a - b
140                 subb    a,b0
141                 mov     r4,a
142                 mov     a,a1
143                 subb    a,b1
144                 mov     r5,a
145                 mov     a,a2
146                 subb    a,b2
147                 mov     r6,a
148                 mov     a,a3
149                 subb    a,b3
150
151                 jc      smaller         ; a >= b?
152
153                 mov     a3,a            ; -> yes;  a = a - b;
154                 mov     a2,r6
155                 mov     a1,r5
156                 mov     a0,r4
157         smaller:                        ; -> no
158                 clr     c
159                 mov     a,b3            ; b >>= 1;
160                 rrc     a
161                 mov     b3,a
162                 mov     a,b2
163                 rrc     a
164                 mov     b2,a
165                 mov     a,b1
166                 rrc     a
167                 mov     b1,a
168                 mov     a,b0
169                 rrc     a
170                 mov     b0,a
171
172                 djnz    count,loop2
173
174                 mov     a,a3            ; prepare the return value
175         div_by_0:
176                 ret
177
178         _endasm ;
179 }
180
181 #elif defined _MODULONG_ASM_SMALL_AUTO
182
183 static void
184 _modlong_dummy (void) _naked
185 {
186         _asm
187
188                 .globl __modulong
189
190         __modulong:
191
192                 #define count   r0
193
194                 #define a0      dpl
195                 #define a1      dph
196                 #define a2      b
197                 #define a3      r1
198
199                 #define b0      r2
200                 #define b1      r3
201                 #define b2      r4
202                 #define b3      r5
203
204                 ar2 = 2                 ; BUG register set is not considered
205                 ar3 = 3
206                 ar4 = 4
207                 ar5 = 5
208
209                 .globl __modlong        ; entry point for __modslong
210
211                                         ; parameter a comes in a, b, dph, dpl
212                 mov     a3,a            ; save parameter a3
213
214                 mov     a,sp
215                 add     a,#-2-3         ; 2 bytes return address, 3 bytes param b
216                 mov     r0,a            ; r1 points to b0
217
218
219                 mov     ar2,@r0         ; load b0
220                 inc     r0              ; r0 points to b1
221                 mov     ar3,@r0         ; b1
222                 inc     r0
223                 mov     ar4,@r0         ; b2
224                 inc     r0
225                 mov     ar5,@r0         ; b3
226
227         __modlong:                      ; entry point for __modslong
228                                         ; a in r1, b, dph, dpl
229                                         ; b in r5, r4, r3, r2 
230
231                 mov     count,#0
232
233                 mov     a,b0            ; b == 0? avoid endless loop
234                 orl     a,b1
235                 orl     a,b2
236                 orl     a,b3
237                 jz      div_by_0
238
239                 mov     count,#0
240                 clr     c               ; when loop1 jumps immediately to loop2
241
242         loop1:  inc     count
243
244                 mov     a,b3            ; if (!MSB_SET(b))
245                 jb      acc.7,loop2
246
247                 mov     a,b0            ; b <<= 1
248                 add     a,acc
249                 mov     b0,a
250                 mov     a,b1
251                 rlc     a
252                 mov     b1,a
253                 mov     a,b2
254                 rlc     a
255                 mov     b2,a
256                 mov     a,b3
257                 rlc     a
258                 mov     b3,a
259
260                 mov     a,a0            ; a - b
261                 subb    a,b0            ; here carry is always clear
262                 mov     a,a1
263                 subb    a,b1
264                 mov     a,a2
265                 subb    a,b2
266                 mov     a,a3
267                 subb    a,b3
268
269                 jnc     loop1
270
271
272                 clr     c
273                 mov     a,b3            ; b >>= 1;
274                 rrc     a
275                 mov     b3,a
276                 mov     a,b2
277                 rrc     a
278                 mov     b2,a
279                 mov     a,b1
280                 rrc     a
281                 mov     b1,a
282                 mov     a,b0
283                 rrc     a
284                 mov     b0,a
285
286         loop2:  ; clr   c                 never set
287                 mov     a,a0            ; a - b
288                 subb    a,b0
289                 mov     a,a1
290                 subb    a,b1
291                 mov     r6,a            ; d1
292                 mov     a,a2
293                 subb    a,b2
294                 mov     r7,a            ; d2
295                 mov     a,a3
296                 subb    a,b3
297
298                 jc      smaller         ; a >= b?
299
300                 mov     a3,a            ; -> yes;  a = a - b;
301                 mov     a2,r7
302                 mov     a1,r6
303                 mov     a,a0
304                 subb    a,b0
305                 mov     a0,a
306         smaller:                        ; -> no
307                 clr     c
308                 mov     a,b3            ; b >>= 1;
309                 rrc     a
310                 mov     b3,a
311                 mov     a,b2
312                 rrc     a
313                 mov     b2,a
314                 mov     a,b1
315                 rrc     a
316                 mov     b1,a
317                 mov     a,b0
318                 rrc     a
319                 mov     b0,a
320
321                 djnz    count,loop2
322
323                 mov     a,a3            ; prepare the return value
324         div_by_0:
325                 ret
326
327         _endasm ;
328 }
329
330 #else // _MODULONG_ASM
331
332 #define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1)
333
334 unsigned long
335 _modulong (unsigned long a, unsigned long b)
336 {
337   unsigned char count = 0;
338
339   while (!MSB_SET(b))
340   {
341      b <<= 1;
342      if (b > a)
343      {
344         b >>=1;
345         break;
346      }
347      count++;
348   }
349   do
350   {
351     if (a >= b)
352       a -= b;
353     b >>= 1;
354   }
355   while (count--);
356
357   return a;
358 }
359
360 #endif // _MODULONG_ASM