* src/device/lib/_mulint.c : new, with assember functions
[fw/sdcc] / device / lib / _modslong.c
1 /*-------------------------------------------------------------------------
2    _modslong.c - routine for modulus of 32 bit signed long
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 #include <sdcc-lib.h>
26
27 #if _SDCC_MANGLES_SUPPORT_FUNS
28 unsigned long _modulong (unsigned long a, unsigned long b);
29 #endif
30
31 /*   Assembler-functions are provided for:
32      mcs51 small
33      mcs51 small stack-auto
34 */
35
36 #if !defined(SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
37 #  if defined(SDCC_mcs51)
38 #    if defined(SDCC_MODEL_SMALL)
39 #      if defined(SDCC_STACK_AUTO)
40 #        define _MODSLONG_ASM_SMALL_AUTO
41 #      else
42 #        define _MODSLONG_ASM_SMALL
43 #      endif
44 #    endif
45 #  endif
46 #endif
47
48 #if defined _MODSLONG_ASM_SMALL
49
50 static void
51 _modslong_dummy (void) _naked
52 {
53         _asm
54
55                 #define a0      dpl
56                 #define a1      dph
57                 #define a2      b
58                 #define a3      r1
59
60                 .globl __modslong
61
62                 // _modslong_PARM_2 shares the same memory with _modulong_PARM_2
63                 // and is defined in _modulong.c
64                 #define b0      (__modslong_PARM_2)
65                 #define b1      (__modslong_PARM_2 + 1)
66                 #define b2      (__modslong_PARM_2 + 2)
67                 #define b3      (__modslong_PARM_2 + 3)
68
69         __modslong:
70                                         ; a3 in acc
71                                         ; b3 in (__modslong_PARM_2 + 3)
72                 mov     a3,a            ; save a3
73
74                 clr     F0              ; Flag 0 in PSW
75                                         ; available to user for general purpose
76                 jnb     acc.7,a_not_negative
77
78                 setb    F0
79
80                 clr     a               ; a = -a;
81                 clr     c
82                 subb    a,a0
83                 mov     a0,a
84                 clr     a
85                 subb    a,a1
86                 mov     a1,a
87                 clr     a
88                 subb    a,a2
89                 mov     a2,a
90                 clr     a
91                 subb    a,a3
92                 mov     a3,a
93
94         a_not_negative:
95
96                 mov     a,b3
97                 jnb     acc.7,b_not_negative
98
99                 cpl     F0
100
101                 clr     a               ; b = -b;
102                 clr     c
103                 subb    a,b0
104                 mov     b0,a
105                 clr     a
106                 subb    a,b1
107                 mov     b1,a
108                 clr     a
109                 subb    a,b2
110                 mov     b2,a
111                 clr     a
112                 subb    a,b3
113                 mov     b3,a
114
115         b_not_negative:
116
117                 mov     a,a3            ; restore a3 in acc
118
119                 lcall   __modulong
120
121                 jnb     F0,not_negative
122
123                                 ; result in (a == r1), b, dph, dpl
124                 clr     a
125                 clr     c
126                 subb    a,a0
127                 mov     a0,a
128                 clr     a
129                 subb    a,a1
130                 mov     a1,a
131                 clr     a
132                 subb    a,a2
133                 mov     a2,a
134                 clr     a
135                 subb    a,a3
136                                 ; result in a, b, dph, dpl
137         not_negative:
138                 ret
139
140         _endasm ;
141 }
142
143 #elif defined _MODSLONG_ASM_SMALL_AUTO
144
145 static void
146 _modslong_dummy (void) _naked
147 {
148         _asm
149
150                 #define a0      dpl
151                 #define a1      dph
152                 #define a2      b
153                 #define a3      r1
154
155                 #define b0      r2
156                 #define b1      r3
157                 #define b2      r4
158                 #define b3      r5
159
160                 ar2 = 2                 ; BUG register set is not considered
161                 ar3 = 3
162                 ar4 = 4
163                 ar5 = 5
164
165                 .globl __modslong
166
167         __modslong:
168
169                                         ; a3 in acc
170                 mov     a3,a            ; save a3
171
172                 clr     F0              ; F0 (Flag 0)
173                                         ; available to user for general purpose
174                 jnb     acc.7,a_not_negative
175
176                 setb    F0
177
178                 clr     a               ; a = -a;
179                 clr     c
180                 subb    a,a0
181                 mov     a0,a
182                 clr     a
183                 subb    a,a1
184                 mov     a1,a
185                 clr     a
186                 subb    a,a2
187                 mov     a2,a
188                 clr     a
189                 subb    a,a3
190                 mov     a3,a
191
192         a_not_negative:
193
194                 mov     a,sp
195                 add     a,#-2-3         ; 2 bytes return address, 3 bytes param b
196                 mov     r0,a            ; r1 points to b0
197
198
199                 mov     ar2,@r0         ; load b0
200                 inc     r0              ; r0 points to b1
201                 mov     ar3,@r0         ; b1
202                 inc     r0
203                 mov     ar4,@r0         ; b2
204                 inc     r0
205                 mov     a,@r0           ; b3
206                 mov     b3,a
207
208                 jnb     acc.7,b_not_negative
209
210                 cpl     F0
211
212                 clr     a               ; b = -b;
213                 clr     c
214                 subb    a,b0
215                 mov     b0,a
216                 clr     a
217                 subb    a,b1
218                 mov     b1,a
219                 clr     a
220                 subb    a,b2
221                 mov     b2,a
222                 clr     a
223                 subb    a,b3
224                 mov     b3,a
225
226         b_not_negative:
227
228                 lcall   __modlong
229
230                 jnb     F0,not_negative
231
232                                 ; result in (a == r1), b, dph, dpl
233                 clr     a
234                 clr     c
235                 subb    a,a0
236                 mov     a0,a
237                 clr     a
238                 subb    a,a1
239                 mov     a1,a
240                 clr     a
241                 subb    a,a2
242                 mov     a2,a
243                 clr     a
244                 subb    a,a3    ; result in a, b, dph, dpl
245
246         not_negative:
247                 ret
248
249         _endasm ;
250 }
251
252 #else // _MODSLONG_ASM
253
254 long
255 _modslong (long a, long b)
256 {
257   long r;
258
259   r = _modulong((a < 0 ? -a : a),
260                 (b < 0 ? -b : b));
261   if ( (a < 0) ^ (b < 0))
262     return -r;
263   else
264     return r;
265 }
266
267 #endif // _MODSLONG_ASM