--- /dev/null
+/*-------------------------------------------------------------------------
+
+ _mulint.c :- routine for (unsigned) int (16 bit) multiplication
+
+ Written By - Sandeep Dutta . sandeep.dutta@usa.net (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
+ 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,
+ 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
+ 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!
+-------------------------------------------------------------------------*/
+
+/* Signed and unsigned multiplication are the same - as long as the output
+ has the same precision as the input.
+
+ To do: _muluint and _mulsint should be replaced by _mulint.
+
+ bernhard@bernhardheld.de
+
+ Assembler-functions are provided for:
+ ds390
+ mcs51 small
+ mcs51 small stack-auto
+ mcs51 large
+*/
+
+#if !defined(SDCC_USE_XSTACK) || defined(_SDCC_NO_ASM_LIB_FUNCS)
+ #if defined(SDCC_ds390)
+ #if !defined(SDCC_STACK_AUTO)
+ #define _MULINT_ASM_LARGE
+ #endif
+ #elif defined(SDCC_mcs51)
+ #if defined(SDCC_MODEL_SMALL)
+ #if defined(SDCC_STACK_AUTO)
+ #define _MULINT_ASM_SMALL_AUTO
+ #else
+ #define _MULINT_ASM_SMALL
+ #endif
+ #else // must be SDCC_MODEL_LARGE
+ #if !defined(SDCC_STACK_AUTO)
+ #define _MULINT_ASM_LARGE
+ #endif
+ #endif
+ #endif
+#endif
+
+#ifdef _MULINT_ASM_LARGE
+
+unsigned int
+_muluint (unsigned int a, unsigned int b) // in future: _mulint
+{
+ a*b; // hush the compiler
+
+ /* mulint=
+ (int)(lsb_a*lsb_b) +
+ (char)(msb_a*lsb_b)<<8 +
+ (char)(lsb_a*msb_b)<<8
+ */
+
+ _asm
+ mov r2,dph ; msb_a
+ mov r3,dpl ; lsb_a
+
+ mov b,r3 ; lsb_a
+ mov dptr,#__muluint_PARM_2
+ movx a,@dptr ; lsb_b
+ mul ab ; lsb_a*lsb_b
+ mov r0,a
+ mov r1,b
+
+ mov b,r2 ; msb_a
+ movx a,@dptr ; lsb_b
+ mul ab ; msb_a*lsb_b
+ add a,r1
+ mov r1,a
+
+ mov b,r3 ; lsb_a
+ inc dptr
+ movx a,@dptr ; msb_b
+ mul ab ; lsb_a*msb_b
+ add a,r1
+
+ mov dph,a
+ mov dpl,r0
+ ret
+ _endasm;
+}
+
+int
+_mulsint (int a, int b) // obsolete
+{
+ return _muluint (a, b);
+}
+
+#elif defined _MULINT_ASM_SMALL || defined _MULINT_ASM_SMALL_AUTO
+
+void
+_mulint_dummy (void) _naked
+{
+ _asm
+
+ __mulint:
+ __muluint: ; obsolete
+ __mulsint: ; obsolete
+
+ .globl __mulint
+ .globl __muluint ; obsolete
+ .globl __mulsint ; obsolete
+
+#if !defined(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
+
+ __mulint_PARM_2:
+ __muluint_PARM_2: ; obsolete
+ __mulsint_PARM_2: ; obsolete
+
+ .globl __mulint_PARM_2
+ .globl __muluint_PARM_2 ; obsolete
+ .globl __mulsint_PARM_2 ; obsolete
+
+ .ds 2
+
+ .area CSEG (CODE)
+
+ ; globbered registers none
+
+ mov a,dpl ; 1 al
+ mov b,__mulint_PARM_2 ; 2 bl
+ mul ab ; 4 al * bl
+ xch a,dpl ; 1 store low-byte of return value, fetch al
+ push b ; 2
+
+ mov b,__mulint_PARM_2 + 1 ; 2 bh
+ mul ab ; 4 al * bh
+ pop b ; 2
+ add a,b ; 1
+ xch a,dph ; 1 ah -> acc
+
+ mov b,__mulint_PARM_2 ; 2 bl
+ mul ab ; 4 ah * bl
+ add a,dph ; 1
+ mov dph,a ; 1
+ ret ; 2
+ ; 30
+
+#else // SDCC_STACK_AUTO
+
+ ; globbered registers r0
+
+ mov a,#-2 ; 1 return address 2 bytes
+ add a,sp ; 1
+ mov r0,a ; 1 r0 points to bh
+
+ mov a,@r0 ; 1 bh
+ mov b,dpl ; 2 al
+ mul ab ; 4 al * bh
+ push acc ; 2
+
+ mov b,dpl ; 2 al
+ dec r0 ; 1
+ mov a,@r0 ; 1 bl
+ mul ab ; 4 al * bl
+
+ mov dpl,a ; 1 low-byte of return-value
+
+ pop acc ; 2
+ add a,b ; 1
+ xch a,dph ; 1 ah -> acc
+
+ mov b,@r0 ; 2 bl
+ mul ab ; 4 ah * bl
+ add a,dph ; 1
+ mov dph,a ; 1
+
+ ret
+
+#endif // SDCC_STACK_AUTO
+
+ _endasm ;
+}
+
+#else
+
+union uu {
+ struct { unsigned char lo,hi ;} s;
+ unsigned int t;
+} ;
+
+unsigned int
+_muluint (unsigned int a, unsigned int b) // in future: _mulint
+{
+#ifdef SDCC_MODEL_LARGE // still needed for large + stack-auto
+ union uu _xdata *x;
+ 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;
+ union uu t;
+ x = (union uu *)&a;
+ y = (union uu *)&b;
+#endif
+
+ t.t = x->s.lo * y->s.lo;
+ 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
+{
+ return _muluint (a, b);
+}
+
+#endif
+
+#undef _MULINT_ASM
--- /dev/null
+/*-------------------------------------------------------------------------
+ _mullong.c - routine for multiplication of 32 bit (unsigned) long
+
+ Written By - 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
+ 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,
+ 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
+ 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!
+-------------------------------------------------------------------------*/
+
+/* Signed and unsigned multiplication are the same - as long as the output
+ has the same precision as the input.
+
+ To do: _mululong and _mulslong should be replaced by _mullong.
+
+ bernhard@bernhardheld.de
+
+ 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 _MULLONG_ASM_SMALL_AUTO
+ #else
+ #define _MULLONG_ASM_SMALL
+ #endif
+ #endif
+ #endif
+#endif
+
+#if defined _MULLONG_ASM_SMALL || defined _MULLONG_ASM_SMALL_AUTO
+
+void
+_mullong_dummy (void) _naked
+{
+ _asm
+
+ __mullong:
+ __mululong: ; obsolete
+ __mulslong: ; obsolete
+
+ .globl __mullong
+ .globl __mululong ; obsolete
+ .globl __mulslong ; obsolete
+
+ ; the result c will be stored in r4...r7
+ #define c0 r4
+ #define c1 r5
+ #define c2 r6
+ #define c3 r7
+
+ ; c0 a0 * b0
+ ; c1 a1 * b0 + a0 * b1
+ ; c2 a2 * b0 + a1 * b1 + a0 * b2
+ ; c3 a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
+
+#if !defined 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
+
+ __mullong_PARM_2:
+ __mululong_PARM_2: ; obsolete
+ __mulslong_PARM_2: ; obsolete
+
+ .globl __mullong_PARM_2
+ .globl __mululong_PARM_2 ; obsolete
+ .globl __mulslong_PARM_2 ; obsolete
+
+ .ds 4
+
+ .area CSEG (CODE)
+
+ ; parameter a comes in a, b, dph, dpl
+ mov r2,b ; save parameter a
+ mov r3,a
+
+ #define a0 dpl
+ #define a1 dph
+ #define a2 r2
+ #define a3 r3
+
+ b0 = __mullong_PARM_2
+ b1 = (__mullong_PARM_2+1)
+ b2 = (__mullong_PARM_2+2)
+ b3 = (__mullong_PARM_2+3)
+
+ ; Byte 0
+ mov a,a0
+ mov b,b0
+ mul ab ; a0 * b0
+ mov c0,a
+ mov c1,b
+
+ ; Byte 1
+ mov a,a1
+ mov b,b0
+ mul ab ; a1 * b0
+ add a,c1
+ mov c1,a
+ clr a
+ addc a,b
+ mov c2,a
+
+
+ mov a,a0
+ mov b,b1
+ mul ab ; a0 * b1
+ add a,c1
+ mov c1,a
+ mov a,b
+ addc a,c2
+ mov c2,a
+ clr a
+ rlc a
+ mov c3,a
+
+ ; Byte 2
+ mov a,a2
+ mov b,b0
+ mul ab ; a2 * b0
+ add a,c2
+ mov c2,a
+ mov a,b
+ addc a,c3
+ mov c3,a
+
+ mov a,a1
+ mov b,b1
+ mul ab ; a1 * b1
+ add a,c2
+ mov c2,a
+ mov a,b
+ addc a,c3
+ mov c3,a
+
+ mov a,a0
+ mov b,b2
+ mul ab ; a0 * b2
+ add a,c2
+ mov c2,a
+ mov a,b
+ addc a,c3
+ mov c3,a
+
+ ; Byte 3
+ mov a,a3
+ mov b,b0
+ mul ab ; a3 * b0
+ add a,c3
+ mov c3,a
+
+ mov a,a2
+ mov b,b1
+ mul ab ; a2 * b1
+ add a,c3
+ mov c3,a
+
+ mov a,a1
+ mov b,b2
+ mul ab ; a1 * b2
+ add a,c3
+ mov c3,a
+
+ mov a,a0
+ mov b,b3
+ mul ab ; a0 * b3
+ add a,c3
+
+ mov b,c2
+ mov dph,c1
+ mov dpl,c0
+ ret
+
+#else // SDCC_STACK_AUTO
+
+ ; parameter a comes in a, b, dph, dpl
+ mov r2,b ; save parameter a
+ mov r3,a
+
+ #define a0 dpl
+ #define a1 dph
+ #define a2 r2
+ #define a3 r3
+
+ #define b0 r1
+
+ mov a,#-2-3 ; 1 return address 2 bytes, b 4 bytes
+ add a,sp ; 1
+ mov r0,a ; 1 r0 points to b0
+
+ ; Byte 0
+ mov a,a0
+ mov b,@r0 ; b0
+ mov b0,b ; we need b0 several times
+ inc r0 ; r0 points to b1
+ mul ab ; a0 * b0
+ mov c0,a
+ mov c1,b
+
+ ; Byte 1
+ mov a,a1
+ mov b,b0
+ mul ab ; a1 * b0
+ add a,c1
+ mov c1,a
+ clr a
+ addc a,b
+ mov c2,a
+
+
+ mov a,a0
+ mov b,@r0 ; b1
+ mul ab ; a0 * b1
+ add a,c1
+ mov c1,a
+ mov a,b
+ addc a,c2
+ mov c2,a
+ clr a
+ rlc a
+ mov c3,a
+
+ ; Byte 2
+ mov a,a2
+ mov b,b0
+ mul ab ; a2 * b0
+ add a,c2
+ mov c2,a
+ mov a,b
+ addc a,c3
+ mov c3,a
+
+ mov a,a1
+ mov b,@r0 ; b1
+ mul ab ; a1 * b1
+ add a,c2
+ mov c2,a
+ mov a,b
+ addc a,c3
+ mov c3,a
+
+ mov a,a0
+ inc r0
+ mov b,@r0 ; b2
+ mul ab ; a0 * b2
+ add a,c2
+ mov c2,a
+ mov a,b
+ addc a,c3
+ mov c3,a
+
+ ; Byte 3
+ mov a,a3
+ mov b,b0
+ mul ab ; a3 * b0
+ add a,c3
+ mov c3,a
+
+ mov a,a1
+ mov b,@r0 ; b2
+ mul ab ; a1 * b2
+ add a,c3
+ mov c3,a
+
+ mov a,a2
+ dec r0
+ mov b,@r0 ; b1
+ mul ab ; a2 * b1
+ add a,c3
+ mov c3,a
+
+ mov a,a0
+ inc r0
+ inc r0
+ mov b,@r0 ; b3
+ mul ab ; a0 * b3
+ add a,c3
+
+ mov b,c2
+ mov dph,c1
+ mov dpl,c0
+
+ ret
+
+#endif // SDCC_STACK_AUTO
+
+ _endasm ;
+}
+
+#else // _MULLONG_ASM_SMALL || _MULLONG_ASM_SMALL_AUTO
+
+struct some_struct {
+ int a ;
+ char b;
+ long c ;};
+union bil {
+ struct {unsigned char b0,b1,b2,b3 ;} b;
+ struct {unsigned int lo,hi ;} i;
+ unsigned long l;
+ struct { unsigned char b0; unsigned int i12; unsigned char b3;} bi;
+} ;
+#if defined(SDCC_MODEL_LARGE) || defined (SDCC_ds390)
+#define bcast(x) ((union bil _xdata *)&(x))
+#elif defined(__z80) || defined(__gbz80)
+#define bcast(x) ((union bil *)&(x))
+#else
+#define bcast(x) ((union bil _near *)&(x))
+#endif
+
+/*
+ 3 2 1 0
+ X 3 2 1 0
+ ----------------------------
+ 0.3 0.2 0.1 0.0
+ 1.3 1.2 1.1 1.0
+ 2.3 2.2 2.1 2.0
+ 3.3 3.2 3.1 3.0
+ ----------------------------
+ |3.3|1.3|0.2|0.0| A
+ |2.3|0.3|0.1| B
+ |3.2|1.2|1.0| C
+ |2.2|1.1| D
+ |3.1|2.0| E
+ |2.1| F
+ |3.0| G
+ |-------> only this side 32 x 32 -> 32
+*/
+unsigned long
+_mululong (unsigned long a, unsigned long b) // in future: _mullong
+{
+ union bil t;
+
+ t.i.hi = bcast(a)->b.b0 * bcast(b)->b.b2; // A
+ t.i.lo = bcast(a)->b.b0 * bcast(b)->b.b0; // A
+ _asm ;johan _endasm;
+ t.b.b3 += bcast(a)->b.b3 *
+ bcast(b)->b.b0; // G
+ t.b.b3 += bcast(a)->b.b2 *
+ bcast(b)->b.b1; // F
+ t.i.hi += bcast(a)->b.b2 * bcast(b)->b.b0; // E <- b lost in .lst
+ // bcast(a)->i.hi is free !
+ t.i.hi += bcast(a)->b.b1 * bcast(b)->b.b1; // D <- b lost in .lst
+
+ bcast(a)->bi.b3 = bcast(a)->b.b1 *
+ bcast(b)->b.b2;
+ bcast(a)->bi.i12 = bcast(a)->b.b1 *
+ bcast(b)->b.b0; // C
+
+ bcast(b)->bi.b3 = bcast(a)->b.b0 *
+ bcast(b)->b.b3;
+ bcast(b)->bi.i12 = bcast(a)->b.b0 *
+ bcast(b)->b.b1; // B
+ bcast(b)->bi.b0 = 0; // B
+ bcast(a)->bi.b0 = 0; // C
+ t.l += a;
+
+ return t.l + b;
+}
+
+long
+_mulslong (long a, long b) // obsolete
+{
+ _mululong (a, b);
+}
+
+#endif // _MULLONG_ASM_SMALL || _MULLONG_ASM_SMALL_AUTO