1 /*-------------------------------------------------------------------------
2    _moduint.c - routine for unsigned int (16 bit) modulus
3 
4    Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net
5    Bug fixes by Martijn van Balen, aed@iae.nl
6 
7    This library is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published by the
9    Free Software Foundation; either version 2, or (at your option) any
10    later version.
11 
12    This library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this library; see the file COPYING. If not, write to the
19    Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
20    MA 02110-1301, USA.
21 
22    As a special exception, if you link this library with other files,
23    some of which are compiled with SDCC, to produce an executable,
24    this library does not by itself cause the resulting executable to
25    be covered by the GNU General Public License. This exception does
26    not however invalidate any other reasons why the executable file
27    might be covered by the GNU General Public License.
28 -------------------------------------------------------------------------*/
29 
30 /*   Assembler-functions are provided for:
31      mcs51 small
32      mcs51 small stack-auto
33 */
34 
35 #if !defined(__SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
36 #  if defined(__SDCC_mcs51)
37 #    if defined(__SDCC_MODEL_SMALL)
38 #      if defined(__SDCC_STACK_AUTO)
39 #        define _MODUINT_ASM_SMALL_AUTO
40 #      else
41 #        define _MODUINT_ASM_SMALL
42 #      endif
43 #    endif
44 #  endif
45 #endif
46 
47 #if defined _MODUINT_ASM_SMALL || defined _MODUINT_ASM_SMALL_AUTO
48 
49 static void
_moduint_dummy(void)50 _moduint_dummy (void) __naked
51 {
52 	__asm
53 
54 	.globl __moduint
55 
56 __moduint:
57 
58 	#define count   r2
59 	#define al      dpl
60 	#define ah      dph
61 
62 #if defined(__SDCC_STACK_AUTO) && !defined(__SDCC_PARMS_IN_BANK1)
63 
64 	ar0 = 0			; BUG register set is not considered
65 	ar1 = 1
66 
67 	.globl __modint
68 
69 	mov	a,sp
70 	add	a,#-2		; 2 bytes return address
71 	mov	r0,a		; r0 points to bh
72 	mov	ar1,@r0		; load bh
73 	dec	r0
74 	mov	ar0,@r0		; load bl
75 
76 	#define bl      r0
77 	#define bh      r1
78 
79 __modint:			; entry point for __modsint
80 
81 
82 #else // __SDCC_STACK_AUTO
83 
84 #if !defined(__SDCC_PARMS_IN_BANK1)
85 #if defined(__SDCC_NOOVERLAY)
86 	.area DSEG    (DATA)
87 #else
88 	.area OSEG    (OVR,DATA)
89 #endif
90 
91 	.globl __moduint_PARM_2
92 	.globl __modsint_PARM_2
93 
94 __moduint_PARM_2:
95 __modsint_PARM_2:
96 	.ds	2
97 
98 	.area CSEG    (CODE)
99 
100 	#define bl      (__moduint_PARM_2)
101 	#define bh      (__moduint_PARM_2 + 1)
102 #else
103 	#define bl      (b1_0)
104 	#define bh      (b1_1)
105 #endif
106 #endif // __SDCC_STACK_AUTO
107 
108 	mov	a,bl		; avoid endless loop
109 	orl	a,bh
110 	jz	div_by_0
111 
112 	mov	count,#1
113 
114 loop1:	mov	a,bl		; b <<= 1
115 	add	a,acc
116 	mov	bl,a
117 	mov	a,bh
118 	rlc	a
119 	jc	msbset
120 	mov	bh,a
121 
122 	mov	a,al		; a - b
123 	subb	a,bl		; here carry is always clear
124 	mov	a,ah
125 	subb	a,bh
126 
127 	jc	start
128 
129 	inc	count
130 	sjmp	loop1
131 
132 start:	clr	c
133 	mov	a,bh		; b >>= 1;
134 msbset:	rrc	a
135 	mov	bh,a
136 	mov	a,bl
137 	rrc	a
138 	mov	bl,a
139 
140 loop2:	clr	c
141 	mov	a,al		; a - b
142 	subb	a,bl
143 
144 	mov	b,a
145 	mov	a,ah
146 	subb	a,bh
147 
148 	jc	smaller		; a >= b?
149 
150 	mov	ah,a		; -> yes;  a = a - b;
151 	mov	al,b
152 smaller:			; -> no
153 	clr	c
154 	mov	a,bh		; b >>= 1;
155 	rrc	a
156 	mov	bh,a
157 	mov	a,bl
158 	rrc	a
159 	mov	bl,a
160 
161 	djnz	count,loop2
162 div_by_0:
163 	ret
164 
165 	__endasm;
166 }
167 
168 #else  // defined _MODUINT_ASM_SMALL || defined _MODUINT_ASM_SMALL_AUTO
169 
170 #define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1)
171 
172 unsigned int
_moduint(unsigned int a,unsigned int b)173 _moduint (unsigned int a, unsigned int b)
174 {
175   unsigned char count = 0;
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
198