_divulong.c (6187B)
1/*------------------------------------------------------------------------- 2 _divulong.c - routine for division of 32 bit unsigned long 3 4 Ecrit par - Jean-Louis Vern . jlvern@writeme.com (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/* Assembler-functions are provided for: 26 mcs51 small 27 mcs51 small stack-auto 28*/ 29 30#if !defined(SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS) 31# if defined(SDCC_mcs51) 32# if defined(SDCC_MODEL_SMALL) 33# if defined(SDCC_STACK_AUTO) 34# define _DIVULONG_ASM_SMALL_AUTO 35# else 36# define _DIVULONG_ASM_SMALL 37# endif 38# endif 39# endif 40#endif 41 42#if defined _DIVULONG_ASM_SMALL 43 44static void 45_divlong_dummy (void) _naked 46{ 47 _asm 48 49 .globl __divulong 50 51 __divulong: 52 53 #define count r2 54 55 #define a0 dpl 56 #define a1 dph 57 #define a2 b 58 #define a3 r3 59 60 #define reste0 r4 61 #define reste1 r5 62 #define reste2 r6 63 #define reste3 r7 64 65#if defined(SDCC_NOOVERLAY) 66 .area DSEG (DATA) 67#else 68 .area OSEG (OVR,DATA) 69#endif 70 71 .globl __divulong_PARM_2 72 .globl __divslong_PARM_2 73 74 __divulong_PARM_2: 75 __divslong_PARM_2: 76 .ds 4 77 78 .area CSEG (CODE) 79 80 #define b0 (__divulong_PARM_2) 81 #define b1 (__divulong_PARM_2 + 1) 82 #define b2 (__divulong_PARM_2 + 2) 83 #define b3 (__divulong_PARM_2 + 3) 84 85 ; parameter a comes in a, b, dph, dpl 86 mov a3,a ; save parameter a3 87 88 mov count,#32 89 clr a 90 mov reste0,a 91 mov reste1,a 92 mov reste2,a 93 mov reste3,a 94 95 ; optimization loop in lp0 until the first bit is shifted into rest 96 97 lp0: mov a,a0 ; a <<= 1 98 add a,a0 99 mov a0,a 100 mov a,a1 101 rlc a 102 mov a1,a 103 mov a,a2 104 rlc a 105 mov a2,a 106 mov a,a3 107 rlc a 108 mov a3,a 109 110 jc in_lp 111 djnz count,lp0 112 113 sjmp exit 114 115 loop: mov a,a0 ; a <<= 1 116 add a,a0 117 mov a0,a 118 mov a,a1 119 rlc a 120 mov a1,a 121 mov a,a2 122 rlc a 123 mov a2,a 124 mov a,a3 125 rlc a 126 mov a3,a 127 128 in_lp: mov a,reste0 ; reste <<= 1 129 rlc a ; feed in carry 130 mov reste0,a 131 mov a,reste1 132 rlc a 133 mov reste1,a 134 mov a,reste2 135 rlc a 136 mov reste2,a 137 mov a,reste3 138 rlc a 139 mov reste3,a 140 141 mov a,reste0 ; reste - b 142 subb a,b0 ; carry is always clear here, because 143 ; reste <<= 1 never overflows 144 mov a,reste1 145 subb a,b1 146 mov a,reste2 147 subb a,b2 148 mov a,reste3 149 subb a,b3 150 151 jc minus ; reste >= b? 152 153 ; -> yes; reste -= b; 154 mov a,reste0 155 subb a,b0 ; carry is always clear here (jc) 156 mov reste0,a 157 mov a,reste1 158 subb a,b1 159 mov reste1,a 160 mov a,reste2 161 subb a,b2 162 mov reste2,a 163 mov a,reste3 164 subb a,b3 165 mov reste3,a 166 167 orl a0,#1 168 169 minus: djnz count,loop ; -> no 170 171 exit: mov a,a3 ; prepare the return value 172 ret 173 174 _endasm ; 175} 176 177#elif defined _DIVULONG_ASM_SMALL_AUTO 178 179static void 180_divlong_dummy (void) _naked 181{ 182 _asm 183 184 .globl __divulong 185 186 __divulong: 187 188 #define count r2 189 190 #define a0 dpl 191 #define a1 dph 192 #define a2 b 193 #define a3 r3 194 195 #define reste0 r4 196 #define reste1 r5 197 #define reste2 r6 198 #define reste3 r7 199 200 .globl __divlong ; entry point for __divslong 201 202 #define b0 r1 203 204 ar0 = 0 ; BUG register set is not considered 205 ar1 = 1 206 207 ; parameter a comes in a, b, dph, dpl 208 mov a3,a ; save parameter a3 209 210 mov a,sp 211 add a,#-2-3 ; 2 bytes return address, 3 bytes param b 212 mov r0,a ; r0 points to b0 213 214 __divlong: ; entry point for __divslong 215 216 mov ar1,@r0 ; load b0 217 inc r0 ; r0 points to b1 218 219 mov count,#32 220 clr a 221 mov reste0,a 222 mov reste1,a 223 mov reste2,a 224 mov reste3,a 225 226 ; optimization loop in lp0 until the first bit is shifted into rest 227 228 lp0: mov a,a0 ; a <<= 1 229 add a,a0 230 mov a0,a 231 mov a,a1 232 rlc a 233 mov a1,a 234 mov a,a2 235 rlc a 236 mov a2,a 237 mov a,a3 238 rlc a 239 mov a3,a 240 241 jc in_lp 242 djnz count,lp0 243 244 sjmp exit 245 246 loop: mov a,a0 ; a <<= 1 247 add a,a0 248 mov a0,a 249 mov a,a1 250 rlc a 251 mov a1,a 252 mov a,a2 253 rlc a 254 mov a2,a 255 mov a,a3 256 rlc a 257 mov a3,a 258 259 in_lp: mov a,reste0 ; reste <<= 1 260 rlc a ; feed in carry 261 mov reste0,a 262 mov a,reste1 263 rlc a 264 mov reste1,a 265 mov a,reste2 266 rlc a 267 mov reste2,a 268 mov a,reste3 269 rlc a 270 mov reste3,a 271 272 mov a,reste0 ; reste - b 273 subb a,b0 ; carry is always clear here, because 274 ; reste <<= 1 never overflows 275 mov a,reste1 276 subb a,@r0 ; b1 277 mov a,reste2 278 inc r0 279 subb a,@r0 ; b2 280 mov a,reste3 281 inc r0 282 subb a,@r0 ; b3 283 dec r0 284 dec r0 285 286 jc minus ; reste >= b? 287 288 ; -> yes; reste -= b; 289 mov a,reste0 290 subb a,b0 ; carry is always clear here (jc) 291 mov reste0,a 292 mov a,reste1 293 subb a,@r0 ; b1 294 mov reste1,a 295 mov a,reste2 296 inc r0 297 subb a,@r0 ; b2 298 mov reste2,a 299 mov a,reste3 300 inc r0 301 subb a,@r0 ; b3 302 mov reste3,a 303 dec r0 304 dec r0 305 306 orl a0,#1 307 308 minus: djnz count,loop ; -> no 309 310 exit: mov a,a3 ; prepare the return value 311 ret 312 313 _endasm ; 314} 315 316#else // _DIVULONG_ASM 317 318#define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1) 319 320unsigned long 321_divulong (unsigned long a, unsigned long b) 322{ 323 unsigned long reste = 0L; 324 unsigned char count = 32; 325 #if defined(__SDCC_STACK_AUTO) || defined(__SDCC_z80) || defined(__SDCC_sm83) 326 char c; 327 #else 328 bit c; 329 #endif 330 331 do 332 { 333 // reste: a <- 0; 334 c = MSB_SET(a); 335 a <<= 1; 336 reste <<= 1; 337 if (c) 338 reste |= 1L; 339 340 if (reste >= b) 341 { 342 reste -= b; 343 // a <- (result = 1) 344 a |= 1L; 345 } 346 } 347 while (--count); 348 return a; 349} 350 351#endif // _DIVULONG_ASM