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