OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 2507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2518 orr(scratch, scratch2, Operand(scratch, LSR, 32 - shift_distance)); | 2518 orr(scratch, scratch2, Operand(scratch, LSR, 32 - shift_distance)); |
2519 // Move down according to the exponent. | 2519 // Move down according to the exponent. |
2520 mov(dest, Operand(scratch, LSR, dest)); | 2520 mov(dest, Operand(scratch, LSR, dest)); |
2521 // Fix sign if sign bit was set. | 2521 // Fix sign if sign bit was set. |
2522 rsb(dest, dest, Operand::Zero(), LeaveCC, ne); | 2522 rsb(dest, dest, Operand::Zero(), LeaveCC, ne); |
2523 bind(&done); | 2523 bind(&done); |
2524 } | 2524 } |
2525 } | 2525 } |
2526 | 2526 |
2527 | 2527 |
2528 void MacroAssembler::TryFastDoubleToInt32(Register result, | 2528 void MacroAssembler::TestDoubleIsInt32(DwVfpRegister double_input, |
2529 DwVfpRegister double_input, | 2529 DwVfpRegister double_scratch) { |
2530 DwVfpRegister double_scratch, | |
2531 Label* done) { | |
2532 ASSERT(!double_input.is(double_scratch)); | 2530 ASSERT(!double_input.is(double_scratch)); |
| 2531 ASSERT(CpuFeatures::IsSupported(VFP2)); |
| 2532 CpuFeatures::Scope scope(VFP2); |
| 2533 |
| 2534 vcvt_s32_f64(double_scratch.low(), double_input); |
| 2535 vcvt_f64_s32(double_scratch, double_scratch.low()); |
| 2536 VFPCompareAndSetFlags(double_input, double_scratch); |
| 2537 } |
| 2538 |
| 2539 |
| 2540 void MacroAssembler::TryDoubleToInt32Exact(Register result, |
| 2541 DwVfpRegister double_input, |
| 2542 DwVfpRegister double_scratch) { |
| 2543 ASSERT(!double_input.is(double_scratch)); |
| 2544 ASSERT(CpuFeatures::IsSupported(VFP2)); |
| 2545 CpuFeatures::Scope scope(VFP2); |
2533 | 2546 |
2534 vcvt_s32_f64(double_scratch.low(), double_input); | 2547 vcvt_s32_f64(double_scratch.low(), double_input); |
2535 vmov(result, double_scratch.low()); | 2548 vmov(result, double_scratch.low()); |
2536 vcvt_f64_s32(double_scratch, double_scratch.low()); | 2549 vcvt_f64_s32(double_scratch, double_scratch.low()); |
2537 VFPCompareAndSetFlags(double_input, double_scratch); | 2550 VFPCompareAndSetFlags(double_input, double_scratch); |
2538 b(eq, done); | |
2539 } | 2551 } |
2540 | 2552 |
2541 | 2553 |
2542 void MacroAssembler::EmitVFPTruncate(VFPRoundingMode rounding_mode, | 2554 void MacroAssembler::TryInt32Floor(Register result, |
2543 Register result, | 2555 DwVfpRegister double_input, |
2544 DwVfpRegister double_input, | 2556 Register input_high, |
2545 Register scratch, | 2557 DwVfpRegister double_scratch, |
2546 DwVfpRegister double_scratch, | 2558 Label* done, |
2547 CheckForInexactConversion check_inexact) { | 2559 Label* exact) { |
2548 ASSERT(!result.is(scratch)); | 2560 ASSERT(!result.is(input_high)); |
2549 ASSERT(!double_input.is(double_scratch)); | 2561 ASSERT(!double_input.is(double_scratch)); |
2550 | |
2551 ASSERT(CpuFeatures::IsSupported(VFP2)); | 2562 ASSERT(CpuFeatures::IsSupported(VFP2)); |
2552 CpuFeatures::Scope scope(VFP2); | 2563 CpuFeatures::Scope scope(VFP2); |
2553 Register prev_fpscr = result; | 2564 Label negative, exception; |
2554 Label done; | |
2555 | 2565 |
2556 // Test for values that can be exactly represented as a signed 32-bit integer. | 2566 // Test for NaN and infinities. |
2557 TryFastDoubleToInt32(result, double_input, double_scratch, &done); | 2567 Sbfx(result, input_high, |
| 2568 HeapNumber::kExponentShift, HeapNumber::kExponentBits); |
| 2569 cmp(result, Operand(-1)); |
| 2570 b(eq, &exception); |
| 2571 // Test for values that can be exactly represented as a |
| 2572 // signed 32-bit integer. |
| 2573 TryDoubleToInt32Exact(result, double_input, double_scratch); |
| 2574 // If exact, return (result already fetched). |
| 2575 b(eq, exact); |
| 2576 cmp(input_high, Operand::Zero()); |
| 2577 b(mi, &negative); |
2558 | 2578 |
2559 // Convert to integer, respecting rounding mode. | 2579 // Input is in ]+0, +inf[. |
2560 int32_t check_inexact_conversion = | 2580 // If result equals 0x7fffffff input was out of range or |
2561 (check_inexact == kCheckForInexactConversion) ? kVFPInexactExceptionBit : 0; | 2581 // in ]0x7fffffff, 0x80000000[. We ignore this last case which |
| 2582 // could fits into an int32, that means we always think input was |
| 2583 // out of range and always go to exception. |
| 2584 // If result < 0x7fffffff, go to done, result fetched. |
| 2585 cmn(result, Operand(1)); |
| 2586 b(mi, &exception); |
| 2587 b(done); |
2562 | 2588 |
2563 // Set custom FPCSR: | 2589 // Input is in ]-inf, -0[. |
2564 // - Set rounding mode. | 2590 // If x is a non integer negative number, |
2565 // - Clear vfp cumulative exception flags. | 2591 // floor(x) <=> round_to_zero(x) - 1. |
2566 // - Make sure Flush-to-zero mode control bit is unset. | 2592 bind(&negative); |
2567 vmrs(prev_fpscr); | 2593 sub(result, result, Operand(1), SetCC); |
2568 bic(scratch, | 2594 // If result is still negative, go to done, result fetched. |
2569 prev_fpscr, | 2595 // Else, we had an overflow and we fall through exception. |
2570 Operand(kVFPExceptionMask | | 2596 b(mi, done); |
2571 check_inexact_conversion | | 2597 bind(&exception); |
2572 kVFPRoundingModeMask | | |
2573 kVFPFlushToZeroMask)); | |
2574 // 'Round To Nearest' is encoded by 0b00 so no bits need to be set. | |
2575 if (rounding_mode != kRoundToNearest) { | |
2576 orr(scratch, scratch, Operand(rounding_mode)); | |
2577 } | |
2578 vmsr(scratch); | |
2579 | |
2580 // Convert the argument to an integer. | |
2581 vcvt_s32_f64(double_scratch.low(), | |
2582 double_input, | |
2583 (rounding_mode == kRoundToZero) ? kDefaultRoundToZero | |
2584 : kFPSCRRounding); | |
2585 | |
2586 // Retrieve FPSCR. | |
2587 vmrs(scratch); | |
2588 // Restore FPSCR. | |
2589 vmsr(prev_fpscr); | |
2590 // Move the converted value into the result register. | |
2591 vmov(result, double_scratch.low()); | |
2592 // Check for vfp exceptions. | |
2593 tst(scratch, Operand(kVFPExceptionMask | check_inexact_conversion)); | |
2594 | |
2595 bind(&done); | |
2596 } | 2598 } |
2597 | 2599 |
2598 | 2600 |
2599 void MacroAssembler::EmitOutOfInt32RangeTruncate(Register result, | 2601 void MacroAssembler::EmitOutOfInt32RangeTruncate(Register result, |
2600 Register input_high, | 2602 Register input_high, |
2601 Register input_low, | 2603 Register input_low, |
2602 Register scratch) { | 2604 Register scratch) { |
2603 Label done, normal_exponent, restore_sign; | 2605 Label done, normal_exponent, restore_sign; |
2604 | 2606 |
2605 // Extract the biased exponent in result. | 2607 // Extract the biased exponent in result. |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2680 ASSERT(!input_low.is(result)); | 2682 ASSERT(!input_low.is(result)); |
2681 ASSERT(!input_low.is(input_high)); | 2683 ASSERT(!input_low.is(input_high)); |
2682 ASSERT(!scratch.is(result) && | 2684 ASSERT(!scratch.is(result) && |
2683 !scratch.is(input_high) && | 2685 !scratch.is(input_high) && |
2684 !scratch.is(input_low)); | 2686 !scratch.is(input_low)); |
2685 ASSERT(!double_input.is(double_scratch)); | 2687 ASSERT(!double_input.is(double_scratch)); |
2686 | 2688 |
2687 Label done; | 2689 Label done; |
2688 | 2690 |
2689 // Test if the value can be exactly represented as a signed integer. | 2691 // Test if the value can be exactly represented as a signed integer. |
2690 vcvt_s32_f64(double_scratch.low(), double_input); | 2692 TryDoubleToInt32Exact(result, double_input, double_scratch); |
2691 vmov(result, double_scratch.low()); | |
2692 vcvt_f64_s32(double_scratch, double_scratch.low()); | |
2693 // Note: this comparison is cheaper than reading the FPSCR exception bits. | |
2694 VFPCompareAndSetFlags(double_input, double_scratch); | |
2695 b(eq, &done); | 2693 b(eq, &done); |
2696 | 2694 |
2697 // Check the exception flags. If they are not set, we are done. | 2695 // Check the exception flags. If they are not set, we are done. |
2698 // If they are set, it could be because of the conversion above, or because | 2696 // If they are set, it could be because of the conversion above, or because |
2699 // they were set before this code. | 2697 // they were set before this code. |
2700 vmrs(scratch); | 2698 vmrs(scratch); |
2701 tst(scratch, Operand(kVFPOverflowExceptionBit | | 2699 tst(scratch, Operand(kVFPInvalidOpExceptionBit)); |
2702 kVFPUnderflowExceptionBit | | |
2703 kVFPInvalidOpExceptionBit)); | |
2704 b(eq, &done); | 2700 b(eq, &done); |
2705 | 2701 |
2706 // Clear cumulative exception flags. | 2702 // Clear cumulative exception flags. |
2707 bic(scratch, scratch, Operand(kVFPExceptionMask)); | 2703 bic(scratch, scratch, Operand(kVFPInvalidOpExceptionBit)); |
2708 vmsr(scratch); | 2704 vmsr(scratch); |
2709 // Try a conversion to a signed integer. | 2705 // Try a conversion to a signed integer. |
2710 vcvt_s32_f64(double_scratch.low(), double_input); | 2706 vcvt_s32_f64(double_scratch.low(), double_input); |
2711 // Retrieve the FPSCR. | 2707 // Retrieve the FPSCR. |
2712 vmrs(scratch); | 2708 vmrs(scratch); |
2713 // Check for overflow and NaNs. | 2709 // Check for invalid conversions (out of range and NaNs). |
2714 tst(scratch, Operand(kVFPOverflowExceptionBit | | 2710 tst(scratch, Operand(kVFPInvalidOpExceptionBit)); |
2715 kVFPUnderflowExceptionBit | | |
2716 kVFPInvalidOpExceptionBit)); | |
2717 // If we had no exceptions we are done. | 2711 // If we had no exceptions we are done. |
2718 b(eq, &done); | 2712 b(eq, &done); |
2719 | 2713 |
2720 // Load the double value and perform a manual truncation. | 2714 // Load the double value and perform a manual truncation. |
2721 vmov(input_low, input_high, double_input); | 2715 vmov(input_low, input_high, double_input); |
2722 EmitOutOfInt32RangeTruncate(result, | 2716 EmitOutOfInt32RangeTruncate(result, |
2723 input_high, | 2717 input_high, |
2724 input_low, | 2718 input_low, |
2725 scratch); | 2719 scratch); |
2726 bind(&done); | 2720 bind(&done); |
(...skipping 1263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3990 void CodePatcher::EmitCondition(Condition cond) { | 3984 void CodePatcher::EmitCondition(Condition cond) { |
3991 Instr instr = Assembler::instr_at(masm_.pc_); | 3985 Instr instr = Assembler::instr_at(masm_.pc_); |
3992 instr = (instr & ~kCondMask) | cond; | 3986 instr = (instr & ~kCondMask) | cond; |
3993 masm_.emit(instr); | 3987 masm_.emit(instr); |
3994 } | 3988 } |
3995 | 3989 |
3996 | 3990 |
3997 } } // namespace v8::internal | 3991 } } // namespace v8::internal |
3998 | 3992 |
3999 #endif // V8_TARGET_ARCH_ARM | 3993 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |