LEFT | RIGHT |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 #undef EXTERN | 5 #undef EXTERN |
6 #define EXTERN | 6 #define EXTERN |
7 #include <u.h> | 7 #include <u.h> |
8 #include <libc.h> | 8 #include <libc.h> |
9 #include "gg.h" | 9 #include "gg.h" |
10 #include "opt.h" | 10 #include "opt.h" |
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 cgen_div(int op, Node *nl, Node *nr, Node *res) | 602 cgen_div(int op, Node *nl, Node *nr, Node *res) |
603 { | 603 { |
604 Node n1, n2, n3; | 604 Node n1, n2, n3; |
605 int w, a; | 605 int w, a; |
606 Magic m; | 606 Magic m; |
607 | 607 |
608 if(nr->op != OLITERAL) | 608 if(nr->op != OLITERAL) |
609 goto longdiv; | 609 goto longdiv; |
610 w = nl->type->width*8; | 610 w = nl->type->width*8; |
611 | 611 |
612 » goto divbymul; | 612 » // Front end handled 32-bit division. We only need to handle 64-bit. |
613 | |
614 divbymul: | |
615 // try to do division by multiply by (2^w)/d | 613 // try to do division by multiply by (2^w)/d |
616 // see hacker's delight chapter 10 | 614 // see hacker's delight chapter 10 |
617 switch(simtype[nl->type->etype]) { | 615 switch(simtype[nl->type->etype]) { |
618 default: | 616 default: |
619 goto longdiv; | 617 goto longdiv; |
620 | 618 |
621 case TUINT8: | |
622 case TUINT16: | |
623 case TUINT32: | |
624 case TUINT64: | 619 case TUINT64: |
625 m.w = w; | 620 m.w = w; |
626 m.ud = mpgetfix(nr->val.u.xval); | 621 m.ud = mpgetfix(nr->val.u.xval); |
627 umagic(&m); | 622 umagic(&m); |
628 if(m.bad) | 623 if(m.bad) |
629 break; | 624 break; |
630 if(op == OMOD) | 625 if(op == OMOD) |
631 goto longmod; | 626 goto longmod; |
632 | 627 |
633 cgenr(nl, &n1, N); | 628 cgenr(nl, &n1, N); |
634 » » nodconst(&n2, nl->type, m.sm); | 629 » » nodconst(&n2, nl->type, m.um); |
635 regalloc(&n3, nl->type, res); | 630 regalloc(&n3, nl->type, res); |
636 cgen_hmul(&n1, &n2, &n3); | 631 cgen_hmul(&n1, &n2, &n3); |
637 | 632 |
638 if(m.ua) { | 633 if(m.ua) { |
639 // need to add numerator accounting for overflow | 634 // need to add numerator accounting for overflow |
640 gins(optoas(OADD, nl->type), &n1, &n3); | 635 gins(optoas(OADD, nl->type), &n1, &n3); |
641 nodconst(&n2, nl->type, 1); | 636 nodconst(&n2, nl->type, 1); |
642 gins(optoas(ORROTC, nl->type), &n2, &n3); | 637 gins(optoas(ORROTC, nl->type), &n2, &n3); |
643 nodconst(&n2, nl->type, m.s-1); | 638 nodconst(&n2, nl->type, m.s-1); |
644 gins(optoas(ORSH, nl->type), &n2, &n3); | 639 gins(optoas(ORSH, nl->type), &n2, &n3); |
645 } else { | 640 } else { |
646 nodconst(&n2, nl->type, m.s); | 641 nodconst(&n2, nl->type, m.s); |
647 gins(optoas(ORSH, nl->type), &n2, &n3); // shift dx | 642 gins(optoas(ORSH, nl->type), &n2, &n3); // shift dx |
648 } | 643 } |
649 | 644 |
650 gmove(&n3, res); | 645 gmove(&n3, res); |
651 regfree(&n1); | 646 regfree(&n1); |
652 regfree(&n3); | 647 regfree(&n3); |
653 return; | 648 return; |
654 | 649 |
655 case TINT8: | |
656 case TINT16: | |
657 case TINT32: | |
658 case TINT64: | 650 case TINT64: |
659 m.w = w; | 651 m.w = w; |
660 m.sd = mpgetfix(nr->val.u.xval); | 652 m.sd = mpgetfix(nr->val.u.xval); |
661 smagic(&m); | 653 smagic(&m); |
662 if(m.bad) | 654 if(m.bad) |
663 break; | 655 break; |
664 if(op == OMOD) | 656 if(op == OMOD) |
665 goto longmod; | 657 goto longmod; |
666 | 658 |
667 cgenr(nl, &n1, res); | 659 cgenr(nl, &n1, res); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
747 cgenr(nr, &n2, N); | 739 cgenr(nr, &n2, N); |
748 nodreg(&ax, t, D_AX); | 740 nodreg(&ax, t, D_AX); |
749 gmove(&n1, &ax); | 741 gmove(&n1, &ax); |
750 gins(a, &n2, N); | 742 gins(a, &n2, N); |
751 regfree(&n2); | 743 regfree(&n2); |
752 regfree(&n1); | 744 regfree(&n1); |
753 | 745 |
754 if(t->width == 1) { | 746 if(t->width == 1) { |
755 // byte multiply behaves differently. | 747 // byte multiply behaves differently. |
756 nodreg(&ax, t, D_AH); | 748 nodreg(&ax, t, D_AH); |
757 » » gmove(&ax, res); | 749 » » nodreg(&dx, t, D_DL); |
758 » » return; | 750 » » gmove(&ax, &dx); |
759 } | 751 } |
760 nodreg(&dx, t, D_DX); | 752 nodreg(&dx, t, D_DX); |
761 gmove(&dx, res); | 753 gmove(&dx, res); |
762 } | 754 } |
763 | 755 |
764 /* | 756 /* |
765 * generate shift according to op, one of: | 757 * generate shift according to op, one of: |
766 * res = nl << nr | 758 * res = nl << nr |
767 * res = nl >> nr | 759 * res = nl >> nr |
768 */ | 760 */ |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 gins(ASTOSB, N, N); // STOB AL,*(DI)+ | 946 gins(ASTOSB, N, N); // STOB AL,*(DI)+ |
955 } else | 947 } else |
956 while(c > 0) { | 948 while(c > 0) { |
957 gins(ASTOSB, N, N); // STOB AL,*(DI)+ | 949 gins(ASTOSB, N, N); // STOB AL,*(DI)+ |
958 c--; | 950 c--; |
959 } | 951 } |
960 | 952 |
961 restx(&n1, &oldn1); | 953 restx(&n1, &oldn1); |
962 restx(&ax, &oldax); | 954 restx(&ax, &oldax); |
963 } | 955 } |
LEFT | RIGHT |