Imported Upstream version 2.9.0
[debian/cc1111] / 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 start:  clr     c
130         mov     a,bh            ; b >>= 1;
131 msbset: rrc     a
132         mov     bh,a
133         mov     a,bl
134         rrc     a
135         mov     bl,a
136
137 loop2:  clr     c
138         mov     a,al            ; a - b
139         subb    a,bl
140
141         mov     b,a
142         mov     a,ah
143         subb    a,bh
144
145         jc      smaller         ; a >= b?
146
147         mov     ah,a            ; -> yes;  a = a - b;
148         mov     al,b
149 smaller:                        ; -> no
150         clr     c
151         mov     a,bh            ; b >>= 1;
152         rrc     a
153         mov     bh,a
154         mov     a,bl
155         rrc     a
156         mov     bl,a
157
158         djnz    count,loop2
159 div_by_0:
160         ret
161
162         __endasm;
163 }
164
165 #else  // defined _MODUINT_ASM_SMALL || defined _MODUINT_ASM_SMALL_AUTO
166
167 #define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1) 
168
169 unsigned int
170 _moduint (unsigned int a, unsigned int b)
171 {
172   unsigned char count = 0;
173     
174     
175   while (!MSB_SET(b))
176   {
177     b <<= 1;
178     if (b > a)
179     {
180       b >>=1;
181       break;
182     }
183     count++;
184   }
185   do
186   {
187     if (a >= b)
188       a -= b;
189     b >>= 1;
190   }
191   while (count--);
192   return a;
193 }
194
195 #endif  // defined _MODUINT_ASM_SMALL || defined _MODUINT_ASM_SMALL_AUTO