* configure.in: added missing mcs51 in status output
[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    Assembler-functions are provided for:
30      mcs51 small
31      mcs51 small stack-auto
32 */
33
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
39 #      else
40 #        define _MULLONG_ASM_SMALL
41 #      endif
42 #    elif defined(SDCC_MODEL_LARGE)
43 #      if !defined(SDCC_STACK_AUTO)
44 #        define _MULLONG_ASM_LARGE
45 #      endif
46 #    endif
47 #  endif
48 #endif
49
50 #if defined(_MULLONG_ASM_SMALL) || defined(_MULLONG_ASM_SMALL_AUTO)
51
52 void
53 _mullong_dummy (void) _naked
54 {
55         _asm
56
57         __mullong:
58
59                 .globl __mullong
60
61                                         ; the result c will be stored in r4...r7
62                 #define c0 r4
63                 #define c1 r5
64                 #define c2 r6
65                 #define c3 r7
66
67                 #define a0 dpl
68                 #define a1 dph
69                 #define a2 r2
70                 #define a3 r3
71
72         ; c0  a0 * b0
73         ; c1  a1 * b0 + a0 * b1
74         ; c2  a2 * b0 + a1 * b1 + a0 * b2
75         ; c3  a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
76
77 #if !defined(SDCC_STACK_AUTO) || defined(SDCC_PARMS_IN_BANK1)
78 #if defined(SDCC_PARMS_IN_BANK1)
79                 #define b0  (b1_0)
80                 #define b1  (b1_1)
81                 #define b2  (b1_2)
82                 #define b3  (b1_3)
83 #else
84 #if defined(SDCC_NOOVERLAY)
85                 .area DSEG    (DATA)
86 #else
87                 .area OSEG    (OVR,DATA)
88 #endif
89
90         __mullong_PARM_2:
91
92                 .globl __mullong_PARM_2
93
94                 .ds     4
95
96                 b0 =  __mullong_PARM_2
97                 b1 = (__mullong_PARM_2+1)
98                 b2 = (__mullong_PARM_2+2)
99                 b3 = (__mullong_PARM_2+3)
100
101 #endif
102                 .area CSEG    (CODE)
103
104                                         ; parameter a comes in a, b, dph, dpl
105                 mov     r2,b            ; save parameter a
106                 mov     r3,a
107
108                                         ;       Byte 0
109                 mov     a,a0
110                 mov     b,b0
111                 mul     ab              ; a0 * b0
112                 mov     c0,a
113                 mov     c1,b
114
115                                         ;       Byte 1
116                 mov     a,a1
117                 mov     b,b0
118                 mul     ab              ; a1 * b0
119                 add     a,c1
120                 mov     c1,a
121                 clr     a
122                 addc    a,b
123                 mov     c2,a
124
125
126                 mov     a,a0
127                 mov     b,b1
128                 mul     ab              ; a0 * b1
129                 add     a,c1
130                 mov     c1,a
131                 mov     a,b
132                 addc    a,c2
133                 mov     c2,a
134                 clr     a
135                 rlc     a
136                 mov     c3,a
137
138                                         ;       Byte 2
139                 mov     a,a2
140                 mov     b,b0
141                 mul     ab              ; a2 * b0
142                 add     a,c2
143                 mov     c2,a
144                 mov     a,b
145                 addc    a,c3
146                 mov     c3,a
147
148                 mov     a,a1
149                 mov     b,b1
150                 mul     ab              ; a1 * b1
151                 add     a,c2
152                 mov     c2,a
153                 mov     a,b
154                 addc    a,c3
155                 mov     c3,a
156
157                 mov     a,a0
158                 mov     b,b2
159                 mul     ab              ; a0 * b2
160                 add     a,c2
161                 mov     c2,a
162                 mov     a,b
163                 addc    a,c3
164                 mov     c3,a
165
166                                         ;       Byte 3
167                 mov     a,a3
168                 mov     b,b0
169                 mul     ab              ; a3 * b0
170                 add     a,c3
171                 mov     c3,a
172
173                 mov     a,a2
174                 mov     b,b1
175                 mul     ab              ; a2 * b1
176                 add     a,c3
177                 mov     c3,a
178
179                 mov     a,a1
180                 mov     b,b2
181                 mul     ab              ; a1 * b2
182                 add     a,c3
183                 mov     c3,a
184
185                 mov     a,a0
186                 mov     b,b3
187                 mul     ab              ; a0 * b3
188                 add     a,c3
189
190                 mov     b,c2
191                 mov     dph,c1
192                 mov     dpl,c0
193                 ret
194
195 #else // SDCC_STACK_AUTO
196
197                                         ; parameter a comes in a, b, dph, dpl
198                 mov     r2,b            ; save parameter a
199                 mov     r3,a
200
201                 #define a0 dpl
202                 #define a1 dph
203                 #define a2 r2
204                 #define a3 r3
205
206                 #define b0 r1
207
208                 mov     a,#-2-3         ;  1  return address 2 bytes, b 4 bytes
209                 add     a,sp            ;  1
210                 mov     r0,a            ;  1  r0 points to b0
211
212                                         ;       Byte 0
213                 mov     a,a0
214                 mov     b,@r0           ; b0
215                 mov     b0,b            ; we need b0 several times
216                 inc     r0              ; r0 points to b1
217                 mul     ab              ; a0 * b0
218                 mov     c0,a
219                 mov     c1,b
220
221                                         ;       Byte 1
222                 mov     a,a1
223                 mov     b,b0
224                 mul     ab              ; a1 * b0
225                 add     a,c1
226                 mov     c1,a
227                 clr     a
228                 addc    a,b
229                 mov     c2,a
230
231
232                 mov     a,a0
233                 mov     b,@r0           ; b1
234                 mul     ab              ; a0 * b1
235                 add     a,c1
236                 mov     c1,a
237                 mov     a,b
238                 addc    a,c2
239                 mov     c2,a
240                 clr     a
241                 rlc     a
242                 mov     c3,a
243
244                                         ;       Byte 2
245                 mov     a,a2
246                 mov     b,b0
247                 mul     ab              ; a2 * b0
248                 add     a,c2
249                 mov     c2,a
250                 mov     a,b
251                 addc    a,c3
252                 mov     c3,a
253
254                 mov     a,a1
255                 mov     b,@r0           ; b1
256                 mul     ab              ; a1 * b1
257                 add     a,c2
258                 mov     c2,a
259                 mov     a,b
260                 addc    a,c3
261                 mov     c3,a
262
263                 mov     a,a0
264                 inc     r0
265                 mov     b,@r0           ; b2
266                 mul     ab              ; a0 * b2
267                 add     a,c2
268                 mov     c2,a
269                 mov     a,b
270                 addc    a,c3
271                 mov     c3,a
272
273                                         ;       Byte 3
274                 mov     a,a3
275                 mov     b,b0
276                 mul     ab              ; a3 * b0
277                 add     a,c3
278                 mov     c3,a
279
280                 mov     a,a1
281                 mov     b,@r0           ; b2
282                 mul     ab              ; a1 * b2
283                 add     a,c3
284                 mov     c3,a
285
286                 mov     a,a2
287                 dec     r0
288                 mov     b,@r0           ; b1
289                 mul     ab              ; a2 * b1
290                 add     a,c3
291                 mov     c3,a
292
293                 mov     a,a0
294                 inc     r0
295                 inc     r0
296                 mov     b,@r0           ; b3
297                 mul     ab              ; a0 * b3
298                 add     a,c3
299
300                 mov     b,c2
301                 mov     dph,c1
302                 mov     dpl,c0
303
304                 ret
305
306 #endif // SDCC_STACK_AUTO
307
308         _endasm ;
309 }
310
311
312 #elif defined(_MULLONG_ASM_LARGE)
313
314 void
315 _mullong_dummy (void) _naked
316 {
317         _asm
318
319         __mullong:
320
321                 .globl __mullong
322
323                                         ; the result c will be stored in r4...r7
324                 #define c0 r4
325                 #define c1 r5
326                 #define c2 r6
327                 #define c3 r7
328
329         ; c0  a0 * b0
330         ; c1  a1 * b0 + a0 * b1
331         ; c2  a2 * b0 + a1 * b1 + a0 * b2
332         ; c3  a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
333
334 #if !defined(SDCC_PARMS_IN_BANK1)
335                 .area XSEG    (XDATA)
336
337         __mullong_PARM_2:
338
339                 .globl __mullong_PARM_2
340
341                 .ds     4
342 #endif
343                 .area CSEG    (CODE)
344
345                                         ; parameter a comes in a, b, dph, dpl
346                 mov     r0,dpl          ; save parameter a
347                 mov     r1,dph
348                 mov     r2,b
349                 mov     r3,a
350
351                 #define a0 r0
352                 #define a1 r1
353                 #define a2 r2
354                 #define a3 r3
355
356                                         ;       Byte 0
357                 mov     b,a0
358 #if defined(SDCC_PARMS_IN_BANK1)
359                 mov     a,b1_0          ; b0
360 #else
361                 mov     dptr,#__mullong_PARM_2
362                 movx    a,@dptr         ; b0
363 #endif
364                 mul     ab              ; a0 * b0
365                 mov     c0,a
366                 mov     c1,b
367
368                                         ;       Byte 1
369                 mov     b,a1
370 #if defined(SDCC_PARMS_IN_BANK1)
371                 mov     a,b1_0          ; b0
372 #else
373                 movx    a,@dptr         ; b0
374 #endif
375                 mul     ab              ; a1 * b0
376                 add     a,c1
377                 mov     c1,a
378                 clr     a
379                 addc    a,b
380                 mov     c2,a
381
382
383                 mov     b,a0
384 #if defined(SDCC_PARMS_IN_BANK1)
385                 mov     a,b1_1          ; b1
386 #else
387                 inc     dptr            ; b1
388                 movx    a,@dptr
389 #endif
390                 mul     ab              ; a0 * b1
391                 add     a,c1
392                 mov     c1,a
393                 mov     a,b
394                 addc    a,c2
395                 mov     c2,a
396                 clr     a
397                 rlc     a
398                 mov     c3,a
399
400                                         ;       Byte 2
401                 mov     b,a1
402 #if defined(SDCC_PARMS_IN_BANK1)
403                 mov     a,b1_1          ; b1
404 #else
405                 movx    a,@dptr         ; b1
406 #endif
407                 mul     ab              ; a1 * b1
408                 add     a,c2
409                 mov     c2,a
410                 mov     a,b
411                 addc    a,c3
412                 mov     c3,a
413
414                 mov     b,a0
415 #if defined(SDCC_PARMS_IN_BANK1)
416                 mov     a,b1_2          ; b2
417 #else
418                 inc     dptr            ; b2
419                 movx    a,@dptr
420 #endif
421                 mul     ab              ; a0 * b2
422                 add     a,c2
423                 mov     c2,a
424                 mov     a,b
425                 addc    a,c3
426                 mov     c3,a
427
428                 mov     b,a2
429 #if defined(SDCC_PARMS_IN_BANK1)
430                 mov     a,b1_0          ; b0
431 #else
432                 mov     dptr,#__mullong_PARM_2
433                 movx    a,@dptr         ; b0
434 #endif
435                 mul     ab              ; a2 * b0
436                 add     a,c2
437                 mov     c2,a
438                 mov     a,b
439                 addc    a,c3
440                 mov     c3,a
441
442                                         ;       Byte 3
443                 mov     b,a3
444 #if defined(SDCC_PARMS_IN_BANK1)
445                 mov     a,b1_0          ; b0
446 #else
447                 movx    a,@dptr         ; b0
448 #endif
449                 mul     ab              ; a3 * b0
450                 add     a,c3
451                 mov     c3,a
452
453                 mov     b,a2
454 #if defined(SDCC_PARMS_IN_BANK1)
455                 mov     a,b1_1          ; b1
456 #else
457                 inc     dptr            ; b1
458                 movx    a,@dptr
459 #endif
460                 mul     ab              ; a2 * b1
461                 add     a,c3
462                 mov     c3,a
463
464                 mov     b,a1
465 #if defined(SDCC_PARMS_IN_BANK1)
466                 mov     a,b1_2          ; b2
467 #else
468                 inc     dptr            ; b2
469                 movx    a,@dptr
470 #endif
471                 mul     ab              ; a1 * b2
472                 add     a,c3
473                 mov     c3,a
474
475                 mov     b,a0
476 #if defined(SDCC_PARMS_IN_BANK1)
477                 mov     a,b1_3          ; b3
478 #else
479                 inc     dptr            ; b3
480                 movx    a,@dptr
481 #endif
482                 mul     ab              ; a0 * b3
483                 add     a,c3
484
485                 mov     b,c2
486                 mov     dph,c1
487                 mov     dpl,c0
488                 ret
489
490         _endasm ;
491 }
492
493 #elif defined(SDCC_USE_XSTACK) && defined(SDCC_STACK_AUTO)
494
495 void
496 _mullong_dummy (void) _naked
497 {
498         _asm
499
500         __mullong:
501
502                 .globl __mullong
503
504                                         ; the result c will be stored in r4...r7
505                 #define c0 r4
506                 #define c1 r5
507                 #define c2 r6
508                 #define c3 r7
509
510                 #define a0 dpl
511                 #define a1 dph
512                 #define a2 r2
513                 #define a3 r3
514
515                 #define b0 r1
516
517         ; c0  a0 * b0
518         ; c1  a1 * b0 + a0 * b1
519         ; c2  a2 * b0 + a1 * b1 + a0 * b2
520         ; c3  a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
521
522
523                                         ; parameter a comes in a, b, dph, dpl
524                 mov     r2,b            ; save parameter a
525                 mov     r3,a
526
527                 mov     a,#-4           ;  1  b 4 bytes
528                 add     a,_spx          ;  1
529                 mov     r0,a            ;  1  r0 points to b0
530
531                                         ;       Byte 0
532                 movx    a,@r0           ; b0
533                 mov     b0,a            ; we need b0 several times
534                 inc     r0              ; r0 points to b1
535                 mov     b,a0
536                 mul     ab              ; a0 * b0
537                 mov     c0,a
538                 mov     c1,b
539
540                                         ;       Byte 1
541                 mov     a,a1
542                 mov     b,b0
543                 mul     ab              ; a1 * b0
544                 add     a,c1
545                 mov     c1,a
546                 clr     a
547                 addc    a,b
548                 mov     c2,a
549
550
551                 mov     b,a0
552                 movx    a,@r0           ; b1
553                 mul     ab              ; a0 * b1
554                 add     a,c1
555                 mov     c1,a
556                 mov     a,b
557                 addc    a,c2
558                 mov     c2,a
559                 clr     a
560                 rlc     a
561                 mov     c3,a
562
563                                         ;       Byte 2
564                 mov     a,a2
565                 mov     b,b0
566                 mul     ab              ; a2 * b0
567                 add     a,c2
568                 mov     c2,a
569                 mov     a,b
570                 addc    a,c3
571                 mov     c3,a
572
573                 mov     b,a1
574                 movx    a,@r0           ; b1
575                 mul     ab              ; a1 * b1
576                 add     a,c2
577                 mov     c2,a
578                 mov     a,b
579                 addc    a,c3
580                 mov     c3,a
581
582                 mov     b,a0
583                 inc     r0
584                 movx    a,@r0           ; b2
585                 mul     ab              ; a0 * b2
586                 add     a,c2
587                 mov     c2,a
588                 mov     a,b
589                 addc    a,c3
590                 mov     c3,a
591
592                                         ;       Byte 3
593                 mov     a,a3
594                 mov     b,b0
595                 mul     ab              ; a3 * b0
596                 add     a,c3
597                 mov     c3,a
598
599                 mov     b,a1
600                 movx    a,@r0           ; b2
601                 mul     ab              ; a1 * b2
602                 add     a,c3
603                 mov     c3,a
604
605                 mov     b,a2
606                 dec     r0
607                 movx    a,@r0           ; b1
608                 mul     ab              ; a2 * b1
609                 add     a,c3
610                 mov     c3,a
611
612                 mov     b,a0
613                 inc     r0
614                 inc     r0
615                 movx    a,@r0           ; b3
616                 mul     ab              ; a0 * b3
617                 add     a,c3
618
619                 mov     b,c2
620                 mov     dph,c1
621                 mov     dpl,c0
622
623                 ret
624
625         _endasm ;
626 }
627
628 #else // _MULLONG_ASM
629
630 struct some_struct {
631         short a ;
632         char b;
633         long c ;};
634 #if defined(SDCC_hc08)
635 /* big endian order */
636 union bil {
637         struct {unsigned char b3,b2,b1,b0 ;} b;
638         struct {unsigned short hi,lo ;} i;
639         unsigned long l;
640         struct { unsigned char b3; unsigned short i12; unsigned char b0;} bi;
641 } ;
642 #else
643 /* little endian order */
644 union bil {
645         struct {unsigned char b0,b1,b2,b3 ;} b;
646         struct {unsigned short lo,hi ;} i;
647         unsigned long l;
648         struct { unsigned char b0; unsigned short i12; unsigned char b3;} bi;
649 } ;
650 #endif
651
652 #if defined(SDCC_USE_XSTACK) || defined(SDCC_MODEL_MEDIUM)
653 #  define bcast(x) ((union bil pdata *)&(x))
654 #elif (defined(SDCC_MODEL_LARGE) || defined (SDCC_ds390) || defined (SDCC_ds400)) && !defined(SDCC_STACK_AUTO)
655 #  define bcast(x) ((union bil xdata *)&(x))
656 #elif defined(__z80) || defined(__gbz80)
657 #  define bcast(x) ((union bil *)&(x))
658 #else
659 #  define bcast(x) ((union bil near  *)&(x))
660 #endif
661
662 /*
663                      3   2   1   0
664        X             3   2   1   0
665        ----------------------------
666                    0.3 0.2 0.1 0.0
667                1.3 1.2 1.1 1.0
668            2.3 2.2 2.1 2.0
669        3.3 3.2 3.1 3.0
670        ----------------------------
671                   |3.3|1.3|0.2|0.0|   A
672                     |2.3|0.3|0.1|     B
673                     |3.2|1.2|1.0|     C
674                       |2.2|1.1|       D
675                       |3.1|2.0|       E
676                         |2.1|         F
677                         |3.0|         G
678                           |-------> only this side 32 x 32 -> 32
679 */
680 #if defined(SDCC_USE_XSTACK)
681 // currently the original code without u fails with --xstack
682 // it runs out of pointer registers
683 long
684 _mullong (long a, long b)
685 {
686         union bil t, u;
687
688         t.i.hi   = bcast(a)->b.b0 * bcast(b)->b.b2;          // A
689         t.i.lo   = bcast(a)->b.b0 * bcast(b)->b.b0;          // A
690         u.bi.b3  = bcast(a)->b.b0 * bcast(b)->b.b3;          // B
691         u.bi.i12 = bcast(a)->b.b0 * bcast(b)->b.b1;          // B
692         u.bi.b0  = 0;                                        // B
693         t.l += u.l;
694
695         t.b.b3  += bcast(a)->b.b3 * bcast(b)->b.b0;          // G
696         t.b.b3  += bcast(a)->b.b2 * bcast(b)->b.b1;          // F
697         t.i.hi  += bcast(a)->b.b2 * bcast(b)->b.b0;          // E
698         t.i.hi  += bcast(a)->b.b1 * bcast(b)->b.b1;          // D
699
700         u.bi.b3  = bcast(a)->b.b1 * bcast(b)->b.b2;          // C
701         u.bi.i12 = bcast(a)->b.b1 * bcast(b)->b.b0;          // C
702         u.bi.b0  = 0;                                        // C
703         t.l += u.l;
704
705         return t.l;
706 }
707 #else
708 long
709 _mullong (long a, long b)
710 {
711         union bil t;
712
713         t.i.hi = bcast(a)->b.b0 * bcast(b)->b.b2;           // A
714         t.i.lo = bcast(a)->b.b0 * bcast(b)->b.b0;           // A
715         t.b.b3 += bcast(a)->b.b3 * bcast(b)->b.b0;          // G
716         t.b.b3 += bcast(a)->b.b2 * bcast(b)->b.b1;          // F
717         t.i.hi += bcast(a)->b.b2 * bcast(b)->b.b0;          // E <- b lost in .lst
718         // bcast(a)->i.hi is free !
719         t.i.hi += bcast(a)->b.b1 * bcast(b)->b.b1;          // D <- b lost in .lst
720
721         bcast(a)->bi.b3 = bcast(a)->b.b1 * bcast(b)->b.b2;  // C
722         bcast(a)->bi.i12 = bcast(a)->b.b1 * bcast(b)->b.b0; // C
723
724         bcast(b)->bi.b3 = bcast(a)->b.b0 * bcast(b)->b.b3;  // B
725         bcast(b)->bi.i12 = bcast(a)->b.b0 * bcast(b)->b.b1; // B
726
727         bcast(b)->bi.b0 = 0;                                // B
728         bcast(a)->bi.b0 = 0;                                // C
729         t.l += a;
730
731         return t.l + b;
732 }
733 #endif
734
735 #endif // _MULLONG_ASM