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_ = |
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 ASSERT((mode == RN) || (mode == RM) || (mode == RZ)); |
| 2658 double max_uint = static_cast<double>(0xffffffffu); |
| 2659 double max_int = static_cast<double>(kMaxInt); |
| 2660 double min_int = static_cast<double>(kMinInt); |
| 2661 |
| 2662 // Check for NaN. |
| 2663 if (val != val) { |
| 2664 return true; |
| 2665 } |
| 2666 |
| 2667 // Check for overflow. This code works because 32bit integers can be |
| 2668 // exactly represented by ieee-754 64bit floating-point values. |
| 2669 switch (mode) { |
| 2670 case RN: |
| 2671 return unsigned_ ? (val >= (max_uint + 0.5)) || |
| 2672 (val < -0.5) |
| 2673 : (val >= (max_int + 0.5)) || |
| 2674 (val < (min_int - 0.5)); |
| 2675 |
| 2676 case RM: |
| 2677 return unsigned_ ? (val >= (max_uint + 1.0)) || |
| 2678 (val < 0) |
| 2679 : (val >= (max_int + 1.0)) || |
| 2680 (val < min_int); |
| 2681 |
| 2682 case RZ: |
| 2683 return unsigned_ ? (val >= (max_uint + 1.0)) || |
| 2684 (val <= -1) |
| 2685 : (val >= (max_int + 1.0)) || |
| 2686 (val <= (min_int - 1.0)); |
| 2687 default: |
| 2688 UNREACHABLE(); |
| 2689 return true; |
| 2690 } |
| 2691 } |
| 2692 |
| 2693 |
| 2694 // We call this function only if we had a vfp invalid exception. |
| 2695 // It returns the correct saturated value. |
| 2696 int VFPConversionSaturate(double val, bool unsigned_res) { |
| 2697 if (val != val) { |
| 2698 return 0; |
| 2699 } else { |
| 2700 if (unsigned_res) { |
| 2701 return (val < 0) ? 0 : 0xffffffffu; |
| 2702 } else { |
| 2703 return (val < 0) ? kMinInt : kMaxInt; |
| 2704 } |
| 2705 } |
| 2706 } |
| 2707 |
2654 | 2708 |
2655 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { | 2709 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { |
2656 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); | 2710 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) && |
| 2711 (instr->Bits(27, 23) == 0x1D)); |
2657 ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || | 2712 ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || |
2658 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); | 2713 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); |
2659 | 2714 |
2660 // Conversion between floating-point and integer. | 2715 // Conversion between floating-point and integer. |
2661 bool to_integer = (instr->Bit(18) == 1); | 2716 bool to_integer = (instr->Bit(18) == 1); |
2662 | 2717 |
2663 VFPRegPrecision src_precision = kSinglePrecision; | 2718 VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision |
2664 if (instr->SzValue() == 1) { | 2719 : kSinglePrecision; |
2665 src_precision = kDoublePrecision; | |
2666 } | |
2667 | 2720 |
2668 if (to_integer) { | 2721 if (to_integer) { |
2669 bool unsigned_integer = (instr->Bit(16) == 0); | 2722 // We are playing with code close to the C++ standard's limits below, |
2670 FPSCRRoundingModes mode; | 2723 // hence the very simple code and heavy checks. |
2671 if (instr->Bit(7) != 1) { | 2724 // |
2672 // Use FPSCR defined rounding mode. | 2725 // Note: |
2673 mode = FPSCR_rounding_mode_; | 2726 // C++ defines default type casting from floating point to integer as |
2674 // Only RZ and RM modes are supported. | 2727 // (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 | 2728 |
2681 int dst = instr->VFPDRegValue(kSinglePrecision); | 2729 int dst = instr->VFPDRegValue(kSinglePrecision); |
2682 int src = instr->VFPMRegValue(src_precision); | 2730 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 | 2731 |
2690 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | 2732 // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding |
| 2733 // mode or the default Round to Zero mode. |
| 2734 VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_ |
| 2735 : RZ; |
| 2736 ASSERT((mode == RM) || (mode == RZ) || (mode == RN)); |
2691 | 2737 |
2692 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | 2738 bool unsigned_integer = (instr->Bit(16) == 0); |
2693 static_cast<int32_t>(val); | 2739 bool double_precision = (src_precision == kDoublePrecision); |
2694 sint = sint > val ? sint - 1 : sint; | |
2695 | 2740 |
2696 set_s_register_from_sinteger(dst, sint); | 2741 double val = double_precision ? get_double_from_d_register(src) |
2697 } else { | 2742 : get_float_from_s_register(src); |
2698 float val = get_float_from_s_register(src); | |
2699 | 2743 |
2700 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | 2744 int temp = unsigned_integer ? static_cast<uint32_t>(val) |
| 2745 : static_cast<int32_t>(val); |
2701 | 2746 |
2702 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | 2747 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 | 2748 |
2706 set_s_register_from_sinteger(dst, sint); | 2749 if (inv_op_vfp_flag_) { |
| 2750 temp = VFPConversionSaturate(val, unsigned_integer); |
| 2751 } else { |
| 2752 switch (mode) { |
| 2753 case RN: { |
| 2754 double abs_diff = |
| 2755 unsigned_integer ? fabs(val - static_cast<uint32_t>(temp)) |
| 2756 : fabs(val - temp); |
| 2757 int val_sign = (val > 0) ? 1 : -1; |
| 2758 if (abs_diff > 0.5) { |
| 2759 temp += val_sign; |
| 2760 } else if (abs_diff == 0.5) { |
| 2761 // Round to even if exactly halfway. |
| 2762 temp = ((temp % 2) == 0) ? temp : temp + val_sign; |
| 2763 } |
| 2764 break; |
2707 } | 2765 } |
2708 break; | |
2709 case RZ: | |
2710 if (src_precision == kDoublePrecision) { | |
2711 double val = get_double_from_d_register(src); | |
2712 | 2766 |
2713 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | 2767 case RM: |
| 2768 temp = temp > val ? temp - 1 : temp; |
| 2769 break; |
2714 | 2770 |
2715 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | 2771 case RZ: |
2716 static_cast<int32_t>(val); | 2772 // Nothing to do. |
| 2773 break; |
2717 | 2774 |
2718 set_s_register_from_sinteger(dst, sint); | 2775 default: |
2719 } else { | 2776 UNREACHABLE(); |
2720 float val = get_float_from_s_register(src); | 2777 } |
| 2778 } |
2721 | 2779 |
2722 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | 2780 // Update the destination register. |
2723 | 2781 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 | 2782 |
2735 } else { | 2783 } else { |
2736 bool unsigned_integer = (instr->Bit(7) == 0); | 2784 bool unsigned_integer = (instr->Bit(7) == 0); |
2737 | 2785 |
2738 int dst = instr->VFPDRegValue(src_precision); | 2786 int dst = instr->VFPDRegValue(src_precision); |
2739 int src = instr->VFPMRegValue(kSinglePrecision); | 2787 int src = instr->VFPMRegValue(kSinglePrecision); |
2740 | 2788 |
2741 int val = get_sinteger_from_s_register(src); | 2789 int val = get_sinteger_from_s_register(src); |
2742 | 2790 |
2743 if (src_precision == kDoublePrecision) { | 2791 if (src_precision == kDoublePrecision) { |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3052 uintptr_t address = *stack_slot; | 3100 uintptr_t address = *stack_slot; |
3053 set_register(sp, current_sp + sizeof(uintptr_t)); | 3101 set_register(sp, current_sp + sizeof(uintptr_t)); |
3054 return address; | 3102 return address; |
3055 } | 3103 } |
3056 | 3104 |
3057 } } // namespace v8::internal | 3105 } } // namespace v8::internal |
3058 | 3106 |
3059 #endif // USE_SIMULATOR | 3107 #endif // USE_SIMULATOR |
3060 | 3108 |
3061 #endif // V8_TARGET_ARCH_ARM | 3109 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |