| 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/osr.h" | 9 #include "src/compiler/osr.h" |
| 10 #include "src/mips/macro-assembler-mips.h" | 10 #include "src/mips/macro-assembler-mips.h" |
| (...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 return false; | 897 return false; |
| 898 } | 898 } |
| 899 | 899 |
| 900 | 900 |
| 901 // Assembles branches after an instruction. | 901 // Assembles branches after an instruction. |
| 902 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 902 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
| 903 MipsOperandConverter i(this, instr); | 903 MipsOperandConverter i(this, instr); |
| 904 Label* tlabel = branch->true_label; | 904 Label* tlabel = branch->true_label; |
| 905 Label* flabel = branch->false_label; | 905 Label* flabel = branch->false_label; |
| 906 Condition cc = kNoCondition; | 906 Condition cc = kNoCondition; |
| 907 | |
| 908 // MIPS does not have condition code flags, so compare and branch are | 907 // MIPS does not have condition code flags, so compare and branch are |
| 909 // implemented differently than on the other arch's. The compare operations | 908 // implemented differently than on the other arch's. The compare operations |
| 910 // emit mips pseudo-instructions, which are handled here by branch | 909 // emit mips pseudo-instructions, which are handled here by branch |
| 911 // instructions that do the actual comparison. Essential that the input | 910 // instructions that do the actual comparison. Essential that the input |
| 912 // registers to compare pseudo-op are not modified before this branch op, as | 911 // registers to compare pseudo-op are not modified before this branch op, as |
| 913 // they are tested here. | 912 // they are tested here. |
| 914 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were | |
| 915 // not separated by other instructions. | |
| 916 | 913 |
| 917 if (instr->arch_opcode() == kMipsTst) { | 914 if (instr->arch_opcode() == kMipsTst) { |
| 918 cc = FlagsConditionToConditionTst(branch->condition); | 915 cc = FlagsConditionToConditionTst(branch->condition); |
| 919 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 916 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
| 920 __ Branch(tlabel, cc, at, Operand(zero_reg)); | 917 __ Branch(tlabel, cc, at, Operand(zero_reg)); |
| 921 } else if (instr->arch_opcode() == kMipsAddOvf || | 918 } else if (instr->arch_opcode() == kMipsAddOvf || |
| 922 instr->arch_opcode() == kMipsSubOvf) { | 919 instr->arch_opcode() == kMipsSubOvf) { |
| 923 // kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow. | 920 // kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow. |
| 924 cc = FlagsConditionToConditionOvf(branch->condition); | 921 cc = FlagsConditionToConditionOvf(branch->condition); |
| 925 __ Branch(tlabel, cc, kCompareReg, Operand(zero_reg)); | 922 __ Branch(tlabel, cc, kCompareReg, Operand(zero_reg)); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 957 FlagsCondition condition) { | 954 FlagsCondition condition) { |
| 958 MipsOperandConverter i(this, instr); | 955 MipsOperandConverter i(this, instr); |
| 959 Label done; | 956 Label done; |
| 960 | 957 |
| 961 // Materialize a full 32-bit 1 or 0 value. The result register is always the | 958 // Materialize a full 32-bit 1 or 0 value. The result register is always the |
| 962 // last output of the instruction. | 959 // last output of the instruction. |
| 963 Label false_value; | 960 Label false_value; |
| 964 DCHECK_NE(0u, instr->OutputCount()); | 961 DCHECK_NE(0u, instr->OutputCount()); |
| 965 Register result = i.OutputRegister(instr->OutputCount() - 1); | 962 Register result = i.OutputRegister(instr->OutputCount() - 1); |
| 966 Condition cc = kNoCondition; | 963 Condition cc = kNoCondition; |
| 967 | |
| 968 // MIPS does not have condition code flags, so compare and branch are | 964 // MIPS does not have condition code flags, so compare and branch are |
| 969 // implemented differently than on the other arch's. The compare operations | 965 // implemented differently than on the other arch's. The compare operations |
| 970 // emit mips psuedo-instructions, which are checked and handled here. | 966 // emit mips psuedo-instructions, which are checked and handled here. |
| 971 | 967 |
| 972 // For materializations, we use delay slot to set the result true, and | |
| 973 // in the false case, where we fall thru the branch, we reset the result | |
| 974 // false. | |
| 975 | |
| 976 if (instr->arch_opcode() == kMipsTst) { | 968 if (instr->arch_opcode() == kMipsTst) { |
| 977 cc = FlagsConditionToConditionTst(condition); | 969 cc = FlagsConditionToConditionTst(condition); |
| 978 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 970 __ And(kScratchReg, i.InputRegister(0), i.InputOperand(1)); |
| 979 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); | 971 __ xori(result, zero_reg, 1); // Create 1 for true. |
| 980 __ li(result, Operand(1)); // In delay slot. | 972 if (IsMipsArchVariant(kMips32r6)) { |
| 981 | 973 if (cc == eq) { |
| 974 __ seleqz(result, result, kScratchReg); |
| 975 } else { |
| 976 __ selnez(result, result, kScratchReg); |
| 977 } |
| 978 } else { |
| 979 if (cc == eq) { |
| 980 __ Movn(result, zero_reg, kScratchReg); |
| 981 } else { |
| 982 __ Movz(result, zero_reg, kScratchReg); |
| 983 } |
| 984 } |
| 985 return; |
| 982 } else if (instr->arch_opcode() == kMipsAddOvf || | 986 } else if (instr->arch_opcode() == kMipsAddOvf || |
| 983 instr->arch_opcode() == kMipsSubOvf) { | 987 instr->arch_opcode() == kMipsSubOvf) { |
| 984 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. | 988 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. |
| 985 cc = FlagsConditionToConditionOvf(condition); | 989 cc = FlagsConditionToConditionOvf(condition); |
| 986 __ Branch(USE_DELAY_SLOT, &done, cc, kCompareReg, Operand(zero_reg)); | 990 // Return 1 on overflow. |
| 987 __ li(result, Operand(1)); // In delay slot. | 991 __ Slt(result, kCompareReg, Operand(zero_reg)); |
| 988 | 992 if (cc == ge) // Invert result on not overflow. |
| 993 __ xori(result, result, 1); |
| 994 return; |
| 989 } else if (instr->arch_opcode() == kMipsCmp) { | 995 } else if (instr->arch_opcode() == kMipsCmp) { |
| 990 Register left = i.InputRegister(0); | |
| 991 Operand right = i.InputOperand(1); | |
| 992 cc = FlagsConditionToConditionCmp(condition); | 996 cc = FlagsConditionToConditionCmp(condition); |
| 993 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); | 997 switch (cc) { |
| 994 __ li(result, Operand(1)); // In delay slot. | 998 case eq: |
| 995 | 999 case ne: { |
| 1000 Register left = i.InputRegister(0); |
| 1001 Operand right = i.InputOperand(1); |
| 1002 __ Subu(kScratchReg, left, right); |
| 1003 __ xori(result, zero_reg, 1); |
| 1004 if (IsMipsArchVariant(kMips32r6)) { |
| 1005 if (cc == eq) { |
| 1006 __ seleqz(result, result, kScratchReg); |
| 1007 } else { |
| 1008 __ selnez(result, result, kScratchReg); |
| 1009 } |
| 1010 } else { |
| 1011 if (cc == eq) { |
| 1012 __ Movn(result, zero_reg, kScratchReg); |
| 1013 } else { |
| 1014 __ Movz(result, zero_reg, kScratchReg); |
| 1015 } |
| 1016 } |
| 1017 } break; |
| 1018 case lt: |
| 1019 case ge: { |
| 1020 Register left = i.InputRegister(0); |
| 1021 Operand right = i.InputOperand(1); |
| 1022 __ Slt(result, left, right); |
| 1023 if (cc == ge) { |
| 1024 __ xori(result, result, 1); |
| 1025 } |
| 1026 } break; |
| 1027 case gt: |
| 1028 case le: { |
| 1029 Register left = i.InputRegister(1); |
| 1030 Operand right = i.InputOperand(0); |
| 1031 __ Slt(result, left, right); |
| 1032 if (cc == le) { |
| 1033 __ xori(result, result, 1); |
| 1034 } |
| 1035 } break; |
| 1036 case lo: |
| 1037 case hs: { |
| 1038 Register left = i.InputRegister(0); |
| 1039 Operand right = i.InputOperand(1); |
| 1040 __ Sltu(result, left, right); |
| 1041 if (cc == hs) { |
| 1042 __ xori(result, result, 1); |
| 1043 } |
| 1044 } break; |
| 1045 case hi: |
| 1046 case ls: { |
| 1047 Register left = i.InputRegister(1); |
| 1048 Operand right = i.InputOperand(0); |
| 1049 __ Sltu(result, left, right); |
| 1050 if (cc == ls) { |
| 1051 __ xori(result, result, 1); |
| 1052 } |
| 1053 } break; |
| 1054 default: |
| 1055 UNREACHABLE(); |
| 1056 } |
| 1057 return; |
| 996 } else if (instr->arch_opcode() == kMipsCmpD || | 1058 } else if (instr->arch_opcode() == kMipsCmpD || |
| 997 instr->arch_opcode() == kMipsCmpS) { | 1059 instr->arch_opcode() == kMipsCmpS) { |
| 998 FPURegister left = i.InputDoubleRegister(0); | 1060 FPURegister left = i.InputDoubleRegister(0); |
| 999 FPURegister right = i.InputDoubleRegister(1); | 1061 FPURegister right = i.InputDoubleRegister(1); |
| 1000 | |
| 1001 bool predicate; | 1062 bool predicate; |
| 1002 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition); | 1063 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition); |
| 1003 if (!IsMipsArchVariant(kMips32r6)) { | 1064 if (!IsMipsArchVariant(kMips32r6)) { |
| 1004 __ li(result, Operand(1)); | 1065 __ li(result, Operand(1)); |
| 1005 if (instr->arch_opcode() == kMipsCmpD) { | 1066 if (instr->arch_opcode() == kMipsCmpD) { |
| 1006 __ c(cc, D, left, right); | 1067 __ c(cc, D, left, right); |
| 1007 } else { | 1068 } else { |
| 1008 DCHECK(instr->arch_opcode() == kMipsCmpS); | 1069 DCHECK(instr->arch_opcode() == kMipsCmpS); |
| 1009 __ c(cc, S, left, right); | 1070 __ c(cc, S, left, right); |
| 1010 } | 1071 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1025 if (!predicate) // Toggle result for not equal. | 1086 if (!predicate) // Toggle result for not equal. |
| 1026 __ xori(result, result, 1); | 1087 __ xori(result, result, 1); |
| 1027 } | 1088 } |
| 1028 return; | 1089 return; |
| 1029 } else { | 1090 } else { |
| 1030 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", | 1091 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", |
| 1031 instr->arch_opcode()); | 1092 instr->arch_opcode()); |
| 1032 TRACE_UNIMPL(); | 1093 TRACE_UNIMPL(); |
| 1033 UNIMPLEMENTED(); | 1094 UNIMPLEMENTED(); |
| 1034 } | 1095 } |
| 1035 | |
| 1036 // Fallthrough case is the false materialization. | |
| 1037 __ bind(&false_value); | |
| 1038 __ li(result, Operand(0)); | |
| 1039 __ bind(&done); | |
| 1040 } | 1096 } |
| 1041 | 1097 |
| 1042 | 1098 |
| 1043 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { | 1099 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { |
| 1044 MipsOperandConverter i(this, instr); | 1100 MipsOperandConverter i(this, instr); |
| 1045 Register input = i.InputRegister(0); | 1101 Register input = i.InputRegister(0); |
| 1046 for (size_t index = 2; index < instr->InputCount(); index += 2) { | 1102 for (size_t index = 2; index < instr->InputCount(); index += 2) { |
| 1047 __ li(at, Operand(i.InputInt32(index + 0))); | 1103 __ li(at, Operand(i.InputInt32(index + 0))); |
| 1048 __ beq(input, at, GetLabel(i.InputRpo(index + 1))); | 1104 __ beq(input, at, GetLabel(i.InputRpo(index + 1))); |
| 1049 } | 1105 } |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1384 padding_size -= v8::internal::Assembler::kInstrSize; | 1440 padding_size -= v8::internal::Assembler::kInstrSize; |
| 1385 } | 1441 } |
| 1386 } | 1442 } |
| 1387 } | 1443 } |
| 1388 | 1444 |
| 1389 #undef __ | 1445 #undef __ |
| 1390 | 1446 |
| 1391 } // namespace compiler | 1447 } // namespace compiler |
| 1392 } // namespace internal | 1448 } // namespace internal |
| 1393 } // namespace v8 | 1449 } // namespace v8 |
| OLD | NEW |