| 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: |
| 238 predicate = true; |
| 227 break; | 239 break; |
| 228 default: | 240 default: |
| 241 predicate = true; |
| 229 break; | 242 break; |
| 230 } | 243 } |
| 231 UNREACHABLE(); | 244 UNREACHABLE(); |
| 232 return kNoCondition; | 245 return kNoCondition; |
| 233 } | 246 } |
| 234 | 247 |
| 235 | 248 |
| 236 Condition FlagsConditionToConditionTst(FlagsCondition condition) { | 249 Condition FlagsConditionToConditionTst(bool& predicate, |
| 250 FlagsCondition condition) { |
| 237 switch (condition) { | 251 switch (condition) { |
| 238 case kNotEqual: | 252 case kNotEqual: |
| 253 predicate = false; |
| 239 return ne; | 254 return ne; |
| 240 case kEqual: | 255 case kEqual: |
| 256 predicate = true; |
| 241 return eq; | 257 return eq; |
| 242 default: | 258 default: |
| 259 predicate = true; |
| 243 break; | 260 break; |
| 244 } | 261 } |
| 245 UNREACHABLE(); | 262 UNREACHABLE(); |
| 246 return kNoCondition; | 263 return kNoCondition; |
| 247 } | 264 } |
| 248 | 265 |
| 249 | 266 |
| 250 Condition FlagsConditionToConditionOvf(FlagsCondition condition) { | 267 Condition FlagsConditionToConditionOvf(bool& predicate, |
| 268 FlagsCondition condition) { |
| 251 switch (condition) { | 269 switch (condition) { |
| 252 case kOverflow: | 270 case kOverflow: |
| 271 predicate = true; |
| 253 return ne; | 272 return ne; |
| 254 case kNotOverflow: | 273 case kNotOverflow: |
| 274 predicate = false; |
| 255 return eq; | 275 return eq; |
| 256 default: | 276 default: |
| 277 predicate = true; |
| 257 break; | 278 break; |
| 258 } | 279 } |
| 259 UNREACHABLE(); | 280 UNREACHABLE(); |
| 260 return kNoCondition; | 281 return kNoCondition; |
| 261 } | 282 } |
| 262 | 283 |
| 263 | 284 |
| 264 FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate, | 285 FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate, |
| 265 FlagsCondition condition) { | 286 FlagsCondition condition) { |
| 266 switch (condition) { | 287 switch (condition) { |
| (...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 958 return false; | 979 return false; |
| 959 } | 980 } |
| 960 | 981 |
| 961 | 982 |
| 962 // Assembles branches after an instruction. | 983 // Assembles branches after an instruction. |
| 963 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 984 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
| 964 MipsOperandConverter i(this, instr); | 985 MipsOperandConverter i(this, instr); |
| 965 Label* tlabel = branch->true_label; | 986 Label* tlabel = branch->true_label; |
| 966 Label* flabel = branch->false_label; | 987 Label* flabel = branch->false_label; |
| 967 Condition cc = kNoCondition; | 988 Condition cc = kNoCondition; |
| 968 | 989 bool predicate; |
| 969 // MIPS does not have condition code flags, so compare and branch are | 990 // MIPS does not have condition code flags, so compare and branch are |
| 970 // implemented differently than on the other arch's. The compare operations | 991 // implemented differently than on the other arch's. The compare operations |
| 971 // emit mips psuedo-instructions, which are handled here by branch | 992 // emit mips psuedo-instructions, which are handled here by branch |
| 972 // instructions that do the actual comparison. Essential that the input | 993 // instructions that do the actual comparison. Essential that the input |
| 973 // registers to compare pseudo-op are not modified before this branch op, as | 994 // registers to compare pseudo-op are not modified before this branch op, as |
| 974 // they are tested here. | 995 // they are tested here. |
| 975 | 996 |
| 976 if (instr->arch_opcode() == kMips64Tst) { | 997 if (instr->arch_opcode() == kMips64Tst) { |
| 977 cc = FlagsConditionToConditionTst(branch->condition); | 998 cc = FlagsConditionToConditionTst(predicate, branch->condition); |
| 978 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 999 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
| 979 __ Branch(tlabel, cc, at, Operand(zero_reg)); | 1000 __ Branch(tlabel, cc, at, Operand(zero_reg)); |
| 980 } else if (instr->arch_opcode() == kMips64Dadd || | 1001 } else if (instr->arch_opcode() == kMips64Dadd || |
| 981 instr->arch_opcode() == kMips64Dsub) { | 1002 instr->arch_opcode() == kMips64Dsub) { |
| 982 cc = FlagsConditionToConditionOvf(branch->condition); | 1003 cc = FlagsConditionToConditionOvf(predicate, branch->condition); |
| 983 __ dsra32(kScratchReg, i.OutputRegister(), 0); | 1004 __ dsra32(kScratchReg, i.OutputRegister(), 0); |
| 984 __ sra(at, i.OutputRegister(), 31); | 1005 __ sra(at, i.OutputRegister(), 31); |
| 985 __ Branch(tlabel, cc, at, Operand(kScratchReg)); | 1006 __ Branch(tlabel, cc, at, Operand(kScratchReg)); |
| 986 } else if (instr->arch_opcode() == kMips64Cmp) { | 1007 } else if (instr->arch_opcode() == kMips64Cmp) { |
| 987 cc = FlagsConditionToConditionCmp(branch->condition); | 1008 cc = FlagsConditionToConditionCmp(predicate, branch->condition); |
| 988 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); | 1009 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); |
| 989 } else if (instr->arch_opcode() == kMips64CmpS) { | 1010 } else if (instr->arch_opcode() == kMips64CmpS) { |
| 990 if (!convertCondition(branch->condition, cc)) { | 1011 if (!convertCondition(branch->condition, cc)) { |
| 991 UNSUPPORTED_COND(kMips64CmpS, branch->condition); | 1012 UNSUPPORTED_COND(kMips64CmpS, branch->condition); |
| 992 } | 1013 } |
| 993 __ BranchF32(tlabel, NULL, cc, i.InputSingleRegister(0), | 1014 __ BranchF32(tlabel, NULL, cc, i.InputSingleRegister(0), |
| 994 i.InputSingleRegister(1)); | 1015 i.InputSingleRegister(1)); |
| 995 } else if (instr->arch_opcode() == kMips64CmpD) { | 1016 } else if (instr->arch_opcode() == kMips64CmpD) { |
| 996 if (!convertCondition(branch->condition, cc)) { | 1017 if (!convertCondition(branch->condition, cc)) { |
| 997 UNSUPPORTED_COND(kMips64CmpD, branch->condition); | 1018 UNSUPPORTED_COND(kMips64CmpD, branch->condition); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1017 FlagsCondition condition) { | 1038 FlagsCondition condition) { |
| 1018 MipsOperandConverter i(this, instr); | 1039 MipsOperandConverter i(this, instr); |
| 1019 Label done; | 1040 Label done; |
| 1020 | 1041 |
| 1021 // Materialize a full 32-bit 1 or 0 value. The result register is always the | 1042 // Materialize a full 32-bit 1 or 0 value. The result register is always the |
| 1022 // last output of the instruction. | 1043 // last output of the instruction. |
| 1023 Label false_value; | 1044 Label false_value; |
| 1024 DCHECK_NE(0u, instr->OutputCount()); | 1045 DCHECK_NE(0u, instr->OutputCount()); |
| 1025 Register result = i.OutputRegister(instr->OutputCount() - 1); | 1046 Register result = i.OutputRegister(instr->OutputCount() - 1); |
| 1026 Condition cc = kNoCondition; | 1047 Condition cc = kNoCondition; |
| 1027 | 1048 bool predicate; |
| 1028 // MIPS does not have condition code flags, so compare and branch are | 1049 // MIPS does not have condition code flags, so compare and branch are |
| 1029 // implemented differently than on the other arch's. The compare operations | 1050 // implemented differently than on the other arch's. The compare operations |
| 1030 // emit mips pseudo-instructions, which are checked and handled here. | 1051 // emit mips pseudo-instructions, which are checked and handled here. |
| 1031 | 1052 |
| 1032 // 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 | |
| 1034 // false. | |
| 1035 | |
| 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); // Create 1 for true. |
| 1040 __ li(result, Operand(1)); // In delay slot. | 1057 if (kArchVariant != kMips64r6) { |
| 1058 if (predicate) { |
| 1059 __ Movn(result, zero_reg, kScratchReg); |
| 1060 __ Movz(result, kScratchReg2, kScratchReg); |
| 1061 } else { |
| 1062 __ Movz(result, zero_reg, kScratchReg); |
| 1063 __ Movn(result, kScratchReg2, kScratchReg); |
| 1064 } |
| 1065 } else { |
| 1066 if (predicate) { |
| 1067 __ seleqz(result, kScratchReg2, kScratchReg); |
| 1068 } else { |
| 1069 __ selnez(result, kScratchReg2, kScratchReg); |
| 1070 } |
| 1071 } |
| 1072 return; |
| 1041 } else if (instr->arch_opcode() == kMips64Dadd || | 1073 } else if (instr->arch_opcode() == kMips64Dadd || |
| 1042 instr->arch_opcode() == kMips64Dsub) { | 1074 instr->arch_opcode() == kMips64Dsub) { |
| 1043 cc = FlagsConditionToConditionOvf(condition); | 1075 FlagsConditionToConditionOvf(predicate, condition); |
| 1044 __ dsra32(kScratchReg, i.OutputRegister(), 0); | 1076 // Check for overflow creates 1 or 0 for result. |
| 1045 __ sra(at, i.OutputRegister(), 31); | 1077 __ dsrl32(kScratchReg, i.OutputRegister(), 31); |
| 1046 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(kScratchReg)); | 1078 __ srl(at, i.OutputRegister(), 31); |
| 1047 __ li(result, Operand(1)); // In delay slot. | 1079 __ xor_(result, kScratchReg, at); |
| 1080 if (!predicate) // Toggle result for not overflow. |
| 1081 __ xori(result, result, 1); |
| 1082 return; |
| 1048 } else if (instr->arch_opcode() == kMips64Cmp) { | 1083 } else if (instr->arch_opcode() == kMips64Cmp) { |
| 1049 Register left = i.InputRegister(0); | 1084 cc = FlagsConditionToConditionCmp(predicate, condition); |
| 1050 Operand right = i.InputOperand(1); | 1085 switch (cc) { |
| 1051 cc = FlagsConditionToConditionCmp(condition); | 1086 case eq: |
| 1052 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); | 1087 case ne: { |
| 1053 __ li(result, Operand(1)); // In delay slot. | 1088 Register left = i.InputRegister(0); |
| 1089 Operand right = i.InputOperand(1); |
| 1090 __ Dsubu(kScratchReg, left, right); |
| 1091 __ xori(kScratchReg2, zero_reg, 1); |
| 1092 if (kArchVariant != kMips64r6) { |
| 1093 if (predicate) { |
| 1094 __ Movn(result, zero_reg, kScratchReg); |
| 1095 __ Movz(result, kScratchReg2, kScratchReg); |
| 1096 } else { |
| 1097 __ Movz(result, zero_reg, kScratchReg); |
| 1098 __ Movn(result, kScratchReg2, kScratchReg); |
| 1099 } |
| 1100 } else { |
| 1101 if (predicate) { |
| 1102 __ seleqz(result, kScratchReg2, kScratchReg); |
| 1103 } else { |
| 1104 __ selnez(result, kScratchReg2, kScratchReg); |
| 1105 } |
| 1106 } |
| 1107 } break; |
| 1108 case lt: |
| 1109 case ge: { |
| 1110 Register left = i.InputRegister(0); |
| 1111 Operand right = i.InputOperand(1); |
| 1112 __ Slt(result, left, right); |
| 1113 if (!predicate) { |
| 1114 __ xori(result, result, 1); |
| 1115 } |
| 1116 } break; |
| 1117 case gt: |
| 1118 case le: { |
| 1119 Register left = i.InputRegister(1); |
| 1120 Operand right = i.InputOperand(0); |
| 1121 __ Slt(result, left, right); |
| 1122 if (!predicate) { |
| 1123 __ xori(result, result, 1); |
| 1124 } |
| 1125 } break; |
| 1126 case lo: |
| 1127 case hs: { |
| 1128 Register left = i.InputRegister(0); |
| 1129 Operand right = i.InputOperand(1); |
| 1130 __ Sltu(result, left, right); |
| 1131 if (!predicate) { |
| 1132 __ xori(result, result, 1); |
| 1133 } |
| 1134 } break; |
| 1135 case hi: |
| 1136 case ls: { |
| 1137 Register left = i.InputRegister(1); |
| 1138 Operand right = i.InputOperand(0); |
| 1139 __ Sltu(result, left, right); |
| 1140 if (!predicate) { |
| 1141 __ xori(result, result, 1); |
| 1142 } |
| 1143 } break; |
| 1144 default: |
| 1145 UNREACHABLE(); |
| 1146 } |
| 1147 return; |
| 1054 } else if (instr->arch_opcode() == kMips64CmpD || | 1148 } else if (instr->arch_opcode() == kMips64CmpD || |
| 1055 instr->arch_opcode() == kMips64CmpS) { | 1149 instr->arch_opcode() == kMips64CmpS) { |
| 1056 FPURegister left = i.InputDoubleRegister(0); | 1150 FPURegister left = i.InputDoubleRegister(0); |
| 1057 FPURegister right = i.InputDoubleRegister(1); | 1151 FPURegister right = i.InputDoubleRegister(1); |
| 1058 | 1152 |
| 1059 bool predicate; | |
| 1060 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition); | 1153 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition); |
| 1061 if (kArchVariant != kMips64r6) { | 1154 if (kArchVariant != kMips64r6) { |
| 1062 __ li(result, Operand(1)); | 1155 __ li(result, Operand(1)); |
| 1063 if (instr->arch_opcode() == kMips64CmpD) { | 1156 if (instr->arch_opcode() == kMips64CmpD) { |
| 1064 __ c(cc, D, left, right); | 1157 __ c(cc, D, left, right); |
| 1065 } else { | 1158 } else { |
| 1066 DCHECK(instr->arch_opcode() == kMips64CmpS); | 1159 DCHECK(instr->arch_opcode() == kMips64CmpS); |
| 1067 __ c(cc, S, left, right); | 1160 __ c(cc, S, left, right); |
| 1068 } | 1161 } |
| 1069 if (predicate) { | 1162 if (predicate) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1083 if (!predicate) // Toggle result for not equal. | 1176 if (!predicate) // Toggle result for not equal. |
| 1084 __ xori(result, result, 1); | 1177 __ xori(result, result, 1); |
| 1085 } | 1178 } |
| 1086 return; | 1179 return; |
| 1087 } else { | 1180 } else { |
| 1088 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", | 1181 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", |
| 1089 instr->arch_opcode()); | 1182 instr->arch_opcode()); |
| 1090 TRACE_UNIMPL(); | 1183 TRACE_UNIMPL(); |
| 1091 UNIMPLEMENTED(); | 1184 UNIMPLEMENTED(); |
| 1092 } | 1185 } |
| 1093 // Fallthru case is the false materialization. | |
| 1094 __ bind(&false_value); | |
| 1095 __ li(result, Operand(static_cast<int64_t>(0))); | |
| 1096 __ bind(&done); | |
| 1097 } | 1186 } |
| 1098 | 1187 |
| 1099 | 1188 |
| 1100 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { | 1189 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { |
| 1101 MipsOperandConverter i(this, instr); | 1190 MipsOperandConverter i(this, instr); |
| 1102 Register input = i.InputRegister(0); | 1191 Register input = i.InputRegister(0); |
| 1103 for (size_t index = 2; index < instr->InputCount(); index += 2) { | 1192 for (size_t index = 2; index < instr->InputCount(); index += 2) { |
| 1104 __ li(at, Operand(i.InputInt32(index + 0))); | 1193 __ li(at, Operand(i.InputInt32(index + 0))); |
| 1105 __ beq(input, at, GetLabel(i.InputRpo(index + 1))); | 1194 __ beq(input, at, GetLabel(i.InputRpo(index + 1))); |
| 1106 } | 1195 } |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1443 } | 1532 } |
| 1444 } | 1533 } |
| 1445 } | 1534 } |
| 1446 } | 1535 } |
| 1447 | 1536 |
| 1448 #undef __ | 1537 #undef __ |
| 1449 | 1538 |
| 1450 } // namespace compiler | 1539 } // namespace compiler |
| 1451 } // namespace internal | 1540 } // namespace internal |
| 1452 } // namespace v8 | 1541 } // namespace v8 |
| OLD | NEW |