Chromium Code Reviews| 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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 193 }; | 193 }; |
| 194 | 194 |
| 195 | 195 |
| 196 class OutOfLineCeil final : public OutOfLineRound { | 196 class OutOfLineCeil final : public OutOfLineRound { |
| 197 public: | 197 public: |
| 198 OutOfLineCeil(CodeGenerator* gen, DoubleRegister result) | 198 OutOfLineCeil(CodeGenerator* gen, DoubleRegister result) |
| 199 : OutOfLineRound(gen, result) {} | 199 : OutOfLineRound(gen, result) {} |
| 200 }; | 200 }; |
| 201 | 201 |
| 202 | 202 |
| 203 Condition FlagsConditionToConditionCmp(FlagsCondition condition) { | 203 Condition FlagsConditionToConditionCmp(bool& predicate, |
| 204 FlagsCondition condition) { | |
| 204 switch (condition) { | 205 switch (condition) { |
| 205 case kEqual: | 206 case kEqual: |
| 207 predicate = true; | |
| 206 return eq; | 208 return eq; |
| 207 case kNotEqual: | 209 case kNotEqual: |
| 210 predicate = false; | |
| 208 return ne; | 211 return ne; |
| 209 case kSignedLessThan: | 212 case kSignedLessThan: |
| 213 predicate = true; | |
| 210 return lt; | 214 return lt; |
| 211 case kSignedGreaterThanOrEqual: | 215 case kSignedGreaterThanOrEqual: |
| 216 predicate = false; | |
| 212 return ge; | 217 return ge; |
| 213 case kSignedLessThanOrEqual: | 218 case kSignedLessThanOrEqual: |
| 219 predicate = false; | |
| 214 return le; | 220 return le; |
| 215 case kSignedGreaterThan: | 221 case kSignedGreaterThan: |
| 222 predicate = true; | |
| 216 return gt; | 223 return gt; |
| 217 case kUnsignedLessThan: | 224 case kUnsignedLessThan: |
| 225 predicate = true; | |
| 218 return lo; | 226 return lo; |
| 219 case kUnsignedGreaterThanOrEqual: | 227 case kUnsignedGreaterThanOrEqual: |
| 228 predicate = false; | |
| 220 return hs; | 229 return hs; |
| 221 case kUnsignedLessThanOrEqual: | 230 case kUnsignedLessThanOrEqual: |
| 231 predicate = false; | |
| 222 return ls; | 232 return ls; |
| 223 case kUnsignedGreaterThan: | 233 case kUnsignedGreaterThan: |
| 234 predicate = true; | |
| 224 return hi; | 235 return hi; |
| 225 case kUnorderedEqual: | 236 case kUnorderedEqual: |
| 226 case kUnorderedNotEqual: | 237 case kUnorderedNotEqual: |
| 227 break; | 238 break; |
| 228 default: | 239 default: |
| 229 break; | 240 break; |
| 230 } | 241 } |
| 231 UNREACHABLE(); | 242 UNREACHABLE(); |
| 232 return kNoCondition; | 243 return kNoCondition; |
| 233 } | 244 } |
| 234 | 245 |
| 235 | 246 |
| 236 Condition FlagsConditionToConditionTst(FlagsCondition condition) { | 247 Condition FlagsConditionToConditionTst(bool& predicate, |
| 248 FlagsCondition condition) { | |
| 237 switch (condition) { | 249 switch (condition) { |
| 238 case kNotEqual: | 250 case kNotEqual: |
| 251 predicate = false; | |
| 239 return ne; | 252 return ne; |
| 240 case kEqual: | 253 case kEqual: |
| 254 predicate = true; | |
| 241 return eq; | 255 return eq; |
| 242 default: | 256 default: |
| 243 break; | 257 break; |
| 244 } | 258 } |
| 245 UNREACHABLE(); | 259 UNREACHABLE(); |
| 246 return kNoCondition; | 260 return kNoCondition; |
| 247 } | 261 } |
| 248 | 262 |
| 249 | 263 |
| 250 Condition FlagsConditionToConditionOvf(FlagsCondition condition) { | 264 Condition FlagsConditionToConditionOvf(bool& predicate, |
| 265 FlagsCondition condition) { | |
| 251 switch (condition) { | 266 switch (condition) { |
| 252 case kOverflow: | 267 case kOverflow: |
| 268 predicate = true; | |
| 253 return ne; | 269 return ne; |
| 254 case kNotOverflow: | 270 case kNotOverflow: |
| 271 predicate = false; | |
| 255 return eq; | 272 return eq; |
| 256 default: | 273 default: |
| 257 break; | 274 break; |
| 258 } | 275 } |
| 259 UNREACHABLE(); | 276 UNREACHABLE(); |
| 260 return kNoCondition; | 277 return kNoCondition; |
| 261 } | 278 } |
| 262 | 279 |
| 263 | 280 |
| 264 FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate, | 281 FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate, |
| (...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 958 return false; | 975 return false; |
| 959 } | 976 } |
| 960 | 977 |
| 961 | 978 |
| 962 // Assembles branches after an instruction. | 979 // Assembles branches after an instruction. |
| 963 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 980 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
| 964 MipsOperandConverter i(this, instr); | 981 MipsOperandConverter i(this, instr); |
| 965 Label* tlabel = branch->true_label; | 982 Label* tlabel = branch->true_label; |
| 966 Label* flabel = branch->false_label; | 983 Label* flabel = branch->false_label; |
| 967 Condition cc = kNoCondition; | 984 Condition cc = kNoCondition; |
| 968 | 985 bool predicate; |
| 969 // MIPS does not have condition code flags, so compare and branch are | 986 // MIPS does not have condition code flags, so compare and branch are |
| 970 // implemented differently than on the other arch's. The compare operations | 987 // implemented differently than on the other arch's. The compare operations |
| 971 // emit mips psuedo-instructions, which are handled here by branch | 988 // emit mips psuedo-instructions, which are handled here by branch |
| 972 // instructions that do the actual comparison. Essential that the input | 989 // instructions that do the actual comparison. Essential that the input |
| 973 // registers to compare pseudo-op are not modified before this branch op, as | 990 // registers to compare pseudo-op are not modified before this branch op, as |
| 974 // they are tested here. | 991 // they are tested here. |
| 975 | 992 |
| 976 if (instr->arch_opcode() == kMips64Tst) { | 993 if (instr->arch_opcode() == kMips64Tst) { |
| 977 cc = FlagsConditionToConditionTst(branch->condition); | 994 cc = FlagsConditionToConditionTst(predicate, branch->condition); |
| 978 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 995 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
| 979 __ Branch(tlabel, cc, at, Operand(zero_reg)); | 996 __ Branch(tlabel, cc, at, Operand(zero_reg)); |
| 980 } else if (instr->arch_opcode() == kMips64Dadd || | 997 } else if (instr->arch_opcode() == kMips64Dadd || |
| 981 instr->arch_opcode() == kMips64Dsub) { | 998 instr->arch_opcode() == kMips64Dsub) { |
| 982 cc = FlagsConditionToConditionOvf(branch->condition); | 999 cc = FlagsConditionToConditionOvf(predicate, branch->condition); |
| 983 __ dsra32(kScratchReg, i.OutputRegister(), 0); | 1000 __ dsra32(kScratchReg, i.OutputRegister(), 0); |
| 984 __ sra(at, i.OutputRegister(), 31); | 1001 __ sra(at, i.OutputRegister(), 31); |
| 985 __ Branch(tlabel, cc, at, Operand(kScratchReg)); | 1002 __ Branch(tlabel, cc, at, Operand(kScratchReg)); |
| 986 } else if (instr->arch_opcode() == kMips64Cmp) { | 1003 } else if (instr->arch_opcode() == kMips64Cmp) { |
| 987 cc = FlagsConditionToConditionCmp(branch->condition); | 1004 cc = FlagsConditionToConditionCmp(predicate, branch->condition); |
| 988 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); | 1005 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); |
| 989 } else if (instr->arch_opcode() == kMips64CmpS) { | 1006 } else if (instr->arch_opcode() == kMips64CmpS) { |
| 990 if (!convertCondition(branch->condition, cc)) { | 1007 if (!convertCondition(branch->condition, cc)) { |
| 991 UNSUPPORTED_COND(kMips64CmpS, branch->condition); | 1008 UNSUPPORTED_COND(kMips64CmpS, branch->condition); |
| 992 } | 1009 } |
| 993 __ BranchF32(tlabel, NULL, cc, i.InputSingleRegister(0), | 1010 __ BranchF32(tlabel, NULL, cc, i.InputSingleRegister(0), |
| 994 i.InputSingleRegister(1)); | 1011 i.InputSingleRegister(1)); |
| 995 } else if (instr->arch_opcode() == kMips64CmpD) { | 1012 } else if (instr->arch_opcode() == kMips64CmpD) { |
| 996 if (!convertCondition(branch->condition, cc)) { | 1013 if (!convertCondition(branch->condition, cc)) { |
| 997 UNSUPPORTED_COND(kMips64CmpD, branch->condition); | 1014 UNSUPPORTED_COND(kMips64CmpD, branch->condition); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1017 FlagsCondition condition) { | 1034 FlagsCondition condition) { |
| 1018 MipsOperandConverter i(this, instr); | 1035 MipsOperandConverter i(this, instr); |
| 1019 Label done; | 1036 Label done; |
| 1020 | 1037 |
| 1021 // Materialize a full 32-bit 1 or 0 value. The result register is always the | 1038 // Materialize a full 32-bit 1 or 0 value. The result register is always the |
| 1022 // last output of the instruction. | 1039 // last output of the instruction. |
| 1023 Label false_value; | 1040 Label false_value; |
| 1024 DCHECK_NE(0u, instr->OutputCount()); | 1041 DCHECK_NE(0u, instr->OutputCount()); |
| 1025 Register result = i.OutputRegister(instr->OutputCount() - 1); | 1042 Register result = i.OutputRegister(instr->OutputCount() - 1); |
| 1026 Condition cc = kNoCondition; | 1043 Condition cc = kNoCondition; |
| 1027 | 1044 bool predicate; |
| 1028 // MIPS does not have condition code flags, so compare and branch are | 1045 // MIPS does not have condition code flags, so compare and branch are |
| 1029 // implemented differently than on the other arch's. The compare operations | 1046 // implemented differently than on the other arch's. The compare operations |
| 1030 // emit mips pseudo-instructions, which are checked and handled here. | 1047 // emit mips pseudo-instructions, which are checked and handled here. |
| 1031 | 1048 |
| 1032 // For materializations, we use delay slot to set the result true, and | 1049 // For materializations, we use delay slot to set the result true, and |
| 1033 // in the false case, where we fall through the branch, we reset the result | 1050 // in the false case, where we fall through the branch, we reset the result |
| 1034 // false. | 1051 // false. |
|
paul.l...
2015/08/15 00:22:31
With your change, the above comment should be dele
| |
| 1035 | 1052 |
| 1036 if (instr->arch_opcode() == kMips64Tst) { | 1053 if (instr->arch_opcode() == kMips64Tst) { |
| 1037 cc = FlagsConditionToConditionTst(condition); | 1054 cc = FlagsConditionToConditionTst(predicate, condition); |
| 1038 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 1055 __ And(kScratchReg, i.InputRegister(0), i.InputOperand(1)); |
| 1039 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); | 1056 __ xori(kScratchReg2, zero_reg, 1); |
| 1040 __ li(result, Operand(1)); // In delay slot. | 1057 if (predicate) { |
| 1058 __ Movn(result, zero_reg, kScratchReg); | |
| 1059 __ Movz(result, kScratchReg2, kScratchReg); | |
|
paul.l...
2015/08/15 00:22:31
I'm not sure this is a good idea anymore, due to t
| |
| 1060 } else { | |
| 1061 __ Movz(result, zero_reg, kScratchReg); | |
| 1062 __ Movn(result, kScratchReg2, kScratchReg); | |
| 1063 } | |
| 1064 return; | |
| 1041 } else if (instr->arch_opcode() == kMips64Dadd || | 1065 } else if (instr->arch_opcode() == kMips64Dadd || |
| 1042 instr->arch_opcode() == kMips64Dsub) { | 1066 instr->arch_opcode() == kMips64Dsub) { |
| 1043 cc = FlagsConditionToConditionOvf(condition); | 1067 FlagsConditionToConditionOvf(predicate, condition); |
| 1044 __ dsra32(kScratchReg, i.OutputRegister(), 0); | 1068 __ dsrl32(kScratchReg, i.OutputRegister(), 31); |
| 1045 __ sra(at, i.OutputRegister(), 31); | 1069 __ srl(at, i.OutputRegister(), 31); |
| 1046 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(kScratchReg)); | 1070 __ xor_(result, kScratchReg, at); |
| 1047 __ li(result, Operand(1)); // In delay slot. | 1071 if (!predicate) __ xori(result, result, 1); |
|
paul.l...
2015/08/15 00:22:31
OK, it must be too late on Friday night, but I am
| |
| 1072 return; | |
| 1048 } else if (instr->arch_opcode() == kMips64Cmp) { | 1073 } else if (instr->arch_opcode() == kMips64Cmp) { |
| 1049 Register left = i.InputRegister(0); | 1074 cc = FlagsConditionToConditionCmp(predicate, condition); |
| 1050 Operand right = i.InputOperand(1); | 1075 switch (cc) { |
| 1051 cc = FlagsConditionToConditionCmp(condition); | 1076 case eq: |
| 1052 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); | 1077 case ne: { |
| 1053 __ li(result, Operand(1)); // In delay slot. | 1078 Register left = i.InputRegister(0); |
| 1079 Operand right = i.InputOperand(1); | |
| 1080 __ Dsubu(kScratchReg, left, right); | |
| 1081 __ xori(kScratchReg2, zero_reg, 1); | |
| 1082 if (predicate) { | |
| 1083 __ Movn(result, zero_reg, kScratchReg); | |
| 1084 __ Movz(result, kScratchReg2, kScratchReg); | |
| 1085 } else { | |
| 1086 __ Movz(result, zero_reg, kScratchReg); | |
| 1087 __ Movn(result, kScratchReg2, kScratchReg); | |
| 1088 } | |
| 1089 } break; | |
| 1090 case lt: | |
| 1091 case ge: { | |
| 1092 Register left = i.InputRegister(0); | |
| 1093 Operand right = i.InputOperand(1); | |
| 1094 __ Slt(result, left, right); | |
| 1095 if (!predicate) { | |
| 1096 __ xori(result, result, 1); | |
| 1097 } | |
| 1098 } break; | |
| 1099 case gt: | |
| 1100 case le: { | |
| 1101 Register left = i.InputRegister(1); | |
| 1102 Operand right = i.InputOperand(0); | |
| 1103 __ Slt(result, left, right); | |
| 1104 if (!predicate) { | |
| 1105 __ xori(result, result, 1); | |
| 1106 } | |
| 1107 } break; | |
| 1108 case lo: | |
| 1109 case hs: { | |
| 1110 Register left = i.InputRegister(0); | |
| 1111 Operand right = i.InputOperand(1); | |
| 1112 __ Sltu(result, left, right); | |
| 1113 if (!predicate) { | |
| 1114 __ xori(result, result, 1); | |
| 1115 } | |
| 1116 } break; | |
| 1117 case hi: | |
| 1118 case ls: { | |
| 1119 Register left = i.InputRegister(1); | |
| 1120 Operand right = i.InputOperand(0); | |
| 1121 __ Sltu(result, left, right); | |
| 1122 if (!predicate) { | |
| 1123 __ xori(result, result, 1); | |
| 1124 } | |
| 1125 } break; | |
| 1126 default: | |
| 1127 UNREACHABLE(); | |
| 1128 } | |
| 1129 return; | |
| 1054 } else if (instr->arch_opcode() == kMips64CmpD || | 1130 } else if (instr->arch_opcode() == kMips64CmpD || |
| 1055 instr->arch_opcode() == kMips64CmpS) { | 1131 instr->arch_opcode() == kMips64CmpS) { |
| 1056 FPURegister left = i.InputDoubleRegister(0); | 1132 FPURegister left = i.InputDoubleRegister(0); |
| 1057 FPURegister right = i.InputDoubleRegister(1); | 1133 FPURegister right = i.InputDoubleRegister(1); |
| 1058 | 1134 |
| 1059 bool predicate; | |
| 1060 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition); | 1135 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition); |
| 1061 if (kArchVariant != kMips64r6) { | 1136 if (kArchVariant != kMips64r6) { |
| 1062 __ li(result, Operand(1)); | 1137 __ li(result, Operand(1)); |
| 1063 if (instr->arch_opcode() == kMips64CmpD) { | 1138 if (instr->arch_opcode() == kMips64CmpD) { |
| 1064 __ c(cc, D, left, right); | 1139 __ c(cc, D, left, right); |
| 1065 } else { | 1140 } else { |
| 1066 DCHECK(instr->arch_opcode() == kMips64CmpS); | 1141 DCHECK(instr->arch_opcode() == kMips64CmpS); |
| 1067 __ c(cc, S, left, right); | 1142 __ c(cc, S, left, right); |
| 1068 } | 1143 } |
| 1069 if (predicate) { | 1144 if (predicate) { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1083 if (!predicate) // Toggle result for not equal. | 1158 if (!predicate) // Toggle result for not equal. |
| 1084 __ xori(result, result, 1); | 1159 __ xori(result, result, 1); |
| 1085 } | 1160 } |
| 1086 return; | 1161 return; |
| 1087 } else { | 1162 } else { |
| 1088 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", | 1163 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", |
| 1089 instr->arch_opcode()); | 1164 instr->arch_opcode()); |
| 1090 TRACE_UNIMPL(); | 1165 TRACE_UNIMPL(); |
| 1091 UNIMPLEMENTED(); | 1166 UNIMPLEMENTED(); |
| 1092 } | 1167 } |
| 1093 // Fallthru case is the false materialization. | |
| 1094 __ bind(&false_value); | |
| 1095 __ li(result, Operand(static_cast<int64_t>(0))); | |
| 1096 __ bind(&done); | |
| 1097 } | 1168 } |
| 1098 | 1169 |
| 1099 | 1170 |
| 1100 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { | 1171 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { |
| 1101 MipsOperandConverter i(this, instr); | 1172 MipsOperandConverter i(this, instr); |
| 1102 Register input = i.InputRegister(0); | 1173 Register input = i.InputRegister(0); |
| 1103 for (size_t index = 2; index < instr->InputCount(); index += 2) { | 1174 for (size_t index = 2; index < instr->InputCount(); index += 2) { |
| 1104 __ li(at, Operand(i.InputInt32(index + 0))); | 1175 __ li(at, Operand(i.InputInt32(index + 0))); |
| 1105 __ beq(input, at, GetLabel(i.InputRpo(index + 1))); | 1176 __ beq(input, at, GetLabel(i.InputRpo(index + 1))); |
| 1106 } | 1177 } |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1443 } | 1514 } |
| 1444 } | 1515 } |
| 1445 } | 1516 } |
| 1446 } | 1517 } |
| 1447 | 1518 |
| 1448 #undef __ | 1519 #undef __ |
| 1449 | 1520 |
| 1450 } // namespace compiler | 1521 } // namespace compiler |
| 1451 } // namespace internal | 1522 } // namespace internal |
| 1452 } // namespace v8 | 1523 } // namespace v8 |
| OLD | NEW |