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 break; | |
paul.l...
2015/01/13 17:34:57
Please remove the unnecessary break's after the re
balazs.kilvady
2015/01/13 18:23:40
Done.
| |
212 case kNotEqual: | |
213 return ne; | |
214 break; | |
215 case kSignedLessThan: | |
216 return lt; | |
217 break; | |
218 case kSignedGreaterThanOrEqual: | |
219 return ge; | |
220 break; | |
221 case kSignedLessThanOrEqual: | |
222 return le; | |
223 break; | |
224 case kSignedGreaterThan: | |
225 return gt; | |
226 break; | |
227 case kUnsignedLessThan: | |
228 return lo; | |
229 break; | |
230 case kUnsignedGreaterThanOrEqual: | |
231 return hs; | |
232 break; | |
233 case kUnsignedLessThanOrEqual: | |
234 return ls; | |
235 break; | |
236 case kUnsignedGreaterThan: | |
237 return hi; | |
238 break; | |
239 default: | |
240 break; | |
241 } | |
242 UNREACHABLE(); | |
243 return kNoCondition; | |
244 } | |
245 | |
246 | |
247 Condition FlagsConditionToConditionTst(FlagsCondition condition) { | |
248 switch (condition) { | |
249 case kNotEqual: | |
250 return ne; | |
251 break; | |
252 case kEqual: | |
253 return eq; | |
254 break; | |
255 default: | |
256 break; | |
257 } | |
258 UNREACHABLE(); | |
259 return kNoCondition; | |
260 } | |
261 | |
262 | |
263 Condition FlagsConditionToConditionOvf(FlagsCondition condition) { | |
264 switch (condition) { | |
265 case kOverflow: | |
266 return lt; | |
267 break; | |
268 case kNotOverflow: | |
269 return ge; | |
270 break; | |
271 default: | |
272 break; | |
273 } | |
274 UNREACHABLE(); | |
275 return kNoCondition; | |
276 } | |
277 | |
206 } // namespace | 278 } // namespace |
207 | 279 |
208 | 280 |
209 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width, asm_instr) \ | 281 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width, asm_instr) \ |
210 do { \ | 282 do { \ |
211 auto result = i.Output##width##Register(); \ | 283 auto result = i.Output##width##Register(); \ |
212 auto ool = new (zone()) OutOfLineLoad##width(this, result); \ | 284 auto ool = new (zone()) OutOfLineLoad##width(this, result); \ |
213 if (instr->InputAt(0)->IsRegister()) { \ | 285 if (instr->InputAt(0)->IsRegister()) { \ |
214 auto offset = i.InputRegister(0); \ | 286 auto offset = i.InputRegister(0); \ |
215 __ Branch(USE_DELAY_SLOT, ool->entry(), hs, offset, i.InputOperand(1)); \ | 287 __ 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 | 711 // MIPS does not have condition code flags, so compare and branch are |
640 // implemented differently than on the other arch's. The compare operations | 712 // implemented differently than on the other arch's. The compare operations |
641 // emit mips pseudo-instructions, which are handled here by branch | 713 // emit mips pseudo-instructions, which are handled here by branch |
642 // instructions that do the actual comparison. Essential that the input | 714 // instructions that do the actual comparison. Essential that the input |
643 // registers to compare pseudo-op are not modified before this branch op, as | 715 // registers to compare pseudo-op are not modified before this branch op, as |
644 // they are tested here. | 716 // they are tested here. |
645 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were | 717 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were |
646 // not separated by other instructions. | 718 // not separated by other instructions. |
647 | 719 |
648 if (instr->arch_opcode() == kMipsTst) { | 720 if (instr->arch_opcode() == kMipsTst) { |
649 switch (branch->condition) { | 721 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)); | 722 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
661 __ Branch(tlabel, cc, at, Operand(zero_reg)); | 723 __ Branch(tlabel, cc, at, Operand(zero_reg)); |
662 | 724 |
663 } else if (instr->arch_opcode() == kMipsAddOvf || | 725 } else if (instr->arch_opcode() == kMipsAddOvf || |
664 instr->arch_opcode() == kMipsSubOvf) { | 726 instr->arch_opcode() == kMipsSubOvf) { |
665 // kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow. | 727 // kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow. |
666 switch (branch->condition) { | 728 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)); | 729 __ Branch(tlabel, cc, kCompareReg, Operand(zero_reg)); |
678 | 730 |
679 } else if (instr->arch_opcode() == kMipsCmp) { | 731 } else if (instr->arch_opcode() == kMipsCmp) { |
680 switch (branch->condition) { | 732 cc = FlagsConditionToConditionCmp(branch->condition); |
681 case kEqual: | 733 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); |
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)); | |
716 | 734 |
717 if (!branch->fallthru) __ Branch(flabel); // no fallthru to flabel. | 735 if (!branch->fallthru) __ Branch(flabel); // no fallthru to flabel. |
718 | 736 |
719 } else if (instr->arch_opcode() == kMipsCmpD) { | 737 } else if (instr->arch_opcode() == kMipsCmpD) { |
720 // TODO(dusmil) optimize unordered checks to use fewer instructions | 738 // TODO(dusmil) optimize unordered checks to use fewer instructions |
721 // even if we have to unfold BranchF macro. | 739 // even if we have to unfold BranchF macro. |
722 Label* nan = flabel; | 740 Label* nan = flabel; |
723 switch (branch->condition) { | 741 switch (branch->condition) { |
724 case kUnorderedEqual: | 742 case kEqual: |
725 cc = eq; | 743 cc = eq; |
726 break; | 744 break; |
727 case kUnorderedNotEqual: | 745 case kNotEqual: |
728 cc = ne; | 746 cc = ne; |
729 nan = tlabel; | 747 nan = tlabel; |
730 break; | 748 break; |
731 case kUnorderedLessThan: | 749 case kUnsignedLessThan: |
732 cc = lt; | 750 cc = lt; |
733 break; | 751 break; |
734 case kUnorderedGreaterThanOrEqual: | 752 case kUnsignedGreaterThanOrEqual: |
735 cc = ge; | 753 cc = ge; |
736 nan = tlabel; | 754 nan = tlabel; |
737 break; | 755 break; |
738 case kUnorderedLessThanOrEqual: | 756 case kUnsignedLessThanOrEqual: |
739 cc = le; | 757 cc = le; |
740 break; | 758 break; |
741 case kUnorderedGreaterThan: | 759 case kUnsignedGreaterThan: |
742 cc = gt; | 760 cc = gt; |
743 nan = tlabel; | 761 nan = tlabel; |
744 break; | 762 break; |
745 default: | 763 default: |
746 UNSUPPORTED_COND(kMipsCmpD, branch->condition); | 764 UNSUPPORTED_COND(kMipsCmpD, branch->condition); |
747 break; | 765 break; |
748 } | 766 } |
749 __ BranchF(tlabel, nan, cc, i.InputDoubleRegister(0), | 767 __ BranchF(tlabel, nan, cc, i.InputDoubleRegister(0), |
750 i.InputDoubleRegister(1)); | 768 i.InputDoubleRegister(1)); |
751 | 769 |
(...skipping 29 matching lines...) Expand all Loading... | |
781 // implemented differently than on the other arch's. The compare operations | 799 // implemented differently than on the other arch's. The compare operations |
782 // emit mips psuedo-instructions, which are checked and handled here. | 800 // emit mips psuedo-instructions, which are checked and handled here. |
783 | 801 |
784 // For materializations, we use delay slot to set the result true, and | 802 // 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 | 803 // in the false case, where we fall thru the branch, we reset the result |
786 // false. | 804 // false. |
787 | 805 |
788 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were | 806 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were |
789 // not separated by other instructions. | 807 // not separated by other instructions. |
790 if (instr->arch_opcode() == kMipsTst) { | 808 if (instr->arch_opcode() == kMipsTst) { |
791 switch (condition) { | 809 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)); | 810 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
803 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); | 811 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); |
804 __ li(result, Operand(1)); // In delay slot. | 812 __ li(result, Operand(1)); // In delay slot. |
805 | 813 |
806 } else if (instr->arch_opcode() == kMipsAddOvf || | 814 } else if (instr->arch_opcode() == kMipsAddOvf || |
807 instr->arch_opcode() == kMipsSubOvf) { | 815 instr->arch_opcode() == kMipsSubOvf) { |
808 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. | 816 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. |
809 switch (condition) { | 817 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)); | 818 __ Branch(USE_DELAY_SLOT, &done, cc, kCompareReg, Operand(zero_reg)); |
821 __ li(result, Operand(1)); // In delay slot. | 819 __ li(result, Operand(1)); // In delay slot. |
822 | 820 |
823 | 821 |
824 } else if (instr->arch_opcode() == kMipsCmp) { | 822 } else if (instr->arch_opcode() == kMipsCmp) { |
825 Register left = i.InputRegister(0); | 823 Register left = i.InputRegister(0); |
826 Operand right = i.InputOperand(1); | 824 Operand right = i.InputOperand(1); |
827 switch (condition) { | 825 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); | 826 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); |
863 __ li(result, Operand(1)); // In delay slot. | 827 __ li(result, Operand(1)); // In delay slot. |
864 | 828 |
865 } else if (instr->arch_opcode() == kMipsCmpD) { | 829 } else if (instr->arch_opcode() == kMipsCmpD) { |
866 FPURegister left = i.InputDoubleRegister(0); | 830 FPURegister left = i.InputDoubleRegister(0); |
867 FPURegister right = i.InputDoubleRegister(1); | 831 FPURegister right = i.InputDoubleRegister(1); |
868 // TODO(plind): Provide NaN-testing macro-asm function without need for | 832 // TODO(plind): Provide NaN-testing macro-asm function without need for |
869 // BranchF. | 833 // BranchF. |
870 FPURegister dummy1 = f0; | 834 FPURegister dummy1 = f0; |
871 FPURegister dummy2 = f2; | 835 FPURegister dummy2 = f2; |
872 switch (condition) { | 836 switch (condition) { |
873 case kUnorderedEqual: | 837 case kEqual: |
874 // TODO(plind): improve the NaN testing throughout this function. | 838 // TODO(plind): improve the NaN testing throughout this function. |
875 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); | 839 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); |
876 cc = eq; | 840 cc = eq; |
877 break; | 841 break; |
878 case kUnorderedNotEqual: | 842 case kNotEqual: |
879 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); | 843 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); |
880 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. | 844 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. |
881 cc = ne; | 845 cc = ne; |
882 break; | 846 break; |
883 case kUnorderedLessThan: | 847 case kUnsignedLessThan: |
884 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); | 848 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); |
885 cc = lt; | 849 cc = lt; |
886 break; | 850 break; |
887 case kUnorderedGreaterThanOrEqual: | 851 case kUnsignedGreaterThanOrEqual: |
888 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); | 852 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); |
889 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. | 853 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. |
890 cc = ge; | 854 cc = ge; |
891 break; | 855 break; |
892 case kUnorderedLessThanOrEqual: | 856 case kUnsignedLessThanOrEqual: |
893 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); | 857 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); |
894 cc = le; | 858 cc = le; |
895 break; | 859 break; |
896 case kUnorderedGreaterThan: | 860 case kUnsignedGreaterThan: |
897 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); | 861 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); |
898 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. | 862 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. |
899 cc = gt; | 863 cc = gt; |
900 break; | 864 break; |
901 default: | 865 default: |
902 UNSUPPORTED_COND(kMipsCmp, condition); | 866 UNSUPPORTED_COND(kMipsCmp, condition); |
903 break; | 867 break; |
904 } | 868 } |
905 __ BranchF(USE_DELAY_SLOT, &done, NULL, cc, left, right); | 869 __ BranchF(USE_DELAY_SLOT, &done, NULL, cc, left, right); |
906 __ li(result, Operand(1)); // In delay slot - branch taken returns 1. | 870 __ 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 } | 1158 } |
1195 } | 1159 } |
1196 MarkLazyDeoptSite(); | 1160 MarkLazyDeoptSite(); |
1197 } | 1161 } |
1198 | 1162 |
1199 #undef __ | 1163 #undef __ |
1200 | 1164 |
1201 } // namespace compiler | 1165 } // namespace compiler |
1202 } // namespace internal | 1166 } // namespace internal |
1203 } // namespace v8 | 1167 } // namespace v8 |
OLD | NEW |