struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / device / lib / _divulong.c
blob235cfbbb0424a71fab5358139791d443215409ee
1 /*-------------------------------------------------------------------------
2 _divulong.c - routine for division of 32 bit unsigned long
4 Copyright (C) 1999, Jean-Louis Vern <jlvern AT gmail.com>
6 This library is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
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 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this library; see the file COPYING. If not, write to the
18 Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
19 MA 02110-1301, USA.
21 As a special exception, if you link this library with other files,
22 some of which are compiled with SDCC, to produce an executable,
23 this library does not by itself cause the resulting executable to
24 be covered by the GNU General Public License. This exception does
25 not however invalidate any other reasons why the executable file
26 might be covered by the GNU General Public License.
27 -------------------------------------------------------------------------*/
29 /* Assembler-functions are provided for:
30 mcs51 small
31 mcs51 small stack-auto
34 #include <stdbool.h>
36 #include <sdcc-lib.h>
38 #if !defined(__SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
39 # if defined(__SDCC_mcs51)
40 # if defined(__SDCC_MODEL_SMALL)
41 # if defined(__SDCC_STACK_AUTO) && !defined(__SDCC_PARMS_IN_BANK1)
42 # define _DIVULONG_ASM_SMALL_AUTO
43 # else
44 # define _DIVULONG_ASM_SMALL
45 # endif
46 # endif
47 # endif
48 #endif
50 #if defined _DIVULONG_ASM_SMALL
52 static void
53 _divlong_dummy (void) __naked
55 __asm
57 .globl __divulong
59 __divulong:
61 #define count r2
63 #define x0 dpl
64 #define x1 dph
65 #define x2 b
66 #define x3 r3
68 #define reste0 r4
69 #define reste1 r5
70 #define reste2 r6
71 #define reste3 r7
72 #if !defined(__SDCC_PARMS_IN_BANK1)
74 #if defined(__SDCC_NOOVERLAY)
75 .area DSEG (DATA)
76 #else
77 .area OSEG (OVR,DATA)
78 #endif
80 .globl __divulong_PARM_2
81 .globl __divslong_PARM_2
83 __divulong_PARM_2:
84 __divslong_PARM_2:
85 .ds 4
87 .area CSEG (CODE)
89 #define y0 (__divulong_PARM_2)
90 #define y1 (__divulong_PARM_2 + 1)
91 #define y2 (__divulong_PARM_2 + 2)
92 #define y3 (__divulong_PARM_2 + 3)
93 #else
94 #define y0 (b1_0)
95 #define y1 (b1_1)
96 #define y2 (b1_2)
97 #define y3 (b1_3)
98 #endif // !__SDCC_PARMS_IN_BANK1
99 ; parameter x comes in a, b, dph, dpl
100 mov x3,a ; save parameter x3
102 mov count,#32
103 clr a
104 mov reste0,a
105 mov reste1,a
106 mov reste2,a
107 mov reste3,a
109 ; optimization loop in lp0 until the first bit is shifted into rest
111 lp0: mov a,x0 ; x <<= 1
112 add a,x0
113 mov x0,a
114 mov a,x1
115 rlc a
116 mov x1,a
117 mov a,x2
118 rlc a
119 mov x2,a
120 mov a,x3
121 rlc a
122 mov x3,a
124 jc in_lp
125 djnz count,lp0
127 sjmp exit
129 loop: mov a,x0 ; x <<= 1
130 add a,x0
131 mov x0,a
132 mov a,x1
133 rlc a
134 mov x1,a
135 mov a,x2
136 rlc a
137 mov x2,a
138 mov a,x3
139 rlc a
140 mov x3,a
142 in_lp: mov a,reste0 ; reste <<= 1
143 rlc a ; feed in carry
144 mov reste0,a
145 mov a,reste1
146 rlc a
147 mov reste1,a
148 mov a,reste2
149 rlc a
150 mov reste2,a
151 mov a,reste3
152 rlc a
153 mov reste3,a
155 mov a,reste0 ; reste - y
156 subb a,y0 ; carry is always clear here, because
157 ; reste <<= 1 never overflows
158 mov a,reste1
159 subb a,y1
160 mov a,reste2
161 subb a,y2
162 mov a,reste3
163 subb a,y3
165 jc minus ; reste >= y?
167 ; -> yes; reste -= y;
168 mov a,reste0
169 subb a,y0 ; carry is always clear here (jc)
170 mov reste0,a
171 mov a,reste1
172 subb a,y1
173 mov reste1,a
174 mov a,reste2
175 subb a,y2
176 mov reste2,a
177 mov a,reste3
178 subb a,y3
179 mov reste3,a
181 orl x0,#1
183 minus: djnz count,loop ; -> no
185 exit: mov a,x3 ; prepare the return value
188 __endasm;
191 #elif defined _DIVULONG_ASM_SMALL_AUTO
193 static void
194 _divlong_dummy (void) __naked
196 __asm
198 .globl __divulong
200 __divulong:
202 #define count r2
204 #define x0 dpl
205 #define x1 dph
206 #define x2 b
207 #define x3 r3
209 #define reste0 r4
210 #define reste1 r5
211 #define reste2 r6
212 #define reste3 r7
214 .globl __divlong ; entry point for __divslong
216 #define y0 r1
218 ; parameter x comes in a, b, dph, dpl
219 mov x3,a ; save parameter x3
221 mov a,sp
222 add a,#-2-3 ; 2 bytes return address, 3 bytes param y
223 mov r0,a ; r0 points to y0
225 __divlong: ; entry point for __divslong
227 mov a,@r0 ; load y0
228 mov y0,a
229 inc r0 ; r0 points to y1
231 mov count,#32
232 clr a
233 mov reste0,a
234 mov reste1,a
235 mov reste2,a
236 mov reste3,a
238 ; optimization loop in lp0 until the first bit is shifted into rest
240 lp0: mov a,x0 ; x <<= 1
241 add a,x0
242 mov x0,a
243 mov a,x1
244 rlc a
245 mov x1,a
246 mov a,x2
247 rlc a
248 mov x2,a
249 mov a,x3
250 rlc a
251 mov x3,a
253 jc in_lp
254 djnz count,lp0
256 sjmp exit
258 loop: mov a,x0 ; x <<= 1
259 add a,x0
260 mov x0,a
261 mov a,x1
262 rlc a
263 mov x1,a
264 mov a,x2
265 rlc a
266 mov x2,a
267 mov a,x3
268 rlc a
269 mov x3,a
271 in_lp: mov a,reste0 ; reste <<= 1
272 rlc a ; feed in carry
273 mov reste0,a
274 mov a,reste1
275 rlc a
276 mov reste1,a
277 mov a,reste2
278 rlc a
279 mov reste2,a
280 mov a,reste3
281 rlc a
282 mov reste3,a
284 mov a,reste0 ; reste - y
285 subb a,y0 ; carry is always clear here, because
286 ; reste <<= 1 never overflows
287 mov a,reste1
288 subb a,@r0 ; y1
289 mov a,reste2
290 inc r0
291 subb a,@r0 ; y2
292 mov a,reste3
293 inc r0
294 subb a,@r0 ; y3
295 dec r0
296 dec r0
298 jc minus ; reste >= y?
300 ; -> yes; reste -= y;
301 mov a,reste0
302 subb a,y0 ; carry is always clear here (jc)
303 mov reste0,a
304 mov a,reste1
305 subb a,@r0 ; y1
306 mov reste1,a
307 mov a,reste2
308 inc r0
309 subb a,@r0 ; y2
310 mov reste2,a
311 mov a,reste3
312 inc r0
313 subb a,@r0 ; y3
314 mov reste3,a
315 dec r0
316 dec r0
318 orl x0,#1
320 minus: djnz count,loop ; -> no
322 exit: mov a,x3 ; prepare the return value
325 __endasm;
328 #else // _DIVULONG_ASM
330 #define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1)
332 unsigned long
333 _divulong (unsigned long x, unsigned long y) __SDCC_NONBANKED
335 unsigned long reste = 0L;
336 unsigned char count = 32;
337 bool c;
341 // reste: x <- 0;
342 c = MSB_SET(x);
343 x <<= 1;
344 reste <<= 1;
345 if (c)
346 reste |= 1L;
348 if (reste >= y)
350 reste -= y;
351 // x <- (result = 1)
352 x |= 1L;
355 while (--count);
356 return x;
359 #endif // _DIVULONG_ASM