Hackfix and re-enable strtoull and wcstoull, see bug #3798.
[sdcc.git] / sdcc / device / lib / _mullong.c
blobc73f9d56c4c00b38c001e07e04332e3313a4cbf5
1 /*-------------------------------------------------------------------------
2 _mullong.c - routine for multiplication of 32 bit (unsigned) long
4 Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net
5 Copyright (C) 1999, Jean Louis VERN jlvern@writeme.com
7 This library is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
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 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this library; see the file COPYING. If not, write to the
19 Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
20 MA 02110-1301, USA.
22 As a special exception, if you link this library with other files,
23 some of which are compiled with SDCC, to produce an executable,
24 this library does not by itself cause the resulting executable to
25 be covered by the GNU General Public License. This exception does
26 not however invalidate any other reasons why the executable file
27 might be covered by the GNU General Public License.
28 -------------------------------------------------------------------------*/
30 /* Signed and unsigned multiplication are the same - as long as the output
31 has the same precision as the input.
33 Assembler-functions are provided for:
34 mcs51 small
35 mcs51 small stack-auto
38 #include <sdcc-lib.h>
40 #if !defined(__SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
41 # if defined(__SDCC_mcs51)
42 # if defined(__SDCC_MODEL_SMALL)
43 # if defined(__SDCC_STACK_AUTO) && !defined(__SDCC_PARMS_IN_BANK1)
44 # define _MULLONG_ASM_SMALL_AUTO
45 # else
46 # define _MULLONG_ASM_SMALL
47 # endif
48 # elif defined(__SDCC_MODEL_LARGE)
49 # if !defined(__SDCC_STACK_AUTO)
50 # define _MULLONG_ASM_LARGE
51 # endif
52 # endif
53 # endif
54 #endif
56 #if defined(_MULLONG_ASM_SMALL) || defined(_MULLONG_ASM_SMALL_AUTO)
58 void
59 _mullong_dummy (void) __naked
61 __asm
63 __mullong:
65 .globl __mullong
67 ; the result c will be stored in r4...r7
68 #define c0 r4
69 #define c1 r5
70 #define c2 r6
71 #define c3 r7
73 #define a0 dpl
74 #define a1 dph
75 #define a2 r2
76 #define a3 r3
78 ; c0 a0 * b0
79 ; c1 a1 * b0 + a0 * b1
80 ; c2 a2 * b0 + a1 * b1 + a0 * b2
81 ; c3 a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
83 #if !defined(__SDCC_STACK_AUTO) || defined(__SDCC_PARMS_IN_BANK1)
84 #if defined(__SDCC_PARMS_IN_BANK1)
85 #define b0 (b1_0)
86 #define b1 (b1_1)
87 #define b2 (b1_2)
88 #define b3 (b1_3)
89 #else
90 #if defined(__SDCC_NOOVERLAY)
91 .area DSEG (DATA)
92 #else
93 .area OSEG (OVR,DATA)
94 #endif
96 __mullong_PARM_2:
98 .globl __mullong_PARM_2
100 .ds 4
102 b0 = __mullong_PARM_2
103 b1 = (__mullong_PARM_2+1)
104 b2 = (__mullong_PARM_2+2)
105 b3 = (__mullong_PARM_2+3)
107 #endif
108 .area CSEG (CODE)
110 ; parameter a comes in a, b, dph, dpl
111 mov r2,b ; save parameter a
112 mov r3,a
114 ; Byte 0
115 mov a,a0
116 mov b,b0
117 mul ab ; a0 * b0
118 mov c0,a
119 mov c1,b
121 ; Byte 1
122 mov a,a1
123 mov b,b0
124 mul ab ; a1 * b0
125 add a,c1
126 mov c1,a
127 clr a
128 addc a,b
129 mov c2,a
131 mov a,a0
132 mov b,b1
133 mul ab ; a0 * b1
134 add a,c1
135 mov c1,a
136 mov a,b
137 addc a,c2
138 mov c2,a
139 clr a
140 rlc a
141 mov c3,a
143 ; Byte 2
144 mov a,a2
145 mov b,b0
146 mul ab ; a2 * b0
147 add a,c2
148 mov c2,a
149 mov a,b
150 addc a,c3
151 mov c3,a
153 mov a,a1
154 mov b,b1
155 mul ab ; a1 * b1
156 add a,c2
157 mov c2,a
158 mov a,b
159 addc a,c3
160 mov c3,a
162 mov a,a0
163 mov b,b2
164 mul ab ; a0 * b2
165 add a,c2
166 mov c2,a
167 mov a,b
168 addc a,c3
169 mov c3,a
171 ; Byte 3
172 mov a,a3
173 mov b,b0
174 mul ab ; a3 * b0
175 add a,c3
176 mov c3,a
178 mov a,a2
179 mov b,b1
180 mul ab ; a2 * b1
181 add a,c3
182 mov c3,a
184 mov a,a1
185 mov b,b2
186 mul ab ; a1 * b2
187 add a,c3
188 mov c3,a
190 mov a,a0
191 mov b,b3
192 mul ab ; a0 * b3
193 add a,c3
195 mov b,c2
196 mov dph,c1
197 mov dpl,c0
200 #else // __SDCC_STACK_AUTO
202 ; parameter a comes in a, b, dph, dpl
203 mov r2,b ; save parameter a
204 mov r3,a
206 #define a0 dpl
207 #define a1 dph
208 #define a2 r2
209 #define a3 r3
211 #define b0 r1
213 mov a,#-2-3 ; 1 return address 2 bytes, b 4 bytes
214 add a,sp ; 1
215 mov r0,a ; 1 r0 points to b0
217 ; Byte 0
218 mov a,a0
219 mov b,@r0 ; b0
220 mov b0,b ; we need b0 several times
221 inc r0 ; r0 points to b1
222 mul ab ; a0 * b0
223 mov c0,a
224 mov c1,b
226 ; Byte 1
227 mov a,a1
228 mov b,b0
229 mul ab ; a1 * b0
230 add a,c1
231 mov c1,a
232 clr a
233 addc a,b
234 mov c2,a
236 mov a,a0
237 mov b,@r0 ; b1
238 mul ab ; a0 * b1
239 add a,c1
240 mov c1,a
241 mov a,b
242 addc a,c2
243 mov c2,a
244 clr a
245 rlc a
246 mov c3,a
248 ; Byte 2
249 mov a,a2
250 mov b,b0
251 mul ab ; a2 * b0
252 add a,c2
253 mov c2,a
254 mov a,b
255 addc a,c3
256 mov c3,a
258 mov a,a1
259 mov b,@r0 ; b1
260 mul ab ; a1 * b1
261 add a,c2
262 mov c2,a
263 mov a,b
264 addc a,c3
265 mov c3,a
267 mov a,a0
268 inc r0
269 mov b,@r0 ; b2
270 mul ab ; a0 * b2
271 add a,c2
272 mov c2,a
273 mov a,b
274 addc a,c3
275 mov c3,a
277 ; Byte 3
278 mov a,a3
279 mov b,b0
280 mul ab ; a3 * b0
281 add a,c3
282 mov c3,a
284 mov a,a1
285 mov b,@r0 ; b2
286 mul ab ; a1 * b2
287 add a,c3
288 mov c3,a
290 mov a,a2
291 dec r0
292 mov b,@r0 ; b1
293 mul ab ; a2 * b1
294 add a,c3
295 mov c3,a
297 mov a,a0
298 inc r0
299 inc r0
300 mov b,@r0 ; b3
301 mul ab ; a0 * b3
302 add a,c3
304 mov b,c2
305 mov dph,c1
306 mov dpl,c0
310 #endif // __SDCC_STACK_AUTO
312 __endasm;
315 #elif defined(_MULLONG_ASM_LARGE)
317 void
318 _mullong_dummy (void) __naked
320 __asm
322 __mullong:
324 .globl __mullong
326 ; the result c will be stored in r4...r7
327 #define c0 r4
328 #define c1 r5
329 #define c2 r6
330 #define c3 r7
332 ; c0 a0 * b0
333 ; c1 a1 * b0 + a0 * b1
334 ; c2 a2 * b0 + a1 * b1 + a0 * b2
335 ; c3 a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
337 #if !defined(__SDCC_PARMS_IN_BANK1)
338 .area XSEG (XDATA)
340 __mullong_PARM_2:
342 .globl __mullong_PARM_2
344 .ds 4
345 #endif
346 .area CSEG (CODE)
348 ; parameter a comes in a, b, dph, dpl
349 mov r0,dpl ; save parameter a
350 mov r1,dph
351 mov r2,b
352 mov r3,a
354 #define a0 r0
355 #define a1 r1
356 #define a2 r2
357 #define a3 r3
359 ; Byte 0
360 mov b,a0
361 #if defined(__SDCC_PARMS_IN_BANK1)
362 mov a,b1_0 ; b0
363 #else
364 mov dptr,#__mullong_PARM_2
365 movx a,@dptr ; b0
366 #endif
367 mul ab ; a0 * b0
368 mov c0,a
369 mov c1,b
371 ; Byte 1
372 mov b,a1
373 #if defined(__SDCC_PARMS_IN_BANK1)
374 mov a,b1_0 ; b0
375 #else
376 movx a,@dptr ; b0
377 #endif
378 mul ab ; a1 * b0
379 add a,c1
380 mov c1,a
381 clr a
382 addc a,b
383 mov c2,a
385 mov b,a0
386 #if defined(__SDCC_PARMS_IN_BANK1)
387 mov a,b1_1 ; b1
388 #else
389 inc dptr ; b1
390 movx a,@dptr
391 #endif
392 mul ab ; a0 * b1
393 add a,c1
394 mov c1,a
395 mov a,b
396 addc a,c2
397 mov c2,a
398 clr a
399 rlc a
400 mov c3,a
402 ; Byte 2
403 mov b,a1
404 #if defined(__SDCC_PARMS_IN_BANK1)
405 mov a,b1_1 ; b1
406 #else
407 movx a,@dptr ; b1
408 #endif
409 mul ab ; a1 * b1
410 add a,c2
411 mov c2,a
412 mov a,b
413 addc a,c3
414 mov c3,a
416 mov b,a0
417 #if defined(__SDCC_PARMS_IN_BANK1)
418 mov a,b1_2 ; b2
419 #else
420 inc dptr ; b2
421 movx a,@dptr
422 #endif
423 mul ab ; a0 * b2
424 add a,c2
425 mov c2,a
426 mov a,b
427 addc a,c3
428 mov c3,a
430 mov b,a2
431 #if defined(__SDCC_PARMS_IN_BANK1)
432 mov a,b1_0 ; b0
433 #else
434 mov dptr,#__mullong_PARM_2
435 movx a,@dptr ; b0
436 #endif
437 mul ab ; a2 * b0
438 add a,c2
439 mov c2,a
440 mov a,b
441 addc a,c3
442 mov c3,a
444 ; Byte 3
445 mov b,a3
446 #if defined(__SDCC_PARMS_IN_BANK1)
447 mov a,b1_0 ; b0
448 #else
449 movx a,@dptr ; b0
450 #endif
451 mul ab ; a3 * b0
452 add a,c3
453 mov c3,a
455 mov b,a2
456 #if defined(__SDCC_PARMS_IN_BANK1)
457 mov a,b1_1 ; b1
458 #else
459 inc dptr ; b1
460 movx a,@dptr
461 #endif
462 mul ab ; a2 * b1
463 add a,c3
464 mov c3,a
466 mov b,a1
467 #if defined(__SDCC_PARMS_IN_BANK1)
468 mov a,b1_2 ; b2
469 #else
470 inc dptr ; b2
471 movx a,@dptr
472 #endif
473 mul ab ; a1 * b2
474 add a,c3
475 mov c3,a
477 mov b,a0
478 #if defined(__SDCC_PARMS_IN_BANK1)
479 mov a,b1_3 ; b3
480 #else
481 inc dptr ; b3
482 movx a,@dptr
483 #endif
484 mul ab ; a0 * b3
485 add a,c3
487 mov b,c2
488 mov dph,c1
489 mov dpl,c0
492 __endasm;
495 #elif defined(__SDCC_USE_XSTACK) && defined(__SDCC_STACK_AUTO)
497 void
498 _mullong_dummy (void) __naked
500 __asm
502 __mullong:
504 .globl __mullong
506 ; the result c will be stored in r4...r7
507 #define c0 r4
508 #define c1 r5
509 #define c2 r6
510 #define c3 r7
512 #define a0 dpl
513 #define a1 dph
514 #define a2 r2
515 #define a3 r3
517 #define b0 r1
519 ; c0 a0 * b0
520 ; c1 a1 * b0 + a0 * b1
521 ; c2 a2 * b0 + a1 * b1 + a0 * b2
522 ; c3 a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3
524 ; parameter a comes in a, b, dph, dpl
525 mov r2,b ; save parameter a
526 mov r3,a
528 mov a,#-4 ; 1 b 4 bytes
529 add a,_spx ; 1
530 mov r0,a ; 1 r0 points to b0
532 ; Byte 0
533 movx a,@r0 ; b0
534 mov b0,a ; we need b0 several times
535 inc r0 ; r0 points to b1
536 mov b,a0
537 mul ab ; a0 * b0
538 mov c0,a
539 mov c1,b
541 ; Byte 1
542 mov a,a1
543 mov b,b0
544 mul ab ; a1 * b0
545 add a,c1
546 mov c1,a
547 clr a
548 addc a,b
549 mov c2,a
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
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
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
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
592 ; Byte 3
593 mov a,a3
594 mov b,b0
595 mul ab ; a3 * b0
596 add a,c3
597 mov c3,a
599 mov b,a1
600 movx a,@r0 ; b2
601 mul ab ; a1 * b2
602 add a,c3
603 mov c3,a
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
612 mov b,a0
613 inc r0
614 inc r0
615 movx a,@r0 ; b3
616 mul ab ; a0 * b3
617 add a,c3
619 mov b,c2
620 mov dph,c1
621 mov dpl,c0
625 __endasm;
628 #else // _MULLONG_ASM
630 struct some_struct {
631 short a ;
632 char b;
633 long c ;};
635 #include <stdbit.h>
637 #if __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_BIG__
638 union bil {
639 struct {unsigned char b3,b2,b1,b0 ;} b;
640 struct {unsigned short hi,lo ;} i;
641 unsigned long l;
642 struct { unsigned char b3; unsigned short i12; unsigned char b0;} bi;
644 #else
645 union bil {
646 struct {unsigned char b0,b1,b2,b3 ;} b;
647 struct {unsigned short lo,hi ;} i;
648 unsigned long l;
649 struct { unsigned char b0; unsigned short i12; unsigned char b3;} bi;
651 #endif
653 #if defined(__SDCC)
654 #include <sdcc-lib.h>
655 #endif
657 #define bcast(x) ((union bil _AUTOMEM *)&(x))
660 3 2 1 0
661 X 3 2 1 0
662 ----------------------------
663 0.3 0.2 0.1 0.0
664 1.3 1.2 1.1 1.0
665 2.3 2.2 2.1 2.0
666 3.3 3.2 3.1 3.0
667 ----------------------------
668 |3.3|1.3|0.2|0.0| A
669 |2.3|0.3|0.1| B
670 |3.2|1.2|1.0| C
671 |2.2|1.1| D
672 |3.1|2.0| E
673 |2.1| F
674 |3.0| G
675 |-------> only this side 32 x 32 -> 32
677 #if defined(__SDCC_USE_XSTACK)
678 // currently the original code without u fails with --xstack
679 // it runs out of pointer registers
680 long
681 _mullong (long a, long b)
683 union bil t, u;
685 t.i.hi = bcast(a)->b.b0 * bcast(b)->b.b2; // A
686 t.i.lo = bcast(a)->b.b0 * bcast(b)->b.b0; // A
687 u.bi.b3 = bcast(a)->b.b0 * bcast(b)->b.b3; // B
688 u.bi.i12 = bcast(a)->b.b0 * bcast(b)->b.b1; // B
689 u.bi.b0 = 0; // B
690 t.l += u.l;
692 t.b.b3 += bcast(a)->b.b3 * bcast(b)->b.b0; // G
693 t.b.b3 += bcast(a)->b.b2 * bcast(b)->b.b1; // F
694 t.i.hi += bcast(a)->b.b2 * bcast(b)->b.b0; // E
695 t.i.hi += bcast(a)->b.b1 * bcast(b)->b.b1; // D
697 u.bi.b3 = bcast(a)->b.b1 * bcast(b)->b.b2; // C
698 u.bi.i12 = bcast(a)->b.b1 * bcast(b)->b.b0; // C
699 u.bi.b0 = 0; // C
700 t.l += u.l;
702 return t.l;
704 #elif defined(__SDCC_z80) || defined(__SDCC_sm83) || defined(__SDCC_r2ka) || defined(__SDCC_r3k) || defined(__SDCC_r3ka)
705 /* 32x32->32 multiplication to be used
706 if 16x16->16 is faster than three 8x8->16.
707 2009, by M.Bodrato ( http://bodrato.it/ )
709 z80 and sm83 don't have any hardware multiplication, not even 8x8.
710 software 16x16 is neqrly as efficient as software 8x8 there.
711 r2k(a) and r3k(a) have 16x16 hardware multiplication,
712 but on r2k it is affected by a hardware bug, and not used by sdcc.
714 long
715 _mullong (long a, long b)
717 unsigned short i12;
719 bcast(a)->i.hi *= bcast(b)->i.lo;
720 bcast(a)->i.hi += bcast(b)->i.hi * bcast(a)->i.lo;
722 /* only (a->i.lo * b->i.lo) 16x16->32 to do. asm? */
723 bcast(a)->i.hi += bcast(a)->b.b1 * bcast(b)->b.b1;
725 i12 = bcast(b)->b.b0 * bcast(a)->b.b1;
726 bcast(b)->bi.i12 = bcast(a)->b.b0 * bcast(b)->b.b1;
728 /* add up the two partial result, store carry in b3 */
729 bcast(b)->b.b3 = ((bcast(b)->bi.i12 += i12) < i12);
731 bcast(a)->i.lo = bcast(a)->b.b0 * bcast(b)->b.b0;
733 bcast(b)->bi.b0 = 0;
735 return a + b;
737 #else
738 long
739 _mullong (long a, long b) __SDCC_NONBANKED
741 union bil t;
743 t.i.hi = bcast(a)->b.b0 * bcast(b)->b.b2; // A
744 t.i.lo = bcast(a)->b.b0 * bcast(b)->b.b0; // A
745 t.b.b3 += bcast(a)->b.b3 * bcast(b)->b.b0; // G
746 t.b.b3 += bcast(a)->b.b2 * bcast(b)->b.b1; // F
747 t.i.hi += bcast(a)->b.b2 * bcast(b)->b.b0; // E <- b lost in .lst
748 // bcast(a)->i.hi is free !
749 t.i.hi += bcast(a)->b.b1 * bcast(b)->b.b1; // D <- b lost in .lst
751 bcast(a)->bi.b3 = bcast(a)->b.b1 * bcast(b)->b.b2; // C
752 bcast(a)->bi.i12 = bcast(a)->b.b1 * bcast(b)->b.b0; // C
754 bcast(b)->bi.b3 = bcast(a)->b.b0 * bcast(b)->b.b3; // B
755 bcast(b)->bi.i12 = bcast(a)->b.b0 * bcast(b)->b.b1; // B
757 bcast(b)->bi.b0 = 0; // B
758 bcast(a)->bi.b0 = 0; // C
759 t.l += a;
761 return t.l + b;
763 #endif
765 #endif // _MULLONG_ASM