From: bernhardheld Date: Wed, 15 Aug 2001 09:17:56 +0000 (+0000) Subject: Assembler functions for _mulint and _mullong X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=7b002d7a2cb29f4f90baedc2a4c146fc8818f8ea;p=fw%2Fsdcc Assembler functions for _mulint and _mullong git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1143 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/device/lib/Makefile.in b/device/lib/Makefile.in index 1c64fa11..ff773e56 100644 --- a/device/lib/Makefile.in +++ b/device/lib/Makefile.in @@ -57,7 +57,8 @@ SOURCES = _atoi.c _atol.c _autobaud.c _bp.c _schar2fs.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 + assert.c _strcat.c time.c printf_fast.c \ + _mulint.c _mullong.c OBJECTS = $(patsubst %.c,$(PORTDIR)/%.rel,$(SOURCES)) @@ -73,7 +74,7 @@ Z80SOURCES = _atoi.c \ puts.c gets.c \ assert.c _strcat.c \ _modslong.c _modulong.c \ - _mulslong.c _mululong.c \ + _mulslong.c _mululong.c _mulint.c _mullong.c \ _divslong.c _divulong.c Z80OBJECTS = $(Z80SOURCES:%.c=$(PORTDIR)/%.o) diff --git a/device/lib/_mulint.c b/device/lib/_mulint.c new file mode 100644 index 00000000..e0465cb7 --- /dev/null +++ b/device/lib/_mulint.c @@ -0,0 +1,238 @@ +/*------------------------------------------------------------------------- + + _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 diff --git a/device/lib/_mullong.c b/device/lib/_mullong.c new file mode 100644 index 00000000..e5fc1de0 --- /dev/null +++ b/device/lib/_mullong.c @@ -0,0 +1,388 @@ +/*------------------------------------------------------------------------- + _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