* src/z80/gen.c (genArrayInit): Made it work for on stack arrays.
[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)
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                 #define b0      (__divsint_PARM_2)
65                 #define b1      (__divsint_PARM_2 + 1)
66
67         __divsint:
68                                         ; a1 in dph
69                                         ; b1 in (__divsint_PARM_2 + 1)
70
71                 clr     F0              ; Flag 0 in PSW
72                                         ; available to user for general purpose
73                 mov     a,a1
74                 jnb     acc.7,a_not_negative
75
76                 setb    F0
77
78                 clr     a
79                 clr     c
80                 subb    a,a0
81                 mov     a0,a
82                 clr     a
83                 subb    a,a1
84                 mov     a1,a
85
86         a_not_negative:
87
88                 mov     a,b1
89                 jnb     acc.7,b_not_negative
90
91                 cpl     F0
92
93                 clr     a
94                 clr     c
95                 subb    a,b0
96                 mov     b0,a
97                 clr     a
98                 subb    a,b1
99                 mov     b1,a
100
101         b_not_negative:
102
103                 lcall   __divuint
104
105                 jnb     F0,not_negative
106
107                 clr     a
108                 clr     c
109                 subb    a,a0
110                 mov     a0,a
111                 clr     a
112                 subb    a,a1
113                 mov     a1,a
114
115         not_negative:
116                 ret
117
118         _endasm ;
119 }
120
121 #elif defined _DIVSINT_ASM_SMALL_AUTO
122
123 static void
124 _divsint_dummy (void) _naked
125 {
126         _asm
127
128                 #define a0      dpl
129                 #define a1      dph
130
131                 ar0 = 0                 ; BUG register set is not considered
132                 ar1 = 1
133
134                 .globl __divsint
135
136         __divsint:
137
138                 clr     F0              ; Flag 0 in PSW
139                                         ; available to user for general purpose
140                 mov     a,a1
141                 jnb     acc.7,a_not_negative
142
143                 setb    F0
144
145                 clr     a
146                 clr     c
147                 subb    a,a0
148                 mov     a0,a
149                 clr     a
150                 subb    a,a1
151                 mov     a1,a
152
153         a_not_negative:
154
155                 mov     a,sp
156                 add     a,#-2           ; 2 bytes return address
157                 mov     r0,a            ; r0 points to b1
158                 mov     a,@r0           ; b1
159
160                 jnb     acc.7,b_not_negative
161
162                 cpl     F0
163
164                 dec     r0
165
166                 clr     a
167                 clr     c
168                 subb    a,@r0           ; b0
169                 mov     @r0,a
170                 clr     a
171                 inc     r0
172                 subb    a,@r0           ; b1
173                 mov     @r0,a
174
175         b_not_negative:
176
177                 mov     ar1,@r0         ; b1
178                 dec     r0
179                 mov     ar0,@r0         ; b0
180
181                 lcall   __divint
182
183                 jnb     F0,not_negative
184
185                 clr     a
186                 clr     c
187                 subb    a,a0
188                 mov     a0,a
189                 clr     a
190                 subb    a,a1
191                 mov     a1,a
192
193         not_negative:
194                 ret
195
196         _endasm ;
197 }
198
199 #else  // _DIVSINT_ASM_
200
201 int
202 _divsint (int a, int b)
203 {
204   register int r;
205
206   r = _divuint((a < 0 ? -a : a),
207                (b < 0 ? -b : b));
208   if ( (a < 0) ^ (b < 0))
209     return -r;
210   else
211     return r;
212 }
213
214 #endif  // _DIVSINT_ASM_