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