Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 2521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2532 // Emulate FPSCR from the Simulator flags. | 2532 // Emulate FPSCR from the Simulator flags. |
| 2533 uint32_t fpscr = (n_flag_FPSCR_ << 31) | | 2533 uint32_t fpscr = (n_flag_FPSCR_ << 31) | |
| 2534 (z_flag_FPSCR_ << 30) | | 2534 (z_flag_FPSCR_ << 30) | |
| 2535 (c_flag_FPSCR_ << 29) | | 2535 (c_flag_FPSCR_ << 29) | |
| 2536 (v_flag_FPSCR_ << 28) | | 2536 (v_flag_FPSCR_ << 28) | |
| 2537 (inexact_vfp_flag_ << 4) | | 2537 (inexact_vfp_flag_ << 4) | |
| 2538 (underflow_vfp_flag_ << 3) | | 2538 (underflow_vfp_flag_ << 3) | |
| 2539 (overflow_vfp_flag_ << 2) | | 2539 (overflow_vfp_flag_ << 2) | |
| 2540 (div_zero_vfp_flag_ << 1) | | 2540 (div_zero_vfp_flag_ << 1) | |
| 2541 (inv_op_vfp_flag_ << 0) | | 2541 (inv_op_vfp_flag_ << 0) | |
| 2542 (FPSCR_rounding_mode_ << 22); | 2542 (FPSCR_rounding_mode_); |
| 2543 set_register(rt, fpscr); | 2543 set_register(rt, fpscr); |
| 2544 } | 2544 } |
| 2545 } else if ((instr->VLValue() == 0x0) && | 2545 } else if ((instr->VLValue() == 0x0) && |
| 2546 (instr->VCValue() == 0x0) && | 2546 (instr->VCValue() == 0x0) && |
| 2547 (instr->VAValue() == 0x7) && | 2547 (instr->VAValue() == 0x7) && |
| 2548 (instr->Bits(19, 16) == 0x1)) { | 2548 (instr->Bits(19, 16) == 0x1)) { |
| 2549 // vmsr | 2549 // vmsr |
| 2550 uint32_t rt = instr->RtValue(); | 2550 uint32_t rt = instr->RtValue(); |
| 2551 if (rt == pc) { | 2551 if (rt == pc) { |
| 2552 UNREACHABLE(); | 2552 UNREACHABLE(); |
| 2553 } else { | 2553 } else { |
| 2554 uint32_t rt_value = get_register(rt); | 2554 uint32_t rt_value = get_register(rt); |
| 2555 n_flag_FPSCR_ = (rt_value >> 31) & 1; | 2555 n_flag_FPSCR_ = (rt_value >> 31) & 1; |
| 2556 z_flag_FPSCR_ = (rt_value >> 30) & 1; | 2556 z_flag_FPSCR_ = (rt_value >> 30) & 1; |
| 2557 c_flag_FPSCR_ = (rt_value >> 29) & 1; | 2557 c_flag_FPSCR_ = (rt_value >> 29) & 1; |
| 2558 v_flag_FPSCR_ = (rt_value >> 28) & 1; | 2558 v_flag_FPSCR_ = (rt_value >> 28) & 1; |
| 2559 inexact_vfp_flag_ = (rt_value >> 4) & 1; | 2559 inexact_vfp_flag_ = (rt_value >> 4) & 1; |
| 2560 underflow_vfp_flag_ = (rt_value >> 3) & 1; | 2560 underflow_vfp_flag_ = (rt_value >> 3) & 1; |
| 2561 overflow_vfp_flag_ = (rt_value >> 2) & 1; | 2561 overflow_vfp_flag_ = (rt_value >> 2) & 1; |
| 2562 div_zero_vfp_flag_ = (rt_value >> 1) & 1; | 2562 div_zero_vfp_flag_ = (rt_value >> 1) & 1; |
| 2563 inv_op_vfp_flag_ = (rt_value >> 0) & 1; | 2563 inv_op_vfp_flag_ = (rt_value >> 0) & 1; |
| 2564 FPSCR_rounding_mode_ = | 2564 FPSCR_rounding_mode_ = |
|
Søren Thygesen Gjesse
2011/02/03 09:07:17
4 char indent.
Rodolph Perfetta
2011/02/03 15:03:39
Done.
| |
| 2565 static_cast<FPSCRRoundingModes>((rt_value >> 22) & 3); | 2565 static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask); |
| 2566 } | 2566 } |
| 2567 } else { | 2567 } else { |
| 2568 UNIMPLEMENTED(); // Not used by V8. | 2568 UNIMPLEMENTED(); // Not used by V8. |
| 2569 } | 2569 } |
| 2570 } | 2570 } |
| 2571 } | 2571 } |
| 2572 | 2572 |
| 2573 | 2573 |
| 2574 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters( | 2574 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters( |
| 2575 Instruction* instr) { | 2575 Instruction* instr) { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2644 | 2644 |
| 2645 if (dst_precision == kSinglePrecision) { | 2645 if (dst_precision == kSinglePrecision) { |
| 2646 double val = get_double_from_d_register(src); | 2646 double val = get_double_from_d_register(src); |
| 2647 set_s_register_from_float(dst, static_cast<float>(val)); | 2647 set_s_register_from_float(dst, static_cast<float>(val)); |
| 2648 } else { | 2648 } else { |
| 2649 float val = get_float_from_s_register(src); | 2649 float val = get_float_from_s_register(src); |
| 2650 set_d_register_from_double(dst, static_cast<double>(val)); | 2650 set_d_register_from_double(dst, static_cast<double>(val)); |
| 2651 } | 2651 } |
| 2652 } | 2652 } |
| 2653 | 2653 |
| 2654 bool get_inv_op_vfp_flag(VFPRoundingMode mode, | |
| 2655 double val, | |
| 2656 bool unsigned_) { | |
| 2657 double max_uint = static_cast<double>(0xffffffffu); | |
| 2658 double max_int = static_cast<double>(kMaxInt); | |
| 2659 double min_int = static_cast<double>(kMinInt); | |
| 2660 // This code works because 32bit integers can be exactly represented by | |
| 2661 // ieee-754 64bit floating-point values. | |
| 2662 switch (mode) { | |
| 2663 case RN: | |
| 2664 return unsigned_ ? (val >= (max_uint + 0.5)) || | |
| 2665 (val < -0.5) || | |
|
Søren Thygesen Gjesse
2011/02/03 09:07:17
Please comment on what val != val checks. Maybe ha
Rodolph Perfetta
2011/02/03 15:03:39
made a separate check for NaN.
| |
| 2666 (val != val) | |
| 2667 : (val >= (max_int + 0.5)) || | |
| 2668 (val < (min_int - 0.5)) || | |
| 2669 (val != val); | |
| 2670 | |
| 2671 case RP: | |
| 2672 UNIMPLEMENTED(); | |
| 2673 return false; | |
| 2674 | |
| 2675 case RM: | |
| 2676 return unsigned_ ? (val >= (max_uint + 1.0)) || | |
| 2677 (val < 0) || | |
| 2678 (val != val) | |
| 2679 : (val >= (max_int + 1.0)) || | |
| 2680 (val < min_int) || | |
| 2681 (val != val); | |
| 2682 | |
| 2683 case RZ: | |
| 2684 return unsigned_ ? (val >= (max_uint + 1.0)) || | |
| 2685 (val <= -1) || | |
| 2686 (val != val) | |
| 2687 : (val >= (max_int + 1.0)) || | |
| 2688 (val <= (min_int - 1.0)) || | |
| 2689 (val != val); | |
| 2690 default: | |
| 2691 UNREACHABLE(); | |
| 2692 return false; | |
| 2693 } | |
| 2694 } | |
| 2695 | |
| 2696 | |
| 2697 // We call this function only if we had a vfp invalid exception. | |
| 2698 // It returns the correct saturated value. | |
| 2699 int VFPConversionSaturate(double val, bool unsigned_res) { | |
| 2700 if (val != val) { | |
| 2701 return 0; | |
| 2702 } else { | |
| 2703 if (unsigned_res) { | |
| 2704 return (val < 0) ? 0 : 0xffffffffu; | |
| 2705 } else { | |
| 2706 return (val < 0) ? kMinInt : kMaxInt; | |
| 2707 } | |
| 2708 } | |
| 2709 } | |
| 2710 | |
| 2654 | 2711 |
| 2655 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { | 2712 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { |
| 2656 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); | 2713 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) && |
| 2714 (instr->Bits(27, 23) == 0x1D)); | |
| 2657 ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || | 2715 ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || |
| 2658 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); | 2716 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); |
| 2659 | 2717 |
| 2660 // Conversion between floating-point and integer. | 2718 // Conversion between floating-point and integer. |
| 2661 bool to_integer = (instr->Bit(18) == 1); | 2719 bool to_integer = (instr->Bit(18) == 1); |
| 2662 | 2720 |
| 2663 VFPRegPrecision src_precision = kSinglePrecision; | 2721 VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision |
| 2664 if (instr->SzValue() == 1) { | 2722 : kSinglePrecision; |
| 2665 src_precision = kDoublePrecision; | |
| 2666 } | |
| 2667 | 2723 |
| 2668 if (to_integer) { | 2724 if (to_integer) { |
| 2669 bool unsigned_integer = (instr->Bit(16) == 0); | 2725 // We are playing with code close to the C++ standard's limits below, |
| 2670 FPSCRRoundingModes mode; | 2726 // hence the very simple code and heavy checks. |
| 2671 if (instr->Bit(7) != 1) { | 2727 // |
| 2672 // Use FPSCR defined rounding mode. | 2728 // Note: |
| 2673 mode = FPSCR_rounding_mode_; | 2729 // C++ defines default type casting from floating point to integer as |
| 2674 // Only RZ and RM modes are supported. | 2730 // (close to) rounding toward zero ("fractional part discarded"). |
| 2675 ASSERT((mode == RM) || (mode == RZ)); | |
| 2676 } else { | |
| 2677 // VFP uses round towards zero by default. | |
| 2678 mode = RZ; | |
| 2679 } | |
| 2680 | 2731 |
| 2681 int dst = instr->VFPDRegValue(kSinglePrecision); | 2732 int dst = instr->VFPDRegValue(kSinglePrecision); |
| 2682 int src = instr->VFPMRegValue(src_precision); | 2733 int src = instr->VFPMRegValue(src_precision); |
| 2683 int32_t kMaxInt = v8::internal::kMaxInt; | |
| 2684 int32_t kMinInt = v8::internal::kMinInt; | |
| 2685 switch (mode) { | |
| 2686 case RM: | |
| 2687 if (src_precision == kDoublePrecision) { | |
| 2688 double val = get_double_from_d_register(src); | |
| 2689 | 2734 |
| 2690 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | 2735 // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding |
| 2736 // mode or the default Round to Zero mode. | |
| 2737 VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_ | |
|
Søren Thygesen Gjesse
2011/02/03 09:07:17
Indentation.
Rodolph Perfetta
2011/02/03 15:03:39
Done.
| |
| 2738 : RZ; | |
| 2739 ASSERT((mode == RM) || (mode == RZ) || (mode == RN)); | |
| 2691 | 2740 |
| 2692 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | 2741 bool unsigned_integer = (instr->Bit(16) == 0); |
| 2693 static_cast<int32_t>(val); | 2742 bool double_precision = (src_precision == kDoublePrecision); |
| 2694 sint = sint > val ? sint - 1 : sint; | |
| 2695 | 2743 |
| 2696 set_s_register_from_sinteger(dst, sint); | 2744 double val = double_precision ? get_double_from_d_register(src) |
| 2697 } else { | 2745 : get_float_from_s_register(src); |
| 2698 float val = get_float_from_s_register(src); | |
| 2699 | 2746 |
| 2700 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | 2747 int temp = unsigned_integer ? static_cast<uint32_t>(val) : |
|
Søren Thygesen Gjesse
2011/02/03 09:07:17
Please be consistent with where the : is placed.
Rodolph Perfetta
2011/02/03 15:03:39
Done.
| |
| 2748 static_cast<int32_t>(val); | |
| 2701 | 2749 |
| 2702 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | 2750 inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer); |
| 2703 static_cast<int32_t>(val); | |
| 2704 sint = sint > val ? sint - 1 : sint; | |
| 2705 | 2751 |
| 2706 set_s_register_from_sinteger(dst, sint); | 2752 if (inv_op_vfp_flag_) { |
| 2753 temp = VFPConversionSaturate(val, unsigned_integer); | |
| 2754 } else { | |
| 2755 switch (mode) { | |
| 2756 case RN: { | |
| 2757 double abs_diff = | |
| 2758 unsigned_integer ? fabs(val - static_cast<uint32_t>(temp)) | |
| 2759 : fabs(val - temp); | |
| 2760 int val_sign = (val > 0) ? 1 : -1; | |
| 2761 if (abs_diff > 0.5) { | |
| 2762 temp += val_sign; | |
| 2763 } else if (abs_diff == 0.5) { | |
| 2764 // Round to even if exactly halfway. | |
| 2765 temp = ((temp % 2) == 0) ? temp : temp + val_sign; | |
| 2766 } | |
| 2767 break; | |
| 2707 } | 2768 } |
| 2708 break; | |
| 2709 case RZ: | |
| 2710 if (src_precision == kDoublePrecision) { | |
| 2711 double val = get_double_from_d_register(src); | |
| 2712 | 2769 |
| 2713 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | 2770 case RM: |
| 2771 temp = temp > val ? temp - 1 : temp; | |
| 2772 break; | |
| 2714 | 2773 |
| 2715 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | 2774 case RZ: |
| 2716 static_cast<int32_t>(val); | 2775 // Nothing to do. |
| 2776 break; | |
| 2717 | 2777 |
| 2718 set_s_register_from_sinteger(dst, sint); | 2778 default: |
| 2719 } else { | 2779 UNREACHABLE(); |
| 2720 float val = get_float_from_s_register(src); | 2780 } |
| 2781 } | |
| 2721 | 2782 |
| 2722 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | 2783 // Update the destination register. |
| 2723 | 2784 set_s_register_from_sinteger(dst, temp); |
| 2724 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | |
| 2725 static_cast<int32_t>(val); | |
| 2726 | |
| 2727 set_s_register_from_sinteger(dst, sint); | |
| 2728 } | |
| 2729 break; | |
| 2730 | |
| 2731 default: | |
| 2732 UNREACHABLE(); | |
| 2733 } | |
| 2734 | 2785 |
| 2735 } else { | 2786 } else { |
| 2736 bool unsigned_integer = (instr->Bit(7) == 0); | 2787 bool unsigned_integer = (instr->Bit(7) == 0); |
| 2737 | 2788 |
| 2738 int dst = instr->VFPDRegValue(src_precision); | 2789 int dst = instr->VFPDRegValue(src_precision); |
| 2739 int src = instr->VFPMRegValue(kSinglePrecision); | 2790 int src = instr->VFPMRegValue(kSinglePrecision); |
| 2740 | 2791 |
| 2741 int val = get_sinteger_from_s_register(src); | 2792 int val = get_sinteger_from_s_register(src); |
| 2742 | 2793 |
| 2743 if (src_precision == kDoublePrecision) { | 2794 if (src_precision == kDoublePrecision) { |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3052 uintptr_t address = *stack_slot; | 3103 uintptr_t address = *stack_slot; |
| 3053 set_register(sp, current_sp + sizeof(uintptr_t)); | 3104 set_register(sp, current_sp + sizeof(uintptr_t)); |
| 3054 return address; | 3105 return address; |
| 3055 } | 3106 } |
| 3056 | 3107 |
| 3057 } } // namespace v8::internal | 3108 } } // namespace v8::internal |
| 3058 | 3109 |
| 3059 #endif // USE_SIMULATOR | 3110 #endif // USE_SIMULATOR |
| 3060 | 3111 |
| 3061 #endif // V8_TARGET_ARCH_ARM | 3112 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |