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 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 private: | 194 private: |
195 Register const object_; | 195 Register const object_; |
196 Register const offset_; | 196 Register const offset_; |
197 Register const value_; | 197 Register const value_; |
198 Register const scratch0_; | 198 Register const scratch0_; |
199 Register const scratch1_; | 199 Register const scratch1_; |
200 RecordWriteMode const mode_; | 200 RecordWriteMode const mode_; |
201 }; | 201 }; |
202 | 202 |
203 | 203 |
204 Condition FlagsConditionToCondition(FlagsCondition condition) { | 204 Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) { |
205 switch (condition) { | 205 switch (condition) { |
206 case kEqual: | 206 case kEqual: |
207 return eq; | 207 return eq; |
208 case kNotEqual: | 208 case kNotEqual: |
209 return ne; | 209 return ne; |
210 case kSignedLessThan: | 210 case kSignedLessThan: |
211 case kUnsignedLessThan: | 211 case kUnsignedLessThan: |
212 return lt; | 212 return lt; |
213 case kSignedGreaterThanOrEqual: | 213 case kSignedGreaterThanOrEqual: |
214 case kUnsignedGreaterThanOrEqual: | 214 case kUnsignedGreaterThanOrEqual: |
215 return ge; | 215 return ge; |
216 case kSignedLessThanOrEqual: | 216 case kSignedLessThanOrEqual: |
217 case kUnsignedLessThanOrEqual: | 217 case kUnsignedLessThanOrEqual: |
218 return le; | 218 return le; |
219 case kSignedGreaterThan: | 219 case kSignedGreaterThan: |
220 case kUnsignedGreaterThan: | 220 case kUnsignedGreaterThan: |
221 return gt; | 221 return gt; |
222 case kOverflow: | 222 case kOverflow: |
| 223 // Overflow checked for add/sub only. |
| 224 switch (op) { |
223 #if V8_TARGET_ARCH_PPC64 | 225 #if V8_TARGET_ARCH_PPC64 |
224 return ne; | 226 case kPPC_Add: |
| 227 case kPPC_Sub: |
| 228 return lt; |
| 229 #endif |
| 230 case kPPC_AddWithOverflow32: |
| 231 case kPPC_SubWithOverflow32: |
| 232 #if V8_TARGET_ARCH_PPC64 |
| 233 return ne; |
225 #else | 234 #else |
226 return lt; | 235 return lt; |
227 #endif | 236 #endif |
| 237 default: |
| 238 break; |
| 239 } |
| 240 break; |
228 case kNotOverflow: | 241 case kNotOverflow: |
| 242 switch (op) { |
229 #if V8_TARGET_ARCH_PPC64 | 243 #if V8_TARGET_ARCH_PPC64 |
230 return eq; | 244 case kPPC_Add: |
| 245 case kPPC_Sub: |
| 246 return ge; |
| 247 #endif |
| 248 case kPPC_AddWithOverflow32: |
| 249 case kPPC_SubWithOverflow32: |
| 250 #if V8_TARGET_ARCH_PPC64 |
| 251 return eq; |
231 #else | 252 #else |
232 return ge; | 253 return ge; |
233 #endif | 254 #endif |
| 255 default: |
| 256 break; |
| 257 } |
| 258 break; |
234 default: | 259 default: |
235 break; | 260 break; |
236 } | 261 } |
237 UNREACHABLE(); | 262 UNREACHABLE(); |
238 return kNoCondition; | 263 return kNoCondition; |
239 } | 264 } |
240 | 265 |
241 } // namespace | 266 } // namespace |
242 | 267 |
243 #define ASSEMBLE_FLOAT_UNOP_RC(asm_instr) \ | 268 #define ASSEMBLE_FLOAT_UNOP_RC(asm_instr) \ |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 if (HasRegisterInput(instr, 1)) { \ | 308 if (HasRegisterInput(instr, 1)) { \ |
284 __ asm_instr_reg(i.OutputRegister(), i.InputRegister(0), \ | 309 __ asm_instr_reg(i.OutputRegister(), i.InputRegister(0), \ |
285 i.InputRegister(1), i.OutputRCBit()); \ | 310 i.InputRegister(1), i.OutputRCBit()); \ |
286 } else { \ | 311 } else { \ |
287 __ asm_instr_imm(i.OutputRegister(), i.InputRegister(0), \ | 312 __ asm_instr_imm(i.OutputRegister(), i.InputRegister(0), \ |
288 i.InputInt32(1), i.OutputRCBit()); \ | 313 i.InputInt32(1), i.OutputRCBit()); \ |
289 } \ | 314 } \ |
290 } while (0) | 315 } while (0) |
291 | 316 |
292 | 317 |
293 #if V8_TARGET_ARCH_PPC64 | |
294 #define ASSEMBLE_ADD_WITH_OVERFLOW() \ | |
295 do { \ | |
296 ASSEMBLE_BINOP(add, addi); \ | |
297 __ TestIfInt32(i.OutputRegister(), r0, cr0); \ | |
298 } while (0) | |
299 #else | |
300 #define ASSEMBLE_ADD_WITH_OVERFLOW() \ | 318 #define ASSEMBLE_ADD_WITH_OVERFLOW() \ |
301 do { \ | 319 do { \ |
302 if (HasRegisterInput(instr, 1)) { \ | 320 if (HasRegisterInput(instr, 1)) { \ |
303 __ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ | 321 __ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ |
304 i.InputRegister(1), kScratchReg, r0); \ | 322 i.InputRegister(1), kScratchReg, r0); \ |
305 } else { \ | 323 } else { \ |
306 __ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ | 324 __ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ |
307 i.InputInt32(1), kScratchReg, r0); \ | 325 i.InputInt32(1), kScratchReg, r0); \ |
308 } \ | 326 } \ |
309 } while (0) | 327 } while (0) |
310 #endif | |
311 | 328 |
312 | 329 |
313 #if V8_TARGET_ARCH_PPC64 | |
314 #define ASSEMBLE_SUB_WITH_OVERFLOW() \ | |
315 do { \ | |
316 ASSEMBLE_BINOP(sub, subi); \ | |
317 __ TestIfInt32(i.OutputRegister(), r0, cr0); \ | |
318 } while (0) | |
319 #else | |
320 #define ASSEMBLE_SUB_WITH_OVERFLOW() \ | 330 #define ASSEMBLE_SUB_WITH_OVERFLOW() \ |
321 do { \ | 331 do { \ |
322 if (HasRegisterInput(instr, 1)) { \ | 332 if (HasRegisterInput(instr, 1)) { \ |
323 __ SubAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ | 333 __ SubAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ |
324 i.InputRegister(1), kScratchReg, r0); \ | 334 i.InputRegister(1), kScratchReg, r0); \ |
325 } else { \ | 335 } else { \ |
326 __ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ | 336 __ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \ |
327 -i.InputInt32(1), kScratchReg, r0); \ | 337 -i.InputInt32(1), kScratchReg, r0); \ |
328 } \ | 338 } \ |
329 } while (0) | 339 } while (0) |
| 340 |
| 341 |
| 342 #if V8_TARGET_ARCH_PPC64 |
| 343 #define ASSEMBLE_ADD_WITH_OVERFLOW32() \ |
| 344 do { \ |
| 345 ASSEMBLE_BINOP(add, addi); \ |
| 346 __ TestIfInt32(i.OutputRegister(), r0, cr0); \ |
| 347 } while (0) |
| 348 |
| 349 |
| 350 #define ASSEMBLE_SUB_WITH_OVERFLOW32() \ |
| 351 do { \ |
| 352 ASSEMBLE_BINOP(sub, subi); \ |
| 353 __ TestIfInt32(i.OutputRegister(), r0, cr0); \ |
| 354 } while (0) |
| 355 #else |
| 356 #define ASSEMBLE_ADD_WITH_OVERFLOW32 ASSEMBLE_ADD_WITH_OVERFLOW |
| 357 #define ASSEMBLE_SUB_WITH_OVERFLOW32 ASSEMBLE_SUB_WITH_OVERFLOW |
330 #endif | 358 #endif |
331 | 359 |
332 | 360 |
333 #define ASSEMBLE_COMPARE(cmp_instr, cmpl_instr) \ | 361 #define ASSEMBLE_COMPARE(cmp_instr, cmpl_instr) \ |
334 do { \ | 362 do { \ |
335 const CRegister cr = cr0; \ | 363 const CRegister cr = cr0; \ |
336 if (HasRegisterInput(instr, 1)) { \ | 364 if (HasRegisterInput(instr, 1)) { \ |
337 if (i.CompareLogical()) { \ | 365 if (i.CompareLogical()) { \ |
338 __ cmpl_instr(i.InputRegister(0), i.InputRegister(1), cr); \ | 366 __ cmpl_instr(i.InputRegister(0), i.InputRegister(1), cr); \ |
339 } else { \ | 367 } else { \ |
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
896 case kPPC_RotLeftAndClearLeft64: | 924 case kPPC_RotLeftAndClearLeft64: |
897 __ rldicl(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1), | 925 __ rldicl(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1), |
898 63 - i.InputInt32(2), i.OutputRCBit()); | 926 63 - i.InputInt32(2), i.OutputRCBit()); |
899 break; | 927 break; |
900 case kPPC_RotLeftAndClearRight64: | 928 case kPPC_RotLeftAndClearRight64: |
901 __ rldicr(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1), | 929 __ rldicr(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1), |
902 63 - i.InputInt32(2), i.OutputRCBit()); | 930 63 - i.InputInt32(2), i.OutputRCBit()); |
903 break; | 931 break; |
904 #endif | 932 #endif |
905 case kPPC_Add: | 933 case kPPC_Add: |
906 if (HasRegisterInput(instr, 1)) { | 934 #if V8_TARGET_ARCH_PPC64 |
907 __ add(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), | 935 if (FlagsModeField::decode(instr->opcode()) != kFlags_none) { |
908 LeaveOE, i.OutputRCBit()); | 936 ASSEMBLE_ADD_WITH_OVERFLOW(); |
909 } else { | 937 } else { |
910 __ addi(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1)); | 938 #endif |
911 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 939 if (HasRegisterInput(instr, 1)) { |
| 940 __ add(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), |
| 941 LeaveOE, i.OutputRCBit()); |
| 942 } else { |
| 943 __ addi(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1)); |
| 944 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
| 945 } |
| 946 #if V8_TARGET_ARCH_PPC64 |
912 } | 947 } |
| 948 #endif |
913 break; | 949 break; |
914 case kPPC_AddWithOverflow32: | 950 case kPPC_AddWithOverflow32: |
915 ASSEMBLE_ADD_WITH_OVERFLOW(); | 951 ASSEMBLE_ADD_WITH_OVERFLOW32(); |
916 break; | 952 break; |
917 case kPPC_AddDouble: | 953 case kPPC_AddDouble: |
918 ASSEMBLE_FLOAT_BINOP_RC(fadd); | 954 ASSEMBLE_FLOAT_BINOP_RC(fadd); |
919 break; | 955 break; |
920 case kPPC_Sub: | 956 case kPPC_Sub: |
921 if (HasRegisterInput(instr, 1)) { | 957 #if V8_TARGET_ARCH_PPC64 |
922 __ sub(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), | 958 if (FlagsModeField::decode(instr->opcode()) != kFlags_none) { |
923 LeaveOE, i.OutputRCBit()); | 959 ASSEMBLE_SUB_WITH_OVERFLOW(); |
924 } else { | 960 } else { |
925 __ subi(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1)); | 961 #endif |
926 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 962 if (HasRegisterInput(instr, 1)) { |
| 963 __ sub(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), |
| 964 LeaveOE, i.OutputRCBit()); |
| 965 } else { |
| 966 __ subi(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1)); |
| 967 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
| 968 } |
| 969 #if V8_TARGET_ARCH_PPC64 |
927 } | 970 } |
| 971 #endif |
928 break; | 972 break; |
929 case kPPC_SubWithOverflow32: | 973 case kPPC_SubWithOverflow32: |
930 ASSEMBLE_SUB_WITH_OVERFLOW(); | 974 ASSEMBLE_SUB_WITH_OVERFLOW32(); |
931 break; | 975 break; |
932 case kPPC_SubDouble: | 976 case kPPC_SubDouble: |
933 ASSEMBLE_FLOAT_BINOP_RC(fsub); | 977 ASSEMBLE_FLOAT_BINOP_RC(fsub); |
934 break; | 978 break; |
935 case kPPC_Mul32: | 979 case kPPC_Mul32: |
936 __ mullw(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), | 980 __ mullw(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), |
937 LeaveOE, i.OutputRCBit()); | 981 LeaveOE, i.OutputRCBit()); |
938 break; | 982 break; |
939 #if V8_TARGET_ARCH_PPC64 | 983 #if V8_TARGET_ARCH_PPC64 |
940 case kPPC_Mul64: | 984 case kPPC_Mul64: |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1121 case kPPC_ExtendSignWord32: | 1165 case kPPC_ExtendSignWord32: |
1122 __ extsw(i.OutputRegister(), i.InputRegister(0)); | 1166 __ extsw(i.OutputRegister(), i.InputRegister(0)); |
1123 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1167 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
1124 break; | 1168 break; |
1125 case kPPC_Uint32ToUint64: | 1169 case kPPC_Uint32ToUint64: |
1126 // Zero extend | 1170 // Zero extend |
1127 __ clrldi(i.OutputRegister(), i.InputRegister(0), Operand(32)); | 1171 __ clrldi(i.OutputRegister(), i.InputRegister(0), Operand(32)); |
1128 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1172 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
1129 break; | 1173 break; |
1130 case kPPC_Int64ToInt32: | 1174 case kPPC_Int64ToInt32: |
1131 // TODO(mbrandy): sign extend? | 1175 __ extsw(i.OutputRegister(), i.InputRegister(0)); |
1132 __ Move(i.OutputRegister(), i.InputRegister(0)); | |
1133 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1176 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
1134 break; | 1177 break; |
1135 case kPPC_Int64ToFloat32: | 1178 case kPPC_Int64ToFloat32: |
1136 __ ConvertInt64ToFloat(i.InputRegister(0), i.OutputDoubleRegister()); | 1179 __ ConvertInt64ToFloat(i.InputRegister(0), i.OutputDoubleRegister()); |
1137 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1180 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
1138 break; | 1181 break; |
1139 case kPPC_Int64ToDouble: | 1182 case kPPC_Int64ToDouble: |
1140 __ ConvertInt64ToDouble(i.InputRegister(0), i.OutputDoubleRegister()); | 1183 __ ConvertInt64ToDouble(i.InputRegister(0), i.OutputDoubleRegister()); |
1141 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1184 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
1142 break; | 1185 break; |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1363 | 1406 |
1364 // Assembles branches after an instruction. | 1407 // Assembles branches after an instruction. |
1365 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 1408 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
1366 PPCOperandConverter i(this, instr); | 1409 PPCOperandConverter i(this, instr); |
1367 Label* tlabel = branch->true_label; | 1410 Label* tlabel = branch->true_label; |
1368 Label* flabel = branch->false_label; | 1411 Label* flabel = branch->false_label; |
1369 ArchOpcode op = instr->arch_opcode(); | 1412 ArchOpcode op = instr->arch_opcode(); |
1370 FlagsCondition condition = branch->condition; | 1413 FlagsCondition condition = branch->condition; |
1371 CRegister cr = cr0; | 1414 CRegister cr = cr0; |
1372 | 1415 |
1373 // Overflow checked for add/sub only. | 1416 Condition cond = FlagsConditionToCondition(condition, op); |
1374 DCHECK((condition != kOverflow && condition != kNotOverflow) || | |
1375 (op == kPPC_AddWithOverflow32 || op == kPPC_SubWithOverflow32)); | |
1376 | |
1377 Condition cond = FlagsConditionToCondition(condition); | |
1378 if (op == kPPC_CmpDouble) { | 1417 if (op == kPPC_CmpDouble) { |
1379 // check for unordered if necessary | 1418 // check for unordered if necessary |
1380 if (cond == le) { | 1419 if (cond == le) { |
1381 __ bunordered(flabel, cr); | 1420 __ bunordered(flabel, cr); |
1382 // Unnecessary for eq/lt since only FU bit will be set. | 1421 // Unnecessary for eq/lt since only FU bit will be set. |
1383 } else if (cond == gt) { | 1422 } else if (cond == gt) { |
1384 __ bunordered(tlabel, cr); | 1423 __ bunordered(tlabel, cr); |
1385 // Unnecessary for ne/ge since only FU bit will be set. | 1424 // Unnecessary for ne/ge since only FU bit will be set. |
1386 } | 1425 } |
1387 } | 1426 } |
1388 __ b(cond, tlabel, cr); | 1427 __ b(cond, tlabel, cr); |
1389 if (!branch->fallthru) __ b(flabel); // no fallthru to flabel. | 1428 if (!branch->fallthru) __ b(flabel); // no fallthru to flabel. |
1390 } | 1429 } |
1391 | 1430 |
1392 | 1431 |
1393 void CodeGenerator::AssembleArchJump(RpoNumber target) { | 1432 void CodeGenerator::AssembleArchJump(RpoNumber target) { |
1394 if (!IsNextInAssemblyOrder(target)) __ b(GetLabel(target)); | 1433 if (!IsNextInAssemblyOrder(target)) __ b(GetLabel(target)); |
1395 } | 1434 } |
1396 | 1435 |
1397 | 1436 |
1398 // Assembles boolean materializations after an instruction. | 1437 // Assembles boolean materializations after an instruction. |
1399 void CodeGenerator::AssembleArchBoolean(Instruction* instr, | 1438 void CodeGenerator::AssembleArchBoolean(Instruction* instr, |
1400 FlagsCondition condition) { | 1439 FlagsCondition condition) { |
1401 PPCOperandConverter i(this, instr); | 1440 PPCOperandConverter i(this, instr); |
1402 Label done; | 1441 Label done; |
1403 ArchOpcode op = instr->arch_opcode(); | 1442 ArchOpcode op = instr->arch_opcode(); |
1404 bool check_unordered = (op == kPPC_CmpDouble); | 1443 bool check_unordered = (op == kPPC_CmpDouble); |
1405 CRegister cr = cr0; | 1444 CRegister cr = cr0; |
1406 | 1445 |
1407 // Overflow checked for add/sub only. | |
1408 DCHECK((condition != kOverflow && condition != kNotOverflow) || | |
1409 (op == kPPC_AddWithOverflow32 || op == kPPC_SubWithOverflow32)); | |
1410 | |
1411 // Materialize a full 32-bit 1 or 0 value. The result register is always the | 1446 // Materialize a full 32-bit 1 or 0 value. The result register is always the |
1412 // last output of the instruction. | 1447 // last output of the instruction. |
1413 DCHECK_NE(0u, instr->OutputCount()); | 1448 DCHECK_NE(0u, instr->OutputCount()); |
1414 Register reg = i.OutputRegister(instr->OutputCount() - 1); | 1449 Register reg = i.OutputRegister(instr->OutputCount() - 1); |
1415 | 1450 |
1416 Condition cond = FlagsConditionToCondition(condition); | 1451 Condition cond = FlagsConditionToCondition(condition, op); |
1417 switch (cond) { | 1452 switch (cond) { |
1418 case eq: | 1453 case eq: |
1419 case lt: | 1454 case lt: |
1420 __ li(reg, Operand::Zero()); | 1455 __ li(reg, Operand::Zero()); |
1421 __ li(kScratchReg, Operand(1)); | 1456 __ li(kScratchReg, Operand(1)); |
1422 __ isel(cond, reg, kScratchReg, reg, cr); | 1457 __ isel(cond, reg, kScratchReg, reg, cr); |
1423 break; | 1458 break; |
1424 case ne: | 1459 case ne: |
1425 case ge: | 1460 case ge: |
1426 __ li(reg, Operand(1)); | 1461 __ li(reg, Operand(1)); |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1806 padding_size -= v8::internal::Assembler::kInstrSize; | 1841 padding_size -= v8::internal::Assembler::kInstrSize; |
1807 } | 1842 } |
1808 } | 1843 } |
1809 } | 1844 } |
1810 | 1845 |
1811 #undef __ | 1846 #undef __ |
1812 | 1847 |
1813 } // namespace compiler | 1848 } // namespace compiler |
1814 } // namespace internal | 1849 } // namespace internal |
1815 } // namespace v8 | 1850 } // namespace v8 |
OLD | NEW |