X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=device%2Flib%2F_divuint.c;h=9cb36f0e69df2aef9bc6a2f095dbd4eed3185a0f;hb=adbc8dc91c89ab015c28bc60ada16efe8f7f788a;hp=bc3a5b15a029b12eee350c173b1ad0ff043fd344;hpb=99fcafaaddfe9eb3de89d61bf643cecacbb8a9d4;p=fw%2Fsdcc diff --git a/device/lib/_divuint.c b/device/lib/_divuint.c index bc3a5b15..9cb36f0e 100644 --- a/device/lib/_divuint.c +++ b/device/lib/_divuint.c @@ -1,54 +1,179 @@ /*------------------------------------------------------------------------- - _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! -------------------------------------------------------------------------*/ -#define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1) +/* Assembler-functions are provided for: + mcs51 small + mcs51 small stack-auto +*/ -unsigned int _divuint (unsigned int a, unsigned int b) +#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 { - unsigned int reste = 0 ; - unsigned char count = 16; -#ifdef SDCC_STACK_AUTO - unsigned char c; + _asm + + .globl __divuint + + __divuint: + + #define count r2 + #define reste_l r3 + #define reste_h r4 + #define al dpl + #define ah dph + +#if defined(SDCC_STACK_AUTO) && !defined(SDCC_PARMS_IN_BANK1) + + ar0 = 0 ; BUG register set is not considered + ar1 = 1 + + .globl __divint + + mov a,sp + add a,#-2 ; 2 bytes return address + mov r0,a ; r0 points to bh + mov ar1,@r0 ; load bh + dec r0 + mov ar0,@r0 ; load bl + + #define bl r0 + #define bh r1 + + __divint: ; entry point for __divsint + + +#else // SDCC_STACK_AUTO + +#if !defined(SDCC_PARMS_IN_BANK1) +#if defined(SDCC_NOOVERLAY) + .area DSEG (DATA) #else - bit c; + .area OSEG (OVR,DATA) #endif - 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; + .globl __divuint_PARM_2 + .globl __divsint_PARM_2 + + __divuint_PARM_2: + __divsint_PARM_2: + .ds 2 + + .area CSEG (CODE) +#endif // !SDCC_PARMS_IN_BANK1 +#if defined(SDCC_PARMS_IN_BANK1) + #define bl (b1_0) + #define bh (b1_1) +#else + #define bl (__divuint_PARM_2) + #define bh (__divuint_PARM_2 + 1) +#endif // SDCC_PARMS_IN_BANK1 +#endif // SDCC_STACK_AUTO + + mov count,#16 + clr a + mov reste_l,a + mov reste_h,a + + loop: mov a,al ; a <<= 1 + add a,acc + mov al,a + mov a,ah + rlc a + mov ah,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 - b + subb a,bl ; here carry is always clear, because + ; reste <<= 1 never overflows + mov b,a + mov a,reste_h + subb a,bh + + jc smaller ; reste >= b? + + mov reste_h,a ; -> yes; reste = reste - b; + mov reste_l,b + orl al,#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 reste = 0; + unsigned char count = 16; + #if defined(SDCC_STACK_AUTO) || defined(SDCC_z80) + char c; + #else + bit c; + #endif + + 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; +} + +#endif // defined _DIVUINT_ASM_SMALL || defined _DIVUINT_ASM_SMALL_AUTO