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 |