diff options
| author | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
|---|---|---|
| committer | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
| commit | 268a53de823a6750d6256ee1fb1e7707b4b45740 (patch) | |
| tree | 42c1799a9a82b2f7d9790ee9fe181d72a7274751 /device/lib/_mulint.c | |
| download | sdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz | |
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'device/lib/_mulint.c')
| -rw-r--r-- | device/lib/_mulint.c | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/device/lib/_mulint.c b/device/lib/_mulint.c new file mode 100644 index 0000000..4e0ad44 --- /dev/null +++ b/device/lib/_mulint.c @@ -0,0 +1,251 @@ +/*------------------------------------------------------------------------- + _mulint.c - routine for (unsigned) int (16 bit) multiplication + + Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net + + This library 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 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 + along with this library; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + As a special exception, if you link this library with other files, + some of which are compiled with SDCC, to produce an executable, + this library does not by itself cause the resulting executable to + be covered by the GNU General Public License. This exception does + not however invalidate any other reasons why the executable file + might be covered by the GNU General Public License. +-------------------------------------------------------------------------*/ + +/* Signed and unsigned multiplication are the same - as long as the output + has the same precision as the input. + + 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) && !defined(__SDCC_PARMS_IN_BANK1) +# 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 + +#if defined(_MULINT_ASM_LARGE) + +#pragma save +#pragma less_pedantic +int +_mulint (int a, int b) +{ + 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 +#if defined(__SDCC_PARMS_IN_BANK1) + mov a,b1_0 +#else + mov dptr,#__mulint_PARM_2 + movx a,@dptr ; lsb_b +#endif + mul ab ; lsb_a*lsb_b + mov r0,a + mov r1,b + + mov b,r2 ; msb_a +#if defined(__SDCC_PARMS_IN_BANK1) + mov a,b1_0 +#else + movx a,@dptr ; lsb_b +#endif + mul ab ; msb_a*lsb_b + add a,r1 + mov r1,a + + mov b,r3 ; lsb_a +#if defined(__SDCC_PARMS_IN_BANK1) + mov a,b1_1 +#else + inc dptr + movx a,@dptr ; msb_b +#endif + mul ab ; lsb_a*msb_b + add a,r1 + + mov dph,a + mov dpl,r0 + ret + __endasm; +} +#pragma restore + +#elif defined(_MULINT_ASM_SMALL) || defined(_MULINT_ASM_SMALL_AUTO) + +#pragma save +#pragma less_pedantic +int +_mulint_dummy (void) __naked +{ + __asm + +__mulint: + + .globl __mulint + +#if !defined(__SDCC_STACK_AUTO) || defined(__SDCC_PARMS_IN_BANK1) + +#if defined(__SDCC_NOOVERLAY) + .area DSEG (DATA) +#else + .area OSEG (OVR,DATA) +#endif +#if defined(__SDCC_PARMS_IN_BANK1) + #define bl (b1_0) + #define bh (b1_1) +#else + #define bl (__mulint_PARM_2) + #define bh (__mulint_PARM_2 + 1) +__mulint_PARM_2: + + .globl __mulint_PARM_2 + + .ds 2 +#endif + + .area CSEG (CODE) + + ; globbered registers none + + mov a,dpl ; 1 al + mov b,bl ; 2 bl + mul ab ; 4 al * bl + xch a,dpl ; 1 store low-byte of return value, fetch al + push b ; 2 + + mov b,bh ; 2 bh + mul ab ; 4 al * bh + pop b ; 2 + add a,b ; 1 + xch a,dph ; 1 ah -> acc + + mov b,bl ; 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; +} +#pragma restore + +#else + +#if defined(__SDCC_hc08) || defined(__SDCC_s08) || defined(__SDCC_stm8) +// Big-endian +union uu { + struct { unsigned char hi, lo ;} s; + unsigned int t; +}; +#else +// Little-endian +union uu { + struct { unsigned char lo,hi ;} s; + unsigned int t; +}; +#endif + +int +_mulint (int a, int b) +{ +#if !defined(__SDCC_STACK_AUTO) && (defined(__SDCC_MODEL_LARGE) || defined(__SDCC_ds390)) // still needed for large + 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 + + // sdcc is bad at handling union accesses. So we use (unsigned char)a instead of x->s.lo here. + t.t = (unsigned char)a * (unsigned char)b; + t.s.hi += ((unsigned char)a * y->s.hi) + (x->s.hi * (unsigned char)b); + + return t.t; +} + +#endif + +#undef _MULINT_ASM |
