Assembler functions for _mulint and _mullong
[fw/sdcc] / device / lib / _mulint.c
1 /*-------------------------------------------------------------------------
2
3   _mulint.c :- routine for (unsigned) int (16 bit) multiplication               
4
5              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
6
7    This program is free software; you can redistribute it and/or modify it
8    under the terms of the GNU 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 program 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 General Public License for more details.
16    
17    You should have received a copy of the GNU 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 /* Signed and unsigned multiplication are the same - as long as the output
27    has the same precision as the input.
28
29    To do: _muluint and _mulsint should be replaced by _mulint.
30
31    bernhard@bernhardheld.de
32
33    Assembler-functions are provided for:
34      ds390
35      mcs51 small
36      mcs51 small stack-auto
37      mcs51 large
38 */
39
40 #if !defined(SDCC_USE_XSTACK) || defined(_SDCC_NO_ASM_LIB_FUNCS)
41   #if defined(SDCC_ds390)
42     #if !defined(SDCC_STACK_AUTO)
43       #define _MULINT_ASM_LARGE
44     #endif
45   #elif defined(SDCC_mcs51)
46     #if defined(SDCC_MODEL_SMALL)
47       #if defined(SDCC_STACK_AUTO)
48         #define _MULINT_ASM_SMALL_AUTO
49       #else
50         #define _MULINT_ASM_SMALL
51       #endif
52     #else // must be SDCC_MODEL_LARGE
53       #if !defined(SDCC_STACK_AUTO)
54         #define _MULINT_ASM_LARGE
55       #endif
56     #endif
57   #endif
58 #endif
59
60 #ifdef _MULINT_ASM_LARGE
61
62 unsigned int
63 _muluint (unsigned int a, unsigned int b)       // in future: _mulint
64 {
65   a*b; // hush the compiler
66
67   /* mulint=
68       (int)(lsb_a*lsb_b) +
69       (char)(msb_a*lsb_b)<<8 +
70       (char)(lsb_a*msb_b)<<8
71   */
72
73   _asm 
74     mov r2,dph ; msb_a
75     mov r3,dpl ; lsb_a
76
77     mov b,r3 ; lsb_a
78     mov dptr,#__muluint_PARM_2
79     movx a,@dptr ; lsb_b
80     mul ab ; lsb_a*lsb_b
81     mov r0,a
82     mov r1,b
83
84     mov b,r2 ; msb_a
85     movx a,@dptr ; lsb_b
86     mul ab ; msb_a*lsb_b
87     add a,r1
88     mov r1,a
89
90     mov b,r3 ; lsb_a
91     inc dptr
92     movx a,@dptr ; msb_b
93     mul ab ; lsb_a*msb_b
94     add a,r1
95
96     mov dph,a
97     mov dpl,r0
98     ret
99   _endasm;
100 }
101
102 int
103 _mulsint (int a, int b)         // obsolete
104 {
105   return _muluint (a, b);
106 }
107
108 #elif defined _MULINT_ASM_SMALL || defined _MULINT_ASM_SMALL_AUTO
109
110 void
111 _mulint_dummy (void) _naked
112 {
113         _asm
114
115         __mulint:
116         __muluint:                              ; obsolete
117         __mulsint:                              ; obsolete
118
119                 .globl __mulint
120                 .globl __muluint                ; obsolete
121                 .globl __mulsint                ; obsolete
122
123 #if !defined(SDCC_STACK_AUTO)
124
125 #if defined(SDCC_NOOVERLAY)             // BUG SDCC_NOOVERLAY is not set by -no-overlay
126                 .area DSEG    (DATA)
127 #else
128                 .area OSEG    (OVR,DATA)
129 #endif
130
131         __mulint_PARM_2:
132         __muluint_PARM_2:                       ; obsolete
133         __mulsint_PARM_2:                       ; obsolete
134
135                 .globl __mulint_PARM_2
136                 .globl __muluint_PARM_2         ; obsolete
137                 .globl __mulsint_PARM_2         ; obsolete
138
139                 .ds     2
140
141                 .area CSEG    (CODE)
142
143                 ; globbered registers none
144
145                 mov     a,dpl                   ;  1  al
146                 mov     b,__mulint_PARM_2       ;  2  bl
147                 mul     ab                      ;  4  al * bl
148                 xch     a,dpl                   ;  1  store low-byte of return value, fetch al
149                 push    b                       ;  2
150
151                 mov     b,__mulint_PARM_2 + 1   ;  2  bh
152                 mul     ab                      ;  4  al * bh
153                 pop     b                       ;  2
154                 add     a,b                     ;  1
155                 xch     a,dph                   ;  1  ah -> acc
156
157                 mov     b,__mulint_PARM_2       ;  2  bl
158                 mul     ab                      ;  4  ah * bl
159                 add     a,dph                   ;  1
160                 mov     dph,a                   ;  1
161                 ret                             ;  2
162                                                 ; 30
163
164 #else // SDCC_STACK_AUTO
165
166                 ; globbered registers r0
167
168                 mov     a,#-2                   ;  1  return address 2 bytes
169                 add     a,sp                    ;  1
170                 mov     r0,a                    ;  1  r0 points to bh
171
172                 mov     a,@r0                   ;  1  bh
173                 mov     b,dpl                   ;  2  al
174                 mul     ab                      ;  4  al * bh
175                 push    acc                     ;  2
176
177                 mov     b,dpl                   ;  2  al
178                 dec     r0                      ;  1
179                 mov     a,@r0                   ;  1  bl
180                 mul     ab                      ;  4  al * bl
181
182                 mov     dpl,a                   ;  1  low-byte of return-value
183
184                 pop     acc                     ;  2
185                 add     a,b                     ;  1
186                 xch     a,dph                   ;  1  ah -> acc
187
188                 mov     b,@r0                   ;  2  bl
189                 mul     ab                      ;  4  ah * bl
190                 add     a,dph                   ;  1
191                 mov     dph,a                   ;  1
192
193                 ret
194         
195 #endif // SDCC_STACK_AUTO
196
197         _endasm ;
198 }
199
200 #else
201
202 union uu {
203         struct { unsigned char lo,hi ;} s;
204         unsigned int t;
205 } ;
206
207 unsigned int
208 _muluint (unsigned int a, unsigned int b)       // in future: _mulint
209 {
210 #ifdef SDCC_MODEL_LARGE         // still needed for large + stack-auto
211         union uu _xdata *x;
212         union uu _xdata *y; 
213         union uu t;
214         x = (union uu _xdata *)&a;
215         y = (union uu _xdata *)&b;
216 #else
217         register union uu *x;
218         register union uu *y; 
219         union uu t;
220         x = (union uu *)&a;
221         y = (union uu *)&b;
222 #endif
223
224         t.t = x->s.lo * y->s.lo;
225         t.s.hi += (x->s.lo * y->s.hi) + (x->s.hi * y->s.lo);
226
227        return t.t;
228
229
230 int
231 _mulsint (int a, int b)         // obsolete
232 {
233   return _muluint (a, b);
234 }
235
236 #endif
237
238 #undef _MULINT_ASM