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