OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 <limits.h> // For LONG_MIN, LONG_MAX. | 5 #include <limits.h> // For LONG_MIN, LONG_MAX. |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/base/division-by-constant.h" | 10 #include "src/base/division-by-constant.h" |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 mov(dst, Operand(value)); | 243 mov(dst, Operand(value)); |
244 } | 244 } |
245 | 245 |
246 | 246 |
247 void MacroAssembler::Move(Register dst, Register src, Condition cond) { | 247 void MacroAssembler::Move(Register dst, Register src, Condition cond) { |
248 if (!dst.is(src)) { | 248 if (!dst.is(src)) { |
249 mov(dst, src, LeaveCC, cond); | 249 mov(dst, src, LeaveCC, cond); |
250 } | 250 } |
251 } | 251 } |
252 | 252 |
253 void MacroAssembler::Move(SwVfpRegister dst, SwVfpRegister src) { | 253 void MacroAssembler::Move(SwVfpRegister dst, SwVfpRegister src, |
| 254 Condition cond) { |
254 if (!dst.is(src)) { | 255 if (!dst.is(src)) { |
255 vmov(dst, src); | 256 vmov(dst, src, cond); |
256 } | 257 } |
257 } | 258 } |
258 | 259 |
259 void MacroAssembler::Move(DwVfpRegister dst, DwVfpRegister src) { | 260 void MacroAssembler::Move(DwVfpRegister dst, DwVfpRegister src, |
| 261 Condition cond) { |
260 if (!dst.is(src)) { | 262 if (!dst.is(src)) { |
261 vmov(dst, src); | 263 vmov(dst, src, cond); |
262 } | 264 } |
263 } | 265 } |
264 | 266 |
265 void MacroAssembler::Mls(Register dst, Register src1, Register src2, | 267 void MacroAssembler::Mls(Register dst, Register src1, Register src2, |
266 Register srcA, Condition cond) { | 268 Register srcA, Condition cond) { |
267 if (CpuFeatures::IsSupported(ARMv7)) { | 269 if (CpuFeatures::IsSupported(ARMv7)) { |
268 CpuFeatureScope scope(this, ARMv7); | 270 CpuFeatureScope scope(this, ARMv7); |
269 mls(dst, src1, src2, srcA, cond); | 271 mls(dst, src1, src2, srcA, cond); |
270 } else { | 272 } else { |
271 DCHECK(!srcA.is(ip)); | 273 DCHECK(!srcA.is(ip)); |
(...skipping 3149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3421 } | 3423 } |
3422 | 3424 |
3423 | 3425 |
3424 void MacroAssembler::RestoreFPRegs(Register location, Register scratch) { | 3426 void MacroAssembler::RestoreFPRegs(Register location, Register scratch) { |
3425 CheckFor32DRegs(scratch); | 3427 CheckFor32DRegs(scratch); |
3426 vldm(ia_w, location, d0, d15); | 3428 vldm(ia_w, location, d0, d15); |
3427 vldm(ia_w, location, d16, d31, ne); | 3429 vldm(ia_w, location, d16, d31, ne); |
3428 add(location, location, Operand(16 * kDoubleSize), LeaveCC, eq); | 3430 add(location, location, Operand(16 * kDoubleSize), LeaveCC, eq); |
3429 } | 3431 } |
3430 | 3432 |
| 3433 template <typename T> |
| 3434 void MacroAssembler::FloatMaxHelper(T result, T left, T right, |
| 3435 Label* out_of_line) { |
| 3436 // This trivial case is caught sooner, so that the out-of-line code can be |
| 3437 // completely avoided. |
| 3438 DCHECK(!left.is(right)); |
| 3439 |
| 3440 if (CpuFeatures::IsSupported(ARMv8)) { |
| 3441 CpuFeatureScope scope(this, ARMv8); |
| 3442 VFPCompareAndSetFlags(left, right); |
| 3443 b(vs, out_of_line); |
| 3444 vmaxnm(result, left, right); |
| 3445 } else { |
| 3446 Label done; |
| 3447 VFPCompareAndSetFlags(left, right); |
| 3448 b(vs, out_of_line); |
| 3449 // Avoid a conditional instruction if the result register is unique. |
| 3450 bool aliased_result_reg = result.is(left) || result.is(right); |
| 3451 Move(result, right, aliased_result_reg ? mi : al); |
| 3452 Move(result, left, gt); |
| 3453 b(ne, &done); |
| 3454 // Left and right are equal, but check for +/-0. |
| 3455 VFPCompareAndSetFlags(left, 0.0); |
| 3456 b(eq, out_of_line); |
| 3457 // The arguments are equal and not zero, so it doesn't matter which input we |
| 3458 // pick. We have already moved one input into the result (if it didn't |
| 3459 // already alias) so there's nothing more to do. |
| 3460 bind(&done); |
| 3461 } |
| 3462 } |
| 3463 |
| 3464 template <typename T> |
| 3465 void MacroAssembler::FloatMaxOutOfLineHelper(T result, T left, T right) { |
| 3466 DCHECK(!left.is(right)); |
| 3467 |
| 3468 // ARMv8: At least one of left and right is a NaN. |
| 3469 // Anything else: At least one of left and right is a NaN, or both left and |
| 3470 // right are zeroes with unknown sign. |
| 3471 |
| 3472 // If left and right are +/-0, select the one with the most positive sign. |
| 3473 // If left or right are NaN, vadd propagates the appropriate one. |
| 3474 vadd(result, left, right); |
| 3475 } |
| 3476 |
| 3477 template <typename T> |
| 3478 void MacroAssembler::FloatMinHelper(T result, T left, T right, |
| 3479 Label* out_of_line) { |
| 3480 // This trivial case is caught sooner, so that the out-of-line code can be |
| 3481 // completely avoided. |
| 3482 DCHECK(!left.is(right)); |
| 3483 |
| 3484 if (CpuFeatures::IsSupported(ARMv8)) { |
| 3485 CpuFeatureScope scope(this, ARMv8); |
| 3486 VFPCompareAndSetFlags(left, right); |
| 3487 b(vs, out_of_line); |
| 3488 vminnm(result, left, right); |
| 3489 } else { |
| 3490 Label done; |
| 3491 VFPCompareAndSetFlags(left, right); |
| 3492 b(vs, out_of_line); |
| 3493 // Avoid a conditional instruction if the result register is unique. |
| 3494 bool aliased_result_reg = result.is(left) || result.is(right); |
| 3495 Move(result, left, aliased_result_reg ? mi : al); |
| 3496 Move(result, right, gt); |
| 3497 b(ne, &done); |
| 3498 // Left and right are equal, but check for +/-0. |
| 3499 VFPCompareAndSetFlags(left, 0.0); |
| 3500 // If the arguments are equal and not zero, it doesn't matter which input we |
| 3501 // pick. We have already moved one input into the result (if it didn't |
| 3502 // already alias) so there's nothing more to do. |
| 3503 b(ne, &done); |
| 3504 // At this point, both left and right are either 0 or -0. |
| 3505 // We could use a single 'vorr' instruction here if we had NEON support. |
| 3506 // The algorithm used is -((-L) + (-R)), which is most efficiently expressed |
| 3507 // as -((-L) - R). |
| 3508 if (left.is(result)) { |
| 3509 DCHECK(!right.is(result)); |
| 3510 vneg(result, left); |
| 3511 vsub(result, result, right); |
| 3512 vneg(result, result); |
| 3513 } else { |
| 3514 DCHECK(!left.is(result)); |
| 3515 vneg(result, right); |
| 3516 vsub(result, result, left); |
| 3517 vneg(result, result); |
| 3518 } |
| 3519 bind(&done); |
| 3520 } |
| 3521 } |
| 3522 |
| 3523 template <typename T> |
| 3524 void MacroAssembler::FloatMinOutOfLineHelper(T result, T left, T right) { |
| 3525 DCHECK(!left.is(right)); |
| 3526 |
| 3527 // At least one of left and right is a NaN. Use vadd to propagate the NaN |
| 3528 // appropriately. +/-0 is handled inline. |
| 3529 vadd(result, left, right); |
| 3530 } |
| 3531 |
| 3532 void MacroAssembler::FloatMax(SwVfpRegister result, SwVfpRegister left, |
| 3533 SwVfpRegister right, Label* out_of_line) { |
| 3534 FloatMaxHelper(result, left, right, out_of_line); |
| 3535 } |
| 3536 |
| 3537 void MacroAssembler::FloatMin(SwVfpRegister result, SwVfpRegister left, |
| 3538 SwVfpRegister right, Label* out_of_line) { |
| 3539 FloatMinHelper(result, left, right, out_of_line); |
| 3540 } |
| 3541 |
| 3542 void MacroAssembler::FloatMax(DwVfpRegister result, DwVfpRegister left, |
| 3543 DwVfpRegister right, Label* out_of_line) { |
| 3544 FloatMaxHelper(result, left, right, out_of_line); |
| 3545 } |
| 3546 |
| 3547 void MacroAssembler::FloatMin(DwVfpRegister result, DwVfpRegister left, |
| 3548 DwVfpRegister right, Label* out_of_line) { |
| 3549 FloatMinHelper(result, left, right, out_of_line); |
| 3550 } |
| 3551 |
| 3552 void MacroAssembler::FloatMaxOutOfLine(SwVfpRegister result, SwVfpRegister left, |
| 3553 SwVfpRegister right) { |
| 3554 FloatMaxOutOfLineHelper(result, left, right); |
| 3555 } |
| 3556 |
| 3557 void MacroAssembler::FloatMinOutOfLine(SwVfpRegister result, SwVfpRegister left, |
| 3558 SwVfpRegister right) { |
| 3559 FloatMinOutOfLineHelper(result, left, right); |
| 3560 } |
| 3561 |
| 3562 void MacroAssembler::FloatMaxOutOfLine(DwVfpRegister result, DwVfpRegister left, |
| 3563 DwVfpRegister right) { |
| 3564 FloatMaxOutOfLineHelper(result, left, right); |
| 3565 } |
| 3566 |
| 3567 void MacroAssembler::FloatMinOutOfLine(DwVfpRegister result, DwVfpRegister left, |
| 3568 DwVfpRegister right) { |
| 3569 FloatMinOutOfLineHelper(result, left, right); |
| 3570 } |
3431 | 3571 |
3432 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte( | 3572 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte( |
3433 Register first, Register second, Register scratch1, Register scratch2, | 3573 Register first, Register second, Register scratch1, Register scratch2, |
3434 Label* failure) { | 3574 Label* failure) { |
3435 const int kFlatOneByteStringMask = | 3575 const int kFlatOneByteStringMask = |
3436 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; | 3576 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; |
3437 const int kFlatOneByteStringTag = | 3577 const int kFlatOneByteStringTag = |
3438 kStringTag | kOneByteStringTag | kSeqStringTag; | 3578 kStringTag | kOneByteStringTag | kSeqStringTag; |
3439 and_(scratch1, first, Operand(kFlatOneByteStringMask)); | 3579 and_(scratch1, first, Operand(kFlatOneByteStringMask)); |
3440 and_(scratch2, second, Operand(kFlatOneByteStringMask)); | 3580 and_(scratch2, second, Operand(kFlatOneByteStringMask)); |
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4026 } | 4166 } |
4027 } | 4167 } |
4028 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); | 4168 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); |
4029 add(result, result, Operand(dividend, LSR, 31)); | 4169 add(result, result, Operand(dividend, LSR, 31)); |
4030 } | 4170 } |
4031 | 4171 |
4032 } // namespace internal | 4172 } // namespace internal |
4033 } // namespace v8 | 4173 } // namespace v8 |
4034 | 4174 |
4035 #endif // V8_TARGET_ARCH_ARM | 4175 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |