Assembler functions for _mulint and _mullong
[fw/sdcc] / device / lib / _mullong.c
1 /*-------------------------------------------------------------------------
2    _mullong.c - routine for multiplication of 32 bit (unsigned) long
3
4              Written By -  Jean Louis VERN jlvern@writeme.com (1999)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24
25 /* Signed and unsigned multiplication are the same - as long as the output
26    has the same precision as the input.
27
28    To do: _mululong and _mulslong should be replaced by _mullong.
29
30    bernhard@bernhardheld.de
31
32    Assembler-functions are provided for:
33      mcs51 small
34      mcs51 small stack-auto
35 */
36
37 #if !defined(SDCC_USE_XSTACK) || defined(_SDCC_NO_ASM_LIB_FUNCS)
38   #if defined(SDCC_mcs51)
39     #if defined(SDCC_MODEL_SMALL)
40       #if defined(SDCC_STACK_AUTO)
41         #define _MULLONG_ASM_SMALL_AUTO
42       #else
43         #define _MULLONG_ASM_SMALL
44       #endif
45     #endif
46   #endif
47 #endif
48
49 #if defined _MULLONG_ASM_SMALL || defined _MULLONG_ASM_SMALL_AUTO
50
51 void
52 _mullong_dummy (void) _naked
53 {
54         _asm
55
56         __mullong:
57         __mululong:                     ; obsolete
58         __mulslong:                     ; obsolete
59
60                 .globl __mullong
61                 .globl __mululong       ; obsolete
62                 .globl __mulslong       ; obsolete
63
64                                         ; the result c will be stored in r4...r7
65                 #define c0 r4
66                 #define c1 r5
67                 #define c2 r6
68                 #define c3 r7
69
70         ; c0  a0 * b0
71         ; c1  a1 * b0 + a0 * b1
72         ; c2  a2 * b0 + a1 * b1 + a0 * b2
73         ; c3  a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
74
75 #if !defined SDCC_STACK_AUTO
76
77 #if defined(SDCC_NOOVERLAY)             // BUG SDCC_NOOVERLAY is not set by -no-overlay
78                 .area DSEG    (DATA)
79 #else
80                 .area OSEG    (OVR,DATA)
81 #endif
82
83         __mullong_PARM_2:
84         __mululong_PARM_2:                      ; obsolete
85         __mulslong_PARM_2:                      ; obsolete
86
87                 .globl __mullong_PARM_2
88                 .globl __mululong_PARM_2        ; obsolete
89                 .globl __mulslong_PARM_2        ; obsolete
90
91                 .ds     4
92
93                 .area CSEG    (CODE)
94
95                                         ; parameter a comes in a, b, dph, dpl
96                 mov     r2,b            ; save parameter a
97                 mov     r3,a
98
99                 #define a0 dpl
100                 #define a1 dph
101                 #define a2 r2
102                 #define a3 r3
103
104                 b0 =  __mullong_PARM_2
105                 b1 = (__mullong_PARM_2+1)
106                 b2 = (__mullong_PARM_2+2)
107                 b3 = (__mullong_PARM_2+3)
108
109                                         ;       Byte 0
110                 mov     a,a0
111                 mov     b,b0
112                 mul     ab              ; a0 * b0
113                 mov     c0,a
114                 mov     c1,b
115
116                                         ;       Byte 1
117                 mov     a,a1
118                 mov     b,b0
119                 mul     ab              ; a1 * b0
120                 add     a,c1
121                 mov     c1,a
122                 clr     a
123                 addc    a,b
124                 mov     c2,a
125                 
126
127                 mov     a,a0
128                 mov     b,b1
129                 mul     ab              ; a0 * b1
130                 add     a,c1
131                 mov     c1,a
132                 mov     a,b
133                 addc    a,c2
134                 mov     c2,a
135                 clr     a
136                 rlc     a
137                 mov     c3,a
138
139                                         ;       Byte 2
140                 mov     a,a2
141                 mov     b,b0
142                 mul     ab              ; a2 * b0
143                 add     a,c2
144                 mov     c2,a
145                 mov     a,b
146                 addc    a,c3
147                 mov     c3,a
148
149                 mov     a,a1
150                 mov     b,b1
151                 mul     ab              ; a1 * b1
152                 add     a,c2
153                 mov     c2,a
154                 mov     a,b
155                 addc    a,c3
156                 mov     c3,a
157
158                 mov     a,a0
159                 mov     b,b2
160                 mul     ab              ; a0 * b2
161                 add     a,c2
162                 mov     c2,a
163                 mov     a,b
164                 addc    a,c3
165                 mov     c3,a
166
167                                         ;       Byte 3
168                 mov     a,a3
169                 mov     b,b0
170                 mul     ab              ; a3 * b0
171                 add     a,c3
172                 mov     c3,a
173
174                 mov     a,a2
175                 mov     b,b1
176                 mul     ab              ; a2 * b1
177                 add     a,c3
178                 mov     c3,a
179
180                 mov     a,a1
181                 mov     b,b2
182                 mul     ab              ; a1 * b2
183                 add     a,c3
184                 mov     c3,a
185
186                 mov     a,a0
187                 mov     b,b3
188                 mul     ab              ; a0 * b3
189                 add     a,c3
190
191                 mov     b,c2
192                 mov     dph,c1
193                 mov     dpl,c0
194                 ret
195
196 #else // SDCC_STACK_AUTO
197
198                                         ; parameter a comes in a, b, dph, dpl
199                 mov     r2,b            ; save parameter a
200                 mov     r3,a
201
202                 #define a0 dpl
203                 #define a1 dph
204                 #define a2 r2
205                 #define a3 r3
206
207                 #define b0 r1
208
209                 mov     a,#-2-3         ;  1  return address 2 bytes, b 4 bytes
210                 add     a,sp            ;  1
211                 mov     r0,a            ;  1  r0 points to b0
212
213                                         ;       Byte 0
214                 mov     a,a0
215                 mov     b,@r0           ; b0
216                 mov     b0,b            ; we need b0 several times
217                 inc     r0              ; r0 points to b1
218                 mul     ab              ; a0 * b0
219                 mov     c0,a
220                 mov     c1,b
221
222                                         ;       Byte 1
223                 mov     a,a1
224                 mov     b,b0
225                 mul     ab              ; a1 * b0
226                 add     a,c1
227                 mov     c1,a
228                 clr     a
229                 addc    a,b
230                 mov     c2,a
231                 
232
233                 mov     a,a0
234                 mov     b,@r0           ; b1
235                 mul     ab              ; a0 * b1
236                 add     a,c1
237                 mov     c1,a
238                 mov     a,b
239                 addc    a,c2
240                 mov     c2,a
241                 clr     a
242                 rlc     a
243                 mov     c3,a
244
245                                         ;       Byte 2
246                 mov     a,a2
247                 mov     b,b0
248                 mul     ab              ; a2 * b0
249                 add     a,c2
250                 mov     c2,a
251                 mov     a,b
252                 addc    a,c3
253                 mov     c3,a
254
255                 mov     a,a1
256                 mov     b,@r0           ; b1
257                 mul     ab              ; a1 * b1
258                 add     a,c2
259                 mov     c2,a
260                 mov     a,b
261                 addc    a,c3
262                 mov     c3,a
263
264                 mov     a,a0
265                 inc     r0
266                 mov     b,@r0           ; b2
267                 mul     ab              ; a0 * b2
268                 add     a,c2
269                 mov     c2,a
270                 mov     a,b
271                 addc    a,c3
272                 mov     c3,a
273
274                                         ;       Byte 3
275                 mov     a,a3
276                 mov     b,b0
277                 mul     ab              ; a3 * b0
278                 add     a,c3
279                 mov     c3,a
280
281                 mov     a,a1
282                 mov     b,@r0           ; b2
283                 mul     ab              ; a1 * b2
284                 add     a,c3
285                 mov     c3,a
286
287                 mov     a,a2
288                 dec     r0
289                 mov     b,@r0           ; b1
290                 mul     ab              ; a2 * b1
291                 add     a,c3
292                 mov     c3,a
293
294                 mov     a,a0
295                 inc     r0
296                 inc     r0
297                 mov     b,@r0           ; b3
298                 mul     ab              ; a0 * b3
299                 add     a,c3
300
301                 mov     b,c2
302                 mov     dph,c1
303                 mov     dpl,c0
304
305                 ret
306
307 #endif // SDCC_STACK_AUTO
308
309         _endasm ;
310 }
311
312 #else // _MULLONG_ASM_SMALL || _MULLONG_ASM_SMALL_AUTO
313
314 struct some_struct {
315         int a ;
316         char b;
317         long c ;};
318 union bil {
319         struct {unsigned char b0,b1,b2,b3 ;} b;
320         struct {unsigned int lo,hi ;} i;
321         unsigned long l;
322         struct { unsigned char b0; unsigned int i12; unsigned char b3;} bi;
323 } ;
324 #if defined(SDCC_MODEL_LARGE) || defined (SDCC_ds390)
325 #define bcast(x) ((union bil _xdata *)&(x))
326 #elif defined(__z80) || defined(__gbz80)
327 #define bcast(x) ((union bil *)&(x))
328 #else
329 #define bcast(x) ((union bil _near  *)&(x))
330 #endif
331
332 /*
333                      3   2   1   0
334        X             3   2   1   0
335        ----------------------------
336                    0.3 0.2 0.1 0.0 
337                1.3 1.2 1.1 1.0 
338            2.3 2.2 2.1 2.0 
339        3.3 3.2 3.1 3.0 
340        ----------------------------
341                   |3.3|1.3|0.2|0.0|   A
342                     |2.3|0.3|0.1|     B
343                     |3.2|1.2|1.0|     C
344                       |2.2|1.1|       D
345                       |3.1|2.0|       E
346                         |2.1|         F
347                         |3.0|         G
348                           |-------> only this side 32 x 32 -> 32
349 */
350 unsigned long
351 _mululong (unsigned long a, unsigned long b)    // in future: _mullong
352 {
353         union bil t;
354
355         t.i.hi = bcast(a)->b.b0 * bcast(b)->b.b2;       // A
356         t.i.lo = bcast(a)->b.b0 * bcast(b)->b.b0;       // A
357         _asm ;johan _endasm;
358         t.b.b3 += bcast(a)->b.b3 *
359                                   bcast(b)->b.b0;       // G
360         t.b.b3 += bcast(a)->b.b2 *
361                                   bcast(b)->b.b1;       // F
362         t.i.hi += bcast(a)->b.b2 * bcast(b)->b.b0;      // E <- b lost in .lst
363         // bcast(a)->i.hi is free !
364         t.i.hi += bcast(a)->b.b1 * bcast(b)->b.b1;      // D <- b lost in .lst
365
366         bcast(a)->bi.b3 = bcast(a)->b.b1 *
367                                           bcast(b)->b.b2;
368         bcast(a)->bi.i12 = bcast(a)->b.b1 *
369                            bcast(b)->b.b0;              // C
370
371         bcast(b)->bi.b3 = bcast(a)->b.b0 *
372                                           bcast(b)->b.b3;
373         bcast(b)->bi.i12 = bcast(a)->b.b0 *
374                            bcast(b)->b.b1;              // B
375         bcast(b)->bi.b0 = 0;                            // B
376         bcast(a)->bi.b0 = 0;                            // C
377         t.l += a;
378
379         return t.l + b;
380 }
381
382 long
383 _mulslong (long a, long b)      // obsolete
384 {
385   _mululong (a, b);
386 }
387
388 #endif // _MULLONG_ASM_SMALL || _MULLONG_ASM_SMALL_AUTO