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