Imported Upstream version 2.9.0
[debian/cc1111] / 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_