| Index: src/arm/macro-assembler-arm.cc
|
| diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
|
| index 496d9bd69261f266eeae53d86aa90834fb24bfad..2e9356967c6e10ce9af35557bba74f7985e78cf2 100644
|
| --- a/src/arm/macro-assembler-arm.cc
|
| +++ b/src/arm/macro-assembler-arm.cc
|
| @@ -250,15 +250,17 @@ void MacroAssembler::Move(Register dst, Register src, Condition cond) {
|
| }
|
| }
|
|
|
| -void MacroAssembler::Move(SwVfpRegister dst, SwVfpRegister src) {
|
| +void MacroAssembler::Move(SwVfpRegister dst, SwVfpRegister src,
|
| + Condition cond) {
|
| if (!dst.is(src)) {
|
| - vmov(dst, src);
|
| + vmov(dst, src, cond);
|
| }
|
| }
|
|
|
| -void MacroAssembler::Move(DwVfpRegister dst, DwVfpRegister src) {
|
| +void MacroAssembler::Move(DwVfpRegister dst, DwVfpRegister src,
|
| + Condition cond) {
|
| if (!dst.is(src)) {
|
| - vmov(dst, src);
|
| + vmov(dst, src, cond);
|
| }
|
| }
|
|
|
| @@ -3428,6 +3430,144 @@ void MacroAssembler::RestoreFPRegs(Register location, Register scratch) {
|
| add(location, location, Operand(16 * kDoubleSize), LeaveCC, eq);
|
| }
|
|
|
| +template <typename T>
|
| +void MacroAssembler::FloatMaxHelper(T result, T left, T right,
|
| + Label* out_of_line) {
|
| + // This trivial case is caught sooner, so that the out-of-line code can be
|
| + // completely avoided.
|
| + DCHECK(!left.is(right));
|
| +
|
| + if (CpuFeatures::IsSupported(ARMv8)) {
|
| + CpuFeatureScope scope(this, ARMv8);
|
| + VFPCompareAndSetFlags(left, right);
|
| + b(vs, out_of_line);
|
| + vmaxnm(result, left, right);
|
| + } else {
|
| + Label done;
|
| + VFPCompareAndSetFlags(left, right);
|
| + b(vs, out_of_line);
|
| + // Avoid a conditional instruction if the result register is unique.
|
| + bool aliased_result_reg = result.is(left) || result.is(right);
|
| + Move(result, right, aliased_result_reg ? mi : al);
|
| + Move(result, left, gt);
|
| + b(ne, &done);
|
| + // Left and right are equal, but check for +/-0.
|
| + VFPCompareAndSetFlags(left, 0.0);
|
| + b(eq, out_of_line);
|
| + // The arguments are equal and not zero, so it doesn't matter which input we
|
| + // pick. We have already moved one input into the result (if it didn't
|
| + // already alias) so there's nothing more to do.
|
| + bind(&done);
|
| + }
|
| +}
|
| +
|
| +template <typename T>
|
| +void MacroAssembler::FloatMaxOutOfLineHelper(T result, T left, T right) {
|
| + DCHECK(!left.is(right));
|
| +
|
| + // ARMv8: At least one of left and right is a NaN.
|
| + // Anything else: At least one of left and right is a NaN, or both left and
|
| + // right are zeroes with unknown sign.
|
| +
|
| + // If left and right are +/-0, select the one with the most positive sign.
|
| + // If left or right are NaN, vadd propagates the appropriate one.
|
| + vadd(result, left, right);
|
| +}
|
| +
|
| +template <typename T>
|
| +void MacroAssembler::FloatMinHelper(T result, T left, T right,
|
| + Label* out_of_line) {
|
| + // This trivial case is caught sooner, so that the out-of-line code can be
|
| + // completely avoided.
|
| + DCHECK(!left.is(right));
|
| +
|
| + if (CpuFeatures::IsSupported(ARMv8)) {
|
| + CpuFeatureScope scope(this, ARMv8);
|
| + VFPCompareAndSetFlags(left, right);
|
| + b(vs, out_of_line);
|
| + vminnm(result, left, right);
|
| + } else {
|
| + Label done;
|
| + VFPCompareAndSetFlags(left, right);
|
| + b(vs, out_of_line);
|
| + // Avoid a conditional instruction if the result register is unique.
|
| + bool aliased_result_reg = result.is(left) || result.is(right);
|
| + Move(result, left, aliased_result_reg ? mi : al);
|
| + Move(result, right, gt);
|
| + b(ne, &done);
|
| + // Left and right are equal, but check for +/-0.
|
| + VFPCompareAndSetFlags(left, 0.0);
|
| + // If the arguments are equal and not zero, it doesn't matter which input we
|
| + // pick. We have already moved one input into the result (if it didn't
|
| + // already alias) so there's nothing more to do.
|
| + b(ne, &done);
|
| + // At this point, both left and right are either 0 or -0.
|
| + // We could use a single 'vorr' instruction here if we had NEON support.
|
| + // The algorithm used is -((-L) + (-R)), which is most efficiently expressed
|
| + // as -((-L) - R).
|
| + if (left.is(result)) {
|
| + DCHECK(!right.is(result));
|
| + vneg(result, left);
|
| + vsub(result, result, right);
|
| + vneg(result, result);
|
| + } else {
|
| + DCHECK(!left.is(result));
|
| + vneg(result, right);
|
| + vsub(result, result, left);
|
| + vneg(result, result);
|
| + }
|
| + bind(&done);
|
| + }
|
| +}
|
| +
|
| +template <typename T>
|
| +void MacroAssembler::FloatMinOutOfLineHelper(T result, T left, T right) {
|
| + DCHECK(!left.is(right));
|
| +
|
| + // At least one of left and right is a NaN. Use vadd to propagate the NaN
|
| + // appropriately. +/-0 is handled inline.
|
| + vadd(result, left, right);
|
| +}
|
| +
|
| +void MacroAssembler::FloatMax(SwVfpRegister result, SwVfpRegister left,
|
| + SwVfpRegister right, Label* out_of_line) {
|
| + FloatMaxHelper(result, left, right, out_of_line);
|
| +}
|
| +
|
| +void MacroAssembler::FloatMin(SwVfpRegister result, SwVfpRegister left,
|
| + SwVfpRegister right, Label* out_of_line) {
|
| + FloatMinHelper(result, left, right, out_of_line);
|
| +}
|
| +
|
| +void MacroAssembler::FloatMax(DwVfpRegister result, DwVfpRegister left,
|
| + DwVfpRegister right, Label* out_of_line) {
|
| + FloatMaxHelper(result, left, right, out_of_line);
|
| +}
|
| +
|
| +void MacroAssembler::FloatMin(DwVfpRegister result, DwVfpRegister left,
|
| + DwVfpRegister right, Label* out_of_line) {
|
| + FloatMinHelper(result, left, right, out_of_line);
|
| +}
|
| +
|
| +void MacroAssembler::FloatMaxOutOfLine(SwVfpRegister result, SwVfpRegister left,
|
| + SwVfpRegister right) {
|
| + FloatMaxOutOfLineHelper(result, left, right);
|
| +}
|
| +
|
| +void MacroAssembler::FloatMinOutOfLine(SwVfpRegister result, SwVfpRegister left,
|
| + SwVfpRegister right) {
|
| + FloatMinOutOfLineHelper(result, left, right);
|
| +}
|
| +
|
| +void MacroAssembler::FloatMaxOutOfLine(DwVfpRegister result, DwVfpRegister left,
|
| + DwVfpRegister right) {
|
| + FloatMaxOutOfLineHelper(result, left, right);
|
| +}
|
| +
|
| +void MacroAssembler::FloatMinOutOfLine(DwVfpRegister result, DwVfpRegister left,
|
| + DwVfpRegister right) {
|
| + FloatMinOutOfLineHelper(result, left, right);
|
| +}
|
|
|
| void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte(
|
| Register first, Register second, Register scratch1, Register scratch2,
|
|
|