Imported Upstream version 2.9.0
[debian/cc1111] / 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         mov     ar2,@r0         ; load b0
202         inc     r0              ; r0 points to b1
203         mov     ar3,@r0         ; b1
204         inc     r0
205         mov     ar4,@r0         ; b2
206         inc     r0
207         mov     a,@r0           ; b3
208         mov     b3,a
209
210         jnb     acc.7,b_not_negative
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)
262     return -r;
263   else
264     return r;
265 }
266
267 #endif // _MODSLONG_ASM