added functions _ltoa _uitoa
[fw/sdcc] / device / lib / _modsint.c
1 /*-------------------------------------------------------------------------
2   _modsint.c :- routine for signed int (16 bit) modulus
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 unsigned _moduint (unsigned a, unsigned b);
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 _MODSINT_ASM_SMALL_AUTO
42 #      else
43 #        define _MODSINT_ASM_SMALL
44 #      endif
45 #    endif
46 #  endif
47 #endif
48
49 #if defined _MODSINT_ASM_SMALL
50
51 static void
52 _modsint_dummy (void) _naked
53 {
54         _asm
55
56                 #define a0      dpl
57                 #define a1      dph
58
59                 .globl __modsint
60 #if defined(SDCC_PARMS_IN_BANK1)
61                 #define b0      (b1_0)
62                 #define b1      (b1_1)
63 #else
64                 // _modsint_PARM_2 shares the same memory with _moduint_PARM_2
65                 // and is defined in _moduint.c
66                 #define b0      (__modsint_PARM_2)
67                 #define b1      (__modsint_PARM_2 + 1)
68 #endif
69         __modsint:
70                                         ; a1 in dph
71                                         ; b1 in (__modsint_PARM_2 + 1)
72
73                 clr     F0              ; Flag 0 in PSW
74                                         ; available to user for general purpose
75                 mov     a,a1
76                 jnb     acc.7,a_not_negative
77
78                 setb    F0
79
80                 clr     a
81                 clr     c
82                 subb    a,a0
83                 mov     a0,a
84                 clr     a
85                 subb    a,a1
86                 mov     a1,a
87
88         a_not_negative:
89
90                 mov     a,b1
91                 jnb     acc.7,b_not_negative
92
93                 cpl     F0
94
95                 clr     a
96                 clr     c
97                 subb    a,b0
98                 mov     b0,a
99                 clr     a
100                 subb    a,b1
101                 mov     b1,a
102
103         b_not_negative:
104
105                 lcall   __moduint
106
107                 jnb     F0,not_negative
108
109                 clr     a
110                 clr     c
111                 subb    a,a0
112                 mov     a0,a
113                 clr     a
114                 subb    a,a1
115                 mov     a1,a
116
117         not_negative:
118                 ret
119
120         _endasm ;
121 }
122
123 #elif defined _MODSINT_ASM_SMALL_AUTO
124
125 static void
126 _modsint_dummy (void) _naked
127 {
128         _asm
129
130                 #define a0      dpl
131                 #define a1      dph
132
133                 ar0 = 0                 ; BUG register set is not considered
134                 ar1 = 1
135
136                 .globl __modsint
137
138         __modsint:
139
140                 clr     F0              ; Flag 0 in PSW
141                                         ; available to user for general purpose
142                 mov     a,a1
143                 jnb     acc.7,a_not_negative
144
145                 setb    F0
146
147                 clr     a
148                 clr     c
149                 subb    a,a0
150                 mov     a0,a
151                 clr     a
152                 subb    a,a1
153                 mov     a1,a
154
155         a_not_negative:
156
157                 mov     a,sp
158                 add     a,#-2           ; 2 bytes return address
159                 mov     r0,a            ; r0 points to b1
160                 mov     a,@r0           ; b1
161
162                 jnb     acc.7,b_not_negative
163
164                 cpl     F0
165
166                 dec     r0
167
168                 clr     a
169                 clr     c
170                 subb    a,@r0           ; b0
171                 mov     @r0,a
172                 clr     a
173                 inc     r0
174                 subb    a,@r0           ; b1
175                 mov     @r0,a
176
177         b_not_negative:
178
179                 mov     ar1,@r0         ; b1
180                 dec     r0
181                 mov     ar0,@r0         ; b0
182
183                 lcall   __modint
184
185                 jnb     F0,not_negative
186
187                 clr     a
188                 clr     c
189                 subb    a,a0
190                 mov     a0,a
191                 clr     a
192                 subb    a,a1
193                 mov     a1,a
194
195         not_negative:
196                 ret
197
198         _endasm ;
199 }
200
201 #else  // _MODSINT_ASM_
202
203 int _modsint (int a, int b)
204 {
205        register int r;
206        
207        r = _moduint((a < 0 ? -a : a),
208                     (b < 0 ? -b : b));
209
210        if ( (a < 0) ^ (b < 0))
211             return -r;
212         else
213             return r;
214 }               
215
216 #endif  // _MODSINT_ASM_