+2001-10-03 Bernhard Held <bernhard@bernhardheld.de>
+
+ * src/device/lib/_mulint.c : new, with assember functions
+
+ * src/device/lib/_mullong.c : new, with assember functions
+
+ * src/device/lib/_divuint.c : with assember functions
+
+ * src/device/lib/_divsint.c : with assember functions
+
+ * src/device/lib/_divulong.c: with assember functions
+
+ * src/device/lib/_divslong.c: with assember functions
+
+ * src/device/lib/_moduint.c : with assember functions
+
+ * src/device/lib/_modsint.c : with assember functions
+
+ * src/device/lib/_modulong.c: with assember functions
+
+ * src/device/lib/_modslong.c: with assember functions
+
+ * src/device/lib/libint.lib: replaced _muluint.c and _mulsint.c by _mulint.c
+
+ * src/device/lib/liblong.lib: replaced _mululong.c and _mulslong.c by _mullong.c
+
+ * src/device/lib/Makefile.in: replaced _muluint.c and _mulsint.c by _mulint.c
+ replaced _mululong.c and _mulslong.c by _mullong.c
+
2001-10-03 Bernhard Held <bernhard@bernhardheld.de>
* src/SDCCsymt.c: sequence of specifiers in pintTypeChain() corrected
_islower.c _isprint.c _ispunct.c _isspace.c \
_isupper.c _isxdigit.c _slong2fs.c _memcmp.c \
_memcpy.c _memset.c _modsint.c _modslong.c \
- _moduint.c _modulong.c _mulsint.c _muluint.c \
- _mululong.c _mulslong.c _ser.c _setjmp.c \
+ _moduint.c _modulong.c _mulint.c _mullong.c \
+ _ser.c _setjmp.c \
_spx.c _startup.c _strchr.c _strcmp.c _strcpy.c \
_strcspn.c _strlen.c _strncat.c _strncmp.c \
_strncpy.c _strpbrk.c _strrchr.c _strspn.c \
_strstr.c _strtok.c _uchar2fs.c _uint2fs.c \
_ulong2fs.c malloc.c serial.c ser_ir.c printfl.c \
printf_large.c vprintf.c puts.c gets.c \
- assert.c _strcat.c time.c printf_fast.c \
- _mulint.c _mullong.c
+ assert.c _strcat.c time.c printf_fast.c
OBJECTS = $(patsubst %.c,$(PORTDIR)/%.rel,$(SOURCES))
/*-------------------------------------------------------------------------
-
_divsint.c :- routine for signed int (16 bit) division. just calls
routine for unsigned division after sign adjustment
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 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 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!
-------------------------------------------------------------------------*/
-int _divsint (int a, int b)
-#ifndef SDCC_STACK_AUTO
- critical
+
+
+#include <sdcc-lib.h>
+
+#if _SDCC_MANGLES_SUPPORT_FUNS
+unsigned unsigned _divuint (unsigned a, unsigned b);
#endif
+
+/* Assembler-functions are provided for:
+ mcs51 small
+ mcs51 small stack-auto
+*/
+
+#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 _DIVSINT_ASM_SMALL_AUTO
+# else
+# define _DIVSINT_ASM_SMALL
+# endif
+# endif
+# endif
+#endif
+
+#if defined _DIVSINT_ASM_SMALL
+
+static void
+_divsint_dummy (void) _naked
{
- register int r;
-
- r = _divuint((a < 0 ? -a : a),
- (b < 0 ? -b : b));
- if ( (a < 0) ^ (b < 0)) {
-
- return -r;
- }
- else {
-
- return r;
- }
+ _asm
+
+ #define a0 dpl
+ #define a1 dph
+
+ .globl __divsint
+
+ // _divsint_PARM_2 shares the same memory with _divuint_PARM_2
+ // and is defined in _divuint.c
+ #define b0 (__divsint_PARM_2)
+ #define b1 (__divsint_PARM_2 + 1)
+
+ __divsint:
+ ; a1 in dph
+ ; b1 in (__divsint_PARM_2 + 1)
+
+ clr F0 ; Flag 0 in PSW
+ ; available to user for general purpose
+ mov a,a1
+ jnb acc.7,a_not_negative
+
+ setb F0
+
+ clr a
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+
+ a_not_negative:
+
+ mov a,b1
+ jnb acc.7,b_not_negative
+
+ cpl F0
+
+ clr a
+ clr c
+ subb a,b0
+ mov b0,a
+ clr a
+ subb a,b1
+ mov b1,a
+
+ b_not_negative:
+
+ lcall __divuint
+
+ jnb F0,not_negative
+
+ clr a
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+
+ not_negative:
+ ret
+
+ _endasm ;
}
+
+#elif defined _DIVSINT_ASM_SMALL_AUTO
+
+static void
+_divsint_dummy (void) _naked
+{
+ _asm
+
+ #define a0 dpl
+ #define a1 dph
+
+ ar0 = 0 ; BUG register set is not considered
+ ar1 = 1
+
+ .globl __divsint
+
+ __divsint:
+
+ clr F0 ; Flag 0 in PSW
+ ; available to user for general purpose
+ mov a,a1
+ jnb acc.7,a_not_negative
+
+ setb F0
+
+ clr a
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+
+ a_not_negative:
+
+ mov a,sp
+ add a,#-2 ; 2 bytes return address
+ mov r0,a ; r0 points to b1
+ mov a,@r0 ; b1
+
+ jnb acc.7,b_not_negative
+
+ cpl F0
+
+ dec r0
+
+ clr a
+ clr c
+ subb a,@r0 ; b0
+ mov @r0,a
+ clr a
+ inc r0
+ subb a,@r0 ; b1
+ mov @r0,a
+
+ b_not_negative:
+
+ mov ar1,@r0 ; b1
+ dec r0
+ mov ar0,@r0 ; b0
+
+ lcall __divint
+
+ jnb F0,not_negative
+
+ clr a
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+
+ not_negative:
+ ret
+
+ _endasm ;
+}
+
+#else // _DIVSINT_ASM_
+
+int
+_divsint (int a, int b)
+{
+ register int r;
+
+ r = _divuint((a < 0 ? -a : a),
+ (b < 0 ? -b : b));
+ if ( (a < 0) ^ (b < 0))
+ return -r;
+ else
+ return r;
+}
+
+#endif // _DIVSINT_ASM_
/*-------------------------------------------------------------------------
- _divslong.c - routine for division of 32 bit signed long
+ _divslong.c - routine for division of 32 bit long
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
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 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 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!
-------------------------------------------------------------------------*/
+
#include <sdcc-lib.h>
#if _SDCC_MANGLES_SUPPORT_FUNS
unsigned long _divulong (unsigned long a, unsigned long b);
#endif
-long _divslong (long a, long b)
+/* Assembler-functions are provided for:
+ mcs51 small
+ mcs51 small stack-auto
+*/
+
+#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 _DIVSLONG_ASM_SMALL_AUTO
+# else
+# define _DIVSLONG_ASM_SMALL
+# endif
+# endif
+# endif
+#endif
+
+#if defined _DIVSLONG_ASM_SMALL
+
+static void
+_divslong_dummy (void) _naked
{
- long r;
-
- r = _divulong((a < 0 ? -a : a),
- (b < 0 ? -b : b));
- if ( (a < 0) ^ (b < 0))
- return -r;
- else
- return r;
-}
+ _asm
+
+ #define a0 dpl
+ #define a1 dph
+ #define a2 b
+ #define a3 r3
+
+ .globl __divslong
+
+ // _divslong_PARM_2 shares the same memory with _divulong_PARM_2
+ // and is defined in _divulong.c
+ #define b0 (__divslong_PARM_2)
+ #define b1 (__divslong_PARM_2 + 1)
+ #define b2 (__divslong_PARM_2 + 2)
+ #define b3 (__divslong_PARM_2 + 3)
+
+ __divslong:
+ ; a3 in acc
+ ; b3 in (__divslong_PARM_2 + 3)
+ mov a3,a ; save a3
+
+ clr F0 ; Flag 0 in PSW
+ ; available to user for general purpose
+ jnb acc.7,a_not_negative
+
+ setb F0
+
+ clr a
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+ clr a
+ subb a,a2
+ mov a2,a
+ clr a
+ subb a,a3
+ mov a3,a
+
+ a_not_negative:
+
+ mov a,b3
+ jnb acc.7,b_not_negative
+
+ cpl F0
+
+ clr a
+ clr c
+ subb a,b0
+ mov b0,a
+ clr a
+ subb a,b1
+ mov b1,a
+ clr a
+ subb a,b2
+ mov b2,a
+ clr a
+ subb a,b3
+ mov b3,a
+
+ b_not_negative:
+
+ mov a,a3 ; restore a3 in acc
+
+ lcall __divulong
+
+ jnb F0,not_negative
+
+ mov a3,a ; save a3
+
+ clr a
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+ clr a
+ subb a,a2
+ mov a2,a
+ clr a
+ subb a,a3
+ mov a3,a
+
+ not_negative:
+ ret
+
+ _endasm ;
+}
+
+#elif defined _DIVSLONG_ASM_SMALL_AUTO
+
+static void
+_divslong_dummy (void) _naked
+{
+ _asm
+
+ #define a0 dpl
+ #define a1 dph
+ #define a2 b
+ #define a3 r3
+
+ .globl __divslong
+
+ __divslong:
+
+ ; a3 in acc
+ mov a3,a ; save a3
+
+ clr F0 ; Flag 0 in PSW
+ ; available to user for general purpose
+ jnb acc.7,a_not_negative
+
+ setb F0
+
+ clr a
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+ clr a
+ subb a,a2
+ mov a2,a
+ clr a
+ subb a,a3
+ mov a3,a
+
+ a_not_negative:
+
+ mov a,sp
+ add a,#-2 ; 2 bytes return address
+ mov r0,a ; r0 points to b3
+ mov a,@r0 ; b3
+
+ jnb acc.7,b_not_negative
+
+ cpl F0
+
+ dec r0
+ dec r0
+ dec r0
+
+ clr a
+ clr c
+ subb a,@r0 ; b0
+ mov @r0,a
+ clr a
+ inc r0
+ subb a,@r0 ; b1
+ mov @r0,a
+ clr a
+ inc r0
+ subb a,@r0 ; b2
+ mov @r0,a
+ clr a
+ inc r0
+ subb a,@r0 ; b3
+ mov @r0,a
+
+ b_not_negative:
+ dec r0
+ dec r0
+ dec r0 ; r0 points to b0
+
+ lcall __divlong
+
+ jnb F0,not_negative
+
+ mov a3,a ; save a3
+
+ clr a
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+ clr a
+ subb a,a2
+ mov a2,a
+ clr a
+ subb a,a3
+ mov a3,a
+
+ not_negative:
+ ret
+
+ _endasm ;
+}
+
+#else // _DIVSLONG_ASM
+
+long
+_divslong (long a, long b)
+{
+ long r;
+
+ r = _divulong((a < 0 ? -a : a),
+ (b < 0 ? -b : b));
+ if ( (a < 0) ^ (b < 0))
+ return -r;
+ else
+ return r;
+}
+
+#endif // _DIVSLONG_ASM
/*-------------------------------------------------------------------------
-
_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;
+ _asm
+
+ .globl __divuint
+
+ __divuint:
+
+ #define count r2
+ #define reste_l r3
+ #define reste_h r4
+ #define al dpl
+ #define ah dph
+
#ifdef SDCC_STACK_AUTO
- unsigned char c;
+
+ 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_NOOVERLAY) // BUG SDCC_NOOVERLAY is not set by -no-overlay
+ .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)
+
+ #define bl (__divuint_PARM_2)
+ #define bh (__divuint_PARM_2 + 1)
+
+#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
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
+*/
+
+#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 _DIVULONG_ASM_SMALL_AUTO
+# else
+# define _DIVULONG_ASM_SMALL
+# endif
+# endif
+# endif
+#endif
+
+#if defined _DIVULONG_ASM_SMALL
+
+static void
+_divlong_dummy (void) _naked
+{
+ _asm
+
+ .globl __divulong
+
+ __divulong:
+
+ #define count r2
+
+ #define a0 dpl
+ #define a1 dph
+ #define a2 b
+ #define a3 r3
+
+ #define reste0 r4
+ #define reste1 r5
+ #define reste2 r6
+ #define reste3 r7
+
+#if defined(SDCC_NOOVERLAY) // BUG SDCC_NOOVERLAY is not set by -no-overlay
+ .area DSEG (DATA)
+#else
+ .area OSEG (OVR,DATA)
+#endif
+
+ .globl __divulong_PARM_2
+ .globl __divslong_PARM_2
+
+ __divulong_PARM_2:
+ __divslong_PARM_2:
+ .ds 4
+
+ .area CSEG (CODE)
+
+ #define b0 (__divulong_PARM_2)
+ #define b1 (__divulong_PARM_2 + 1)
+ #define b2 (__divulong_PARM_2 + 2)
+ #define b3 (__divulong_PARM_2 + 3)
+
+ ; parameter a comes in a, b, dph, dpl
+ mov a3,a ; save parameter a3
+
+ mov count,#32
+ clr a
+ mov reste0,a
+ mov reste1,a
+ mov reste2,a
+ mov reste3,a
+
+ ; optimization loop in lp0 until the first bit is shifted into rest
+
+ lp0: mov a,a0 ; a <<= 1
+ add a,a0
+ mov a0,a
+ mov a,a1
+ rlc a
+ mov a1,a
+ mov a,a2
+ rlc a
+ mov a2,a
+ mov a,a3
+ rlc a
+ mov a3,a
+
+ jc in_lp
+ djnz count,lp0
+
+ sjmp exit
+
+ loop: mov a,a0 ; a <<= 1
+ add a,a0
+ mov a0,a
+ mov a,a1
+ rlc a
+ mov a1,a
+ mov a,a2
+ rlc a
+ mov a2,a
+ mov a,a3
+ rlc a
+ mov a3,a
+
+ in_lp: mov a,reste0 ; reste <<= 1
+ rlc a ; feed in carry
+ mov reste0,a
+ mov a,reste1
+ rlc a
+ mov reste1,a
+ mov a,reste2
+ rlc a
+ mov reste2,a
+ mov a,reste3
+ rlc a
+ mov reste3,a
+
+ mov a,reste0 ; reste - b
+ subb a,b0 ; carry is always clear here, because
+ ; reste <<= 1 never overflows
+ mov a,reste1
+ subb a,b1
+ mov a,reste2
+ subb a,b2
+ mov a,reste3
+ subb a,b3
+
+ jc minus ; reste >= b?
+
+ ; -> yes; reste -= b;
+ mov a,reste0
+ subb a,b0 ; carry is always clear here (jc)
+ mov reste0,a
+ mov a,reste1
+ subb a,b1
+ mov reste1,a
+ mov a,reste2
+ subb a,b2
+ mov reste2,a
+ mov a,reste3
+ subb a,b3
+ mov reste3,a
+
+ orl a0,#1
+
+ minus: djnz count,loop ; -> no
+
+ exit: mov a,a3 ; prepare the return value
+ ret
+
+ _endasm ;
+}
+
+#elif defined _DIVULONG_ASM_SMALL_AUTO
-unsigned long _divulong (unsigned long a, unsigned long b)
+static void
+_divlong_dummy (void) _naked
{
- unsigned long reste = 0L;
- unsigned char count = 32;
- char c;
-
- do{
- // reste:a <- 0;
- c = MSB_SET(a);
- a <<= 1;
- reste <<= 1;
- if(c)
- reste |= 1L;
-
- if(reste >= b){
- reste -= b;
- // a <- (result = 1)
- a |= 1L;
- }
- } while(--count);
-
- return a;
+ _asm
+
+ .globl __divulong
+
+ __divulong:
+
+ #define count r2
+
+ #define a0 dpl
+ #define a1 dph
+ #define a2 b
+ #define a3 r3
+
+ #define reste0 r4
+ #define reste1 r5
+ #define reste2 r6
+ #define reste3 r7
+
+ .globl __divlong ; entry point for __divslong
+
+ #define b0 r1
+
+ ar0 = 0 ; BUG register set is not considered
+ ar1 = 1
+
+ ; parameter a comes in a, b, dph, dpl
+ mov a3,a ; save parameter a3
+
+ mov a,sp
+ add a,#-2-3 ; 2 bytes return address, 3 bytes param b
+ mov r0,a ; r0 points to b0
+
+ __divlong: ; entry point for __divslong
+
+ mov ar1,@r0 ; load b0
+ inc r0 ; r0 points to b1
+
+ mov count,#32
+ clr a
+ mov reste0,a
+ mov reste1,a
+ mov reste2,a
+ mov reste3,a
+
+ ; optimization loop in lp0 until the first bit is shifted into rest
+
+ lp0: mov a,a0 ; a <<= 1
+ add a,a0
+ mov a0,a
+ mov a,a1
+ rlc a
+ mov a1,a
+ mov a,a2
+ rlc a
+ mov a2,a
+ mov a,a3
+ rlc a
+ mov a3,a
+
+ jc in_lp
+ djnz count,lp0
+
+ sjmp exit
+
+ loop: mov a,a0 ; a <<= 1
+ add a,a0
+ mov a0,a
+ mov a,a1
+ rlc a
+ mov a1,a
+ mov a,a2
+ rlc a
+ mov a2,a
+ mov a,a3
+ rlc a
+ mov a3,a
+
+ in_lp: mov a,reste0 ; reste <<= 1
+ rlc a ; feed in carry
+ mov reste0,a
+ mov a,reste1
+ rlc a
+ mov reste1,a
+ mov a,reste2
+ rlc a
+ mov reste2,a
+ mov a,reste3
+ rlc a
+ mov reste3,a
+
+ mov a,reste0 ; reste - b
+ subb a,b0 ; carry is always clear here, because
+ ; reste <<= 1 never overflows
+ mov a,reste1
+ subb a,@r0 ; b1
+ mov a,reste2
+ inc r0
+ subb a,@r0 ; b2
+ mov a,reste3
+ inc r0
+ subb a,@r0 ; b3
+ dec r0
+ dec r0
+
+ jc minus ; reste >= b?
+
+ ; -> yes; reste -= b;
+ mov a,reste0
+ subb a,b0 ; carry is always clear here (jc)
+ mov reste0,a
+ mov a,reste1
+ subb a,@r0 ; b1
+ mov reste1,a
+ mov a,reste2
+ inc r0
+ subb a,@r0 ; b2
+ mov reste2,a
+ mov a,reste3
+ inc r0
+ subb a,@r0 ; b3
+ mov reste3,a
+ dec r0
+ dec r0
+
+ orl a0,#1
+
+ minus: djnz count,loop ; -> no
+
+ exit: mov a,a3 ; prepare the return value
+ ret
+
+ _endasm ;
}
+
+#else // _DIVULONG_ASM
+
+#define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1)
+
+unsigned long
+_divulong (unsigned long a, unsigned long b)
+{
+ unsigned long reste = 0L;
+ unsigned char count = 32;
+ #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 |= 1L;
+
+ if (reste >= b)
+ {
+ reste -= b;
+ // a <- (result = 1)
+ a |= 1L;
+ }
+ }
+ while (--count);
+ return a;
+}
+
+#endif // _DIVULONG_ASM
/*-------------------------------------------------------------------------
-
_modsint.c :- routine for signed int (16 bit) modulus
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
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 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 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!
-------------------------------------------------------------------------*/
+
+#include <sdcc-lib.h>
+
+#if _SDCC_MANGLES_SUPPORT_FUNS
+unsigned unsigned _moduint (unsigned a, unsigned b);
+#endif
+
+/* Assembler-functions are provided for:
+ mcs51 small
+ mcs51 small stack-auto
+*/
+
+#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 _MODSINT_ASM_SMALL_AUTO
+# else
+# define _MODSINT_ASM_SMALL
+# endif
+# endif
+# endif
+#endif
+
+#if defined _MODSINT_ASM_SMALL
+
+static void
+_modsint_dummy (void) _naked
+{
+ _asm
+
+ #define a0 dpl
+ #define a1 dph
+
+ .globl __modsint
+
+ // _modsint_PARM_2 shares the same memory with _moduint_PARM_2
+ // and is defined in _moduint.c
+ #define b0 (__modsint_PARM_2)
+ #define b1 (__modsint_PARM_2 + 1)
+
+ __modsint:
+ ; a1 in dph
+ ; b1 in (__modsint_PARM_2 + 1)
+
+ clr F0 ; Flag 0 in PSW
+ ; available to user for general purpose
+ mov a,a1
+ jnb acc.7,a_not_negative
+
+ setb F0
+
+ clr a
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+
+ a_not_negative:
+
+ mov a,b1
+ jnb acc.7,b_not_negative
+
+ cpl F0
+
+ clr a
+ clr c
+ subb a,b0
+ mov b0,a
+ clr a
+ subb a,b1
+ mov b1,a
+
+ b_not_negative:
+
+ lcall __moduint
+
+ jnb F0,not_negative
+
+ clr a
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+
+ not_negative:
+ ret
+
+ _endasm ;
+}
+
+#elif defined _MODSINT_ASM_SMALL_AUTO
+
+static void
+_modsint_dummy (void) _naked
+{
+ _asm
+
+ #define a0 dpl
+ #define a1 dph
+
+ ar0 = 0 ; BUG register set is not considered
+ ar1 = 1
+
+ .globl __modsint
+
+ __modsint:
+
+ clr F0 ; Flag 0 in PSW
+ ; available to user for general purpose
+ mov a,a1
+ jnb acc.7,a_not_negative
+
+ setb F0
+
+ clr a
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+
+ a_not_negative:
+
+ mov a,sp
+ add a,#-2 ; 2 bytes return address
+ mov r0,a ; r0 points to b1
+ mov a,@r0 ; b1
+
+ jnb acc.7,b_not_negative
+
+ cpl F0
+
+ dec r0
+
+ clr a
+ clr c
+ subb a,@r0 ; b0
+ mov @r0,a
+ clr a
+ inc r0
+ subb a,@r0 ; b1
+ mov @r0,a
+
+ b_not_negative:
+
+ mov ar1,@r0 ; b1
+ dec r0
+ mov ar0,@r0 ; b0
+
+ lcall __modint
+
+ jnb F0,not_negative
+
+ clr a
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+
+ not_negative:
+ ret
+
+ _endasm ;
+}
+
+#else // _MODSINT_ASM_
+
int _modsint (int a, int b)
{
register int r;
else
return r;
}
+
+#endif // _MODSINT_ASM_
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 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 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!
-------------------------------------------------------------------------*/
#include <sdcc-lib.h>
unsigned long _modulong (unsigned long a, unsigned long b);
#endif
-long _modslong (long a, long b)
+/* Assembler-functions are provided for:
+ mcs51 small
+ mcs51 small stack-auto
+*/
+
+#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 _MODSLONG_ASM_SMALL_AUTO
+# else
+# define _MODSLONG_ASM_SMALL
+# endif
+# endif
+# endif
+#endif
+
+#if defined _MODSLONG_ASM_SMALL
+
+static void
+_modslong_dummy (void) _naked
+{
+ _asm
+
+ #define a0 dpl
+ #define a1 dph
+ #define a2 b
+ #define a3 r1
+
+ .globl __modslong
+
+ // _modslong_PARM_2 shares the same memory with _modulong_PARM_2
+ // and is defined in _modulong.c
+ #define b0 (__modslong_PARM_2)
+ #define b1 (__modslong_PARM_2 + 1)
+ #define b2 (__modslong_PARM_2 + 2)
+ #define b3 (__modslong_PARM_2 + 3)
+
+ __modslong:
+ ; a3 in acc
+ ; b3 in (__modslong_PARM_2 + 3)
+ mov a3,a ; save a3
+
+ clr F0 ; Flag 0 in PSW
+ ; available to user for general purpose
+ jnb acc.7,a_not_negative
+
+ setb F0
+
+ clr a ; a = -a;
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+ clr a
+ subb a,a2
+ mov a2,a
+ clr a
+ subb a,a3
+ mov a3,a
+
+ a_not_negative:
+
+ mov a,b3
+ jnb acc.7,b_not_negative
+
+ cpl F0
+
+ clr a ; b = -b;
+ clr c
+ subb a,b0
+ mov b0,a
+ clr a
+ subb a,b1
+ mov b1,a
+ clr a
+ subb a,b2
+ mov b2,a
+ clr a
+ subb a,b3
+ mov b3,a
+
+ b_not_negative:
+
+ mov a,a3 ; restore a3 in acc
+
+ lcall __modulong
+
+ jnb F0,not_negative
+
+ ; result in (a == r1), b, dph, dpl
+ clr a
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+ clr a
+ subb a,a2
+ mov a2,a
+ clr a
+ subb a,a3
+ ; result in a, b, dph, dpl
+ not_negative:
+ ret
+
+ _endasm ;
+}
+
+#elif defined _MODSLONG_ASM_SMALL_AUTO
+
+static void
+_modslong_dummy (void) _naked
{
- long r;
-
- r = _modulong((a < 0 ? -a : a),
- (b < 0 ? -b : b));
-
- if ( (a < 0) ^ (b < 0))
- return -r;
- else
- return r;
-}
+ _asm
+
+ #define a0 dpl
+ #define a1 dph
+ #define a2 b
+ #define a3 r1
+
+ #define b0 r2
+ #define b1 r3
+ #define b2 r4
+ #define b3 r5
+
+ ar2 = 2 ; BUG register set is not considered
+ ar3 = 3
+ ar4 = 4
+ ar5 = 5
+
+ .globl __modslong
+
+ __modslong:
+
+ ; a3 in acc
+ mov a3,a ; save a3
+
+ clr F0 ; F0 (Flag 0)
+ ; available to user for general purpose
+ jnb acc.7,a_not_negative
+
+ setb F0
+
+ clr a ; a = -a;
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+ clr a
+ subb a,a2
+ mov a2,a
+ clr a
+ subb a,a3
+ mov a3,a
+
+ a_not_negative:
+
+ mov a,sp
+ add a,#-2-3 ; 2 bytes return address, 3 bytes param b
+ mov r0,a ; r1 points to b0
+
+
+ mov ar2,@r0 ; load b0
+ inc r0 ; r0 points to b1
+ mov ar3,@r0 ; b1
+ inc r0
+ mov ar4,@r0 ; b2
+ inc r0
+ mov a,@r0 ; b3
+ mov b3,a
+
+ jnb acc.7,b_not_negative
+
+ cpl F0
+
+ clr a ; b = -b;
+ clr c
+ subb a,b0
+ mov b0,a
+ clr a
+ subb a,b1
+ mov b1,a
+ clr a
+ subb a,b2
+ mov b2,a
+ clr a
+ subb a,b3
+ mov b3,a
+
+ b_not_negative:
+
+ lcall __modlong
+
+ jnb F0,not_negative
+
+ ; result in (a == r1), b, dph, dpl
+ clr a
+ clr c
+ subb a,a0
+ mov a0,a
+ clr a
+ subb a,a1
+ mov a1,a
+ clr a
+ subb a,a2
+ mov a2,a
+ clr a
+ subb a,a3 ; result in a, b, dph, dpl
+
+ not_negative:
+ ret
+
+ _endasm ;
+}
+
+#else // _MODSLONG_ASM
+
+long
+_modslong (long a, long b)
+{
+ long r;
+
+ r = _modulong((a < 0 ? -a : a),
+ (b < 0 ? -b : b));
+ if ( (a < 0) ^ (b < 0))
+ return -r;
+ else
+ return r;
+}
+
+#endif // _MODSLONG_ASM
/*-------------------------------------------------------------------------
-
_moduint.c :- routine for unsigned int (16 bit) modulus
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
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 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 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
+*/
+
+#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 _MODUINT_ASM_SMALL_AUTO
+# else
+# define _MODUINT_ASM_SMALL
+# endif
+# endif
+# endif
+#endif
+
+#if defined _MODUINT_ASM_SMALL || defined _MODUINT_ASM_SMALL_AUTO
+
+static void
+_moduint_dummy (void) _naked
+{
+ _asm
+
+ .globl __moduint
+
+ __moduint:
+
+ #define count r2
+ #define al dpl
+ #define ah dph
+
+#ifdef SDCC_STACK_AUTO
+
+ ar0 = 0 ; BUG register set is not considered
+ ar1 = 1
+
+ .globl __modint
+
+ 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
+
+ __modint: ; entry point for __modsint
+
+
+#else // SDCC_STACK_AUTO
+
+#if defined(SDCC_NOOVERLAY) // BUG SDCC_NOOVERLAY is not set by -no-overlay
+ .area DSEG (DATA)
+#else
+ .area OSEG (OVR,DATA)
+#endif
+
+ .globl __moduint_PARM_2
+ .globl __modsint_PARM_2
+
+ __moduint_PARM_2:
+ __modsint_PARM_2:
+ .ds 2
+
+ .area CSEG (CODE)
+
+ #define bl (__moduint_PARM_2)
+ #define bh (__moduint_PARM_2 + 1)
+
+#endif // SDCC_STACK_AUTO
+
+ mov a,bl ; avoid endless loop
+ orl a,bh
+ jz div_by_0
+
+ mov count,#1
+
+ loop1: mov a,bl ; b <<= 1
+ add a,acc
+ mov bl,a
+ mov a,bh
+ rlc a
+ jc msbset
+ mov bh,a
+
+ mov a,al ; a - b
+ subb a,bl ; here carry is always clear
+ mov a,ah
+ subb a,bh
+
+ jc start
+
+ inc count
+ sjmp loop1
+
+
+ start: clr c
+ mov a,bh ; b >>= 1;
+ msbset: rrc a
+ mov bh,a
+ mov a,bl
+ rrc a
+ mov bl,a
+
+
+ loop2: clr c
+ mov a,al ; a - b
+ subb a,bl
+
+ mov b,a
+ mov a,ah
+ subb a,bh
+
+ jc smaller ; a >= b?
+
+ mov ah,a ; -> yes; a = a - b;
+ mov al,b
+ smaller: ; -> no
+ clr c
+ mov a,bh ; b >>= 1;
+ rrc a
+ mov bh,a
+ mov a,bl
+ rrc a
+ mov bl,a
+
+ djnz count,loop2
+ div_by_0:
+ ret
+
+ _endasm ;
+}
+
+#else // defined _MODUINT_ASM_SMALL || defined _MODUINT_ASM_SMALL_AUTO
+
#define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1)
-unsigned int _moduint (unsigned int a ,unsigned int b)
+unsigned int
+_moduint (unsigned int a, unsigned int b)
{
- unsigned char count = 0;
+ unsigned char count = 0;
- while (!MSB_SET(b)) {
- b <<= 1;
- if (b > a)
- {
- b >>=1;
- break;
- }
- count++;
- }
-
- do {
- if (b <= a) {
- a -= b;
- }
- b >>= 1;
- } while (count--);
-
- return a;
+ while (!MSB_SET(b))
+ {
+ b <<= 1;
+ if (b > a)
+ {
+ b >>=1;
+ break;
+ }
+ count++;
+ }
+ do
+ {
+ if (a >= b)
+ a -= b;
+ b >>= 1;
+ }
+ while (count--);
+ return a;
}
+
+#endif // defined _MODUINT_ASM_SMALL || defined _MODUINT_ASM_SMALL_AUTO
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 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 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
+*/
+
+#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 _MODULONG_ASM_SMALL_AUTO
+# else
+# define _MODULONG_ASM_SMALL
+# endif
+# endif
+# endif
+#endif
+
+#if defined _MODULONG_ASM_SMALL
+
+static void
+_modlong_dummy (void) _naked
+{
+ _asm
+
+ .globl __modulong
+
+ __modulong:
+
+#if defined(SDCC_NOOVERLAY) // BUG SDCC_NOOVERLAY is not set by -no-overlay
+ .area DSEG (DATA)
+#else
+ .area OSEG (OVR,DATA)
+#endif
+
+ .globl __modulong_PARM_2
+ .globl __modslong_PARM_2
+
+ __modulong_PARM_2:
+ __modslong_PARM_2:
+ .ds 4
+
+ .area CSEG (CODE)
+
+ #define count r0
+
+ #define a0 dpl
+ #define a1 dph
+ #define a2 b
+ #define a3 r1
+
+ #define b0 (__modulong_PARM_2)
+ #define b1 (__modulong_PARM_2 + 1)
+ #define b2 (__modulong_PARM_2 + 2)
+ #define b3 (__modulong_PARM_2 + 3)
+
+ ; parameter a comes in a, b, dph, dpl
+ mov a3,a ; save parameter a3
+
+ mov a,b0 ; b == 0? avoid endless loop
+ orl a,b1
+ orl a,b2
+ orl a,b3
+ jz div_by_0
+
+ mov count,#0
+ clr c ; when loop1 jumps immediately to loop2
+
+ loop1: inc count
+
+ mov a,b3 ; if (!MSB_SET(b))
+ jb acc.7,loop2
+
+ mov a,b0 ; b <<= 1
+ add a,acc
+ mov b0,a
+ mov a,b1
+ rlc a
+ mov b1,a
+ mov a,b2
+ rlc a
+ mov b2,a
+ mov a,b3
+ rlc a
+ mov b3,a
+
+ mov a,a0 ; a - b
+ subb a,b0 ; here carry is always clear
+ mov a,a1
+ subb a,b1
+ mov a,a2
+ subb a,b2
+ mov a,a3
+ subb a,b3
+
+ jnc loop1
+
+
+ clr c
+ mov a,b3 ; b >>= 1;
+ rrc a
+ mov b3,a
+ mov a,b2
+ rrc a
+ mov b2,a
+ mov a,b1
+ rrc a
+ mov b1,a
+ mov a,b0
+ rrc a
+ mov b0,a
+
+ loop2: ; clr c never set
+ mov a,a0 ; a - b
+ subb a,b0
+ mov r4,a
+ mov a,a1
+ subb a,b1
+ mov r5,a
+ mov a,a2
+ subb a,b2
+ mov r6,a
+ mov a,a3
+ subb a,b3
+
+ jc smaller ; a >= b?
+
+ mov a3,a ; -> yes; a = a - b;
+ mov a2,r6
+ mov a1,r5
+ mov a0,r4
+ smaller: ; -> no
+ clr c
+ mov a,b3 ; b >>= 1;
+ rrc a
+ mov b3,a
+ mov a,b2
+ rrc a
+ mov b2,a
+ mov a,b1
+ rrc a
+ mov b1,a
+ mov a,b0
+ rrc a
+ mov b0,a
+
+ djnz count,loop2
+
+ mov a,a3 ; prepare the return value
+ div_by_0:
+ ret
+
+ _endasm ;
+}
+
+#elif defined _MODULONG_ASM_SMALL_AUTO
+
+static void
+_modlong_dummy (void) _naked
+{
+ _asm
+
+ .globl __modulong
+
+ __modulong:
+
+ #define count r0
+
+ #define a0 dpl
+ #define a1 dph
+ #define a2 b
+ #define a3 r1
+
+ #define b0 r2
+ #define b1 r3
+ #define b2 r4
+ #define b3 r5
+
+ ar2 = 2 ; BUG register set is not considered
+ ar3 = 3
+ ar4 = 4
+ ar5 = 5
+
+ .globl __modlong ; entry point for __modslong
+
+ ; parameter a comes in a, b, dph, dpl
+ mov a3,a ; save parameter a3
+
+ mov a,sp
+ add a,#-2-3 ; 2 bytes return address, 3 bytes param b
+ mov r0,a ; r1 points to b0
+
+
+ mov ar2,@r0 ; load b0
+ inc r0 ; r0 points to b1
+ mov ar3,@r0 ; b1
+ inc r0
+ mov ar4,@r0 ; b2
+ inc r0
+ mov ar5,@r0 ; b3
+
+ __modlong: ; entry point for __modslong
+ ; a in r1, b, dph, dpl
+ ; b in r5, r4, r3, r2
+
+ mov count,#0
+
+ mov a,b0 ; b == 0? avoid endless loop
+ orl a,b1
+ orl a,b2
+ orl a,b3
+ jz div_by_0
+
+ mov count,#0
+ clr c ; when loop1 jumps immediately to loop2
+
+ loop1: inc count
+
+ mov a,b3 ; if (!MSB_SET(b))
+ jb acc.7,loop2
-unsigned long _modulong (unsigned long a ,unsigned long b)
+ mov a,b0 ; b <<= 1
+ add a,acc
+ mov b0,a
+ mov a,b1
+ rlc a
+ mov b1,a
+ mov a,b2
+ rlc a
+ mov b2,a
+ mov a,b3
+ rlc a
+ mov b3,a
+
+ mov a,a0 ; a - b
+ subb a,b0 ; here carry is always clear
+ mov a,a1
+ subb a,b1
+ mov a,a2
+ subb a,b2
+ mov a,a3
+ subb a,b3
+
+ jnc loop1
+
+
+ clr c
+ mov a,b3 ; b >>= 1;
+ rrc a
+ mov b3,a
+ mov a,b2
+ rrc a
+ mov b2,a
+ mov a,b1
+ rrc a
+ mov b1,a
+ mov a,b0
+ rrc a
+ mov b0,a
+
+ loop2: ; clr c never set
+ mov a,a0 ; a - b
+ subb a,b0
+ mov a,a1
+ subb a,b1
+ mov r6,a ; d1
+ mov a,a2
+ subb a,b2
+ mov r7,a ; d2
+ mov a,a3
+ subb a,b3
+
+ jc smaller ; a >= b?
+
+ mov a3,a ; -> yes; a = a - b;
+ mov a2,r7
+ mov a1,r6
+ mov a,a0
+ subb a,b0
+ mov a0,a
+ smaller: ; -> no
+ clr c
+ mov a,b3 ; b >>= 1;
+ rrc a
+ mov b3,a
+ mov a,b2
+ rrc a
+ mov b2,a
+ mov a,b1
+ rrc a
+ mov b1,a
+ mov a,b0
+ rrc a
+ mov b0,a
+
+ djnz count,loop2
+
+ mov a,a3 ; prepare the return value
+ div_by_0:
+ ret
+
+ _endasm ;
+}
+
+#else // _MODULONG_ASM
+
+#define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1)
+
+unsigned long
+_modulong (unsigned long a, unsigned long b)
{
- unsigned char count = 0;
-
-
- while (!MSB_SET(b)) {
- b <<= 1;
- if (b > a)
- {
- b >>=1;
- break;
- }
- count++;
- }
-
- do {
- if (b <= a) {
- a -= b;
- }
- b >>= 1;
- } while (count--);
-
- return a;
+ unsigned char count = 0;
+
+ while (!MSB_SET(b))
+ {
+ b <<= 1;
+ if (b > a)
+ {
+ b >>=1;
+ break;
+ }
+ count++;
+ }
+ do
+ {
+ if (a >= b)
+ a -= b;
+ b >>= 1;
+ }
+ while (count--);
+
+ return a;
}
+
+#endif // _MODULONG_ASM
/*-------------------------------------------------------------------------
- _mulint.c :- routine for (unsigned) int (16 bit) multiplication
+ _mulint.c :- routine for (unsigned) int (16 bit) multiplication
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
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 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 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!
-------------------------------------------------------------------------*/
/* Signed and unsigned multiplication are the same - as long as the output
(char)(lsb_a*msb_b)<<8
*/
- _asm
+ _asm
mov r2,dph ; msb_a
mov r3,dpl ; lsb_a
mov dph,a ; 1
ret
-
+
#endif // SDCC_STACK_AUTO
_endasm ;
{
#ifdef SDCC_MODEL_LARGE // still needed for large + stack-auto
union uu xdata *x;
- union uu xdata *y;
+ union uu xdata *y;
union uu t;
x = (union uu xdata *)&a;
y = (union uu xdata *)&b;
#else
register union uu *x;
- register union uu *y;
+ register union uu *y;
union uu t;
x = (union uu *)&a;
y = (union uu *)&b;
t.s.hi += (x->s.lo * y->s.hi) + (x->s.hi * y->s.lo);
return t.t;
-}
+}
int
_mulsint (int a, int b) // obsolete
#elif defined(__z80) || defined(__gbz80)
#define bcast(x) ((union bil *)&(x))
#else
-#define bcast(x) ((union bil near *)&(x))
+#define bcast(x) ((union bil near *)&(x))
#endif
/*
_divuint
_modsint
_moduint
-_mulsint
-_muluint
+_mulint
_divulong.rel
_modslong.rel
_modulong.rel
-_mululong.rel
-_mulslong.rel
+_mullong.rel