| 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 957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 968 return false; | 968 return false; |
| 969 } | 969 } |
| 970 | 970 |
| 971 | 971 |
| 972 // Assembles branches after an instruction. | 972 // Assembles branches after an instruction. |
| 973 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 973 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
| 974 MipsOperandConverter i(this, instr); | 974 MipsOperandConverter i(this, instr); |
| 975 Label* tlabel = branch->true_label; | 975 Label* tlabel = branch->true_label; |
| 976 Label* flabel = branch->false_label; | 976 Label* flabel = branch->false_label; |
| 977 Condition cc = kNoCondition; | 977 Condition cc = kNoCondition; |
| 978 | |
| 979 // MIPS does not have condition code flags, so compare and branch are | 978 // MIPS does not have condition code flags, so compare and branch are |
| 980 // implemented differently than on the other arch's. The compare operations | 979 // implemented differently than on the other arch's. The compare operations |
| 981 // emit mips psuedo-instructions, which are handled here by branch | 980 // emit mips psuedo-instructions, which are handled here by branch |
| 982 // instructions that do the actual comparison. Essential that the input | 981 // instructions that do the actual comparison. Essential that the input |
| 983 // registers to compare pseudo-op are not modified before this branch op, as | 982 // registers to compare pseudo-op are not modified before this branch op, as |
| 984 // they are tested here. | 983 // they are tested here. |
| 985 | 984 |
| 986 if (instr->arch_opcode() == kMips64Tst) { | 985 if (instr->arch_opcode() == kMips64Tst) { |
| 987 cc = FlagsConditionToConditionTst(branch->condition); | 986 cc = FlagsConditionToConditionTst(branch->condition); |
| 988 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 987 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1027 FlagsCondition condition) { | 1026 FlagsCondition condition) { |
| 1028 MipsOperandConverter i(this, instr); | 1027 MipsOperandConverter i(this, instr); |
| 1029 Label done; | 1028 Label done; |
| 1030 | 1029 |
| 1031 // Materialize a full 32-bit 1 or 0 value. The result register is always the | 1030 // Materialize a full 32-bit 1 or 0 value. The result register is always the |
| 1032 // last output of the instruction. | 1031 // last output of the instruction. |
| 1033 Label false_value; | 1032 Label false_value; |
| 1034 DCHECK_NE(0u, instr->OutputCount()); | 1033 DCHECK_NE(0u, instr->OutputCount()); |
| 1035 Register result = i.OutputRegister(instr->OutputCount() - 1); | 1034 Register result = i.OutputRegister(instr->OutputCount() - 1); |
| 1036 Condition cc = kNoCondition; | 1035 Condition cc = kNoCondition; |
| 1037 | |
| 1038 // MIPS does not have condition code flags, so compare and branch are | 1036 // MIPS does not have condition code flags, so compare and branch are |
| 1039 // implemented differently than on the other arch's. The compare operations | 1037 // implemented differently than on the other arch's. The compare operations |
| 1040 // emit mips pseudo-instructions, which are checked and handled here. | 1038 // emit mips pseudo-instructions, which are checked and handled here. |
| 1041 | 1039 |
| 1042 // For materializations, we use delay slot to set the result true, and | |
| 1043 // in the false case, where we fall through the branch, we reset the result | |
| 1044 // false. | |
| 1045 | |
| 1046 if (instr->arch_opcode() == kMips64Tst) { | 1040 if (instr->arch_opcode() == kMips64Tst) { |
| 1047 cc = FlagsConditionToConditionTst(condition); | 1041 cc = FlagsConditionToConditionTst(condition); |
| 1048 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 1042 __ And(kScratchReg, i.InputRegister(0), i.InputOperand(1)); |
| 1049 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); | 1043 __ xori(result, zero_reg, 1); // Create 1 for true. |
| 1050 __ li(result, Operand(1)); // In delay slot. | 1044 if (kArchVariant == kMips64r6) { |
| 1045 if (cc == eq) { |
| 1046 __ seleqz(result, result, kScratchReg); |
| 1047 } else { |
| 1048 __ selnez(result, result, kScratchReg); |
| 1049 } |
| 1050 } else { |
| 1051 if (cc == eq) { |
| 1052 __ Movn(result, zero_reg, kScratchReg); |
| 1053 } else { |
| 1054 __ Movz(result, zero_reg, kScratchReg); |
| 1055 } |
| 1056 } |
| 1057 return; |
| 1051 } else if (instr->arch_opcode() == kMips64Dadd || | 1058 } else if (instr->arch_opcode() == kMips64Dadd || |
| 1052 instr->arch_opcode() == kMips64Dsub) { | 1059 instr->arch_opcode() == kMips64Dsub) { |
| 1053 cc = FlagsConditionToConditionOvf(condition); | 1060 cc = FlagsConditionToConditionOvf(condition); |
| 1054 __ dsra32(kScratchReg, i.OutputRegister(), 0); | 1061 // Check for overflow creates 1 or 0 for result. |
| 1055 __ sra(at, i.OutputRegister(), 31); | 1062 __ dsrl32(kScratchReg, i.OutputRegister(), 31); |
| 1056 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(kScratchReg)); | 1063 __ srl(at, i.OutputRegister(), 31); |
| 1057 __ li(result, Operand(1)); // In delay slot. | 1064 __ xor_(result, kScratchReg, at); |
| 1065 if (cc == eq) // Toggle result for not overflow. |
| 1066 __ xori(result, result, 1); |
| 1067 return; |
| 1058 } else if (instr->arch_opcode() == kMips64Cmp) { | 1068 } else if (instr->arch_opcode() == kMips64Cmp) { |
| 1059 Register left = i.InputRegister(0); | |
| 1060 Operand right = i.InputOperand(1); | |
| 1061 cc = FlagsConditionToConditionCmp(condition); | 1069 cc = FlagsConditionToConditionCmp(condition); |
| 1062 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); | 1070 switch (cc) { |
| 1063 __ li(result, Operand(1)); // In delay slot. | 1071 case eq: |
| 1072 case ne: { |
| 1073 Register left = i.InputRegister(0); |
| 1074 Operand right = i.InputOperand(1); |
| 1075 __ Dsubu(kScratchReg, left, right); |
| 1076 __ xori(result, zero_reg, 1); |
| 1077 if (kArchVariant == kMips64r6) { |
| 1078 if (cc == eq) { |
| 1079 __ seleqz(result, result, kScratchReg); |
| 1080 } else { |
| 1081 __ selnez(result, result, kScratchReg); |
| 1082 } |
| 1083 } else { |
| 1084 if (cc == eq) { |
| 1085 __ Movn(result, zero_reg, kScratchReg); |
| 1086 } else { |
| 1087 __ Movz(result, zero_reg, kScratchReg); |
| 1088 } |
| 1089 } |
| 1090 } break; |
| 1091 case lt: |
| 1092 case ge: { |
| 1093 Register left = i.InputRegister(0); |
| 1094 Operand right = i.InputOperand(1); |
| 1095 __ Slt(result, left, right); |
| 1096 if (cc == ge) { |
| 1097 __ xori(result, result, 1); |
| 1098 } |
| 1099 } break; |
| 1100 case gt: |
| 1101 case le: { |
| 1102 Register left = i.InputRegister(1); |
| 1103 Operand right = i.InputOperand(0); |
| 1104 __ Slt(result, left, right); |
| 1105 if (cc == le) { |
| 1106 __ xori(result, result, 1); |
| 1107 } |
| 1108 } break; |
| 1109 case lo: |
| 1110 case hs: { |
| 1111 Register left = i.InputRegister(0); |
| 1112 Operand right = i.InputOperand(1); |
| 1113 __ Sltu(result, left, right); |
| 1114 if (cc == hs) { |
| 1115 __ xori(result, result, 1); |
| 1116 } |
| 1117 } break; |
| 1118 case hi: |
| 1119 case ls: { |
| 1120 Register left = i.InputRegister(1); |
| 1121 Operand right = i.InputOperand(0); |
| 1122 __ Sltu(result, left, right); |
| 1123 if (cc == ls) { |
| 1124 __ xori(result, result, 1); |
| 1125 } |
| 1126 } break; |
| 1127 default: |
| 1128 UNREACHABLE(); |
| 1129 } |
| 1130 return; |
| 1064 } else if (instr->arch_opcode() == kMips64CmpD || | 1131 } else if (instr->arch_opcode() == kMips64CmpD || |
| 1065 instr->arch_opcode() == kMips64CmpS) { | 1132 instr->arch_opcode() == kMips64CmpS) { |
| 1066 FPURegister left = i.InputDoubleRegister(0); | 1133 FPURegister left = i.InputDoubleRegister(0); |
| 1067 FPURegister right = i.InputDoubleRegister(1); | 1134 FPURegister right = i.InputDoubleRegister(1); |
| 1068 | |
| 1069 bool predicate; | 1135 bool predicate; |
| 1070 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition); | 1136 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition); |
| 1071 if (kArchVariant != kMips64r6) { | 1137 if (kArchVariant != kMips64r6) { |
| 1072 __ li(result, Operand(1)); | 1138 __ li(result, Operand(1)); |
| 1073 if (instr->arch_opcode() == kMips64CmpD) { | 1139 if (instr->arch_opcode() == kMips64CmpD) { |
| 1074 __ c(cc, D, left, right); | 1140 __ c(cc, D, left, right); |
| 1075 } else { | 1141 } else { |
| 1076 DCHECK(instr->arch_opcode() == kMips64CmpS); | 1142 DCHECK(instr->arch_opcode() == kMips64CmpS); |
| 1077 __ c(cc, S, left, right); | 1143 __ c(cc, S, left, right); |
| 1078 } | 1144 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1093 if (!predicate) // Toggle result for not equal. | 1159 if (!predicate) // Toggle result for not equal. |
| 1094 __ xori(result, result, 1); | 1160 __ xori(result, result, 1); |
| 1095 } | 1161 } |
| 1096 return; | 1162 return; |
| 1097 } else { | 1163 } else { |
| 1098 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", | 1164 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", |
| 1099 instr->arch_opcode()); | 1165 instr->arch_opcode()); |
| 1100 TRACE_UNIMPL(); | 1166 TRACE_UNIMPL(); |
| 1101 UNIMPLEMENTED(); | 1167 UNIMPLEMENTED(); |
| 1102 } | 1168 } |
| 1103 // Fallthru case is the false materialization. | |
| 1104 __ bind(&false_value); | |
| 1105 __ li(result, Operand(static_cast<int64_t>(0))); | |
| 1106 __ bind(&done); | |
| 1107 } | 1169 } |
| 1108 | 1170 |
| 1109 | 1171 |
| 1110 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { | 1172 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { |
| 1111 MipsOperandConverter i(this, instr); | 1173 MipsOperandConverter i(this, instr); |
| 1112 Register input = i.InputRegister(0); | 1174 Register input = i.InputRegister(0); |
| 1113 for (size_t index = 2; index < instr->InputCount(); index += 2) { | 1175 for (size_t index = 2; index < instr->InputCount(); index += 2) { |
| 1114 __ li(at, Operand(i.InputInt32(index + 0))); | 1176 __ li(at, Operand(i.InputInt32(index + 0))); |
| 1115 __ beq(input, at, GetLabel(i.InputRpo(index + 1))); | 1177 __ beq(input, at, GetLabel(i.InputRpo(index + 1))); |
| 1116 } | 1178 } |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1453 padding_size -= v8::internal::Assembler::kInstrSize; | 1515 padding_size -= v8::internal::Assembler::kInstrSize; |
| 1454 } | 1516 } |
| 1455 } | 1517 } |
| 1456 } | 1518 } |
| 1457 | 1519 |
| 1458 #undef __ | 1520 #undef __ |
| 1459 | 1521 |
| 1460 } // namespace compiler | 1522 } // namespace compiler |
| 1461 } // namespace internal | 1523 } // namespace internal |
| 1462 } // namespace v8 | 1524 } // namespace v8 |
| OLD | NEW |