* configure.in: pic16 libraries build 2nd try - enable running
[fw/sdcc] / device / lib / _moduint.c
1 /*-------------------------------------------------------------------------
2   _moduint.c :- routine for unsigned int (16 bit) modulus
3
4              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
5
6              Bug fixes by Martijn van Balen, aed@iae.nl
7
8    This library is free software; you can redistribute it and/or modify it
9    under the terms of the GNU Library General Public License as published by the
10    Free Software Foundation; either version 2, or (at your option) any
11    later version.
12
13    This library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU Library General Public License for more details.
17
18    You should have received a copy of the GNU Library General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22    In other words, you are welcome to use, share and improve this program.
23    You are forbidden to forbid anyone else to use, share and improve
24    what you give them.   Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
26
27 /*   Assembler-functions are provided for:
28      mcs51 small
29      mcs51 small stack-auto
30 */
31
32 #if !defined(SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
33 #  if defined(SDCC_mcs51)
34 #    if defined(SDCC_MODEL_SMALL)
35 #      if defined(SDCC_STACK_AUTO)
36 #        define _MODUINT_ASM_SMALL_AUTO
37 #      else
38 #        define _MODUINT_ASM_SMALL
39 #      endif
40 #    endif
41 #  endif
42 #endif
43
44 #if defined _MODUINT_ASM_SMALL || defined _MODUINT_ASM_SMALL_AUTO
45
46 static void
47 _moduint_dummy (void) _naked
48 {
49         _asm
50
51                 .globl __moduint
52
53         __moduint:
54
55                 #define count   r2
56                 #define al      dpl
57                 #define ah      dph
58
59 #if defined(SDCC_STACK_AUTO) && !defined(SDCC_PARMS_IN_BANK1)
60
61                 ar0 = 0                 ; BUG register set is not considered
62                 ar1 = 1
63
64                 .globl __modint
65
66                 mov     a,sp
67                 add     a,#-2           ; 2 bytes return address
68                 mov     r0,a            ; r0 points to bh
69                 mov     ar1,@r0         ; load bh
70                 dec     r0
71                 mov     ar0,@r0         ; load bl
72
73                 #define bl      r0
74                 #define bh      r1
75
76         __modint:                       ; entry point for __modsint
77
78
79 #else // SDCC_STACK_AUTO
80
81 #if !defined(SDCC_PARMS_IN_BANK1)
82 #if defined(SDCC_NOOVERLAY)
83                 .area DSEG    (DATA)
84 #else
85                 .area OSEG    (OVR,DATA)
86 #endif
87
88                 .globl __moduint_PARM_2
89                 .globl __modsint_PARM_2
90
91         __moduint_PARM_2:
92         __modsint_PARM_2:
93                 .ds     2
94
95                 .area CSEG    (CODE)
96
97                 #define bl      (__moduint_PARM_2)
98                 #define bh      (__moduint_PARM_2 + 1)
99 #else
100                 #define bl      (b1_0)
101                 #define bh      (b1_1)
102 #endif
103 #endif // SDCC_STACK_AUTO
104
105                 mov     a,bl            ; avoid endless loop
106                 orl     a,bh
107                 jz      div_by_0
108
109                 mov     count,#1
110
111         loop1:  mov     a,bl            ; b <<= 1
112                 add     a,acc
113                 mov     bl,a
114                 mov     a,bh
115                 rlc     a
116                 jc      msbset
117                 mov     bh,a
118
119                 mov     a,al            ; a - b
120                 subb    a,bl            ; here carry is always clear
121                 mov     a,ah
122                 subb    a,bh
123
124                 jc      start
125
126                 inc     count
127                 sjmp    loop1
128
129
130         start:  clr     c
131                 mov     a,bh            ; b >>= 1;
132         msbset: rrc     a
133                 mov     bh,a
134                 mov     a,bl
135                 rrc     a
136                 mov     bl,a
137
138
139         loop2:  clr     c
140                 mov     a,al            ; a - b
141                 subb    a,bl
142
143                 mov     b,a
144                 mov     a,ah
145                 subb    a,bh
146
147                 jc      smaller         ; a >= b?
148
149                 mov     ah,a            ; -> yes;  a = a - b;
150                 mov     al,b
151         smaller:                        ; -> no
152                 clr     c
153                 mov     a,bh            ; b >>= 1;
154                 rrc     a
155                 mov     bh,a
156                 mov     a,bl
157                 rrc     a
158                 mov     bl,a
159
160                 djnz    count,loop2
161         div_by_0:
162                 ret
163
164         _endasm ;
165 }
166
167 #else  // defined _MODUINT_ASM_SMALL || defined _MODUINT_ASM_SMALL_AUTO
168
169 #define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1) 
170
171 unsigned int
172 _moduint (unsigned int a, unsigned int b)
173 {
174   unsigned char count = 0;
175     
176     
177   while (!MSB_SET(b))
178   {
179     b <<= 1;
180     if (b > a)
181     {
182       b >>=1;
183       break;
184     }
185     count++;
186   }
187   do
188   {
189     if (a >= b)
190       a -= b;
191     b >>= 1;
192   }
193   while (count--);
194   return a;
195 }
196
197 #endif  // defined _MODUINT_ASM_SMALL || defined _MODUINT_ASM_SMALL_AUTO