* src/*.c, src/pic16/{gen.c,glue.c,main.c}: applied Vangelis
[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                 dec     r0
163
164                 clr     a
165                 clr     c
166                 subb    a,@r0           ; b0
167                 mov     @r0,a
168                 clr     a
169                 inc     r0
170                 subb    a,@r0           ; b1
171                 mov     @r0,a
172
173         b_not_negative:
174
175                 mov     ar1,@r0         ; b1
176                 dec     r0
177                 mov     ar0,@r0         ; b0
178
179                 lcall   __modint
180
181                 jnb     F0,not_negative
182
183                 clr     a
184                 clr     c
185                 subb    a,a0
186                 mov     a0,a
187                 clr     a
188                 subb    a,a1
189                 mov     a1,a
190
191         not_negative:
192                 ret
193
194         _endasm ;
195 }
196
197 #else  // _MODSINT_ASM_
198
199 int _modsint (int a, int b)
200 {
201        register int r;
202        
203        r = _moduint((a < 0 ? -a : a),
204                     (b < 0 ? -b : b));
205
206        if (a < 0)
207             return -r;
208         else
209             return r;
210 }               
211
212 #endif  // _MODSINT_ASM_