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 |