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