* device/lib/_modsint.c,
[fw/sdcc] / device / lib / _modsint.c
1 /*-------------------------------------------------------------------------
2   _modsint.c :- routine for signed int (16 bit) modulus
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
26 #include <sdcc-lib.h>
27
28 #if _SDCC_MANGLES_SUPPORT_FUNS
29 unsigned unsigned _moduint (unsigned a, unsigned b);
30 #endif
31
32 /*   Assembler-functions are provided for:
33      mcs51 small
34      mcs51 small stack-auto
35 */
36
37 #if !defined(SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
38 #  if defined(SDCC_mcs51)
39 #    if defined(SDCC_MODEL_SMALL)
40 #      if defined(SDCC_STACK_AUTO) && !defined(SDCC_PARMS_IN_BANK1)
41 #        define _MODSINT_ASM_SMALL_AUTO
42 #      else
43 #        define _MODSINT_ASM_SMALL
44 #      endif
45 #    endif
46 #  endif
47 #endif
48
49 #if defined _MODSINT_ASM_SMALL
50
51 static void
52 _modsint_dummy (void) _naked
53 {
54         _asm
55
56                 #define a0      dpl
57                 #define a1      dph
58
59                 .globl __modsint
60 #if defined(SDCC_PARMS_IN_BANK1)
61                 #define b0      (b1_0)
62                 #define b1      (b1_1)
63 #else
64                 // _modsint_PARM_2 shares the same memory with _moduint_PARM_2
65                 // and is defined in _moduint.c
66                 #define b0      (__modsint_PARM_2)
67                 #define b1      (__modsint_PARM_2 + 1)
68 #endif
69         __modsint:
70                                         ; a1 in dph
71                                         ; b1 in (__modsint_PARM_2 + 1)
72
73                 clr     F0              ; Flag 0 in PSW
74                                         ; available to user for general purpose
75                 mov     a,a1
76                 jnb     acc.7,a_not_negative
77
78                 setb    F0
79
80                 clr     a
81                 clr     c
82                 subb    a,a0
83                 mov     a0,a
84                 clr     a
85                 subb    a,a1
86                 mov     a1,a
87
88         a_not_negative:
89
90                 mov     a,b1
91                 jnb     acc.7,b_not_negative
92
93                 clr     a
94                 clr     c
95                 subb    a,b0
96                 mov     b0,a
97                 clr     a
98                 subb    a,b1
99                 mov     b1,a
100
101         b_not_negative:
102
103                 lcall   __moduint
104
105                 jnb     F0,not_negative
106
107                 clr     a
108                 clr     c
109                 subb    a,a0
110                 mov     a0,a
111                 clr     a
112                 subb    a,a1
113                 mov     a1,a
114
115         not_negative:
116                 ret
117
118         _endasm ;
119 }
120
121 #elif defined _MODSINT_ASM_SMALL_AUTO
122
123 static void
124 _modsint_dummy (void) _naked
125 {
126         _asm
127
128                 #define a0      dpl
129                 #define a1      dph
130
131                 ar0 = 0                 ; BUG register set is not considered
132                 ar1 = 1
133
134                 .globl __modsint
135
136         __modsint:
137
138                 clr     F0              ; Flag 0 in PSW
139                                         ; available to user for general purpose
140                 mov     a,a1
141                 jnb     acc.7,a_not_negative
142
143                 setb    F0
144
145                 clr     a
146                 clr     c
147                 subb    a,a0
148                 mov     a0,a
149                 clr     a
150                 subb    a,a1
151                 mov     a1,a
152
153         a_not_negative:
154
155                 mov     a,sp
156                 add     a,#-2           ; 2 bytes return address
157                 mov     r0,a            ; r0 points to b1
158                 mov     a,@r0           ; b1
159
160                 jnb     acc.7,b_not_negative
161
162                 cpl     F0
163
164                 dec     r0
165
166                 clr     a
167                 clr     c
168                 subb    a,@r0           ; b0
169                 mov     @r0,a
170                 clr     a
171                 inc     r0
172                 subb    a,@r0           ; b1
173                 mov     @r0,a
174
175         b_not_negative:
176
177                 mov     ar1,@r0         ; b1
178                 dec     r0
179                 mov     ar0,@r0         ; b0
180
181                 lcall   __modint
182
183                 jnb     F0,not_negative
184
185                 clr     a
186                 clr     c
187                 subb    a,a0
188                 mov     a0,a
189                 clr     a
190                 subb    a,a1
191                 mov     a1,a
192
193         not_negative:
194                 ret
195
196         _endasm ;
197 }
198
199 #else  // _MODSINT_ASM_
200
201 int _modsint (int a, int b)
202 {
203        register int r;
204        
205        r = _moduint((a < 0 ? -a : a),
206                     (b < 0 ? -b : b));
207
208        if ( (a < 0) ^ (b < 0))
209             return -r;
210         else
211             return r;
212 }               
213
214 #endif  // _MODSINT_ASM_