Chromium Code Reviews| 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 |