summaryrefslogtreecommitdiff
path: root/device/lib/_mullong.c
diff options
context:
space:
mode:
authorXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
committerXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
commit268a53de823a6750d6256ee1fb1e7707b4b45740 (patch)
tree42c1799a9a82b2f7d9790ee9fe181d72a7274751 /device/lib/_mullong.c
downloadsdcc-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/_mullong.c')
-rw-r--r--device/lib/_mullong.c760
1 files changed, 760 insertions, 0 deletions
diff --git a/device/lib/_mullong.c b/device/lib/_mullong.c
new file mode 100644
index 0000000..9bd4161
--- /dev/null
+++ b/device/lib/_mullong.c
@@ -0,0 +1,760 @@
+/*-------------------------------------------------------------------------
+ _mullong.c - routine for multiplication of 32 bit (unsigned) long
+
+ Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net
+ Copyright (C) 1999, Jean Louis VERN jlvern@writeme.com
+
+ 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:
+ 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) && !defined(__SDCC_PARMS_IN_BANK1)
+# define _MULLONG_ASM_SMALL_AUTO
+# else
+# define _MULLONG_ASM_SMALL
+# endif
+# elif defined(__SDCC_MODEL_LARGE)
+# if !defined(__SDCC_STACK_AUTO)
+# define _MULLONG_ASM_LARGE
+# endif
+# endif
+# endif
+#endif
+
+#if defined(_MULLONG_ASM_SMALL) || defined(_MULLONG_ASM_SMALL_AUTO)
+
+void
+_mullong_dummy (void) __naked
+{
+ __asm
+
+__mullong:
+
+ .globl __mullong
+
+ ; the result c will be stored in r4...r7
+ #define c0 r4
+ #define c1 r5
+ #define c2 r6
+ #define c3 r7
+
+ #define a0 dpl
+ #define a1 dph
+ #define a2 r2
+ #define a3 r3
+
+ ; 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) || defined(__SDCC_PARMS_IN_BANK1)
+#if defined(__SDCC_PARMS_IN_BANK1)
+ #define b0 (b1_0)
+ #define b1 (b1_1)
+ #define b2 (b1_2)
+ #define b3 (b1_3)
+#else
+#if defined(__SDCC_NOOVERLAY)
+ .area DSEG (DATA)
+#else
+ .area OSEG (OVR,DATA)
+#endif
+
+__mullong_PARM_2:
+
+ .globl __mullong_PARM_2
+
+ .ds 4
+
+ b0 = __mullong_PARM_2
+ b1 = (__mullong_PARM_2+1)
+ b2 = (__mullong_PARM_2+2)
+ b3 = (__mullong_PARM_2+3)
+
+#endif
+ .area CSEG (CODE)
+
+ ; parameter a comes in a, b, dph, dpl
+ mov r2,b ; save parameter a
+ mov r3,a
+
+ ; 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;
+}
+
+#elif defined(_MULLONG_ASM_LARGE)
+
+void
+_mullong_dummy (void) __naked
+{
+ __asm
+
+__mullong:
+
+ .globl __mullong
+
+ ; 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_PARMS_IN_BANK1)
+ .area XSEG (XDATA)
+
+__mullong_PARM_2:
+
+ .globl __mullong_PARM_2
+
+ .ds 4
+#endif
+ .area CSEG (CODE)
+
+ ; parameter a comes in a, b, dph, dpl
+ mov r0,dpl ; save parameter a
+ mov r1,dph
+ mov r2,b
+ mov r3,a
+
+ #define a0 r0
+ #define a1 r1
+ #define a2 r2
+ #define a3 r3
+
+ ; Byte 0
+ mov b,a0
+#if defined(__SDCC_PARMS_IN_BANK1)
+ mov a,b1_0 ; b0
+#else
+ mov dptr,#__mullong_PARM_2
+ movx a,@dptr ; b0
+#endif
+ mul ab ; a0 * b0
+ mov c0,a
+ mov c1,b
+
+ ; Byte 1
+ mov b,a1
+#if defined(__SDCC_PARMS_IN_BANK1)
+ mov a,b1_0 ; b0
+#else
+ movx a,@dptr ; b0
+#endif
+ mul ab ; a1 * b0
+ add a,c1
+ mov c1,a
+ clr a
+ addc a,b
+ mov c2,a
+
+ mov b,a0
+#if defined(__SDCC_PARMS_IN_BANK1)
+ mov a,b1_1 ; b1
+#else
+ inc dptr ; b1
+ movx a,@dptr
+#endif
+ 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 b,a1
+#if defined(__SDCC_PARMS_IN_BANK1)
+ mov a,b1_1 ; b1
+#else
+ movx a,@dptr ; b1
+#endif
+ mul ab ; a1 * b1
+ add a,c2
+ mov c2,a
+ mov a,b
+ addc a,c3
+ mov c3,a
+
+ mov b,a0
+#if defined(__SDCC_PARMS_IN_BANK1)
+ mov a,b1_2 ; b2
+#else
+ inc dptr ; b2
+ movx a,@dptr
+#endif
+ mul ab ; a0 * b2
+ add a,c2
+ mov c2,a
+ mov a,b
+ addc a,c3
+ mov c3,a
+
+ mov b,a2
+#if defined(__SDCC_PARMS_IN_BANK1)
+ mov a,b1_0 ; b0
+#else
+ mov dptr,#__mullong_PARM_2
+ movx a,@dptr ; b0
+#endif
+ mul ab ; a2 * b0
+ add a,c2
+ mov c2,a
+ mov a,b
+ addc a,c3
+ mov c3,a
+
+ ; Byte 3
+ mov b,a3
+#if defined(__SDCC_PARMS_IN_BANK1)
+ mov a,b1_0 ; b0
+#else
+ movx a,@dptr ; b0
+#endif
+ mul ab ; a3 * b0
+ add a,c3
+ mov c3,a
+
+ mov b,a2
+#if defined(__SDCC_PARMS_IN_BANK1)
+ mov a,b1_1 ; b1
+#else
+ inc dptr ; b1
+ movx a,@dptr
+#endif
+ mul ab ; a2 * b1
+ add a,c3
+ mov c3,a
+
+ mov b,a1
+#if defined(__SDCC_PARMS_IN_BANK1)
+ mov a,b1_2 ; b2
+#else
+ inc dptr ; b2
+ movx a,@dptr
+#endif
+ mul ab ; a1 * b2
+ add a,c3
+ mov c3,a
+
+ mov b,a0
+#if defined(__SDCC_PARMS_IN_BANK1)
+ mov a,b1_3 ; b3
+#else
+ inc dptr ; b3
+ movx a,@dptr
+#endif
+ mul ab ; a0 * b3
+ add a,c3
+
+ mov b,c2
+ mov dph,c1
+ mov dpl,c0
+ ret
+
+ __endasm;
+}
+
+#elif defined(__SDCC_USE_XSTACK) && defined(__SDCC_STACK_AUTO)
+
+void
+_mullong_dummy (void) __naked
+{
+ __asm
+
+__mullong:
+
+ .globl __mullong
+
+ ; the result c will be stored in r4...r7
+ #define c0 r4
+ #define c1 r5
+ #define c2 r6
+ #define c3 r7
+
+ #define a0 dpl
+ #define a1 dph
+ #define a2 r2
+ #define a3 r3
+
+ #define b0 r1
+
+ ; c0 a0 * b0
+ ; c1 a1 * b0 + a0 * b1
+ ; c2 a2 * b0 + a1 * b1 + a0 * b2
+ ; c3 a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
+
+ ; parameter a comes in a, b, dph, dpl
+ mov r2,b ; save parameter a
+ mov r3,a
+
+ mov a,#-4 ; 1 b 4 bytes
+ add a,_spx ; 1
+ mov r0,a ; 1 r0 points to b0
+
+ ; Byte 0
+ movx a,@r0 ; b0
+ mov b0,a ; we need b0 several times
+ inc r0 ; r0 points to b1
+ mov b,a0
+ 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 b,a0
+ movx a,@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 b,a1
+ movx a,@r0 ; b1
+ mul ab ; a1 * b1
+ add a,c2
+ mov c2,a
+ mov a,b
+ addc a,c3
+ mov c3,a
+
+ mov b,a0
+ inc r0
+ movx a,@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 b,a1
+ movx a,@r0 ; b2
+ mul ab ; a1 * b2
+ add a,c3
+ mov c3,a
+
+ mov b,a2
+ dec r0
+ movx a,@r0 ; b1
+ mul ab ; a2 * b1
+ add a,c3
+ mov c3,a
+
+ mov b,a0
+ inc r0
+ inc r0
+ movx a,@r0 ; b3
+ mul ab ; a0 * b3
+ add a,c3
+
+ mov b,c2
+ mov dph,c1
+ mov dpl,c0
+
+ ret
+
+ __endasm;
+}
+
+#else // _MULLONG_ASM
+
+struct some_struct {
+ short a ;
+ char b;
+ long c ;};
+#if defined(__SDCC_hc08) || defined(__SDCC_s08) || defined(__SDCC_stm8)
+/* big endian order */
+union bil {
+ struct {unsigned char b3,b2,b1,b0 ;} b;
+ struct {unsigned short hi,lo ;} i;
+ unsigned long l;
+ struct { unsigned char b3; unsigned short i12; unsigned char b0;} bi;
+} ;
+#else
+/* little endian order */
+union bil {
+ struct {unsigned char b0,b1,b2,b3 ;} b;
+ struct {unsigned short lo,hi ;} i;
+ unsigned long l;
+ struct { unsigned char b0; unsigned short i12; unsigned char b3;} bi;
+} ;
+#endif
+
+#if defined(__SDCC)
+ #include <sdcc-lib.h>
+#endif
+
+#define bcast(x) ((union bil _AUTOMEM *)&(x))
+
+/*
+ 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
+*/
+#if defined(__SDCC_USE_XSTACK)
+// currently the original code without u fails with --xstack
+// it runs out of pointer registers
+long
+_mullong (long a, long b)
+{
+ union bil t, u;
+
+ t.i.hi = bcast(a)->b.b0 * bcast(b)->b.b2; // A
+ t.i.lo = bcast(a)->b.b0 * bcast(b)->b.b0; // A
+ u.bi.b3 = bcast(a)->b.b0 * bcast(b)->b.b3; // B
+ u.bi.i12 = bcast(a)->b.b0 * bcast(b)->b.b1; // B
+ u.bi.b0 = 0; // B
+ t.l += u.l;
+
+ 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
+ t.i.hi += bcast(a)->b.b1 * bcast(b)->b.b1; // D
+
+ u.bi.b3 = bcast(a)->b.b1 * bcast(b)->b.b2; // C
+ u.bi.i12 = bcast(a)->b.b1 * bcast(b)->b.b0; // C
+ u.bi.b0 = 0; // C
+ t.l += u.l;
+
+ return t.l;
+}
+#elif defined(__SDCC_z80) || defined(__SDCC_gbz80) || defined(__SDCC_r2k) || defined(__SDCC_r3k)
+/* 32x32->32 multiplication to be used
+ if 16x16->16 is faster than three 8x8->16.
+ 2009, by M.Bodrato ( http://bodrato.it/ )
+
+ z80 and gbz80 don't have any hardware multiplication.
+ r2k and r3k have 16x16 hardware multiplication.
+ */
+long
+_mullong (long a, long b)
+{
+ unsigned short i12;
+
+ bcast(a)->i.hi *= bcast(b)->i.lo;
+ bcast(a)->i.hi += bcast(b)->i.hi * bcast(a)->i.lo;
+
+ /* only (a->i.lo * b->i.lo) 16x16->32 to do. asm? */
+ bcast(a)->i.hi += bcast(a)->b.b1 * bcast(b)->b.b1;
+
+ i12 = bcast(b)->b.b0 * bcast(a)->b.b1;
+ bcast(b)->bi.i12 = bcast(a)->b.b0 * bcast(b)->b.b1;
+
+ /* add up the two partial result, store carry in b3 */
+ bcast(b)->b.b3 = ((bcast(b)->bi.i12 += i12) < i12);
+
+ bcast(a)->i.lo = bcast(a)->b.b0 * bcast(b)->b.b0;
+
+ bcast(b)->bi.b0 = 0;
+
+ return a + b;
+}
+#else
+long
+_mullong (long a, long b)
+{
+ 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
+ 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; // C
+ 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; // B
+ 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;
+}
+#endif
+
+#endif // _MULLONG_ASM