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 755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
766 // even though s_registers_ & d_registers_ share the same | 766 // even though s_registers_ & d_registers_ share the same |
767 // physical registers in the target. | 767 // physical registers in the target. |
768 for (int i = 0; i < num_d_registers * 2; i++) { | 768 for (int i = 0; i < num_d_registers * 2; i++) { |
769 vfp_registers_[i] = 0; | 769 vfp_registers_[i] = 0; |
770 } | 770 } |
771 n_flag_FPSCR_ = false; | 771 n_flag_FPSCR_ = false; |
772 z_flag_FPSCR_ = false; | 772 z_flag_FPSCR_ = false; |
773 c_flag_FPSCR_ = false; | 773 c_flag_FPSCR_ = false; |
774 v_flag_FPSCR_ = false; | 774 v_flag_FPSCR_ = false; |
775 FPSCR_rounding_mode_ = RZ; | 775 FPSCR_rounding_mode_ = RZ; |
776 FPSCR_default_NaN_mode_ = true; | |
776 | 777 |
777 inv_op_vfp_flag_ = false; | 778 inv_op_vfp_flag_ = false; |
778 div_zero_vfp_flag_ = false; | 779 div_zero_vfp_flag_ = false; |
779 overflow_vfp_flag_ = false; | 780 overflow_vfp_flag_ = false; |
780 underflow_vfp_flag_ = false; | 781 underflow_vfp_flag_ = false; |
781 inexact_vfp_flag_ = false; | 782 inexact_vfp_flag_ = false; |
782 | 783 |
783 // The sp is initialized to point to the bottom (high address) of the | 784 // The sp is initialized to point to the bottom (high address) of the |
784 // allocated stack area. To be safe in potential stack underflows we leave | 785 // allocated stack area. To be safe in potential stack underflows we leave |
785 // some buffer below. | 786 // some buffer below. |
(...skipping 1075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1861 } else { | 1862 } else { |
1862 // This is not a valid svc code. | 1863 // This is not a valid svc code. |
1863 UNREACHABLE(); | 1864 UNREACHABLE(); |
1864 break; | 1865 break; |
1865 } | 1866 } |
1866 } | 1867 } |
1867 } | 1868 } |
1868 } | 1869 } |
1869 | 1870 |
1870 | 1871 |
1872 double Simulator::canonicalizeNaN(double value) { | |
1873 return (FPSCR_default_NaN_mode_ && isnan(value)) ? | |
1874 FixedDoubleArray::canonical_not_the_hole_nan_as_double(): value; | |
ulan
2013/04/15 15:00:56
Add space before ":".
| |
1875 } | |
1876 | |
1871 // Stop helper functions. | 1877 // Stop helper functions. |
1872 bool Simulator::isStopInstruction(Instruction* instr) { | 1878 bool Simulator::isStopInstruction(Instruction* instr) { |
1873 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode); | 1879 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode); |
1874 } | 1880 } |
1875 | 1881 |
1876 | 1882 |
1877 bool Simulator::isWatchedStop(uint32_t code) { | 1883 bool Simulator::isWatchedStop(uint32_t code) { |
1878 ASSERT(code <= kMaxStopCode); | 1884 ASSERT(code <= kMaxStopCode); |
1879 return code < kNumOfWatchedStops; | 1885 return code < kNumOfWatchedStops; |
1880 } | 1886 } |
(...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2721 set_d_register_from_double(d, get_double_from_d_register(m)); | 2727 set_d_register_from_double(d, get_double_from_d_register(m)); |
2722 } else { | 2728 } else { |
2723 int m = instr->VFPMRegValue(kSinglePrecision); | 2729 int m = instr->VFPMRegValue(kSinglePrecision); |
2724 int d = instr->VFPDRegValue(kSinglePrecision); | 2730 int d = instr->VFPDRegValue(kSinglePrecision); |
2725 set_s_register_from_float(d, get_float_from_s_register(m)); | 2731 set_s_register_from_float(d, get_float_from_s_register(m)); |
2726 } | 2732 } |
2727 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { | 2733 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { |
2728 // vabs | 2734 // vabs |
2729 double dm_value = get_double_from_d_register(vm); | 2735 double dm_value = get_double_from_d_register(vm); |
2730 double dd_value = fabs(dm_value); | 2736 double dd_value = fabs(dm_value); |
2737 dd_value = canonicalizeNaN(dd_value); | |
2731 set_d_register_from_double(vd, dd_value); | 2738 set_d_register_from_double(vd, dd_value); |
2732 } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) { | 2739 } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) { |
2733 // vneg | 2740 // vneg |
2734 double dm_value = get_double_from_d_register(vm); | 2741 double dm_value = get_double_from_d_register(vm); |
2735 double dd_value = -dm_value; | 2742 double dd_value = -dm_value; |
2743 dd_value = canonicalizeNaN(dd_value); | |
2736 set_d_register_from_double(vd, dd_value); | 2744 set_d_register_from_double(vd, dd_value); |
2737 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { | 2745 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { |
2738 DecodeVCVTBetweenDoubleAndSingle(instr); | 2746 DecodeVCVTBetweenDoubleAndSingle(instr); |
2739 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { | 2747 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { |
2740 DecodeVCVTBetweenFloatingPointAndInteger(instr); | 2748 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
2741 } else if (((instr->Opc2Value() >> 1) == 0x6) && | 2749 } else if (((instr->Opc2Value() >> 1) == 0x6) && |
2742 (instr->Opc3Value() & 0x1)) { | 2750 (instr->Opc3Value() & 0x1)) { |
2743 DecodeVCVTBetweenFloatingPointAndInteger(instr); | 2751 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
2744 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && | 2752 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && |
2745 (instr->Opc3Value() & 0x1)) { | 2753 (instr->Opc3Value() & 0x1)) { |
2746 DecodeVCMP(instr); | 2754 DecodeVCMP(instr); |
2747 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { | 2755 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { |
2748 // vsqrt | 2756 // vsqrt |
2749 double dm_value = get_double_from_d_register(vm); | 2757 double dm_value = get_double_from_d_register(vm); |
2750 double dd_value = sqrt(dm_value); | 2758 double dd_value = sqrt(dm_value); |
2759 dd_value = canonicalizeNaN(dd_value); | |
2751 set_d_register_from_double(vd, dd_value); | 2760 set_d_register_from_double(vd, dd_value); |
2752 } else if (instr->Opc3Value() == 0x0) { | 2761 } else if (instr->Opc3Value() == 0x0) { |
2753 // vmov immediate. | 2762 // vmov immediate. |
2754 if (instr->SzValue() == 0x1) { | 2763 if (instr->SzValue() == 0x1) { |
2755 set_d_register_from_double(vd, instr->DoubleImmedVmov()); | 2764 set_d_register_from_double(vd, instr->DoubleImmedVmov()); |
2756 } else { | 2765 } else { |
2757 UNREACHABLE(); // Not used by v8. | 2766 UNREACHABLE(); // Not used by v8. |
2758 } | 2767 } |
2759 } else { | 2768 } else { |
2760 UNREACHABLE(); // Not used by V8. | 2769 UNREACHABLE(); // Not used by V8. |
2761 } | 2770 } |
2762 } else if (instr->Opc1Value() == 0x3) { | 2771 } else if (instr->Opc1Value() == 0x3) { |
2763 if (instr->SzValue() != 0x1) { | 2772 if (instr->SzValue() != 0x1) { |
2764 UNREACHABLE(); // Not used by V8. | 2773 UNREACHABLE(); // Not used by V8. |
2765 } | 2774 } |
2766 | 2775 |
2767 if (instr->Opc3Value() & 0x1) { | 2776 if (instr->Opc3Value() & 0x1) { |
2768 // vsub | 2777 // vsub |
2769 double dn_value = get_double_from_d_register(vn); | 2778 double dn_value = get_double_from_d_register(vn); |
2770 double dm_value = get_double_from_d_register(vm); | 2779 double dm_value = get_double_from_d_register(vm); |
2771 double dd_value = dn_value - dm_value; | 2780 double dd_value = dn_value - dm_value; |
2781 dd_value = canonicalizeNaN(dd_value); | |
2772 set_d_register_from_double(vd, dd_value); | 2782 set_d_register_from_double(vd, dd_value); |
2773 } else { | 2783 } else { |
2774 // vadd | 2784 // vadd |
2775 double dn_value = get_double_from_d_register(vn); | 2785 double dn_value = get_double_from_d_register(vn); |
2776 double dm_value = get_double_from_d_register(vm); | 2786 double dm_value = get_double_from_d_register(vm); |
2777 double dd_value = dn_value + dm_value; | 2787 double dd_value = dn_value + dm_value; |
2788 dd_value = canonicalizeNaN(dd_value); | |
2778 set_d_register_from_double(vd, dd_value); | 2789 set_d_register_from_double(vd, dd_value); |
2779 } | 2790 } |
2780 } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) { | 2791 } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) { |
2781 // vmul | 2792 // vmul |
2782 if (instr->SzValue() != 0x1) { | 2793 if (instr->SzValue() != 0x1) { |
2783 UNREACHABLE(); // Not used by V8. | 2794 UNREACHABLE(); // Not used by V8. |
2784 } | 2795 } |
2785 | 2796 |
2786 double dn_value = get_double_from_d_register(vn); | 2797 double dn_value = get_double_from_d_register(vn); |
2787 double dm_value = get_double_from_d_register(vm); | 2798 double dm_value = get_double_from_d_register(vm); |
2788 double dd_value = dn_value * dm_value; | 2799 double dd_value = dn_value * dm_value; |
2800 dd_value = canonicalizeNaN(dd_value); | |
2789 set_d_register_from_double(vd, dd_value); | 2801 set_d_register_from_double(vd, dd_value); |
2790 } else if ((instr->Opc1Value() == 0x0)) { | 2802 } else if ((instr->Opc1Value() == 0x0)) { |
2791 // vmla, vmls | 2803 // vmla, vmls |
2792 const bool is_vmls = (instr->Opc3Value() & 0x1); | 2804 const bool is_vmls = (instr->Opc3Value() & 0x1); |
2793 | 2805 |
2794 if (instr->SzValue() != 0x1) { | 2806 if (instr->SzValue() != 0x1) { |
2795 UNREACHABLE(); // Not used by V8. | 2807 UNREACHABLE(); // Not used by V8. |
2796 } | 2808 } |
2797 | 2809 |
2798 const double dd_val = get_double_from_d_register(vd); | 2810 const double dd_val = get_double_from_d_register(vd); |
2799 const double dn_val = get_double_from_d_register(vn); | 2811 const double dn_val = get_double_from_d_register(vn); |
2800 const double dm_val = get_double_from_d_register(vm); | 2812 const double dm_val = get_double_from_d_register(vm); |
2801 | 2813 |
2802 // Note: we do the mul and add/sub in separate steps to avoid getting a | 2814 // Note: we do the mul and add/sub in separate steps to avoid getting a |
2803 // result with too high precision. | 2815 // result with too high precision. |
2804 set_d_register_from_double(vd, dn_val * dm_val); | 2816 set_d_register_from_double(vd, dn_val * dm_val); |
2805 if (is_vmls) { | 2817 if (is_vmls) { |
2806 set_d_register_from_double(vd, dd_val - get_double_from_d_register(vd)); | 2818 set_d_register_from_double( |
2819 vd, | |
2820 canonicalizeNaN(dd_val - get_double_from_d_register(vd))); | |
2807 } else { | 2821 } else { |
2808 set_d_register_from_double(vd, dd_val + get_double_from_d_register(vd)); | 2822 set_d_register_from_double( |
2823 vd, | |
2824 canonicalizeNaN(dd_val + get_double_from_d_register(vd))); | |
2809 } | 2825 } |
2810 } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) { | 2826 } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) { |
2811 // vdiv | 2827 // vdiv |
2812 if (instr->SzValue() != 0x1) { | 2828 if (instr->SzValue() != 0x1) { |
2813 UNREACHABLE(); // Not used by V8. | 2829 UNREACHABLE(); // Not used by V8. |
2814 } | 2830 } |
2815 | 2831 |
2816 double dn_value = get_double_from_d_register(vn); | 2832 double dn_value = get_double_from_d_register(vn); |
2817 double dm_value = get_double_from_d_register(vm); | 2833 double dm_value = get_double_from_d_register(vm); |
2818 double dd_value = dn_value / dm_value; | 2834 double dd_value = dn_value / dm_value; |
2819 div_zero_vfp_flag_ = (dm_value == 0); | 2835 div_zero_vfp_flag_ = (dm_value == 0); |
2836 dd_value = canonicalizeNaN(dd_value); | |
2820 set_d_register_from_double(vd, dd_value); | 2837 set_d_register_from_double(vd, dd_value); |
2821 } else { | 2838 } else { |
2822 UNIMPLEMENTED(); // Not used by V8. | 2839 UNIMPLEMENTED(); // Not used by V8. |
2823 } | 2840 } |
2824 } else { | 2841 } else { |
2825 if ((instr->VCValue() == 0x0) && | 2842 if ((instr->VCValue() == 0x0) && |
2826 (instr->VAValue() == 0x0)) { | 2843 (instr->VAValue() == 0x0)) { |
2827 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); | 2844 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); |
2828 } else if ((instr->VLValue() == 0x0) && | 2845 } else if ((instr->VLValue() == 0x0) && |
2829 (instr->VCValue() == 0x1) && | 2846 (instr->VCValue() == 0x1) && |
(...skipping 13 matching lines...) Expand all Loading... | |
2843 // vmrs | 2860 // vmrs |
2844 uint32_t rt = instr->RtValue(); | 2861 uint32_t rt = instr->RtValue(); |
2845 if (rt == 0xF) { | 2862 if (rt == 0xF) { |
2846 Copy_FPSCR_to_APSR(); | 2863 Copy_FPSCR_to_APSR(); |
2847 } else { | 2864 } else { |
2848 // Emulate FPSCR from the Simulator flags. | 2865 // Emulate FPSCR from the Simulator flags. |
2849 uint32_t fpscr = (n_flag_FPSCR_ << 31) | | 2866 uint32_t fpscr = (n_flag_FPSCR_ << 31) | |
2850 (z_flag_FPSCR_ << 30) | | 2867 (z_flag_FPSCR_ << 30) | |
2851 (c_flag_FPSCR_ << 29) | | 2868 (c_flag_FPSCR_ << 29) | |
2852 (v_flag_FPSCR_ << 28) | | 2869 (v_flag_FPSCR_ << 28) | |
2870 (FPSCR_default_NaN_mode_ << 25) | | |
2853 (inexact_vfp_flag_ << 4) | | 2871 (inexact_vfp_flag_ << 4) | |
2854 (underflow_vfp_flag_ << 3) | | 2872 (underflow_vfp_flag_ << 3) | |
2855 (overflow_vfp_flag_ << 2) | | 2873 (overflow_vfp_flag_ << 2) | |
2856 (div_zero_vfp_flag_ << 1) | | 2874 (div_zero_vfp_flag_ << 1) | |
2857 (inv_op_vfp_flag_ << 0) | | 2875 (inv_op_vfp_flag_ << 0) | |
2858 (FPSCR_rounding_mode_); | 2876 (FPSCR_rounding_mode_); |
2859 set_register(rt, fpscr); | 2877 set_register(rt, fpscr); |
2860 } | 2878 } |
2861 } else if ((instr->VLValue() == 0x0) && | 2879 } else if ((instr->VLValue() == 0x0) && |
2862 (instr->VCValue() == 0x0) && | 2880 (instr->VCValue() == 0x0) && |
2863 (instr->VAValue() == 0x7) && | 2881 (instr->VAValue() == 0x7) && |
2864 (instr->Bits(19, 16) == 0x1)) { | 2882 (instr->Bits(19, 16) == 0x1)) { |
2865 // vmsr | 2883 // vmsr |
2866 uint32_t rt = instr->RtValue(); | 2884 uint32_t rt = instr->RtValue(); |
2867 if (rt == pc) { | 2885 if (rt == pc) { |
2868 UNREACHABLE(); | 2886 UNREACHABLE(); |
2869 } else { | 2887 } else { |
2870 uint32_t rt_value = get_register(rt); | 2888 uint32_t rt_value = get_register(rt); |
2871 n_flag_FPSCR_ = (rt_value >> 31) & 1; | 2889 n_flag_FPSCR_ = (rt_value >> 31) & 1; |
2872 z_flag_FPSCR_ = (rt_value >> 30) & 1; | 2890 z_flag_FPSCR_ = (rt_value >> 30) & 1; |
2873 c_flag_FPSCR_ = (rt_value >> 29) & 1; | 2891 c_flag_FPSCR_ = (rt_value >> 29) & 1; |
2874 v_flag_FPSCR_ = (rt_value >> 28) & 1; | 2892 v_flag_FPSCR_ = (rt_value >> 28) & 1; |
2893 FPSCR_default_NaN_mode_ = (rt_value >> 25) & 1; | |
2875 inexact_vfp_flag_ = (rt_value >> 4) & 1; | 2894 inexact_vfp_flag_ = (rt_value >> 4) & 1; |
2876 underflow_vfp_flag_ = (rt_value >> 3) & 1; | 2895 underflow_vfp_flag_ = (rt_value >> 3) & 1; |
2877 overflow_vfp_flag_ = (rt_value >> 2) & 1; | 2896 overflow_vfp_flag_ = (rt_value >> 2) & 1; |
2878 div_zero_vfp_flag_ = (rt_value >> 1) & 1; | 2897 div_zero_vfp_flag_ = (rt_value >> 1) & 1; |
2879 inv_op_vfp_flag_ = (rt_value >> 0) & 1; | 2898 inv_op_vfp_flag_ = (rt_value >> 0) & 1; |
2880 FPSCR_rounding_mode_ = | 2899 FPSCR_rounding_mode_ = |
2881 static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask); | 2900 static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask); |
2882 } | 2901 } |
2883 } else { | 2902 } else { |
2884 UNIMPLEMENTED(); // Not used by V8. | 2903 UNIMPLEMENTED(); // Not used by V8. |
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3470 uintptr_t address = *stack_slot; | 3489 uintptr_t address = *stack_slot; |
3471 set_register(sp, current_sp + sizeof(uintptr_t)); | 3490 set_register(sp, current_sp + sizeof(uintptr_t)); |
3472 return address; | 3491 return address; |
3473 } | 3492 } |
3474 | 3493 |
3475 } } // namespace v8::internal | 3494 } } // namespace v8::internal |
3476 | 3495 |
3477 #endif // USE_SIMULATOR | 3496 #endif // USE_SIMULATOR |
3478 | 3497 |
3479 #endif // V8_TARGET_ARCH_ARM | 3498 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |