Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: src/arm/macro-assembler-arm.cc

Issue 12393008: [v8-dev] Split and replace the EmitVFPTruncate routine to only do what is needed. Floor (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698