7afdc5afefe572dbd3f7505d76d84652cd15eaff
[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              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 /* Signed and unsigned multiplication are the same - as long as the output
27    has the same precision as the input.
28
29    To do: _mululong and _mulslong should be replaced by _mullong.
30
31    bernhard@bernhardheld.de
32
33    Assembler-functions are provided for:
34      mcs51 small
35      mcs51 small stack-auto
36 */
37
38 #if !defined(SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
39 #  if defined(SDCC_mcs51)
40 #    if defined(SDCC_MODEL_SMALL)
41 #      if defined(SDCC_STACK_AUTO) && !defined(SDCC_PARMS_IN_BANK1)
42 #        define _MULLONG_ASM_SMALL_AUTO
43 #      else
44 #        define _MULLONG_ASM_SMALL
45 #      endif
46 #    elif defined(SDCC_MODEL_LARGE)
47 #      if !defined(SDCC_STACK_AUTO)
48 #        define _MULLONG_ASM_LARGE
49 #      endif
50 #    endif
51 #  endif
52 #endif
53
54 #if defined _MULLONG_ASM_SMALL || defined _MULLONG_ASM_SMALL_AUTO
55
56 void
57 _mullong_dummy (void) _naked
58 {
59         _asm
60
61         __mullong:
62         __mululong:                     ; obsolete
63         __mulslong:                     ; obsolete
64
65                 .globl __mullong
66                 .globl __mululong       ; obsolete
67                 .globl __mulslong       ; obsolete
68
69                                         ; the result c will be stored in r4...r7
70                 #define c0 r4
71                 #define c1 r5
72                 #define c2 r6
73                 #define c3 r7
74
75                 #define a0 dpl
76                 #define a1 dph
77                 #define a2 r2
78                 #define a3 r3
79
80         ; c0  a0 * b0
81         ; c1  a1 * b0 + a0 * b1
82         ; c2  a2 * b0 + a1 * b1 + a0 * b2
83         ; c3  a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
84
85 #if !defined(SDCC_STACK_AUTO) || defined(SDCC_PARMS_IN_BANK1)
86 #if defined(SDCC_PARMS_IN_BANK1)
87                 #define b0  (b1_0)
88                 #define b1  (b1_1)
89                 #define b2  (b1_2)
90                 #define b3  (b1_3)
91 #else
92 #if defined(SDCC_NOOVERLAY)
93                 .area DSEG    (DATA)
94 #else
95                 .area OSEG    (OVR,DATA)
96 #endif
97
98         __mullong_PARM_2:
99         __mululong_PARM_2:                      ; obsolete
100         __mulslong_PARM_2:                      ; obsolete
101
102                 .globl __mullong_PARM_2
103                 .globl __mululong_PARM_2        ; obsolete
104                 .globl __mulslong_PARM_2        ; obsolete
105
106                 .ds     4
107
108                 b0 =  __mullong_PARM_2
109                 b1 = (__mullong_PARM_2+1)
110                 b2 = (__mullong_PARM_2+2)
111                 b3 = (__mullong_PARM_2+3)
112
113 #endif
114                 .area CSEG    (CODE)
115
116                                         ; parameter a comes in a, b, dph, dpl
117                 mov     r2,b            ; save parameter a
118                 mov     r3,a
119
120                                         ;       Byte 0
121                 mov     a,a0
122                 mov     b,b0
123                 mul     ab              ; a0 * b0
124                 mov     c0,a
125                 mov     c1,b
126
127                                         ;       Byte 1
128                 mov     a,a1
129                 mov     b,b0
130                 mul     ab              ; a1 * b0
131                 add     a,c1
132                 mov     c1,a
133                 clr     a
134                 addc    a,b
135                 mov     c2,a
136                 
137
138                 mov     a,a0
139                 mov     b,b1
140                 mul     ab              ; a0 * b1
141                 add     a,c1
142                 mov     c1,a
143                 mov     a,b
144                 addc    a,c2
145                 mov     c2,a
146                 clr     a
147                 rlc     a
148                 mov     c3,a
149
150                                         ;       Byte 2
151                 mov     a,a2
152                 mov     b,b0
153                 mul     ab              ; a2 * b0
154                 add     a,c2
155                 mov     c2,a
156                 mov     a,b
157                 addc    a,c3
158                 mov     c3,a
159
160                 mov     a,a1
161                 mov     b,b1
162                 mul     ab              ; a1 * b1
163                 add     a,c2
164                 mov     c2,a
165                 mov     a,b
166                 addc    a,c3
167                 mov     c3,a
168
169                 mov     a,a0
170                 mov     b,b2
171                 mul     ab              ; a0 * b2
172                 add     a,c2
173                 mov     c2,a
174                 mov     a,b
175                 addc    a,c3
176                 mov     c3,a
177
178                                         ;       Byte 3
179                 mov     a,a3
180                 mov     b,b0
181                 mul     ab              ; a3 * b0
182                 add     a,c3
183                 mov     c3,a
184
185                 mov     a,a2
186                 mov     b,b1
187                 mul     ab              ; a2 * b1
188                 add     a,c3
189                 mov     c3,a
190
191                 mov     a,a1
192                 mov     b,b2
193                 mul     ab              ; a1 * b2
194                 add     a,c3
195                 mov     c3,a
196
197                 mov     a,a0
198                 mov     b,b3
199                 mul     ab              ; a0 * b3
200                 add     a,c3
201
202                 mov     b,c2
203                 mov     dph,c1
204                 mov     dpl,c0
205                 ret
206
207 #else // SDCC_STACK_AUTO
208
209                                         ; parameter a comes in a, b, dph, dpl
210                 mov     r2,b            ; save parameter a
211                 mov     r3,a
212
213                 #define a0 dpl
214                 #define a1 dph
215                 #define a2 r2
216                 #define a3 r3
217
218                 #define b0 r1
219
220                 mov     a,#-2-3         ;  1  return address 2 bytes, b 4 bytes
221                 add     a,sp            ;  1
222                 mov     r0,a            ;  1  r0 points to b0
223
224                                         ;       Byte 0
225                 mov     a,a0
226                 mov     b,@r0           ; b0
227                 mov     b0,b            ; we need b0 several times
228                 inc     r0              ; r0 points to b1
229                 mul     ab              ; a0 * b0
230                 mov     c0,a
231                 mov     c1,b
232
233                                         ;       Byte 1
234                 mov     a,a1
235                 mov     b,b0
236                 mul     ab              ; a1 * b0
237                 add     a,c1
238                 mov     c1,a
239                 clr     a
240                 addc    a,b
241                 mov     c2,a
242                 
243
244                 mov     a,a0
245                 mov     b,@r0           ; b1
246                 mul     ab              ; a0 * b1
247                 add     a,c1
248                 mov     c1,a
249                 mov     a,b
250                 addc    a,c2
251                 mov     c2,a
252                 clr     a
253                 rlc     a
254                 mov     c3,a
255
256                                         ;       Byte 2
257                 mov     a,a2
258                 mov     b,b0
259                 mul     ab              ; a2 * b0
260                 add     a,c2
261                 mov     c2,a
262                 mov     a,b
263                 addc    a,c3
264                 mov     c3,a
265
266                 mov     a,a1
267                 mov     b,@r0           ; b1
268                 mul     ab              ; a1 * b1
269                 add     a,c2
270                 mov     c2,a
271                 mov     a,b
272                 addc    a,c3
273                 mov     c3,a
274
275                 mov     a,a0
276                 inc     r0
277                 mov     b,@r0           ; b2
278                 mul     ab              ; a0 * b2
279                 add     a,c2
280                 mov     c2,a
281                 mov     a,b
282                 addc    a,c3
283                 mov     c3,a
284
285                                         ;       Byte 3
286                 mov     a,a3
287                 mov     b,b0
288                 mul     ab              ; a3 * b0
289                 add     a,c3
290                 mov     c3,a
291
292                 mov     a,a1
293                 mov     b,@r0           ; b2
294                 mul     ab              ; a1 * b2
295                 add     a,c3
296                 mov     c3,a
297
298                 mov     a,a2
299                 dec     r0
300                 mov     b,@r0           ; b1
301                 mul     ab              ; a2 * b1
302                 add     a,c3
303                 mov     c3,a
304
305                 mov     a,a0
306                 inc     r0
307                 inc     r0
308                 mov     b,@r0           ; b3
309                 mul     ab              ; a0 * b3
310                 add     a,c3
311
312                 mov     b,c2
313                 mov     dph,c1
314                 mov     dpl,c0
315
316                 ret
317
318 #endif // SDCC_STACK_AUTO
319
320         _endasm ;
321 }
322
323
324 #elif defined _MULLONG_ASM_LARGE
325
326 void
327 _mullong_dummy (void) _naked
328 {
329         _asm
330
331         __mullong:
332         __mululong:                     ; obsolete
333         __mulslong:                     ; obsolete
334
335                 .globl __mullong
336                 .globl __mululong       ; obsolete
337                 .globl __mulslong       ; obsolete
338
339                                         ; the result c will be stored in r4...r7
340                 #define c0 r4
341                 #define c1 r5
342                 #define c2 r6
343                 #define c3 r7
344
345         ; c0  a0 * b0
346         ; c1  a1 * b0 + a0 * b1
347         ; c2  a2 * b0 + a1 * b1 + a0 * b2
348         ; c3  a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
349
350 #if !defined(SDCC_PARMS_IN_BANK1)
351                 .area XSEG    (XDATA)
352
353         __mullong_PARM_2:
354         __mululong_PARM_2:                      ; obsolete
355         __mulslong_PARM_2:                      ; obsolete
356
357                 .globl __mullong_PARM_2
358                 .globl __mululong_PARM_2        ; obsolete
359                 .globl __mulslong_PARM_2        ; obsolete
360
361                 .ds     4
362 #endif
363                 .area CSEG    (CODE)
364
365                                         ; parameter a comes in a, b, dph, dpl
366                 mov     r0,dpl          ; save parameter a
367                 mov     r1,dph
368                 mov     r2,b
369                 mov     r3,a
370
371                 #define a0 r0
372                 #define a1 r1
373                 #define a2 r2
374                 #define a3 r3
375
376                                         ;       Byte 0
377                 mov     b,a0
378 #if defined(SDCC_PARMS_IN_BANK1)
379                 mov     a,b1_0          ; b0                                               
380 #else
381                 mov     dptr,#__mullong_PARM_2
382                 movx    a,@dptr         ; b0
383 #endif
384                 mul     ab              ; a0 * b0
385                 mov     c0,a
386                 mov     c1,b
387
388                                         ;       Byte 1
389                 mov     b,a1
390 #if defined(SDCC_PARMS_IN_BANK1)
391                 mov     a,b1_0          ; b0                                               
392 #else
393                 movx    a,@dptr         ; b0
394 #endif
395                 mul     ab              ; a1 * b0
396                 add     a,c1
397                 mov     c1,a
398                 clr     a
399                 addc    a,b
400                 mov     c2,a
401                 
402
403                 mov     b,a0
404 #if defined(SDCC_PARMS_IN_BANK1)
405                 mov     a,b1_1          ; b1
406 #else
407                 inc     dptr            ; b1
408                 movx    a,@dptr
409 #endif
410                 mul     ab              ; a0 * b1
411                 add     a,c1
412                 mov     c1,a
413                 mov     a,b
414                 addc    a,c2
415                 mov     c2,a
416                 clr     a
417                 rlc     a
418                 mov     c3,a
419
420                                         ;       Byte 2
421                 mov     b,a1
422 #if defined(SDCC_PARMS_IN_BANK1)
423                 mov     a,b1_1          ; b1
424 #else
425                 movx    a,@dptr         ; b1
426 #endif
427                 mul     ab              ; a1 * b1
428                 add     a,c2
429                 mov     c2,a
430                 mov     a,b
431                 addc    a,c3
432                 mov     c3,a
433
434                 mov     b,a0
435 #if defined(SDCC_PARMS_IN_BANK1)
436                 mov     a,b1_2          ; b2
437 #else
438                 inc     dptr            ; b2
439                 movx    a,@dptr
440 #endif
441                 mul     ab              ; a0 * b2
442                 add     a,c2
443                 mov     c2,a
444                 mov     a,b
445                 addc    a,c3
446                 mov     c3,a
447
448                 mov     b,a2
449 #if defined(SDCC_PARMS_IN_BANK1)
450                 mov     a,b1_0          ; b0
451 #else
452                 mov     dptr,#__mullong_PARM_2
453                 movx    a,@dptr         ; b0
454 #endif
455                 mul     ab              ; a2 * b0
456                 add     a,c2
457                 mov     c2,a
458                 mov     a,b
459                 addc    a,c3
460                 mov     c3,a
461
462                                         ;       Byte 3
463                 mov     b,a3
464 #if defined(SDCC_PARMS_IN_BANK1)
465                 mov     a,b1_0          ; b0
466 #else
467                 movx    a,@dptr         ; b0
468 #endif
469                 mul     ab              ; a3 * b0
470                 add     a,c3
471                 mov     c3,a
472
473                 mov     b,a2
474 #if defined(SDCC_PARMS_IN_BANK1)
475                 mov     a,b1_1          ; b1
476 #else
477                 inc     dptr            ; b1
478                 movx    a,@dptr
479 #endif
480                 mul     ab              ; a2 * b1
481                 add     a,c3
482                 mov     c3,a
483
484                 mov     b,a1
485 #if defined(SDCC_PARMS_IN_BANK1)
486                 mov     a,b1_2          ; b2
487 #else
488                 inc     dptr            ; b2
489                 movx    a,@dptr
490 #endif
491                 mul     ab              ; a1 * b2
492                 add     a,c3
493                 mov     c3,a
494
495                 mov     b,a0
496 #if defined(SDCC_PARMS_IN_BANK1)
497                 mov     a,b1_3          ; b3
498 #else
499                 inc     dptr            ; b3
500                 movx    a,@dptr
501 #endif
502                 mul     ab              ; a0 * b3
503                 add     a,c3
504
505                 mov     b,c2
506                 mov     dph,c1
507                 mov     dpl,c0
508                 ret
509
510         _endasm ;
511 }
512
513 #else // _MULLONG_ASM
514
515 struct some_struct {
516         int a ;
517         char b;
518         long c ;};
519 union bil {
520         struct {unsigned char b0,b1,b2,b3 ;} b;
521         struct {unsigned int lo,hi ;} i;
522         unsigned long l;
523         struct { unsigned char b0; unsigned int i12; unsigned char b3;} bi;
524 } ;
525 #if defined(SDCC_MODEL_LARGE) || defined (SDCC_ds390)
526 #define bcast(x) ((union bil xdata *)&(x))
527 #elif defined(__z80) || defined(__gbz80)
528 #define bcast(x) ((union bil *)&(x))
529 #else
530 #define bcast(x) ((union bil near  *)&(x))
531 #endif
532
533 /*
534                      3   2   1   0
535        X             3   2   1   0
536        ----------------------------
537                    0.3 0.2 0.1 0.0 
538                1.3 1.2 1.1 1.0 
539            2.3 2.2 2.1 2.0 
540        3.3 3.2 3.1 3.0 
541        ----------------------------
542                   |3.3|1.3|0.2|0.0|   A
543                     |2.3|0.3|0.1|     B
544                     |3.2|1.2|1.0|     C
545                       |2.2|1.1|       D
546                       |3.1|2.0|       E
547                         |2.1|         F
548                         |3.0|         G
549                           |-------> only this side 32 x 32 -> 32
550 */
551 unsigned long
552 _mululong (unsigned long a, unsigned long b)    // in future: _mullong
553 {
554         union bil t;
555
556         t.i.hi = bcast(a)->b.b0 * bcast(b)->b.b2;       // A
557         t.i.lo = bcast(a)->b.b0 * bcast(b)->b.b0;       // A
558         _asm ;johan _endasm;
559         t.b.b3 += bcast(a)->b.b3 *
560                                   bcast(b)->b.b0;       // G
561         t.b.b3 += bcast(a)->b.b2 *
562                                   bcast(b)->b.b1;       // F
563         t.i.hi += bcast(a)->b.b2 * bcast(b)->b.b0;      // E <- b lost in .lst
564         // bcast(a)->i.hi is free !
565         t.i.hi += bcast(a)->b.b1 * bcast(b)->b.b1;      // D <- b lost in .lst
566
567         bcast(a)->bi.b3 = bcast(a)->b.b1 *
568                                           bcast(b)->b.b2;
569         bcast(a)->bi.i12 = bcast(a)->b.b1 *
570                            bcast(b)->b.b0;              // C
571
572         bcast(b)->bi.b3 = bcast(a)->b.b0 *
573                                           bcast(b)->b.b3;
574         bcast(b)->bi.i12 = bcast(a)->b.b0 *
575                            bcast(b)->b.b1;              // B
576         bcast(b)->bi.b0 = 0;                            // B
577         bcast(a)->bi.b0 = 0;                            // C
578         t.l += a;
579
580         return t.l + b;
581 }
582
583 long
584 _mulslong (long a, long b)      // obsolete
585 {
586   return _mululong (a, b);
587 }
588
589 #endif // _MULLONG_ASM