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