adjusted for --parms-in-bank1 option
[fw/sdcc] / device / lib / _divslong.c
1 /*-------------------------------------------------------------------------
2    _divslong.c - routine for division of 32 bit long
3
4              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (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
26 #include <sdcc-lib.h>
27
28 #if _SDCC_MANGLES_SUPPORT_FUNS
29 unsigned long _divulong (unsigned long a, unsigned long b);
30 #endif
31
32 /*   Assembler-functions are provided for:
33      mcs51 small
34      mcs51 small stack-auto
35 */
36
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 _DIVSLONG_ASM_SMALL_AUTO
42 #      else
43 #        define _DIVSLONG_ASM_SMALL
44 #      endif
45 #    endif
46 #  endif
47 #endif
48
49 #if defined _DIVSLONG_ASM_SMALL
50
51 static void
52 _divslong_dummy (void) _naked
53 {
54         _asm
55
56                 #define a0      dpl
57                 #define a1      dph
58                 #define a2      b
59                 #define a3      r3
60
61                 .globl __divslong
62
63                 // _divslong_PARM_2 shares the same memory with _divulong_PARM_2
64                 // and is defined in _divulong.c
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                 #define b0      (__divslong_PARM_2)
72                 #define b1      (__divslong_PARM_2 + 1)
73                 #define b2      (__divslong_PARM_2 + 2)
74                 #define b3      (__divslong_PARM_2 + 3)
75 #endif
76         __divslong:
77                                         ; a3 in acc
78                                         ; b3 in (__divslong_PARM_2 + 3)
79                 mov     a3,a            ; save a3
80
81                 clr     F0              ; Flag 0 in PSW
82                                         ; available to user for general purpose
83                 jnb     acc.7,a_not_negative
84
85                 setb    F0
86
87                 clr     a
88                 clr     c
89                 subb    a,a0
90                 mov     a0,a
91                 clr     a
92                 subb    a,a1
93                 mov     a1,a
94                 clr     a
95                 subb    a,a2
96                 mov     a2,a
97                 clr     a
98                 subb    a,a3
99                 mov     a3,a
100
101         a_not_negative:
102
103                 mov     a,b3
104                 jnb     acc.7,b_not_negative
105
106                 cpl     F0
107
108                 clr     a
109                 clr     c
110                 subb    a,b0
111                 mov     b0,a
112                 clr     a
113                 subb    a,b1
114                 mov     b1,a
115                 clr     a
116                 subb    a,b2
117                 mov     b2,a
118                 clr     a
119                 subb    a,b3
120                 mov     b3,a
121
122         b_not_negative:
123
124                 mov     a,a3            ; restore a3 in acc
125
126                 lcall   __divulong
127
128                 jnb     F0,not_negative
129
130                 mov     a3,a            ; save a3
131
132                 clr     a
133                 clr     c
134                 subb    a,a0
135                 mov     a0,a
136                 clr     a
137                 subb    a,a1
138                 mov     a1,a
139                 clr     a
140                 subb    a,a2
141                 mov     a2,a
142                 clr     a
143                 subb    a,a3
144                 mov     a3,a
145
146         not_negative:
147                 ret
148
149         _endasm ;
150 }
151
152 #elif defined _DIVSLONG_ASM_SMALL_AUTO
153
154 static void
155 _divslong_dummy (void) _naked
156 {
157         _asm
158
159                 #define a0      dpl
160                 #define a1      dph
161                 #define a2      b
162                 #define a3      r3
163
164                 .globl __divslong
165
166         __divslong:
167
168                                         ; a3 in acc
169                 mov     a3,a            ; save a3
170
171                 clr     F0              ; Flag 0 in PSW
172                                         ; available to user for general purpose
173                 jnb     acc.7,a_not_negative
174
175                 setb    F0
176
177                 clr     a
178                 clr     c
179                 subb    a,a0
180                 mov     a0,a
181                 clr     a
182                 subb    a,a1
183                 mov     a1,a
184                 clr     a
185                 subb    a,a2
186                 mov     a2,a
187                 clr     a
188                 subb    a,a3
189                 mov     a3,a
190
191         a_not_negative:
192
193                 mov     a,sp
194                 add     a,#-2           ; 2 bytes return address
195                 mov     r0,a            ; r0 points to b3
196                 mov     a,@r0           ; b3
197
198                 jnb     acc.7,b_not_negative
199
200                 cpl     F0
201
202                 dec     r0
203                 dec     r0
204                 dec     r0
205
206                 clr     a
207                 clr     c
208                 subb    a,@r0           ; b0
209                 mov     @r0,a
210                 clr     a
211                 inc     r0
212                 subb    a,@r0           ; b1
213                 mov     @r0,a
214                 clr     a
215                 inc     r0
216                 subb    a,@r0           ; b2
217                 mov     @r0,a
218                 clr     a
219                 inc     r0
220                 subb    a,@r0           ; b3
221                 mov     @r0,a
222
223         b_not_negative:
224                 dec     r0
225                 dec     r0
226                 dec     r0              ; r0 points to b0
227
228                 lcall   __divlong
229
230                 jnb     F0,not_negative
231
232                 mov     a3,a            ; save a3
233
234                 clr     a
235                 clr     c
236                 subb    a,a0
237                 mov     a0,a
238                 clr     a
239                 subb    a,a1
240                 mov     a1,a
241                 clr     a
242                 subb    a,a2
243                 mov     a2,a
244                 clr     a
245                 subb    a,a3
246                 mov     a3,a
247
248         not_negative:
249                 ret
250
251         _endasm ;
252 }
253
254 #else // _DIVSLONG_ASM
255
256 long
257 _divslong (long a, long b)
258 {
259   long r;
260
261   r = _divulong((a < 0 ? -a : a),
262                 (b < 0 ? -b : b));
263   if ( (a < 0) ^ (b < 0))
264     return -r;
265   else
266     return r;
267 }
268
269 #endif // _DIVSLONG_ASM