X-Git-Url: https://git.gag.com/?a=blobdiff_plain;ds=sidebyside;f=device%2Flib%2F_divuint.c;h=03b91998313be3276c678af1cc71470e141e56bd;hb=fd1585554b77cef31505cd53e5f9cebbb9916502;hp=bba3abf8d2620f0cb263e96c899d0cae97f44ee0;hpb=c629d2f5c76ed1e47ad9fc28127dcbe9552664ed;p=fw%2Fsdcc diff --git a/device/lib/_divuint.c b/device/lib/_divuint.c index bba3abf8..03b91998 100644 --- a/device/lib/_divuint.c +++ b/device/lib/_divuint.c @@ -1,50 +1,176 @@ /*------------------------------------------------------------------------- - _divuint.c :- routine for unsigned int (16 bit) division Ecrit par - Jean-Louis Vern . jlvern@writeme.com (1999) - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, + + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + In other words, you are welcome to use, share and improve this program. You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! + what you give them. Help stamp out software-hoarding! -------------------------------------------------------------------------*/ +/* Assembler-functions are provided for: + mcs51 small + mcs51 small stack-auto +*/ + +#include + +#if !defined(SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS) +# if defined(SDCC_mcs51) +# if defined(SDCC_MODEL_SMALL) +# if defined(SDCC_STACK_AUTO) +# define _DIVUINT_ASM_SMALL_AUTO +# else +# define _DIVUINT_ASM_SMALL +# endif +# endif +# endif +#endif + +#if defined _DIVUINT_ASM_SMALL || defined _DIVUINT_ASM_SMALL_AUTO + +static void +_divuint_dummy (void) _naked +{ + _asm + + .globl __divuint + + __divuint: + + #define count r2 + #define reste_l r3 + #define reste_h r4 + #define xl dpl + #define xh dph + +#if defined(SDCC_PARMS_IN_BANK1) + #define yl (b1_0) + #define yh (b1_1) +#else // SDCC_PARMS_IN_BANK1 + #if defined(SDCC_STACK_AUTO) + + .globl __divint + + mov a,sp + add a,#-2 ; 2 bytes return address + mov r0,a ; r0 points to yh + mov a,@r0 ; load yh + mov r1,a + dec r0 + mov a,@r0 ; load yl + mov r0,a + + #define yl r0 + #define yh r1 + + __divint: ; entry point for __divsint + + + #else // SDCC_STACK_AUTO + + #if defined(SDCC_NOOVERLAY) + .area DSEG (DATA) + #else + .area OSEG (OVR,DATA) + #endif + + .globl __divuint_PARM_2 + .globl __divsint_PARM_2 + + __divuint_PARM_2: + __divsint_PARM_2: + .ds 2 + + .area CSEG (CODE) + + #define yl (__divuint_PARM_2) + #define yh (__divuint_PARM_2 + 1) + + #endif // SDCC_STACK_AUTO +#endif // SDCC_PARMS_IN_BANK1 + + mov count,#16 + clr a + mov reste_l,a + mov reste_h,a + + loop: mov a,xl ; x <<= 1 + add a,acc + mov xl,a + mov a,xh + rlc a + mov xh,a + + mov a,reste_l ; reste <<= 1 + rlc a ; feed in carry + mov reste_l,a + mov a,reste_h + rlc a + mov reste_h,a + + mov a,reste_l ; reste - y + subb a,yl ; here carry is always clear, because + ; reste <<= 1 never overflows + mov b,a + mov a,reste_h + subb a,yh + + jc smaller ; reste >= y? + + mov reste_h,a ; -> yes; reste = reste - y; + mov reste_l,b + orl xl,#1 + smaller: ; -> no + djnz count,loop + ret + + _endasm ; +} + +#else // defined _DIVUINT_ASM_SMALL || defined _DIVUINT_ASM_SMALL_AUTO + #define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1) -unsigned int _divuint (unsigned int a, unsigned int b) +unsigned int +_divuint (unsigned int x, unsigned int y) { - unsigned int reste = 0 ; - unsigned char count = 16; - bit c; - - do{ - // reste:a <- 0; - c = MSB_SET(a); - a <<= 1; - reste <<= 1; - if(c) - reste |= 1; - - if(reste >= b){ - reste -= b; - // a <- (result = 1) - a |= 1; - } - } while(--count); - - return a; + unsigned int reste = 0; + unsigned char count = 16; + BOOL c; + + do + { + // reste: x <- 0; + c = MSB_SET(x); + x <<= 1; + reste <<= 1; + if (c) + reste |= 1; + + if (reste >= y) + { + reste -= y; + // x <- (result = 1) + x |= 1; + } + } + while (--count); + return x; } + +#endif // defined _DIVUINT_ASM_SMALL || defined _DIVUINT_ASM_SMALL_AUTO