fix float overflow checki in printf_fast_f, bug #1525093
[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 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