OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 #include "src/compiler/code-generator-impl.h" | 6 #include "src/compiler/code-generator-impl.h" |
7 #include "src/compiler/gap-resolver.h" | 7 #include "src/compiler/gap-resolver.h" |
8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
9 #include "src/compiler/node-properties-inl.h" | 9 #include "src/compiler/node-properties-inl.h" |
10 #include "src/compiler/osr.h" | 10 #include "src/compiler/osr.h" |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 : OutOfLineRound(gen, result) {} | 196 : OutOfLineRound(gen, result) {} |
197 }; | 197 }; |
198 | 198 |
199 | 199 |
200 class OutOfLineCeil FINAL : public OutOfLineRound { | 200 class OutOfLineCeil FINAL : public OutOfLineRound { |
201 public: | 201 public: |
202 OutOfLineCeil(CodeGenerator* gen, DoubleRegister result) | 202 OutOfLineCeil(CodeGenerator* gen, DoubleRegister result) |
203 : OutOfLineRound(gen, result) {} | 203 : OutOfLineRound(gen, result) {} |
204 }; | 204 }; |
205 | 205 |
| 206 |
| 207 Condition FlagsConditionToConditionCmp(FlagsCondition condition) { |
| 208 switch (condition) { |
| 209 case kEqual: |
| 210 return eq; |
| 211 case kNotEqual: |
| 212 return ne; |
| 213 case kSignedLessThan: |
| 214 return lt; |
| 215 case kSignedGreaterThanOrEqual: |
| 216 return ge; |
| 217 case kSignedLessThanOrEqual: |
| 218 return le; |
| 219 case kSignedGreaterThan: |
| 220 return gt; |
| 221 case kUnsignedLessThan: |
| 222 return lo; |
| 223 case kUnsignedGreaterThanOrEqual: |
| 224 return hs; |
| 225 case kUnsignedLessThanOrEqual: |
| 226 return ls; |
| 227 case kUnsignedGreaterThan: |
| 228 return hi; |
| 229 case kUnorderedEqual: |
| 230 case kUnorderedNotEqual: |
| 231 break; |
| 232 default: |
| 233 break; |
| 234 } |
| 235 UNREACHABLE(); |
| 236 return kNoCondition; |
| 237 } |
| 238 |
| 239 |
| 240 Condition FlagsConditionToConditionTst(FlagsCondition condition) { |
| 241 switch (condition) { |
| 242 case kNotEqual: |
| 243 return ne; |
| 244 case kEqual: |
| 245 return eq; |
| 246 default: |
| 247 break; |
| 248 } |
| 249 UNREACHABLE(); |
| 250 return kNoCondition; |
| 251 } |
| 252 |
| 253 |
| 254 Condition FlagsConditionToConditionOvf(FlagsCondition condition) { |
| 255 switch (condition) { |
| 256 case kOverflow: |
| 257 return lt; |
| 258 case kNotOverflow: |
| 259 return ge; |
| 260 default: |
| 261 break; |
| 262 } |
| 263 UNREACHABLE(); |
| 264 return kNoCondition; |
| 265 } |
| 266 |
206 } // namespace | 267 } // namespace |
207 | 268 |
208 | 269 |
209 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width, asm_instr) \ | 270 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width, asm_instr) \ |
210 do { \ | 271 do { \ |
211 auto result = i.Output##width##Register(); \ | 272 auto result = i.Output##width##Register(); \ |
212 auto ool = new (zone()) OutOfLineLoad##width(this, result); \ | 273 auto ool = new (zone()) OutOfLineLoad##width(this, result); \ |
213 if (instr->InputAt(0)->IsRegister()) { \ | 274 if (instr->InputAt(0)->IsRegister()) { \ |
214 auto offset = i.InputRegister(0); \ | 275 auto offset = i.InputRegister(0); \ |
215 __ Branch(USE_DELAY_SLOT, ool->entry(), hs, offset, i.InputOperand(1)); \ | 276 __ Branch(USE_DELAY_SLOT, ool->entry(), hs, offset, i.InputOperand(1)); \ |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 // MIPS does not have condition code flags, so compare and branch are | 700 // MIPS does not have condition code flags, so compare and branch are |
640 // implemented differently than on the other arch's. The compare operations | 701 // implemented differently than on the other arch's. The compare operations |
641 // emit mips pseudo-instructions, which are handled here by branch | 702 // emit mips pseudo-instructions, which are handled here by branch |
642 // instructions that do the actual comparison. Essential that the input | 703 // instructions that do the actual comparison. Essential that the input |
643 // registers to compare pseudo-op are not modified before this branch op, as | 704 // registers to compare pseudo-op are not modified before this branch op, as |
644 // they are tested here. | 705 // they are tested here. |
645 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were | 706 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were |
646 // not separated by other instructions. | 707 // not separated by other instructions. |
647 | 708 |
648 if (instr->arch_opcode() == kMipsTst) { | 709 if (instr->arch_opcode() == kMipsTst) { |
649 switch (branch->condition) { | 710 cc = FlagsConditionToConditionTst(branch->condition); |
650 case kNotEqual: | |
651 cc = ne; | |
652 break; | |
653 case kEqual: | |
654 cc = eq; | |
655 break; | |
656 default: | |
657 UNSUPPORTED_COND(kMipsTst, branch->condition); | |
658 break; | |
659 } | |
660 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 711 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
661 __ Branch(tlabel, cc, at, Operand(zero_reg)); | 712 __ Branch(tlabel, cc, at, Operand(zero_reg)); |
662 | 713 |
663 } else if (instr->arch_opcode() == kMipsAddOvf || | 714 } else if (instr->arch_opcode() == kMipsAddOvf || |
664 instr->arch_opcode() == kMipsSubOvf) { | 715 instr->arch_opcode() == kMipsSubOvf) { |
665 // kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow. | 716 // kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow. |
666 switch (branch->condition) { | 717 cc = FlagsConditionToConditionOvf(branch->condition); |
667 case kOverflow: | |
668 cc = lt; | |
669 break; | |
670 case kNotOverflow: | |
671 cc = ge; | |
672 break; | |
673 default: | |
674 UNSUPPORTED_COND(kMipsAddOvf, branch->condition); | |
675 break; | |
676 } | |
677 __ Branch(tlabel, cc, kCompareReg, Operand(zero_reg)); | 718 __ Branch(tlabel, cc, kCompareReg, Operand(zero_reg)); |
678 | 719 |
679 } else if (instr->arch_opcode() == kMipsCmp) { | 720 } else if (instr->arch_opcode() == kMipsCmp) { |
680 switch (branch->condition) { | 721 cc = FlagsConditionToConditionCmp(branch->condition); |
681 case kEqual: | |
682 cc = eq; | |
683 break; | |
684 case kNotEqual: | |
685 cc = ne; | |
686 break; | |
687 case kSignedLessThan: | |
688 cc = lt; | |
689 break; | |
690 case kSignedGreaterThanOrEqual: | |
691 cc = ge; | |
692 break; | |
693 case kSignedLessThanOrEqual: | |
694 cc = le; | |
695 break; | |
696 case kSignedGreaterThan: | |
697 cc = gt; | |
698 break; | |
699 case kUnsignedLessThan: | |
700 cc = lo; | |
701 break; | |
702 case kUnsignedGreaterThanOrEqual: | |
703 cc = hs; | |
704 break; | |
705 case kUnsignedLessThanOrEqual: | |
706 cc = ls; | |
707 break; | |
708 case kUnsignedGreaterThan: | |
709 cc = hi; | |
710 break; | |
711 default: | |
712 UNSUPPORTED_COND(kMipsCmp, branch->condition); | |
713 break; | |
714 } | |
715 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); | 722 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); |
716 | 723 |
717 if (!branch->fallthru) __ Branch(flabel); // no fallthru to flabel. | 724 if (!branch->fallthru) __ Branch(flabel); // no fallthru to flabel. |
718 | 725 |
719 } else if (instr->arch_opcode() == kMipsCmpD) { | 726 } else if (instr->arch_opcode() == kMipsCmpD) { |
720 // TODO(dusmil) optimize unordered checks to use fewer instructions | 727 // TODO(dusmil) optimize unordered checks to use fewer instructions |
721 // even if we have to unfold BranchF macro. | 728 // even if we have to unfold BranchF macro. |
722 Label* nan = flabel; | 729 Label* nan = flabel; |
723 switch (branch->condition) { | 730 switch (branch->condition) { |
724 case kUnorderedEqual: | 731 case kEqual: |
725 cc = eq; | 732 cc = eq; |
726 break; | 733 break; |
727 case kUnorderedNotEqual: | 734 case kNotEqual: |
728 cc = ne; | 735 cc = ne; |
729 nan = tlabel; | 736 nan = tlabel; |
730 break; | 737 break; |
731 case kUnorderedLessThan: | 738 case kUnsignedLessThan: |
732 cc = lt; | 739 cc = lt; |
733 break; | 740 break; |
734 case kUnorderedGreaterThanOrEqual: | 741 case kUnsignedGreaterThanOrEqual: |
735 cc = ge; | 742 cc = ge; |
736 nan = tlabel; | 743 nan = tlabel; |
737 break; | 744 break; |
738 case kUnorderedLessThanOrEqual: | 745 case kUnsignedLessThanOrEqual: |
739 cc = le; | 746 cc = le; |
740 break; | 747 break; |
741 case kUnorderedGreaterThan: | 748 case kUnsignedGreaterThan: |
742 cc = gt; | 749 cc = gt; |
743 nan = tlabel; | 750 nan = tlabel; |
744 break; | 751 break; |
745 default: | 752 default: |
746 UNSUPPORTED_COND(kMipsCmpD, branch->condition); | 753 UNSUPPORTED_COND(kMipsCmpD, branch->condition); |
747 break; | 754 break; |
748 } | 755 } |
749 __ BranchF(tlabel, nan, cc, i.InputDoubleRegister(0), | 756 __ BranchF(tlabel, nan, cc, i.InputDoubleRegister(0), |
750 i.InputDoubleRegister(1)); | 757 i.InputDoubleRegister(1)); |
751 | 758 |
(...skipping 29 matching lines...) Expand all Loading... |
781 // implemented differently than on the other arch's. The compare operations | 788 // implemented differently than on the other arch's. The compare operations |
782 // emit mips psuedo-instructions, which are checked and handled here. | 789 // emit mips psuedo-instructions, which are checked and handled here. |
783 | 790 |
784 // For materializations, we use delay slot to set the result true, and | 791 // For materializations, we use delay slot to set the result true, and |
785 // in the false case, where we fall thru the branch, we reset the result | 792 // in the false case, where we fall thru the branch, we reset the result |
786 // false. | 793 // false. |
787 | 794 |
788 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were | 795 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were |
789 // not separated by other instructions. | 796 // not separated by other instructions. |
790 if (instr->arch_opcode() == kMipsTst) { | 797 if (instr->arch_opcode() == kMipsTst) { |
791 switch (condition) { | 798 cc = FlagsConditionToConditionTst(condition); |
792 case kNotEqual: | |
793 cc = ne; | |
794 break; | |
795 case kEqual: | |
796 cc = eq; | |
797 break; | |
798 default: | |
799 UNSUPPORTED_COND(kMipsTst, condition); | |
800 break; | |
801 } | |
802 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 799 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
803 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); | 800 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); |
804 __ li(result, Operand(1)); // In delay slot. | 801 __ li(result, Operand(1)); // In delay slot. |
805 | 802 |
806 } else if (instr->arch_opcode() == kMipsAddOvf || | 803 } else if (instr->arch_opcode() == kMipsAddOvf || |
807 instr->arch_opcode() == kMipsSubOvf) { | 804 instr->arch_opcode() == kMipsSubOvf) { |
808 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. | 805 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. |
809 switch (condition) { | 806 cc = FlagsConditionToConditionOvf(condition); |
810 case kOverflow: | |
811 cc = lt; | |
812 break; | |
813 case kNotOverflow: | |
814 cc = ge; | |
815 break; | |
816 default: | |
817 UNSUPPORTED_COND(kMipsAddOvf, condition); | |
818 break; | |
819 } | |
820 __ Branch(USE_DELAY_SLOT, &done, cc, kCompareReg, Operand(zero_reg)); | 807 __ Branch(USE_DELAY_SLOT, &done, cc, kCompareReg, Operand(zero_reg)); |
821 __ li(result, Operand(1)); // In delay slot. | 808 __ li(result, Operand(1)); // In delay slot. |
822 | 809 |
823 | 810 |
824 } else if (instr->arch_opcode() == kMipsCmp) { | 811 } else if (instr->arch_opcode() == kMipsCmp) { |
825 Register left = i.InputRegister(0); | 812 Register left = i.InputRegister(0); |
826 Operand right = i.InputOperand(1); | 813 Operand right = i.InputOperand(1); |
827 switch (condition) { | 814 cc = FlagsConditionToConditionCmp(condition); |
828 case kEqual: | |
829 cc = eq; | |
830 break; | |
831 case kNotEqual: | |
832 cc = ne; | |
833 break; | |
834 case kSignedLessThan: | |
835 cc = lt; | |
836 break; | |
837 case kSignedGreaterThanOrEqual: | |
838 cc = ge; | |
839 break; | |
840 case kSignedLessThanOrEqual: | |
841 cc = le; | |
842 break; | |
843 case kSignedGreaterThan: | |
844 cc = gt; | |
845 break; | |
846 case kUnsignedLessThan: | |
847 cc = lo; | |
848 break; | |
849 case kUnsignedGreaterThanOrEqual: | |
850 cc = hs; | |
851 break; | |
852 case kUnsignedLessThanOrEqual: | |
853 cc = ls; | |
854 break; | |
855 case kUnsignedGreaterThan: | |
856 cc = hi; | |
857 break; | |
858 default: | |
859 UNSUPPORTED_COND(kMipsCmp, condition); | |
860 break; | |
861 } | |
862 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); | 815 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); |
863 __ li(result, Operand(1)); // In delay slot. | 816 __ li(result, Operand(1)); // In delay slot. |
864 | 817 |
865 } else if (instr->arch_opcode() == kMipsCmpD) { | 818 } else if (instr->arch_opcode() == kMipsCmpD) { |
866 FPURegister left = i.InputDoubleRegister(0); | 819 FPURegister left = i.InputDoubleRegister(0); |
867 FPURegister right = i.InputDoubleRegister(1); | 820 FPURegister right = i.InputDoubleRegister(1); |
868 // TODO(plind): Provide NaN-testing macro-asm function without need for | 821 // TODO(plind): Provide NaN-testing macro-asm function without need for |
869 // BranchF. | 822 // BranchF. |
870 FPURegister dummy1 = f0; | 823 FPURegister dummy1 = f0; |
871 FPURegister dummy2 = f2; | 824 FPURegister dummy2 = f2; |
872 switch (condition) { | 825 switch (condition) { |
873 case kUnorderedEqual: | 826 case kEqual: |
874 // TODO(plind): improve the NaN testing throughout this function. | 827 // TODO(plind): improve the NaN testing throughout this function. |
875 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); | 828 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); |
876 cc = eq; | 829 cc = eq; |
877 break; | 830 break; |
878 case kUnorderedNotEqual: | 831 case kNotEqual: |
879 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); | 832 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); |
880 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. | 833 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. |
881 cc = ne; | 834 cc = ne; |
882 break; | 835 break; |
883 case kUnorderedLessThan: | 836 case kUnsignedLessThan: |
884 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); | 837 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); |
885 cc = lt; | 838 cc = lt; |
886 break; | 839 break; |
887 case kUnorderedGreaterThanOrEqual: | 840 case kUnsignedGreaterThanOrEqual: |
888 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); | 841 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); |
889 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. | 842 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. |
890 cc = ge; | 843 cc = ge; |
891 break; | 844 break; |
892 case kUnorderedLessThanOrEqual: | 845 case kUnsignedLessThanOrEqual: |
893 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); | 846 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); |
894 cc = le; | 847 cc = le; |
895 break; | 848 break; |
896 case kUnorderedGreaterThan: | 849 case kUnsignedGreaterThan: |
897 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); | 850 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); |
898 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. | 851 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. |
899 cc = gt; | 852 cc = gt; |
900 break; | 853 break; |
901 default: | 854 default: |
902 UNSUPPORTED_COND(kMipsCmp, condition); | 855 UNSUPPORTED_COND(kMipsCmp, condition); |
903 break; | 856 break; |
904 } | 857 } |
905 __ BranchF(USE_DELAY_SLOT, &done, NULL, cc, left, right); | 858 __ BranchF(USE_DELAY_SLOT, &done, NULL, cc, left, right); |
906 __ li(result, Operand(1)); // In delay slot - branch taken returns 1. | 859 __ li(result, Operand(1)); // In delay slot - branch taken returns 1. |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1194 } | 1147 } |
1195 } | 1148 } |
1196 MarkLazyDeoptSite(); | 1149 MarkLazyDeoptSite(); |
1197 } | 1150 } |
1198 | 1151 |
1199 #undef __ | 1152 #undef __ |
1200 | 1153 |
1201 } // namespace compiler | 1154 } // namespace compiler |
1202 } // namespace internal | 1155 } // namespace internal |
1203 } // namespace v8 | 1156 } // namespace v8 |
OLD | NEW |