* src/device/lib/_mulint.c : new, with assember functions
[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)
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                 #define b0      (__divslong_PARM_2)
66                 #define b1      (__divslong_PARM_2 + 1)
67                 #define b2      (__divslong_PARM_2 + 2)
68                 #define b3      (__divslong_PARM_2 + 3)
69
70         __divslong:
71                                         ; a3 in acc
72                                         ; b3 in (__divslong_PARM_2 + 3)
73                 mov     a3,a            ; save a3
74
75                 clr     F0              ; Flag 0 in PSW
76                                         ; available to user for general purpose
77                 jnb     acc.7,a_not_negative
78
79                 setb    F0
80
81                 clr     a
82                 clr     c
83                 subb    a,a0
84                 mov     a0,a
85                 clr     a
86                 subb    a,a1
87                 mov     a1,a
88                 clr     a
89                 subb    a,a2
90                 mov     a2,a
91                 clr     a
92                 subb    a,a3
93                 mov     a3,a
94
95         a_not_negative:
96
97                 mov     a,b3
98                 jnb     acc.7,b_not_negative
99
100                 cpl     F0
101
102                 clr     a
103                 clr     c
104                 subb    a,b0
105                 mov     b0,a
106                 clr     a
107                 subb    a,b1
108                 mov     b1,a
109                 clr     a
110                 subb    a,b2
111                 mov     b2,a
112                 clr     a
113                 subb    a,b3
114                 mov     b3,a
115
116         b_not_negative:
117
118                 mov     a,a3            ; restore a3 in acc
119
120                 lcall   __divulong
121
122                 jnb     F0,not_negative
123
124                 mov     a3,a            ; save a3
125
126                 clr     a
127                 clr     c
128                 subb    a,a0
129                 mov     a0,a
130                 clr     a
131                 subb    a,a1
132                 mov     a1,a
133                 clr     a
134                 subb    a,a2
135                 mov     a2,a
136                 clr     a
137                 subb    a,a3
138                 mov     a3,a
139
140         not_negative:
141                 ret
142
143         _endasm ;
144 }
145
146 #elif defined _DIVSLONG_ASM_SMALL_AUTO
147
148 static void
149 _divslong_dummy (void) _naked
150 {
151         _asm
152
153                 #define a0      dpl
154                 #define a1      dph
155                 #define a2      b
156                 #define a3      r3
157
158                 .globl __divslong
159
160         __divslong:
161
162                                         ; a3 in acc
163                 mov     a3,a            ; save a3
164
165                 clr     F0              ; Flag 0 in PSW
166                                         ; available to user for general purpose
167                 jnb     acc.7,a_not_negative
168
169                 setb    F0
170
171                 clr     a
172                 clr     c
173                 subb    a,a0
174                 mov     a0,a
175                 clr     a
176                 subb    a,a1
177                 mov     a1,a
178                 clr     a
179                 subb    a,a2
180                 mov     a2,a
181                 clr     a
182                 subb    a,a3
183                 mov     a3,a
184
185         a_not_negative:
186
187                 mov     a,sp
188                 add     a,#-2           ; 2 bytes return address
189                 mov     r0,a            ; r0 points to b3
190                 mov     a,@r0           ; b3
191
192                 jnb     acc.7,b_not_negative
193
194                 cpl     F0
195
196                 dec     r0
197                 dec     r0
198                 dec     r0
199
200                 clr     a
201                 clr     c
202                 subb    a,@r0           ; b0
203                 mov     @r0,a
204                 clr     a
205                 inc     r0
206                 subb    a,@r0           ; b1
207                 mov     @r0,a
208                 clr     a
209                 inc     r0
210                 subb    a,@r0           ; b2
211                 mov     @r0,a
212                 clr     a
213                 inc     r0
214                 subb    a,@r0           ; b3
215                 mov     @r0,a
216
217         b_not_negative:
218                 dec     r0
219                 dec     r0
220                 dec     r0              ; r0 points to b0
221
222                 lcall   __divlong
223
224                 jnb     F0,not_negative
225
226                 mov     a3,a            ; save a3
227
228                 clr     a
229                 clr     c
230                 subb    a,a0
231                 mov     a0,a
232                 clr     a
233                 subb    a,a1
234                 mov     a1,a
235                 clr     a
236                 subb    a,a2
237                 mov     a2,a
238                 clr     a
239                 subb    a,a3
240                 mov     a3,a
241
242         not_negative:
243                 ret
244
245         _endasm ;
246 }
247
248 #else // _DIVSLONG_ASM
249
250 long
251 _divslong (long a, long b)
252 {
253   long r;
254
255   r = _divulong((a < 0 ? -a : a),
256                 (b < 0 ? -b : b));
257   if ( (a < 0) ^ (b < 0))
258     return -r;
259   else
260     return r;
261 }
262
263 #endif // _DIVSLONG_ASM