* as/mcs51/lkarea.c: removed old K&R style,
[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 #else // _MULLONG_ASM
494
495 struct some_struct {
496         short a ;
497         char b;
498         long c ;};
499 #if defined(SDCC_hc08)
500 /* big endian order */
501 union bil {
502         struct {unsigned char b3,b2,b1,b0 ;} b;
503         struct {unsigned short hi,lo ;} i;
504         unsigned long l;
505         struct { unsigned char b3; unsigned short i12; unsigned char b0;} bi;
506 } ;
507 #else
508 /* little endian order */
509 union bil {
510         struct {unsigned char b0,b1,b2,b3 ;} b;
511         struct {unsigned short lo,hi ;} i;
512         unsigned long l;
513         struct { unsigned char b0; unsigned short i12; unsigned char b3;} bi;
514 } ;
515 #endif
516
517 #if defined(SDCC_USE_XSTACK)
518 #  define bcast(x) ((union bil pdata *)&(x))
519 #elif (defined(SDCC_MODEL_LARGE) || defined (SDCC_ds390) || defined (SDCC_ds400)) && !defined(SDCC_STACK_AUTO)
520 #  define bcast(x) ((union bil xdata *)&(x))
521 #elif defined(__z80) || defined(__gbz80)
522 #  define bcast(x) ((union bil *)&(x))
523 #else
524 #  define bcast(x) ((union bil near  *)&(x))
525 #endif
526
527 /*
528                      3   2   1   0
529        X             3   2   1   0
530        ----------------------------
531                    0.3 0.2 0.1 0.0
532                1.3 1.2 1.1 1.0
533            2.3 2.2 2.1 2.0
534        3.3 3.2 3.1 3.0
535        ----------------------------
536                   |3.3|1.3|0.2|0.0|   A
537                     |2.3|0.3|0.1|     B
538                     |3.2|1.2|1.0|     C
539                       |2.2|1.1|       D
540                       |3.1|2.0|       E
541                         |2.1|         F
542                         |3.0|         G
543                           |-------> only this side 32 x 32 -> 32
544 */
545 #if defined(SDCC_USE_XSTACK)
546 // currently the original code without u fails with --xstack
547 // it runs out of pointer registers
548 long
549 _mullong (long a, long b)
550 {
551         union bil t, u;
552
553         t.i.hi   = bcast(a)->b.b0 * bcast(b)->b.b2;          // A
554         t.i.lo   = bcast(a)->b.b0 * bcast(b)->b.b0;          // A
555         u.bi.b3  = bcast(a)->b.b0 * bcast(b)->b.b3;          // B
556         u.bi.i12 = bcast(a)->b.b0 * bcast(b)->b.b1;          // B
557         u.bi.b0  = 0;                                        // B
558         t.l += u.l;
559
560         t.b.b3  += bcast(a)->b.b3 * bcast(b)->b.b0;          // G
561         t.b.b3  += bcast(a)->b.b2 * bcast(b)->b.b1;          // F
562         t.i.hi  += bcast(a)->b.b2 * bcast(b)->b.b0;          // E
563         t.i.hi  += bcast(a)->b.b1 * bcast(b)->b.b1;          // D
564
565         u.bi.b3  = bcast(a)->b.b1 * bcast(b)->b.b2;          // C
566         u.bi.i12 = bcast(a)->b.b1 * bcast(b)->b.b0;          // C
567         u.bi.b0  = 0;                                        // C
568         t.l += u.l;
569
570         return t.l;
571 }
572 #else
573 long
574 _mullong (long a, long b)
575 {
576         union bil t;
577
578         t.i.hi = bcast(a)->b.b0 * bcast(b)->b.b2;       // A
579         t.i.lo = bcast(a)->b.b0 * bcast(b)->b.b0;       // A
580         t.b.b3 += bcast(a)->b.b3 *
581                                   bcast(b)->b.b0;       // G
582         t.b.b3 += bcast(a)->b.b2 *
583                                   bcast(b)->b.b1;       // F
584         t.i.hi += bcast(a)->b.b2 * bcast(b)->b.b0;      // E <- b lost in .lst
585         // bcast(a)->i.hi is free !
586         t.i.hi += bcast(a)->b.b1 * bcast(b)->b.b1;      // D <- b lost in .lst
587
588         bcast(a)->bi.b3 = bcast(a)->b.b1 *
589                                           bcast(b)->b.b2;
590         bcast(a)->bi.i12 = bcast(a)->b.b1 *
591                            bcast(b)->b.b0;              // C
592
593         bcast(b)->bi.b3 = bcast(a)->b.b0 *
594                                           bcast(b)->b.b3;
595         bcast(b)->bi.i12 = bcast(a)->b.b0 *
596                            bcast(b)->b.b1;              // B
597         bcast(b)->bi.b0 = 0;                            // B
598         bcast(a)->bi.b0 = 0;                            // C
599         t.l += a;
600
601         return t.l + b;
602 }
603 #endif
604
605 #endif // _MULLONG_ASM