Imported Upstream version 2.9.0
[debian/cc1111] / 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_