Left: | ||
Right: |
OLD | NEW |
---|---|
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 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
594 } | 594 } |
595 | 595 |
596 /* | 596 /* |
597 * generate division according to op, one of: | 597 * generate division according to op, one of: |
598 * res = nl / nr | 598 * res = nl / nr |
599 * res = nl % nr | 599 * res = nl % nr |
600 */ | 600 */ |
601 void | 601 void |
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, savl, savr; | 604 » Node n1, n2, n3; |
605 » Node ax, dx, oldax, olddx; | 605 » int w, a; |
606 » int n, w, s, a; | |
607 Magic m; | 606 Magic m; |
608 | 607 |
609 if(nl->ullman >= UINF) { | |
610 tempname(&savl, nl->type); | |
611 cgen(nl, &savl); | |
612 nl = &savl; | |
613 } | |
614 if(nr->ullman >= UINF) { | |
615 tempname(&savr, nr->type); | |
616 cgen(nr, &savr); | |
617 nr = &savr; | |
618 } | |
619 | |
620 if(nr->op != OLITERAL) | 608 if(nr->op != OLITERAL) |
621 goto longdiv; | 609 goto longdiv; |
610 w = nl->type->width*8; | |
622 | 611 |
623 » // special cases of mod/div | 612 » goto divbymul; |
rsc
2012/11/26 16:28:34
Can delete this goto and the label.
remyoudompheng
2012/11/26 21:18:55
Done.
| |
624 » // by a constant | |
625 » w = nl->type->width*8; | |
626 » s = 0; | |
627 » n = powtwo(nr); | |
628 » if(n >= 1000) { | |
629 » » // negative power of 2 | |
630 » » s = 1; | |
631 » » n -= 1000; | |
632 » } | |
633 | |
634 » if(n+1 >= w) { | |
635 » » // just sign bit | |
636 » » goto longdiv; | |
637 » } | |
638 | |
639 » if(n < 0) | |
640 » » goto divbymul; | |
641 » switch(n) { | |
642 » case 0: | |
643 » » // divide by 1 | |
644 » » regalloc(&n1, nl->type, res); | |
645 » » cgen(nl, &n1); | |
646 » » if(op == OMOD) { | |
647 » » » gins(optoas(OXOR, nl->type), &n1, &n1); | |
648 » » } else | |
649 » » if(s) | |
650 » » » gins(optoas(OMINUS, nl->type), N, &n1); | |
651 » » gmove(&n1, res); | |
652 » » regfree(&n1); | |
653 » » return; | |
654 » case 1: | |
655 » » // divide by 2 | |
656 » » if(op == OMOD) { | |
657 » » » if(issigned[nl->type->etype]) | |
658 » » » » goto longmod; | |
659 » » » regalloc(&n1, nl->type, res); | |
660 » » » cgen(nl, &n1); | |
661 » » » nodconst(&n2, nl->type, 1); | |
662 » » » gins(optoas(OAND, nl->type), &n2, &n1); | |
663 » » » gmove(&n1, res); | |
664 » » » regfree(&n1); | |
665 » » » return; | |
666 » » } | |
667 » » regalloc(&n1, nl->type, res); | |
668 » » cgen(nl, &n1); | |
669 » » if(!issigned[nl->type->etype]) | |
670 » » » break; | |
671 | |
672 » » // develop -1 iff nl is negative | |
673 » » regalloc(&n2, nl->type, N); | |
674 » » gmove(&n1, &n2); | |
675 » » nodconst(&n3, nl->type, w-1); | |
676 » » gins(optoas(ORSH, nl->type), &n3, &n2); | |
677 » » gins(optoas(OSUB, nl->type), &n2, &n1); | |
678 » » regfree(&n2); | |
679 » » break; | |
680 » default: | |
681 » » if(op == OMOD) { | |
682 » » » if(issigned[nl->type->etype]) | |
683 » » » » goto longmod; | |
684 » » » regalloc(&n1, nl->type, res); | |
685 » » » cgen(nl, &n1); | |
686 » » » nodconst(&n2, nl->type, mpgetfix(nr->val.u.xval)-1); | |
687 » » » if(!smallintconst(&n2)) { | |
688 » » » » regalloc(&n3, nl->type, N); | |
689 » » » » gmove(&n2, &n3); | |
690 » » » » gins(optoas(OAND, nl->type), &n3, &n1); | |
691 » » » » regfree(&n3); | |
692 » » » } else | |
693 » » » » gins(optoas(OAND, nl->type), &n2, &n1); | |
694 » » » gmove(&n1, res); | |
695 » » » regfree(&n1); | |
696 » » » return; | |
697 » » } | |
698 » » regalloc(&n1, nl->type, res); | |
699 » » cgen(nl, &n1); | |
700 » » if(!issigned[nl->type->etype]) | |
701 » » » break; | |
702 | |
703 » » // develop (2^k)-1 iff nl is negative | |
704 » » regalloc(&n2, nl->type, N); | |
705 » » gmove(&n1, &n2); | |
706 » » nodconst(&n3, nl->type, w-1); | |
707 » » gins(optoas(ORSH, nl->type), &n3, &n2); | |
708 » » nodconst(&n3, nl->type, w-n); | |
709 » » gins(optoas(ORSH, tounsigned(nl->type)), &n3, &n2); | |
710 » » gins(optoas(OADD, nl->type), &n2, &n1); | |
711 » » regfree(&n2); | |
712 » » break; | |
713 » } | |
714 » nodconst(&n2, nl->type, n); | |
715 » gins(optoas(ORSH, nl->type), &n2, &n1); | |
716 » if(s) | |
717 » » gins(optoas(OMINUS, nl->type), N, &n1); | |
718 » gmove(&n1, res); | |
719 » regfree(&n1); | |
720 » return; | |
721 | 613 |
722 divbymul: | 614 divbymul: |
rsc
2012/11/26 16:28:34
// Front end handled 32-bit division. We only need
remyoudompheng
2012/11/26 21:18:55
Done.
| |
723 // try to do division by multiply by (2^w)/d | 615 // try to do division by multiply by (2^w)/d |
724 // see hacker's delight chapter 10 | 616 // see hacker's delight chapter 10 |
725 switch(simtype[nl->type->etype]) { | 617 switch(simtype[nl->type->etype]) { |
726 default: | 618 default: |
727 goto longdiv; | 619 goto longdiv; |
728 | 620 |
729 case TUINT8: | 621 case TUINT8: |
rsc
2012/11/26 16:28:34
delete these cases, leaving only TUINT64.
remyoudompheng
2012/11/26 21:18:55
Done.
| |
730 case TUINT16: | 622 case TUINT16: |
731 case TUINT32: | 623 case TUINT32: |
732 case TUINT64: | 624 case TUINT64: |
733 m.w = w; | 625 m.w = w; |
734 m.ud = mpgetfix(nr->val.u.xval); | 626 m.ud = mpgetfix(nr->val.u.xval); |
735 umagic(&m); | 627 umagic(&m); |
736 if(m.bad) | 628 if(m.bad) |
737 break; | 629 break; |
738 if(op == OMOD) | 630 if(op == OMOD) |
739 goto longmod; | 631 goto longmod; |
740 | 632 |
741 » » regalloc(&n1, nl->type, N); | 633 » » cgenr(nl, &n1, N); |
742 » » cgen(nl, &n1);» » » » // num -> reg(n1) | |
743 | |
744 » » savex(D_AX, &ax, &oldax, res, nl->type); | |
745 » » savex(D_DX, &dx, &olddx, res, nl->type); | |
746 | |
747 nodconst(&n2, nl->type, m.um); | 634 nodconst(&n2, nl->type, m.um); |
748 » » gmove(&n2, &ax);» » » // const->ax | 635 » » regalloc(&n3, nl->type, res); |
749 | 636 » » cgen_hmul(&n1, &n2, &n3); |
750 » » gins(optoas(OHMUL, nl->type), &n1, N);» // imul reg | |
751 » » if(w == 8) { | |
752 » » » // fix up 8-bit multiply | |
753 » » » Node ah, dl; | |
754 » » » nodreg(&ah, types[TUINT8], D_AH); | |
755 » » » nodreg(&dl, types[TUINT8], D_DL); | |
756 » » » gins(AMOVB, &ah, &dl); | |
757 » » } | |
758 | 637 |
759 if(m.ua) { | 638 if(m.ua) { |
760 // need to add numerator accounting for overflow | 639 // need to add numerator accounting for overflow |
761 » » » gins(optoas(OADD, nl->type), &n1, &dx); | 640 » » » gins(optoas(OADD, nl->type), &n1, &n3); |
762 nodconst(&n2, nl->type, 1); | 641 nodconst(&n2, nl->type, 1); |
763 » » » gins(optoas(ORROTC, nl->type), &n2, &dx); | 642 » » » gins(optoas(ORROTC, nl->type), &n2, &n3); |
764 nodconst(&n2, nl->type, m.s-1); | 643 nodconst(&n2, nl->type, m.s-1); |
765 » » » gins(optoas(ORSH, nl->type), &n2, &dx); | 644 » » » gins(optoas(ORSH, nl->type), &n2, &n3); |
766 } else { | 645 } else { |
767 nodconst(&n2, nl->type, m.s); | 646 nodconst(&n2, nl->type, m.s); |
768 » » » gins(optoas(ORSH, nl->type), &n2, &dx);»// shift dx | 647 » » » gins(optoas(ORSH, nl->type), &n2, &n3);»// shift dx |
769 } | 648 } |
770 | 649 |
771 | 650 » » gmove(&n3, res); |
772 regfree(&n1); | 651 regfree(&n1); |
773 » » gmove(&dx, res); | 652 » » regfree(&n3); |
774 | |
775 » » restx(&ax, &oldax); | |
776 » » restx(&dx, &olddx); | |
777 return; | 653 return; |
778 | 654 |
779 case TINT8: | 655 case TINT8: |
rsc
2012/11/26 16:28:34
same
remyoudompheng
2012/11/26 21:18:55
Done.
| |
780 case TINT16: | 656 case TINT16: |
781 case TINT32: | 657 case TINT32: |
782 case TINT64: | 658 case TINT64: |
783 m.w = w; | 659 m.w = w; |
784 m.sd = mpgetfix(nr->val.u.xval); | 660 m.sd = mpgetfix(nr->val.u.xval); |
785 smagic(&m); | 661 smagic(&m); |
786 if(m.bad) | 662 if(m.bad) |
787 break; | 663 break; |
788 if(op == OMOD) | 664 if(op == OMOD) |
789 goto longmod; | 665 goto longmod; |
790 | 666 |
791 » » regalloc(&n1, nl->type, N); | 667 » » cgenr(nl, &n1, res); |
792 » » cgen(nl, &n1);» » » » // num -> reg(n1) | |
793 | |
794 » » savex(D_AX, &ax, &oldax, res, nl->type); | |
795 » » savex(D_DX, &dx, &olddx, res, nl->type); | |
796 | |
797 nodconst(&n2, nl->type, m.sm); | 668 nodconst(&n2, nl->type, m.sm); |
798 » » gmove(&n2, &ax);» » » // const->ax | 669 » » regalloc(&n3, nl->type, N); |
799 | 670 » » cgen_hmul(&n1, &n2, &n3); |
800 » » gins(optoas(OHMUL, nl->type), &n1, N);» // imul reg | |
801 » » if(w == 8) { | |
802 » » » // fix up 8-bit multiply | |
803 » » » Node ah, dl; | |
804 » » » nodreg(&ah, types[TUINT8], D_AH); | |
805 » » » nodreg(&dl, types[TUINT8], D_DL); | |
806 » » » gins(AMOVB, &ah, &dl); | |
807 » » } | |
808 | 671 |
809 if(m.sm < 0) { | 672 if(m.sm < 0) { |
810 // need to add numerator | 673 // need to add numerator |
811 » » » gins(optoas(OADD, nl->type), &n1, &dx); | 674 » » » gins(optoas(OADD, nl->type), &n1, &n3); |
812 } | 675 } |
813 | 676 |
814 nodconst(&n2, nl->type, m.s); | 677 nodconst(&n2, nl->type, m.s); |
815 » » gins(optoas(ORSH, nl->type), &n2, &dx);»// shift dx | 678 » » gins(optoas(ORSH, nl->type), &n2, &n3);»// shift n3 |
816 | 679 |
817 nodconst(&n2, nl->type, w-1); | 680 nodconst(&n2, nl->type, w-1); |
818 gins(optoas(ORSH, nl->type), &n2, &n1); // -1 iff num is neg | 681 gins(optoas(ORSH, nl->type), &n2, &n1); // -1 iff num is neg |
819 » » gins(optoas(OSUB, nl->type), &n1, &dx);»// added | 682 » » gins(optoas(OSUB, nl->type), &n1, &n3);»// added |
820 | 683 |
821 if(m.sd < 0) { | 684 if(m.sd < 0) { |
822 // this could probably be removed | 685 // this could probably be removed |
823 // by factoring it into the multiplier | 686 // by factoring it into the multiplier |
824 » » » gins(optoas(OMINUS, nl->type), N, &dx); | 687 » » » gins(optoas(OMINUS, nl->type), N, &n3); |
825 } | 688 } |
826 | 689 |
690 gmove(&n3, res); | |
827 regfree(&n1); | 691 regfree(&n1); |
828 » » gmove(&dx, res); | 692 » » regfree(&n3); |
829 | |
830 » » restx(&ax, &oldax); | |
831 » » restx(&dx, &olddx); | |
832 return; | 693 return; |
833 } | 694 } |
834 goto longdiv; | 695 goto longdiv; |
835 | 696 |
836 longdiv: | 697 longdiv: |
837 // division and mod using (slow) hardware instruction | 698 // division and mod using (slow) hardware instruction |
838 dodiv(op, nl, nr, res); | 699 dodiv(op, nl, nr, res); |
839 return; | 700 return; |
840 | 701 |
841 longmod: | 702 longmod: |
(...skipping 16 matching lines...) Expand all Loading... | |
858 regfree(&n3); | 719 regfree(&n3); |
859 } else | 720 } else |
860 gins(a, nr, &n2); | 721 gins(a, nr, &n2); |
861 gins(optoas(OSUB, nl->type), &n2, &n1); | 722 gins(optoas(OSUB, nl->type), &n2, &n1); |
862 gmove(&n1, res); | 723 gmove(&n1, res); |
863 regfree(&n1); | 724 regfree(&n1); |
864 regfree(&n2); | 725 regfree(&n2); |
865 } | 726 } |
866 | 727 |
867 /* | 728 /* |
729 * generate high multiply: | |
730 * res = (nl*nr) >> width | |
731 */ | |
732 void | |
733 cgen_hmul(Node *nl, Node *nr, Node *res) | |
734 { | |
735 Type *t; | |
736 int a; | |
737 Node n1, n2, ax, dx, *tmp; | |
738 | |
739 t = nl->type; | |
740 a = optoas(OHMUL, t); | |
741 if(nl->ullman < nr->ullman) { | |
742 tmp = nl; | |
743 nl = nr; | |
744 nr = tmp; | |
745 } | |
746 cgenr(nl, &n1, res); | |
747 cgenr(nr, &n2, N); | |
748 nodreg(&ax, t, D_AX); | |
749 gmove(&n1, &ax); | |
750 gins(a, &n2, N); | |
751 regfree(&n2); | |
752 regfree(&n1); | |
753 | |
754 if(t->width == 1) { | |
755 // byte multiply behaves differently. | |
756 nodreg(&ax, t, D_AH); | |
757 nodreg(&dx, t, D_DL); | |
758 gmove(&ax, &dx); | |
759 } | |
760 nodreg(&dx, t, D_DX); | |
761 gmove(&dx, res); | |
762 } | |
763 | |
764 /* | |
868 * generate shift according to op, one of: | 765 * generate shift according to op, one of: |
869 * res = nl << nr | 766 * res = nl << nr |
870 * res = nl >> nr | 767 * res = nl >> nr |
871 */ | 768 */ |
872 void | 769 void |
873 cgen_shift(int op, int bounded, Node *nl, Node *nr, Node *res) | 770 cgen_shift(int op, int bounded, Node *nl, Node *nr, Node *res) |
874 { | 771 { |
875 Node n1, n2, n3, n4, n5, cx, oldcx; | 772 Node n1, n2, n3, n4, n5, cx, oldcx; |
876 int a, rcx; | 773 int a, rcx; |
877 Prog *p1; | 774 Prog *p1; |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1057 gins(ASTOSB, N, N); // STOB AL,*(DI)+ | 954 gins(ASTOSB, N, N); // STOB AL,*(DI)+ |
1058 } else | 955 } else |
1059 while(c > 0) { | 956 while(c > 0) { |
1060 gins(ASTOSB, N, N); // STOB AL,*(DI)+ | 957 gins(ASTOSB, N, N); // STOB AL,*(DI)+ |
1061 c--; | 958 c--; |
1062 } | 959 } |
1063 | 960 |
1064 restx(&n1, &oldn1); | 961 restx(&n1, &oldn1); |
1065 restx(&ax, &oldax); | 962 restx(&ax, &oldax); |
1066 } | 963 } |
OLD | NEW |