d5b923bfc05c66acadaae473b0ff18053e466210
[fw/sdcc] / device / lib / _muluint.c
1 /*-------------------------------------------------------------------------
2
3   _muluint.c :- routine for unsigned int (16 bit) multiplication               
4
5              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
6
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
10    later version.
11    
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.
16    
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.
20    
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 -------------------------------------------------------------------------*/
25
26 #if defined(__ds390) || defined (__mcs51)
27
28 // we can do this faster and more efficient in assembler
29
30 unsigned int _muluint (unsigned int a, unsigned int b) 
31 {
32   a*b; // hush the compiler
33
34   /* muluint=
35       (int)(lsb_a*lsb_b) +
36       (char)(msb_a*lsb_b)<<8 +
37       (char)(lsb_a*msb_b)<<8
38   */
39
40   _asm 
41     mov r2,dph ; msb_a
42     mov r3,dpl ; lsb_a
43
44     mov b,r3 ; lsb_a
45 #if defined(SDCC_ds390) || defined(SDCC_MODEL_LARGE)
46     mov dptr,#__muluint_PARM_2
47     movx a,@dptr ; lsb_b
48 #else // must be SDCC_MODEL_SMALL
49     mov a,__muluint_PARM_2 ; lsb_b
50 #endif
51     mul ab ; lsb_a*lsb_b
52     mov r0,a
53     mov r1,b
54
55     mov b,r2 ; msb_a
56 #if defined(SDCC_ds390) || defined(SDCC_MODEL_LARGE)
57     movx a,@dptr ; lsb_b
58 #else // must be SDCC_MODEL_SMALL
59     mov a,__muluint_PARM_2 ; lsb_b
60 #endif
61     mul ab ; msb_a*lsb_b
62     add a,r1
63     mov r1,a
64
65     mov b,r3 ; lsb_a
66 #if defined(SDCC_ds390) || defined(SDCC_MODEL_LARGE)
67     inc dptr
68     movx a,@dptr ; msb_b
69 #else // must be SDCC_MODEL_SMALL
70     mov a,1+__muluint_PARM_2 ; msb_b
71 #endif
72     mul ab ; lsb_a*msb_b
73     add a,r1
74
75     mov dph,a
76     mov dpl,r0
77     ret
78   _endasm;
79 }
80
81 #else
82
83 // we have to do it the hard way
84
85 union uu {
86   struct { unsigned char lo,hi ;} s;
87   unsigned int t;
88 };
89
90 unsigned int _muluint (unsigned int a, unsigned int b) 
91 {
92   union uu *x;
93   union uu *y; 
94   union uu t;
95   x = (union uu *)&a;
96   y = (union uu *)&b;
97
98   t.t = x->s.lo * y->s.lo;
99   t.s.hi += (x->s.lo * y->s.hi) + (x->s.hi * y->s.lo);
100   
101   return t.t;
102
103
104 #endif