* configure.in: added missing mcs51 in status output
[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 x, unsigned y);
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 xl      dpl
58                 #define xh      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 yl      (b1_0)
66                 #define yh      (b1_1)
67 #else
68                 #define yl      (__divsint_PARM_2)
69                 #define yh      (__divsint_PARM_2 + 1)
70 #endif
71         __divsint:
72                                         ; xh in dph
73                                         ; yh in (__divsint_PARM_2 + 1)
74
75                 clr     F0              ; Flag 0 in PSW
76                                         ; available to user for general purpose
77                 mov     a,xh
78                 jnb     acc.7,a_not_negative
79
80                 setb    F0
81
82                 clr     a
83                 clr     c
84                 subb    a,xl
85                 mov     xl,a
86                 clr     a
87                 subb    a,xh
88                 mov     xh,a
89
90         a_not_negative:
91
92                 mov     a,yh
93                 jnb     acc.7,b_not_negative
94
95                 cpl     F0
96
97                 clr     a
98                 clr     c
99                 subb    a,yl
100                 mov     yl,a
101                 clr     a
102                 subb    a,yh
103                 mov     yh,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,xl
114                 mov     xl,a
115                 clr     a
116                 subb    a,xh
117                 mov     xh,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 xl      dpl
133                 #define xh      dph
134
135                 .globl __divsint
136
137         __divsint:
138
139                 clr     F0              ; Flag 0 in PSW
140                                         ; available to user for general purpose
141                 mov     a,xh
142                 jnb     acc.7,a_not_negative
143
144                 setb    F0
145
146                 clr     a
147                 clr     c
148                 subb    a,xl
149                 mov     xl,a
150                 clr     a
151                 subb    a,xh
152                 mov     xh,a
153
154         a_not_negative:
155
156                 mov     a,sp
157                 add     a,#-2           ; 2 bytes return address
158                 mov     r0,a            ; r0 points to yh
159                 mov     a,@r0           ; a = yh
160
161                 jnb     acc.7,b_not_negative
162
163                 cpl     F0
164
165                 dec     r0
166
167                 clr     a
168                 clr     c
169                 subb    a,@r0           ; yl
170                 mov     @r0,a
171                 clr     a
172                 inc     r0
173                 subb    a,@r0           ; a = yh
174
175         b_not_negative:
176
177                 mov     r1,a            ; yh
178                 dec     r0
179                 mov     a,@r0           ; yl
180                 mov     r0,a
181
182                 lcall   __divint
183
184                 jnb     F0,not_negative
185
186                 clr     a
187                 clr     c
188                 subb    a,xl
189                 mov     xl,a
190                 clr     a
191                 subb    a,xh
192                 mov     xh,a
193
194         not_negative:
195                 ret
196
197         _endasm ;
198 }
199
200 #else  // _DIVSINT_ASM_
201
202 int
203 _divsint (int x, int y)
204 {
205   register int r;
206
207   r = _divuint((x < 0 ? -x : x),
208                (y < 0 ? -y : y));
209   if ( (x < 0) ^ (y < 0))
210     return -r;
211   else
212     return r;
213 }
214
215 #endif  // _DIVSINT_ASM_