| 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/arm/macro-assembler-arm.h" | 7 #include "src/arm/macro-assembler-arm.h" |
| 8 #include "src/compilation-info.h" | 8 #include "src/compilation-info.h" |
| 9 #include "src/compiler/code-generator-impl.h" | 9 #include "src/compiler/code-generator-impl.h" |
| 10 #include "src/compiler/gap-resolver.h" | 10 #include "src/compiler/gap-resolver.h" |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 Register const index_; | 264 Register const index_; |
| 265 int32_t const index_immediate_; // Valid if index_.is(no_reg). | 265 int32_t const index_immediate_; // Valid if index_.is(no_reg). |
| 266 Register const value_; | 266 Register const value_; |
| 267 Register const scratch0_; | 267 Register const scratch0_; |
| 268 Register const scratch1_; | 268 Register const scratch1_; |
| 269 RecordWriteMode const mode_; | 269 RecordWriteMode const mode_; |
| 270 bool must_save_lr_; | 270 bool must_save_lr_; |
| 271 UnwindingInfoWriter* const unwinding_info_writer_; | 271 UnwindingInfoWriter* const unwinding_info_writer_; |
| 272 }; | 272 }; |
| 273 | 273 |
| 274 template <typename T> |
| 275 class OutOfLineFloatMin final : public OutOfLineCode { |
| 276 public: |
| 277 OutOfLineFloatMin(CodeGenerator* gen, T result, T left, T right) |
| 278 : OutOfLineCode(gen), result_(result), left_(left), right_(right) {} |
| 279 |
| 280 void Generate() final { __ FloatMinOutOfLine(result_, left_, right_); } |
| 281 |
| 282 private: |
| 283 T const result_; |
| 284 T const left_; |
| 285 T const right_; |
| 286 }; |
| 287 typedef OutOfLineFloatMin<SwVfpRegister> OutOfLineFloat32Min; |
| 288 typedef OutOfLineFloatMin<DwVfpRegister> OutOfLineFloat64Min; |
| 289 |
| 290 template <typename T> |
| 291 class OutOfLineFloatMax final : public OutOfLineCode { |
| 292 public: |
| 293 OutOfLineFloatMax(CodeGenerator* gen, T result, T left, T right) |
| 294 : OutOfLineCode(gen), result_(result), left_(left), right_(right) {} |
| 295 |
| 296 void Generate() final { __ FloatMaxOutOfLine(result_, left_, right_); } |
| 297 |
| 298 private: |
| 299 T const result_; |
| 300 T const left_; |
| 301 T const right_; |
| 302 }; |
| 303 typedef OutOfLineFloatMax<SwVfpRegister> OutOfLineFloat32Max; |
| 304 typedef OutOfLineFloatMax<DwVfpRegister> OutOfLineFloat64Max; |
| 274 | 305 |
| 275 Condition FlagsConditionToCondition(FlagsCondition condition) { | 306 Condition FlagsConditionToCondition(FlagsCondition condition) { |
| 276 switch (condition) { | 307 switch (condition) { |
| 277 case kEqual: | 308 case kEqual: |
| 278 return eq; | 309 return eq; |
| 279 case kNotEqual: | 310 case kNotEqual: |
| 280 return ne; | 311 return ne; |
| 281 case kSignedLessThan: | 312 case kSignedLessThan: |
| 282 return lt; | 313 return lt; |
| 283 case kSignedGreaterThanOrEqual: | 314 case kSignedGreaterThanOrEqual: |
| (...skipping 1086 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1370 break; | 1401 break; |
| 1371 case kArmVldrF64: | 1402 case kArmVldrF64: |
| 1372 __ vldr(i.OutputDoubleRegister(), i.InputOffset()); | 1403 __ vldr(i.OutputDoubleRegister(), i.InputOffset()); |
| 1373 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 1404 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 1374 break; | 1405 break; |
| 1375 case kArmVstrF64: | 1406 case kArmVstrF64: |
| 1376 __ vstr(i.InputDoubleRegister(0), i.InputOffset(1)); | 1407 __ vstr(i.InputDoubleRegister(0), i.InputOffset(1)); |
| 1377 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 1408 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 1378 break; | 1409 break; |
| 1379 case kArmFloat32Max: { | 1410 case kArmFloat32Max: { |
| 1380 FloatRegister left_reg = i.InputFloat32Register(0); | 1411 SwVfpRegister result = i.OutputFloat32Register(); |
| 1381 FloatRegister right_reg = i.InputFloat32Register(1); | 1412 SwVfpRegister left = i.InputFloat32Register(0); |
| 1382 FloatRegister result_reg = i.OutputFloat32Register(); | 1413 SwVfpRegister right = i.InputFloat32Register(1); |
| 1383 Label result_is_nan, return_left, return_right, check_zero, done; | 1414 if (left.is(right)) { |
| 1384 __ VFPCompareAndSetFlags(left_reg, right_reg); | 1415 __ Move(result, left); |
| 1385 __ b(mi, &return_right); | |
| 1386 __ b(gt, &return_left); | |
| 1387 __ b(vs, &result_is_nan); | |
| 1388 // Left equals right => check for -0. | |
| 1389 __ VFPCompareAndSetFlags(left_reg, 0.0); | |
| 1390 if (left_reg.is(result_reg) || right_reg.is(result_reg)) { | |
| 1391 __ b(ne, &done); // left == right != 0. | |
| 1392 } else { | 1416 } else { |
| 1393 __ b(ne, &return_left); // left == right != 0. | 1417 auto ool = new (zone()) OutOfLineFloat32Max(this, result, left, right); |
| 1418 __ FloatMax(result, left, right, ool->entry()); |
| 1419 __ bind(ool->exit()); |
| 1394 } | 1420 } |
| 1395 // At this point, both left and right are either 0 or -0. | 1421 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 1396 // Since we operate on +0 and/or -0, vadd and vand have the same effect; | |
| 1397 // the decision for vadd is easy because vand is a NEON instruction. | |
| 1398 __ vadd(result_reg, left_reg, right_reg); | |
| 1399 __ b(&done); | |
| 1400 __ bind(&result_is_nan); | |
| 1401 __ vadd(result_reg, left_reg, right_reg); | |
| 1402 __ b(&done); | |
| 1403 __ bind(&return_right); | |
| 1404 __ Move(result_reg, right_reg); | |
| 1405 if (!left_reg.is(result_reg)) __ b(&done); | |
| 1406 __ bind(&return_left); | |
| 1407 __ Move(result_reg, left_reg); | |
| 1408 __ bind(&done); | |
| 1409 break; | 1422 break; |
| 1410 } | 1423 } |
| 1411 case kArmFloat64Max: { | 1424 case kArmFloat64Max: { |
| 1412 DwVfpRegister left_reg = i.InputDoubleRegister(0); | 1425 DwVfpRegister result = i.OutputDoubleRegister(); |
| 1413 DwVfpRegister right_reg = i.InputDoubleRegister(1); | 1426 DwVfpRegister left = i.InputDoubleRegister(0); |
| 1414 DwVfpRegister result_reg = i.OutputDoubleRegister(); | 1427 DwVfpRegister right = i.InputDoubleRegister(1); |
| 1415 Label result_is_nan, return_left, return_right, check_zero, done; | 1428 if (left.is(right)) { |
| 1416 __ VFPCompareAndSetFlags(left_reg, right_reg); | 1429 __ Move(result, left); |
| 1417 __ b(mi, &return_right); | |
| 1418 __ b(gt, &return_left); | |
| 1419 __ b(vs, &result_is_nan); | |
| 1420 // Left equals right => check for -0. | |
| 1421 __ VFPCompareAndSetFlags(left_reg, 0.0); | |
| 1422 if (left_reg.is(result_reg) || right_reg.is(result_reg)) { | |
| 1423 __ b(ne, &done); // left == right != 0. | |
| 1424 } else { | 1430 } else { |
| 1425 __ b(ne, &return_left); // left == right != 0. | 1431 auto ool = new (zone()) OutOfLineFloat64Max(this, result, left, right); |
| 1432 __ FloatMax(result, left, right, ool->entry()); |
| 1433 __ bind(ool->exit()); |
| 1426 } | 1434 } |
| 1427 // At this point, both left and right are either 0 or -0. | 1435 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 1428 // Since we operate on +0 and/or -0, vadd and vand have the same effect; | |
| 1429 // the decision for vadd is easy because vand is a NEON instruction. | |
| 1430 __ vadd(result_reg, left_reg, right_reg); | |
| 1431 __ b(&done); | |
| 1432 __ bind(&result_is_nan); | |
| 1433 __ vadd(result_reg, left_reg, right_reg); | |
| 1434 __ b(&done); | |
| 1435 __ bind(&return_right); | |
| 1436 __ Move(result_reg, right_reg); | |
| 1437 if (!left_reg.is(result_reg)) __ b(&done); | |
| 1438 __ bind(&return_left); | |
| 1439 __ Move(result_reg, left_reg); | |
| 1440 __ bind(&done); | |
| 1441 break; | 1436 break; |
| 1442 } | 1437 } |
| 1443 case kArmFloat32Min: { | 1438 case kArmFloat32Min: { |
| 1444 FloatRegister left_reg = i.InputFloat32Register(0); | 1439 SwVfpRegister result = i.OutputFloat32Register(); |
| 1445 FloatRegister right_reg = i.InputFloat32Register(1); | 1440 SwVfpRegister left = i.InputFloat32Register(0); |
| 1446 FloatRegister result_reg = i.OutputFloat32Register(); | 1441 SwVfpRegister right = i.InputFloat32Register(1); |
| 1447 Label result_is_nan, return_left, return_right, check_zero, done; | 1442 if (left.is(right)) { |
| 1448 __ VFPCompareAndSetFlags(left_reg, right_reg); | 1443 __ Move(result, left); |
| 1449 __ b(mi, &return_left); | |
| 1450 __ b(gt, &return_right); | |
| 1451 __ b(vs, &result_is_nan); | |
| 1452 // Left equals right => check for -0. | |
| 1453 __ VFPCompareAndSetFlags(left_reg, 0.0); | |
| 1454 if (left_reg.is(result_reg) || right_reg.is(result_reg)) { | |
| 1455 __ b(ne, &done); // left == right != 0. | |
| 1456 } else { | 1444 } else { |
| 1457 __ b(ne, &return_left); // left == right != 0. | 1445 auto ool = new (zone()) OutOfLineFloat32Min(this, result, left, right); |
| 1446 __ FloatMin(result, left, right, ool->entry()); |
| 1447 __ bind(ool->exit()); |
| 1458 } | 1448 } |
| 1459 // At this point, both left and right are either 0 or -0. | 1449 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 1460 // We could use a single 'vorr' instruction here if we had NEON support. | |
| 1461 // The algorithm is: -((-L) + (-R)), which in case of L and R being | |
| 1462 // different registers is most efficiently expressed as -((-L) - R). | |
| 1463 __ vneg(left_reg, left_reg); | |
| 1464 if (left_reg.is(right_reg)) { | |
| 1465 __ vadd(result_reg, left_reg, right_reg); | |
| 1466 } else { | |
| 1467 __ vsub(result_reg, left_reg, right_reg); | |
| 1468 } | |
| 1469 __ vneg(result_reg, result_reg); | |
| 1470 __ b(&done); | |
| 1471 __ bind(&result_is_nan); | |
| 1472 __ vadd(result_reg, left_reg, right_reg); | |
| 1473 __ b(&done); | |
| 1474 __ bind(&return_right); | |
| 1475 __ Move(result_reg, right_reg); | |
| 1476 if (!left_reg.is(result_reg)) __ b(&done); | |
| 1477 __ bind(&return_left); | |
| 1478 __ Move(result_reg, left_reg); | |
| 1479 __ bind(&done); | |
| 1480 break; | 1450 break; |
| 1481 } | 1451 } |
| 1482 case kArmFloat64Min: { | 1452 case kArmFloat64Min: { |
| 1483 DwVfpRegister left_reg = i.InputDoubleRegister(0); | 1453 DwVfpRegister result = i.OutputDoubleRegister(); |
| 1484 DwVfpRegister right_reg = i.InputDoubleRegister(1); | 1454 DwVfpRegister left = i.InputDoubleRegister(0); |
| 1485 DwVfpRegister result_reg = i.OutputDoubleRegister(); | 1455 DwVfpRegister right = i.InputDoubleRegister(1); |
| 1486 Label result_is_nan, return_left, return_right, check_zero, done; | 1456 if (left.is(right)) { |
| 1487 __ VFPCompareAndSetFlags(left_reg, right_reg); | 1457 __ Move(result, left); |
| 1488 __ b(mi, &return_left); | |
| 1489 __ b(gt, &return_right); | |
| 1490 __ b(vs, &result_is_nan); | |
| 1491 // Left equals right => check for -0. | |
| 1492 __ VFPCompareAndSetFlags(left_reg, 0.0); | |
| 1493 if (left_reg.is(result_reg) || right_reg.is(result_reg)) { | |
| 1494 __ b(ne, &done); // left == right != 0. | |
| 1495 } else { | 1458 } else { |
| 1496 __ b(ne, &return_left); // left == right != 0. | 1459 auto ool = new (zone()) OutOfLineFloat64Min(this, result, left, right); |
| 1460 __ FloatMin(result, left, right, ool->entry()); |
| 1461 __ bind(ool->exit()); |
| 1497 } | 1462 } |
| 1498 // At this point, both left and right are either 0 or -0. | 1463 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 1499 // We could use a single 'vorr' instruction here if we had NEON support. | |
| 1500 // The algorithm is: -((-L) + (-R)), which in case of L and R being | |
| 1501 // different registers is most efficiently expressed as -((-L) - R). | |
| 1502 __ vneg(left_reg, left_reg); | |
| 1503 if (left_reg.is(right_reg)) { | |
| 1504 __ vadd(result_reg, left_reg, right_reg); | |
| 1505 } else { | |
| 1506 __ vsub(result_reg, left_reg, right_reg); | |
| 1507 } | |
| 1508 __ vneg(result_reg, result_reg); | |
| 1509 __ b(&done); | |
| 1510 __ bind(&result_is_nan); | |
| 1511 __ vadd(result_reg, left_reg, right_reg); | |
| 1512 __ b(&done); | |
| 1513 __ bind(&return_right); | |
| 1514 __ Move(result_reg, right_reg); | |
| 1515 if (!left_reg.is(result_reg)) __ b(&done); | |
| 1516 __ bind(&return_left); | |
| 1517 __ Move(result_reg, left_reg); | |
| 1518 __ bind(&done); | |
| 1519 break; | 1464 break; |
| 1520 } | 1465 } |
| 1521 case kArmFloat64SilenceNaN: { | 1466 case kArmFloat64SilenceNaN: { |
| 1522 DwVfpRegister value = i.InputDoubleRegister(0); | 1467 DwVfpRegister value = i.InputDoubleRegister(0); |
| 1523 DwVfpRegister result = i.OutputDoubleRegister(); | 1468 DwVfpRegister result = i.OutputDoubleRegister(); |
| 1524 __ VFPCanonicalizeNaN(result, value); | 1469 __ VFPCanonicalizeNaN(result, value); |
| 1525 break; | 1470 break; |
| 1526 } | 1471 } |
| 1527 case kArmPush: | 1472 case kArmPush: |
| 1528 if (instr->InputAt(0)->IsFPRegister()) { | 1473 if (instr->InputAt(0)->IsFPRegister()) { |
| (...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2026 padding_size -= v8::internal::Assembler::kInstrSize; | 1971 padding_size -= v8::internal::Assembler::kInstrSize; |
| 2027 } | 1972 } |
| 2028 } | 1973 } |
| 2029 } | 1974 } |
| 2030 | 1975 |
| 2031 #undef __ | 1976 #undef __ |
| 2032 | 1977 |
| 2033 } // namespace compiler | 1978 } // namespace compiler |
| 2034 } // namespace internal | 1979 } // namespace internal |
| 2035 } // namespace v8 | 1980 } // namespace v8 |
| OLD | NEW |