* sdcc/device/lib/Makefile.in: added library sources for mcs51, small,
[fw/sdcc] / device / lib / _divsint.c
1 /*-------------------------------------------------------------------------
2   _divsint.c :- routine for signed int (16 bit) division. just calls
3                 routine for unsigned division after sign adjustment
4
5              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
6
7    This library is free software; you can redistribute it and/or modify it
8    under the terms of the GNU Library General Public License as published by the
9    Free Software Foundation; either version 2, or (at your option) any
10    later version.
11
12    This library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU Library General Public License for more details.
16
17    You should have received a copy of the GNU Library General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
21    In other words, you are welcome to use, share and improve this program.
22    You are forbidden to forbid anyone else to use, share and improve
23    what you give them.   Help stamp out software-hoarding!
24 -------------------------------------------------------------------------*/
25
26
27 #include <sdcc-lib.h>
28
29 #if _SDCC_MANGLES_SUPPORT_FUNS
30 unsigned unsigned _divuint (unsigned a, unsigned b);
31 #endif
32
33 /*   Assembler-functions are provided for:
34      mcs51 small
35      mcs51 small stack-auto
36 */
37
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 _DIVSINT_ASM_SMALL_AUTO
43 #      else
44 #        define _DIVSINT_ASM_SMALL
45 #      endif
46 #    endif
47 #  endif
48 #endif
49
50 #if defined _DIVSINT_ASM_SMALL
51
52 static void
53 _divsint_dummy (void) _naked
54 {
55         _asm
56
57                 #define a0      dpl
58                 #define a1      dph
59
60                 .globl __divsint
61
62                 // _divsint_PARM_2 shares the same memory with _divuint_PARM_2
63                 // and is defined in _divuint.c
64 #if defined(SDCC_PARMS_IN_BANK1)
65                 #define b0      (b1_0)
66                 #define b1      (b1_1)
67 #else
68                 #define b0      (__divsint_PARM_2)
69                 #define b1      (__divsint_PARM_2 + 1)
70 #endif
71         __divsint:
72                                         ; a1 in dph
73                                         ; b1 in (__divsint_PARM_2 + 1)
74
75                 clr     F0              ; Flag 0 in PSW
76                                         ; available to user for general purpose
77                 mov     a,a1
78                 jnb     acc.7,a_not_negative
79
80                 setb    F0
81
82                 clr     a
83                 clr     c
84                 subb    a,a0
85                 mov     a0,a
86                 clr     a
87                 subb    a,a1
88                 mov     a1,a
89
90         a_not_negative:
91
92                 mov     a,b1
93                 jnb     acc.7,b_not_negative
94
95                 cpl     F0
96
97                 clr     a
98                 clr     c
99                 subb    a,b0
100                 mov     b0,a
101                 clr     a
102                 subb    a,b1
103                 mov     b1,a
104
105         b_not_negative:
106
107                 lcall   __divuint
108
109                 jnb     F0,not_negative
110
111                 clr     a
112                 clr     c
113                 subb    a,a0
114                 mov     a0,a
115                 clr     a
116                 subb    a,a1
117                 mov     a1,a
118
119         not_negative:
120                 ret
121
122         _endasm ;
123 }
124
125 #elif defined _DIVSINT_ASM_SMALL_AUTO
126
127 static void
128 _divsint_dummy (void) _naked
129 {
130         _asm
131
132                 #define a0      dpl
133                 #define a1      dph
134
135                 ar0 = 0                 ; BUG register set is not considered
136                 ar1 = 1
137
138                 .globl __divsint
139
140         __divsint:
141
142                 clr     F0              ; Flag 0 in PSW
143                                         ; available to user for general purpose
144                 mov     a,a1
145                 jnb     acc.7,a_not_negative
146
147                 setb    F0
148
149                 clr     a
150                 clr     c
151                 subb    a,a0
152                 mov     a0,a
153                 clr     a
154                 subb    a,a1
155                 mov     a1,a
156
157         a_not_negative:
158
159                 mov     a,sp
160                 add     a,#-2           ; 2 bytes return address
161                 mov     r0,a            ; r0 points to b1
162                 mov     a,@r0           ; b1
163
164                 jnb     acc.7,b_not_negative
165
166                 cpl     F0
167
168                 dec     r0
169
170                 clr     a
171                 clr     c
172                 subb    a,@r0           ; b0
173                 mov     @r0,a
174                 clr     a
175                 inc     r0
176                 subb    a,@r0           ; b1
177                 mov     @r0,a
178
179         b_not_negative:
180
181                 mov     ar1,@r0         ; b1
182                 dec     r0
183                 mov     ar0,@r0         ; b0
184
185                 lcall   __divint
186
187                 jnb     F0,not_negative
188
189                 clr     a
190                 clr     c
191                 subb    a,a0
192                 mov     a0,a
193                 clr     a
194                 subb    a,a1
195                 mov     a1,a
196
197         not_negative:
198                 ret
199
200         _endasm ;
201 }
202
203 #else  // _DIVSINT_ASM_
204
205 int
206 _divsint (int a, int b)
207 {
208   register int r;
209
210   r = _divuint((a < 0 ? -a : a),
211                (b < 0 ? -b : b));
212   if ( (a < 0) ^ (b < 0))
213     return -r;
214   else
215     return r;
216 }
217
218 #endif  // _DIVSINT_ASM_