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/mips/macro-assembler-mips.h" | 9 #include "src/mips/macro-assembler-mips.h" |
10 #include "src/scopes.h" | 10 #include "src/scopes.h" |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 return lt; | 255 return lt; |
256 case kNotOverflow: | 256 case kNotOverflow: |
257 return ge; | 257 return ge; |
258 default: | 258 default: |
259 break; | 259 break; |
260 } | 260 } |
261 UNREACHABLE(); | 261 UNREACHABLE(); |
262 return kNoCondition; | 262 return kNoCondition; |
263 } | 263 } |
264 | 264 |
| 265 FPUCondition FlagsConditionToConditionCmpD(bool& predicate, |
| 266 FlagsCondition condition) { |
| 267 switch (condition) { |
| 268 case kEqual: |
| 269 predicate = true; |
| 270 return EQ; |
| 271 case kNotEqual: |
| 272 predicate = false; |
| 273 return EQ; |
| 274 case kUnsignedLessThan: |
| 275 predicate = true; |
| 276 return OLT; |
| 277 case kUnsignedGreaterThanOrEqual: |
| 278 predicate = false; |
| 279 return ULT; |
| 280 case kUnsignedLessThanOrEqual: |
| 281 predicate = true; |
| 282 return OLE; |
| 283 case kUnsignedGreaterThan: |
| 284 predicate = false; |
| 285 return ULE; |
| 286 case kUnorderedEqual: |
| 287 case kUnorderedNotEqual: |
| 288 predicate = true; |
| 289 break; |
| 290 default: |
| 291 predicate = true; |
| 292 break; |
| 293 } |
| 294 UNREACHABLE(); |
| 295 return kNoFPUCondition; |
| 296 } |
| 297 |
265 } // namespace | 298 } // namespace |
266 | 299 |
267 | 300 |
268 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width, asm_instr) \ | 301 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width, asm_instr) \ |
269 do { \ | 302 do { \ |
270 auto result = i.Output##width##Register(); \ | 303 auto result = i.Output##width##Register(); \ |
271 auto ool = new (zone()) OutOfLineLoad##width(this, result); \ | 304 auto ool = new (zone()) OutOfLineLoad##width(this, result); \ |
272 if (instr->InputAt(0)->IsRegister()) { \ | 305 if (instr->InputAt(0)->IsRegister()) { \ |
273 auto offset = i.InputRegister(0); \ | 306 auto offset = i.InputRegister(0); \ |
274 __ Branch(USE_DELAY_SLOT, ool->entry(), hs, offset, i.InputOperand(1)); \ | 307 __ Branch(USE_DELAY_SLOT, ool->entry(), hs, offset, i.InputOperand(1)); \ |
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 Condition cc = kNoCondition; | 816 Condition cc = kNoCondition; |
784 | 817 |
785 // MIPS does not have condition code flags, so compare and branch are | 818 // MIPS does not have condition code flags, so compare and branch are |
786 // implemented differently than on the other arch's. The compare operations | 819 // implemented differently than on the other arch's. The compare operations |
787 // emit mips psuedo-instructions, which are checked and handled here. | 820 // emit mips psuedo-instructions, which are checked and handled here. |
788 | 821 |
789 // For materializations, we use delay slot to set the result true, and | 822 // For materializations, we use delay slot to set the result true, and |
790 // in the false case, where we fall thru the branch, we reset the result | 823 // in the false case, where we fall thru the branch, we reset the result |
791 // false. | 824 // false. |
792 | 825 |
793 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were | |
794 // not separated by other instructions. | |
795 if (instr->arch_opcode() == kMipsTst) { | 826 if (instr->arch_opcode() == kMipsTst) { |
796 cc = FlagsConditionToConditionTst(condition); | 827 cc = FlagsConditionToConditionTst(condition); |
797 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 828 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
798 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); | 829 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); |
799 __ li(result, Operand(1)); // In delay slot. | 830 __ li(result, Operand(1)); // In delay slot. |
800 | 831 |
801 } else if (instr->arch_opcode() == kMipsAddOvf || | 832 } else if (instr->arch_opcode() == kMipsAddOvf || |
802 instr->arch_opcode() == kMipsSubOvf) { | 833 instr->arch_opcode() == kMipsSubOvf) { |
803 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. | 834 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. |
804 cc = FlagsConditionToConditionOvf(condition); | 835 cc = FlagsConditionToConditionOvf(condition); |
805 __ Branch(USE_DELAY_SLOT, &done, cc, kCompareReg, Operand(zero_reg)); | 836 __ Branch(USE_DELAY_SLOT, &done, cc, kCompareReg, Operand(zero_reg)); |
806 __ li(result, Operand(1)); // In delay slot. | 837 __ li(result, Operand(1)); // In delay slot. |
807 | 838 |
808 | |
809 } else if (instr->arch_opcode() == kMipsCmp) { | 839 } else if (instr->arch_opcode() == kMipsCmp) { |
810 Register left = i.InputRegister(0); | 840 Register left = i.InputRegister(0); |
811 Operand right = i.InputOperand(1); | 841 Operand right = i.InputOperand(1); |
812 cc = FlagsConditionToConditionCmp(condition); | 842 cc = FlagsConditionToConditionCmp(condition); |
813 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); | 843 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); |
814 __ li(result, Operand(1)); // In delay slot. | 844 __ li(result, Operand(1)); // In delay slot. |
815 | 845 |
816 } else if (instr->arch_opcode() == kMipsCmpD) { | 846 } else if (instr->arch_opcode() == kMipsCmpD) { |
817 FPURegister left = i.InputDoubleRegister(0); | 847 FPURegister left = i.InputDoubleRegister(0); |
818 FPURegister right = i.InputDoubleRegister(1); | 848 FPURegister right = i.InputDoubleRegister(1); |
819 // TODO(plind): Provide NaN-testing macro-asm function without need for | 849 |
820 // BranchF. | 850 bool predicate; |
821 FPURegister dummy1 = f0; | 851 FPUCondition cc = FlagsConditionToConditionCmpD(predicate, condition); |
822 FPURegister dummy2 = f2; | 852 if (!IsMipsArchVariant(kMips32r6)) { |
823 switch (condition) { | 853 __ li(result, Operand(1)); |
824 case kEqual: | 854 __ c(cc, D, left, right); |
825 // TODO(plind): improve the NaN testing throughout this function. | 855 if (predicate) { |
826 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); | 856 __ Movf(result, zero_reg); |
827 cc = eq; | 857 } else { |
828 break; | 858 __ Movt(result, zero_reg); |
829 case kNotEqual: | 859 } |
830 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); | 860 } else { |
831 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. | 861 __ cmp(cc, L, kDoubleCompareReg, left, right); |
832 cc = ne; | 862 __ mfc1(at, kDoubleCompareReg); |
833 break; | 863 __ srl(result, at, 31); // Cmp returns all 1s for true. |
834 case kUnsignedLessThan: | 864 if (!predicate) // Toggle result for not equal. |
835 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); | 865 __ xori(result, result, 1); |
836 cc = lt; | |
837 break; | |
838 case kUnsignedGreaterThanOrEqual: | |
839 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); | |
840 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. | |
841 cc = ge; | |
842 break; | |
843 case kUnsignedLessThanOrEqual: | |
844 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); | |
845 cc = le; | |
846 break; | |
847 case kUnsignedGreaterThan: | |
848 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); | |
849 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. | |
850 cc = gt; | |
851 break; | |
852 default: | |
853 UNSUPPORTED_COND(kMipsCmp, condition); | |
854 break; | |
855 } | 866 } |
856 __ BranchF(USE_DELAY_SLOT, &done, NULL, cc, left, right); | 867 return; |
857 __ li(result, Operand(1)); // In delay slot - branch taken returns 1. | |
858 // Fall-thru (branch not taken) returns 0. | |
859 | |
860 } else { | 868 } else { |
861 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", | 869 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", |
862 instr->arch_opcode()); | 870 instr->arch_opcode()); |
863 TRACE_UNIMPL(); | 871 TRACE_UNIMPL(); |
864 UNIMPLEMENTED(); | 872 UNIMPLEMENTED(); |
865 } | 873 } |
866 // Fallthru case is the false materialization. | 874 |
| 875 // Fallthrough case is the false materialization. |
867 __ bind(&false_value); | 876 __ bind(&false_value); |
868 __ li(result, Operand(0)); | 877 __ li(result, Operand(0)); |
869 __ bind(&done); | 878 __ bind(&done); |
870 } | 879 } |
871 | 880 |
872 | 881 |
873 void CodeGenerator::AssembleDeoptimizerCall(int deoptimization_id) { | 882 void CodeGenerator::AssembleDeoptimizerCall(int deoptimization_id) { |
874 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( | 883 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( |
875 isolate(), deoptimization_id, Deoptimizer::LAZY); | 884 isolate(), deoptimization_id, Deoptimizer::LAZY); |
876 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); | 885 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1143 } | 1152 } |
1144 } | 1153 } |
1145 MarkLazyDeoptSite(); | 1154 MarkLazyDeoptSite(); |
1146 } | 1155 } |
1147 | 1156 |
1148 #undef __ | 1157 #undef __ |
1149 | 1158 |
1150 } // namespace compiler | 1159 } // namespace compiler |
1151 } // namespace internal | 1160 } // namespace internal |
1152 } // namespace v8 | 1161 } // namespace v8 |
OLD | NEW |