| 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 |