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/ast/scopes.h" | 8 #include "src/ast/scopes.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 1342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1353 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 1353 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
1354 break; | 1354 break; |
1355 case kArmVldrF64: | 1355 case kArmVldrF64: |
1356 __ vldr(i.OutputDoubleRegister(), i.InputOffset()); | 1356 __ vldr(i.OutputDoubleRegister(), i.InputOffset()); |
1357 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 1357 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
1358 break; | 1358 break; |
1359 case kArmVstrF64: | 1359 case kArmVstrF64: |
1360 __ vstr(i.InputDoubleRegister(0), i.InputOffset(1)); | 1360 __ vstr(i.InputDoubleRegister(0), i.InputOffset(1)); |
1361 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 1361 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
1362 break; | 1362 break; |
1363 case kArmFloat32Max: { | |
1364 CpuFeatureScope scope(masm(), ARMv8); | |
1365 // (b < a) ? a : b | |
1366 SwVfpRegister a = i.InputFloatRegister(0); | |
1367 SwVfpRegister b = i.InputFloatRegister(1); | |
1368 SwVfpRegister result = i.OutputFloatRegister(); | |
1369 __ VFPCompareAndSetFlags(a, b); | |
1370 __ vsel(gt, result, a, b); | |
1371 break; | |
1372 } | |
1373 case kArmFloat32Min: { | |
1374 CpuFeatureScope scope(masm(), ARMv8); | |
1375 // (a < b) ? a : b | |
1376 SwVfpRegister a = i.InputFloatRegister(0); | |
1377 SwVfpRegister b = i.InputFloatRegister(1); | |
1378 SwVfpRegister result = i.OutputFloatRegister(); | |
1379 __ VFPCompareAndSetFlags(b, a); | |
1380 __ vsel(gt, result, a, b); | |
1381 break; | |
1382 } | |
1383 case kArmFloat64Max: { | 1363 case kArmFloat64Max: { |
1384 CpuFeatureScope scope(masm(), ARMv8); | 1364 DwVfpRegister left_reg = i.InputDoubleRegister(0); |
1385 // (b < a) ? a : b | 1365 DwVfpRegister right_reg = i.InputDoubleRegister(1); |
1386 DwVfpRegister a = i.InputDoubleRegister(0); | 1366 DwVfpRegister result_reg = i.OutputDoubleRegister(); |
1387 DwVfpRegister b = i.InputDoubleRegister(1); | 1367 Label result_is_nan, return_left, return_right, check_zero, done; |
1388 DwVfpRegister result = i.OutputDoubleRegister(); | 1368 __ VFPCompareAndSetFlags(left_reg, right_reg); |
1389 __ VFPCompareAndSetFlags(a, b); | 1369 __ b(mi, &return_right); |
1390 __ vsel(gt, result, a, b); | 1370 __ b(gt, &return_left); |
| 1371 __ b(vs, &result_is_nan); |
| 1372 // Left equals right => check for -0. |
| 1373 __ VFPCompareAndSetFlags(left_reg, 0.0); |
| 1374 if (left_reg.is(result_reg) || right_reg.is(result_reg)) { |
| 1375 __ b(ne, &done); // left == right != 0. |
| 1376 } else { |
| 1377 __ b(ne, &return_left); // left == right != 0. |
| 1378 } |
| 1379 // At this point, both left and right are either 0 or -0. |
| 1380 // Since we operate on +0 and/or -0, vadd and vand have the same effect; |
| 1381 // the decision for vadd is easy because vand is a NEON instruction. |
| 1382 __ vadd(result_reg, left_reg, right_reg); |
| 1383 __ b(&done); |
| 1384 __ bind(&result_is_nan); |
| 1385 __ vadd(result_reg, left_reg, right_reg); |
| 1386 __ b(&done); |
| 1387 __ bind(&return_right); |
| 1388 __ Move(result_reg, right_reg); |
| 1389 if (!left_reg.is(result_reg)) __ b(&done); |
| 1390 __ bind(&return_left); |
| 1391 __ Move(result_reg, left_reg); |
| 1392 __ bind(&done); |
1391 break; | 1393 break; |
1392 } | 1394 } |
1393 case kArmFloat64Min: { | 1395 case kArmFloat64Min: { |
1394 CpuFeatureScope scope(masm(), ARMv8); | 1396 DwVfpRegister left_reg = i.InputDoubleRegister(0); |
1395 // (a < b) ? a : b | 1397 DwVfpRegister right_reg = i.InputDoubleRegister(1); |
1396 DwVfpRegister a = i.InputDoubleRegister(0); | 1398 DwVfpRegister result_reg = i.OutputDoubleRegister(); |
1397 DwVfpRegister b = i.InputDoubleRegister(1); | 1399 Label result_is_nan, return_left, return_right, check_zero, done; |
1398 DwVfpRegister result = i.OutputDoubleRegister(); | 1400 __ VFPCompareAndSetFlags(left_reg, right_reg); |
1399 __ VFPCompareAndSetFlags(b, a); | 1401 __ b(mi, &return_left); |
1400 __ vsel(gt, result, a, b); | 1402 __ b(gt, &return_right); |
| 1403 __ b(vs, &result_is_nan); |
| 1404 // Left equals right => check for -0. |
| 1405 __ VFPCompareAndSetFlags(left_reg, 0.0); |
| 1406 if (left_reg.is(result_reg) || right_reg.is(result_reg)) { |
| 1407 __ b(ne, &done); // left == right != 0. |
| 1408 } else { |
| 1409 __ b(ne, &return_left); // left == right != 0. |
| 1410 } |
| 1411 // At this point, both left and right are either 0 or -0. |
| 1412 // We could use a single 'vorr' instruction here if we had NEON support. |
| 1413 // The algorithm is: -((-L) + (-R)), which in case of L and R being |
| 1414 // different registers is most efficiently expressed as -((-L) - R). |
| 1415 __ vneg(left_reg, left_reg); |
| 1416 if (left_reg.is(right_reg)) { |
| 1417 __ vadd(result_reg, left_reg, right_reg); |
| 1418 } else { |
| 1419 __ vsub(result_reg, left_reg, right_reg); |
| 1420 } |
| 1421 __ vneg(result_reg, result_reg); |
| 1422 __ b(&done); |
| 1423 __ bind(&result_is_nan); |
| 1424 __ vadd(result_reg, left_reg, right_reg); |
| 1425 __ b(&done); |
| 1426 __ bind(&return_right); |
| 1427 __ Move(result_reg, right_reg); |
| 1428 if (!left_reg.is(result_reg)) __ b(&done); |
| 1429 __ bind(&return_left); |
| 1430 __ Move(result_reg, left_reg); |
| 1431 __ bind(&done); |
1401 break; | 1432 break; |
1402 } | 1433 } |
1403 case kArmFloat64SilenceNaN: { | 1434 case kArmFloat64SilenceNaN: { |
1404 DwVfpRegister value = i.InputDoubleRegister(0); | 1435 DwVfpRegister value = i.InputDoubleRegister(0); |
1405 DwVfpRegister result = i.OutputDoubleRegister(); | 1436 DwVfpRegister result = i.OutputDoubleRegister(); |
1406 __ VFPCanonicalizeNaN(result, value); | 1437 __ VFPCanonicalizeNaN(result, value); |
1407 break; | 1438 break; |
1408 } | 1439 } |
1409 case kArmPush: | 1440 case kArmPush: |
1410 if (instr->InputAt(0)->IsFPRegister()) { | 1441 if (instr->InputAt(0)->IsFPRegister()) { |
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1962 padding_size -= v8::internal::Assembler::kInstrSize; | 1993 padding_size -= v8::internal::Assembler::kInstrSize; |
1963 } | 1994 } |
1964 } | 1995 } |
1965 } | 1996 } |
1966 | 1997 |
1967 #undef __ | 1998 #undef __ |
1968 | 1999 |
1969 } // namespace compiler | 2000 } // namespace compiler |
1970 } // namespace internal | 2001 } // namespace internal |
1971 } // namespace v8 | 2002 } // namespace v8 |
OLD | NEW |