* configure.in: added missing mcs51 in status output
[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                 clr     a               ; b = -b;
214                 clr     c
215                 subb    a,b0
216                 mov     b0,a
217                 clr     a
218                 subb    a,b1
219                 mov     b1,a
220                 clr     a
221                 subb    a,b2
222                 mov     b2,a
223                 clr     a
224                 subb    a,b3
225                 mov     b3,a
226
227         b_not_negative:
228
229                 lcall   __modlong
230
231                 jnb     F0,not_negative
232
233                                 ; result in (a == r1), b, dph, dpl
234                 clr     a
235                 clr     c
236                 subb    a,a0
237                 mov     a0,a
238                 clr     a
239                 subb    a,a1
240                 mov     a1,a
241                 clr     a
242                 subb    a,a2
243                 mov     a2,a
244                 clr     a
245                 subb    a,a3    ; result in a, b, dph, dpl
246
247         not_negative:
248                 ret
249
250         _endasm ;
251 }
252
253 #else // _MODSLONG_ASM
254
255 long
256 _modslong (long a, long b)
257 {
258   long r;
259
260   r = _modulong((a < 0 ? -a : a),
261                 (b < 0 ? -b : b));
262   if (a < 0)
263     return -r;
264   else
265     return r;
266 }
267
268 #endif // _MODSLONG_ASM