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 |