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