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