1 /*-------------------------------------------------------------------------
2 _mullong.c - routine for multiplication of 32 bit (unsigned) long
4 Written By - Jean Louis VERN jlvern@writeme.com (1999)
5 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
7 This library is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Library General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 In other words, you are welcome to use, share and improve this program.
22 You are forbidden to forbid anyone else to use, share and improve
23 what you give them. Help stamp out software-hoarding!
24 -------------------------------------------------------------------------*/
26 /* Signed and unsigned multiplication are the same - as long as the output
27 has the same precision as the input.
29 Assembler-functions are provided for:
31 mcs51 small stack-auto
34 #if !defined(SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
35 # if defined(SDCC_mcs51)
36 # if defined(SDCC_MODEL_SMALL)
37 # if defined(SDCC_STACK_AUTO) && !defined(SDCC_PARMS_IN_BANK1)
38 # define _MULLONG_ASM_SMALL_AUTO
40 # define _MULLONG_ASM_SMALL
42 # elif defined(SDCC_MODEL_LARGE)
43 # if !defined(SDCC_STACK_AUTO)
44 # define _MULLONG_ASM_LARGE
50 #if defined(_MULLONG_ASM_SMALL) || defined(_MULLONG_ASM_SMALL_AUTO)
53 _mullong_dummy (void) __naked
61 ; the result c will be stored in r4...r7
73 ; c1 a1 * b0 + a0 * b1
74 ; c2 a2 * b0 + a1 * b1 + a0 * b2
75 ; c3 a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
77 #if !defined(SDCC_STACK_AUTO) || defined(SDCC_PARMS_IN_BANK1)
78 #if defined(SDCC_PARMS_IN_BANK1)
84 #if defined(SDCC_NOOVERLAY)
92 .globl __mullong_PARM_2
97 b1 = (__mullong_PARM_2+1)
98 b2 = (__mullong_PARM_2+2)
99 b3 = (__mullong_PARM_2+3)
104 ; parameter a comes in a, b, dph, dpl
105 mov r2,b ; save parameter a
194 #else // SDCC_STACK_AUTO
196 ; parameter a comes in a, b, dph, dpl
197 mov r2,b ; save parameter a
207 mov a,#-2-3 ; 1 return address 2 bytes, b 4 bytes
209 mov r0,a ; 1 r0 points to b0
214 mov b0,b ; we need b0 several times
215 inc r0 ; r0 points to b1
304 #endif // SDCC_STACK_AUTO
309 #elif defined(_MULLONG_ASM_LARGE)
312 _mullong_dummy (void) __naked
320 ; the result c will be stored in r4...r7
327 ; c1 a1 * b0 + a0 * b1
328 ; c2 a2 * b0 + a1 * b1 + a0 * b2
329 ; c3 a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
331 #if !defined(SDCC_PARMS_IN_BANK1)
336 .globl __mullong_PARM_2
342 ; parameter a comes in a, b, dph, dpl
343 mov r0,dpl ; save parameter a
355 #if defined(SDCC_PARMS_IN_BANK1)
358 mov dptr,#__mullong_PARM_2
367 #if defined(SDCC_PARMS_IN_BANK1)
380 #if defined(SDCC_PARMS_IN_BANK1)
398 #if defined(SDCC_PARMS_IN_BANK1)
411 #if defined(SDCC_PARMS_IN_BANK1)
425 #if defined(SDCC_PARMS_IN_BANK1)
428 mov dptr,#__mullong_PARM_2
440 #if defined(SDCC_PARMS_IN_BANK1)
450 #if defined(SDCC_PARMS_IN_BANK1)
461 #if defined(SDCC_PARMS_IN_BANK1)
472 #if defined(SDCC_PARMS_IN_BANK1)
489 #elif defined(SDCC_USE_XSTACK) && defined(SDCC_STACK_AUTO)
492 _mullong_dummy (void) __naked
500 ; the result c will be stored in r4...r7
514 ; c1 a1 * b0 + a0 * b1
515 ; c2 a2 * b0 + a1 * b1 + a0 * b2
516 ; c3 a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
518 ; parameter a comes in a, b, dph, dpl
519 mov r2,b ; save parameter a
522 mov a,#-4 ; 1 b 4 bytes
524 mov r0,a ; 1 r0 points to b0
528 mov b0,a ; we need b0 several times
529 inc r0 ; r0 points to b1
622 #else // _MULLONG_ASM
628 #if defined(SDCC_hc08)
629 /* big endian order */
631 struct {unsigned char b3,b2,b1,b0 ;} b;
632 struct {unsigned short hi,lo ;} i;
634 struct { unsigned char b3; unsigned short i12; unsigned char b0;} bi;
637 /* little endian order */
639 struct {unsigned char b0,b1,b2,b3 ;} b;
640 struct {unsigned short lo,hi ;} i;
642 struct { unsigned char b0; unsigned short i12; unsigned char b3;} bi;
646 #if defined(SDCC_USE_XSTACK) || defined(SDCC_MODEL_MEDIUM)
647 # define bcast(x) ((union bil __pdata *)&(x))
648 #elif (defined(SDCC_MODEL_LARGE) || defined (SDCC_ds390) || defined (SDCC_ds400)) && !defined(SDCC_STACK_AUTO)
649 # define bcast(x) ((union bil __xdata *)&(x))
650 #elif defined(__z80) || defined(__gbz80)
651 # define bcast(x) ((union bil *)&(x))
653 # define bcast(x) ((union bil __near *)&(x))
659 ----------------------------
664 ----------------------------
672 |-------> only this side 32 x 32 -> 32
674 #if defined(SDCC_USE_XSTACK)
675 // currently the original code without u fails with --xstack
676 // it runs out of pointer registers
678 _mullong (long a, long b)
682 t.i.hi = bcast(a)->b.b0 * bcast(b)->b.b2; // A
683 t.i.lo = bcast(a)->b.b0 * bcast(b)->b.b0; // A
684 u.bi.b3 = bcast(a)->b.b0 * bcast(b)->b.b3; // B
685 u.bi.i12 = bcast(a)->b.b0 * bcast(b)->b.b1; // B
689 t.b.b3 += bcast(a)->b.b3 * bcast(b)->b.b0; // G
690 t.b.b3 += bcast(a)->b.b2 * bcast(b)->b.b1; // F
691 t.i.hi += bcast(a)->b.b2 * bcast(b)->b.b0; // E
692 t.i.hi += bcast(a)->b.b1 * bcast(b)->b.b1; // D
694 u.bi.b3 = bcast(a)->b.b1 * bcast(b)->b.b2; // C
695 u.bi.i12 = bcast(a)->b.b1 * bcast(b)->b.b0; // C
703 _mullong (long a, long b)
707 t.i.hi = bcast(a)->b.b0 * bcast(b)->b.b2; // A
708 t.i.lo = bcast(a)->b.b0 * bcast(b)->b.b0; // A
709 t.b.b3 += bcast(a)->b.b3 * bcast(b)->b.b0; // G
710 t.b.b3 += bcast(a)->b.b2 * bcast(b)->b.b1; // F
711 t.i.hi += bcast(a)->b.b2 * bcast(b)->b.b0; // E <- b lost in .lst
712 // bcast(a)->i.hi is free !
713 t.i.hi += bcast(a)->b.b1 * bcast(b)->b.b1; // D <- b lost in .lst
715 bcast(a)->bi.b3 = bcast(a)->b.b1 * bcast(b)->b.b2; // C
716 bcast(a)->bi.i12 = bcast(a)->b.b1 * bcast(b)->b.b0; // C
718 bcast(b)->bi.b3 = bcast(a)->b.b0 * bcast(b)->b.b3; // B
719 bcast(b)->bi.i12 = bcast(a)->b.b0 * bcast(b)->b.b1; // B
721 bcast(b)->bi.b0 = 0; // B
722 bcast(a)->bi.b0 = 0; // C
729 #endif // _MULLONG_ASM