Assembler functions for _mulint and _mullong
authorbernhardheld <bernhardheld@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 15 Aug 2001 09:17:56 +0000 (09:17 +0000)
committerbernhardheld <bernhardheld@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 15 Aug 2001 09:17:56 +0000 (09:17 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1143 4a8a32a2-be11-0410-ad9d-d568d2c75423

device/lib/Makefile.in
device/lib/_mulint.c [new file with mode: 0644]
device/lib/_mullong.c [new file with mode: 0644]

index 1c64fa1198622f26ba37b142005012a640bab0f3..ff773e56d4e48dca1760970e5e2a262562296814 100644 (file)
@@ -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 (file)
index 0000000..e0465cb
--- /dev/null
@@ -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 (file)
index 0000000..e5fc1de
--- /dev/null
@@ -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