OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdarg.h> | 5 #include <stdarg.h> |
6 #include <stdlib.h> | 6 #include <stdlib.h> |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 1291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1302 // operands have different signs | 1302 // operands have different signs |
1303 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0)) | 1303 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0)) |
1304 // and first operand and result have different signs | 1304 // and first operand and result have different signs |
1305 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); | 1305 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); |
1306 } | 1306 } |
1307 return overflow; | 1307 return overflow; |
1308 } | 1308 } |
1309 | 1309 |
1310 | 1310 |
1311 // Support for VFP comparisons. | 1311 // Support for VFP comparisons. |
| 1312 void Simulator::Compute_FPSCR_Flags(float val1, float val2) { |
| 1313 if (std::isnan(val1) || std::isnan(val2)) { |
| 1314 n_flag_FPSCR_ = false; |
| 1315 z_flag_FPSCR_ = false; |
| 1316 c_flag_FPSCR_ = true; |
| 1317 v_flag_FPSCR_ = true; |
| 1318 // All non-NaN cases. |
| 1319 } else if (val1 == val2) { |
| 1320 n_flag_FPSCR_ = false; |
| 1321 z_flag_FPSCR_ = true; |
| 1322 c_flag_FPSCR_ = true; |
| 1323 v_flag_FPSCR_ = false; |
| 1324 } else if (val1 < val2) { |
| 1325 n_flag_FPSCR_ = true; |
| 1326 z_flag_FPSCR_ = false; |
| 1327 c_flag_FPSCR_ = false; |
| 1328 v_flag_FPSCR_ = false; |
| 1329 } else { |
| 1330 // Case when (val1 > val2). |
| 1331 n_flag_FPSCR_ = false; |
| 1332 z_flag_FPSCR_ = false; |
| 1333 c_flag_FPSCR_ = true; |
| 1334 v_flag_FPSCR_ = false; |
| 1335 } |
| 1336 } |
| 1337 |
| 1338 |
1312 void Simulator::Compute_FPSCR_Flags(double val1, double val2) { | 1339 void Simulator::Compute_FPSCR_Flags(double val1, double val2) { |
1313 if (std::isnan(val1) || std::isnan(val2)) { | 1340 if (std::isnan(val1) || std::isnan(val2)) { |
1314 n_flag_FPSCR_ = false; | 1341 n_flag_FPSCR_ = false; |
1315 z_flag_FPSCR_ = false; | 1342 z_flag_FPSCR_ = false; |
1316 c_flag_FPSCR_ = true; | 1343 c_flag_FPSCR_ = true; |
1317 v_flag_FPSCR_ = true; | 1344 v_flag_FPSCR_ = true; |
1318 // All non-NaN cases. | 1345 // All non-NaN cases. |
1319 } else if (val1 == val2) { | 1346 } else if (val1 == val2) { |
1320 n_flag_FPSCR_ = false; | 1347 n_flag_FPSCR_ = false; |
1321 z_flag_FPSCR_ = true; | 1348 z_flag_FPSCR_ = true; |
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1907 } else { | 1934 } else { |
1908 // This is not a valid svc code. | 1935 // This is not a valid svc code. |
1909 UNREACHABLE(); | 1936 UNREACHABLE(); |
1910 break; | 1937 break; |
1911 } | 1938 } |
1912 } | 1939 } |
1913 } | 1940 } |
1914 } | 1941 } |
1915 | 1942 |
1916 | 1943 |
| 1944 float Simulator::canonicalizeNaN(float value) { |
| 1945 // Default NaN value, see "NaN handling" in "IEEE 754 standard implementation |
| 1946 // choices" of the ARM Reference Manual. |
| 1947 const uint32_t kDefaultNaN = 0x7FC00000u; |
| 1948 if (FPSCR_default_NaN_mode_ && std::isnan(value)) { |
| 1949 value = bit_cast<float>(kDefaultNaN); |
| 1950 } |
| 1951 return value; |
| 1952 } |
| 1953 |
| 1954 |
1917 double Simulator::canonicalizeNaN(double value) { | 1955 double Simulator::canonicalizeNaN(double value) { |
1918 // Default NaN value, see "NaN handling" in "IEEE 754 standard implementation | 1956 // Default NaN value, see "NaN handling" in "IEEE 754 standard implementation |
1919 // choices" of the ARM Reference Manual. | 1957 // choices" of the ARM Reference Manual. |
1920 const uint64_t kDefaultNaN = V8_UINT64_C(0x7FF8000000000000); | 1958 const uint64_t kDefaultNaN = V8_UINT64_C(0x7FF8000000000000); |
1921 if (FPSCR_default_NaN_mode_ && std::isnan(value)) { | 1959 if (FPSCR_default_NaN_mode_ && std::isnan(value)) { |
1922 value = bit_cast<double>(kDefaultNaN); | 1960 value = bit_cast<double>(kDefaultNaN); |
1923 } | 1961 } |
1924 return value; | 1962 return value; |
1925 } | 1963 } |
1926 | 1964 |
(...skipping 1075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3002 | 3040 |
3003 | 3041 |
3004 // void Simulator::DecodeTypeVFP(Instruction* instr) | 3042 // void Simulator::DecodeTypeVFP(Instruction* instr) |
3005 // The Following ARMv7 VFPv instructions are currently supported. | 3043 // The Following ARMv7 VFPv instructions are currently supported. |
3006 // vmov :Sn = Rt | 3044 // vmov :Sn = Rt |
3007 // vmov :Rt = Sn | 3045 // vmov :Rt = Sn |
3008 // vcvt: Dd = Sm | 3046 // vcvt: Dd = Sm |
3009 // vcvt: Sd = Dm | 3047 // vcvt: Sd = Dm |
3010 // vcvt.f64.s32 Dd, Dd, #<fbits> | 3048 // vcvt.f64.s32 Dd, Dd, #<fbits> |
3011 // Dd = vabs(Dm) | 3049 // Dd = vabs(Dm) |
| 3050 // Sd = vabs(Sm) |
3012 // Dd = vneg(Dm) | 3051 // Dd = vneg(Dm) |
| 3052 // Sd = vneg(Sm) |
3013 // Dd = vadd(Dn, Dm) | 3053 // Dd = vadd(Dn, Dm) |
| 3054 // Sd = vadd(Sn, Sm) |
3014 // Dd = vsub(Dn, Dm) | 3055 // Dd = vsub(Dn, Dm) |
| 3056 // Sd = vsub(Sn, Sm) |
3015 // Dd = vmul(Dn, Dm) | 3057 // Dd = vmul(Dn, Dm) |
| 3058 // Sd = vmul(Sn, Sm) |
3016 // Dd = vdiv(Dn, Dm) | 3059 // Dd = vdiv(Dn, Dm) |
| 3060 // Sd = vdiv(Sn, Sm) |
3017 // vcmp(Dd, Dm) | 3061 // vcmp(Dd, Dm) |
| 3062 // vcmp(Sd, Sm) |
| 3063 // Dd = vsqrt(Dm) |
| 3064 // Sd = vsqrt(Sm) |
3018 // vmrs | 3065 // vmrs |
3019 // Dd = vsqrt(Dm) | |
3020 void Simulator::DecodeTypeVFP(Instruction* instr) { | 3066 void Simulator::DecodeTypeVFP(Instruction* instr) { |
3021 DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); | 3067 DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); |
3022 DCHECK(instr->Bits(11, 9) == 0x5); | 3068 DCHECK(instr->Bits(11, 9) == 0x5); |
3023 | 3069 |
| 3070 // Obtain single precision register codes. |
| 3071 int m = instr->VFPMRegValue(kSinglePrecision); |
| 3072 int d = instr->VFPDRegValue(kSinglePrecision); |
| 3073 int n = instr->VFPNRegValue(kSinglePrecision); |
3024 // Obtain double precision register codes. | 3074 // Obtain double precision register codes. |
3025 int vm = instr->VFPMRegValue(kDoublePrecision); | 3075 int vm = instr->VFPMRegValue(kDoublePrecision); |
3026 int vd = instr->VFPDRegValue(kDoublePrecision); | 3076 int vd = instr->VFPDRegValue(kDoublePrecision); |
3027 int vn = instr->VFPNRegValue(kDoublePrecision); | 3077 int vn = instr->VFPNRegValue(kDoublePrecision); |
3028 | 3078 |
3029 if (instr->Bit(4) == 0) { | 3079 if (instr->Bit(4) == 0) { |
3030 if (instr->Opc1Value() == 0x7) { | 3080 if (instr->Opc1Value() == 0x7) { |
3031 // Other data processing instructions | 3081 // Other data processing instructions |
3032 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) { | 3082 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) { |
3033 // vmov register to register. | 3083 // vmov register to register. |
3034 if (instr->SzValue() == 0x1) { | 3084 if (instr->SzValue() == 0x1) { |
3035 int m = instr->VFPMRegValue(kDoublePrecision); | |
3036 int d = instr->VFPDRegValue(kDoublePrecision); | |
3037 uint32_t data[2]; | 3085 uint32_t data[2]; |
3038 get_d_register(m, data); | 3086 get_d_register(vm, data); |
3039 set_d_register(d, data); | 3087 set_d_register(vd, data); |
3040 } else { | 3088 } else { |
3041 int m = instr->VFPMRegValue(kSinglePrecision); | 3089 set_s_register(d, get_s_register(m)); |
3042 int d = instr->VFPDRegValue(kSinglePrecision); | |
3043 set_s_register_from_float(d, get_float_from_s_register(m)); | |
3044 } | 3090 } |
3045 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { | 3091 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { |
3046 // vabs | 3092 // vabs |
3047 double dm_value = get_double_from_d_register(vm); | 3093 if (instr->SzValue() == 0x1) { |
3048 double dd_value = std::fabs(dm_value); | 3094 double dm_value = get_double_from_d_register(vm); |
3049 dd_value = canonicalizeNaN(dd_value); | 3095 double dd_value = std::fabs(dm_value); |
3050 set_d_register_from_double(vd, dd_value); | 3096 dd_value = canonicalizeNaN(dd_value); |
| 3097 set_d_register_from_double(vd, dd_value); |
| 3098 } else { |
| 3099 float sm_value = get_float_from_s_register(m); |
| 3100 float sd_value = std::fabs(sm_value); |
| 3101 sd_value = canonicalizeNaN(sd_value); |
| 3102 set_s_register_from_float(d, sd_value); |
| 3103 } |
3051 } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) { | 3104 } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) { |
3052 // vneg | 3105 // vneg |
3053 double dm_value = get_double_from_d_register(vm); | 3106 if (instr->SzValue() == 0x1) { |
3054 double dd_value = -dm_value; | 3107 double dm_value = get_double_from_d_register(vm); |
3055 dd_value = canonicalizeNaN(dd_value); | 3108 double dd_value = -dm_value; |
3056 set_d_register_from_double(vd, dd_value); | 3109 dd_value = canonicalizeNaN(dd_value); |
| 3110 set_d_register_from_double(vd, dd_value); |
| 3111 } else { |
| 3112 float sm_value = get_float_from_s_register(m); |
| 3113 float sd_value = -sm_value; |
| 3114 sd_value = canonicalizeNaN(sd_value); |
| 3115 set_s_register_from_float(d, sd_value); |
| 3116 } |
3057 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { | 3117 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { |
3058 DecodeVCVTBetweenDoubleAndSingle(instr); | 3118 DecodeVCVTBetweenDoubleAndSingle(instr); |
3059 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { | 3119 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { |
3060 DecodeVCVTBetweenFloatingPointAndInteger(instr); | 3120 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
3061 } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) && | 3121 } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) && |
3062 (instr->Bit(8) == 1)) { | 3122 (instr->Bit(8) == 1)) { |
3063 // vcvt.f64.s32 Dd, Dd, #<fbits> | 3123 // vcvt.f64.s32 Dd, Dd, #<fbits> |
3064 int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5)); | 3124 int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5)); |
3065 int fixed_value = get_sinteger_from_s_register(vd * 2); | 3125 int fixed_value = get_sinteger_from_s_register(vd * 2); |
3066 double divide = 1 << fraction_bits; | 3126 double divide = 1 << fraction_bits; |
3067 set_d_register_from_double(vd, fixed_value / divide); | 3127 set_d_register_from_double(vd, fixed_value / divide); |
3068 } else if (((instr->Opc2Value() >> 1) == 0x6) && | 3128 } else if (((instr->Opc2Value() >> 1) == 0x6) && |
3069 (instr->Opc3Value() & 0x1)) { | 3129 (instr->Opc3Value() & 0x1)) { |
3070 DecodeVCVTBetweenFloatingPointAndInteger(instr); | 3130 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
3071 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && | 3131 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && |
3072 (instr->Opc3Value() & 0x1)) { | 3132 (instr->Opc3Value() & 0x1)) { |
3073 DecodeVCMP(instr); | 3133 DecodeVCMP(instr); |
3074 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { | 3134 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { |
3075 // vsqrt | 3135 // vsqrt |
3076 double dm_value = get_double_from_d_register(vm); | 3136 if (instr->SzValue() == 0x1) { |
3077 double dd_value = fast_sqrt(dm_value); | 3137 double dm_value = get_double_from_d_register(vm); |
3078 dd_value = canonicalizeNaN(dd_value); | 3138 double dd_value = fast_sqrt(dm_value); |
3079 set_d_register_from_double(vd, dd_value); | 3139 dd_value = canonicalizeNaN(dd_value); |
| 3140 set_d_register_from_double(vd, dd_value); |
| 3141 } else { |
| 3142 float sm_value = get_float_from_s_register(m); |
| 3143 float sd_value = fast_sqrt(sm_value); |
| 3144 sd_value = canonicalizeNaN(sd_value); |
| 3145 set_s_register_from_float(d, sd_value); |
| 3146 } |
3080 } else if (instr->Opc3Value() == 0x0) { | 3147 } else if (instr->Opc3Value() == 0x0) { |
3081 // vmov immediate. | 3148 // vmov immediate. |
3082 if (instr->SzValue() == 0x1) { | 3149 if (instr->SzValue() == 0x1) { |
3083 set_d_register_from_double(vd, instr->DoubleImmedVmov()); | 3150 set_d_register_from_double(vd, instr->DoubleImmedVmov()); |
3084 } else { | 3151 } else { |
3085 UNREACHABLE(); // Not used by v8. | 3152 UNREACHABLE(); // Not used by v8. |
3086 } | 3153 } |
3087 } else if (((instr->Opc2Value() == 0x6)) && (instr->Opc3Value() == 0x3)) { | 3154 } else if (((instr->Opc2Value() == 0x6)) && (instr->Opc3Value() == 0x3)) { |
3088 // vrintz - truncate | 3155 // vrintz - truncate |
3089 double dm_value = get_double_from_d_register(vm); | 3156 double dm_value = get_double_from_d_register(vm); |
3090 double dd_value = trunc(dm_value); | 3157 double dd_value = trunc(dm_value); |
3091 dd_value = canonicalizeNaN(dd_value); | 3158 dd_value = canonicalizeNaN(dd_value); |
3092 set_d_register_from_double(vd, dd_value); | 3159 set_d_register_from_double(vd, dd_value); |
3093 } else { | 3160 } else { |
3094 UNREACHABLE(); // Not used by V8. | 3161 UNREACHABLE(); // Not used by V8. |
3095 } | 3162 } |
3096 } else if (instr->Opc1Value() == 0x3) { | 3163 } else if (instr->Opc1Value() == 0x3) { |
3097 if (instr->SzValue() != 0x1) { | |
3098 UNREACHABLE(); // Not used by V8. | |
3099 } | |
3100 | |
3101 if (instr->Opc3Value() & 0x1) { | 3164 if (instr->Opc3Value() & 0x1) { |
3102 // vsub | 3165 // vsub |
| 3166 if (instr->SzValue() == 0x1) { |
| 3167 double dn_value = get_double_from_d_register(vn); |
| 3168 double dm_value = get_double_from_d_register(vm); |
| 3169 double dd_value = dn_value - dm_value; |
| 3170 dd_value = canonicalizeNaN(dd_value); |
| 3171 set_d_register_from_double(vd, dd_value); |
| 3172 } else { |
| 3173 float sn_value = get_float_from_s_register(n); |
| 3174 float sm_value = get_float_from_s_register(m); |
| 3175 float sd_value = sn_value - sm_value; |
| 3176 sd_value = canonicalizeNaN(sd_value); |
| 3177 set_s_register_from_float(d, sd_value); |
| 3178 } |
| 3179 } else { |
| 3180 // vadd |
| 3181 if (instr->SzValue() == 0x1) { |
| 3182 double dn_value = get_double_from_d_register(vn); |
| 3183 double dm_value = get_double_from_d_register(vm); |
| 3184 double dd_value = dn_value + dm_value; |
| 3185 dd_value = canonicalizeNaN(dd_value); |
| 3186 set_d_register_from_double(vd, dd_value); |
| 3187 } else { |
| 3188 float sn_value = get_float_from_s_register(n); |
| 3189 float sm_value = get_float_from_s_register(m); |
| 3190 float sd_value = sn_value + sm_value; |
| 3191 sd_value = canonicalizeNaN(sd_value); |
| 3192 set_s_register_from_float(d, sd_value); |
| 3193 } |
| 3194 } |
| 3195 } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) { |
| 3196 // vmul |
| 3197 if (instr->SzValue() == 0x1) { |
3103 double dn_value = get_double_from_d_register(vn); | 3198 double dn_value = get_double_from_d_register(vn); |
3104 double dm_value = get_double_from_d_register(vm); | 3199 double dm_value = get_double_from_d_register(vm); |
3105 double dd_value = dn_value - dm_value; | 3200 double dd_value = dn_value * dm_value; |
3106 dd_value = canonicalizeNaN(dd_value); | 3201 dd_value = canonicalizeNaN(dd_value); |
3107 set_d_register_from_double(vd, dd_value); | 3202 set_d_register_from_double(vd, dd_value); |
3108 } else { | 3203 } else { |
3109 // vadd | 3204 float sn_value = get_float_from_s_register(n); |
3110 double dn_value = get_double_from_d_register(vn); | 3205 float sm_value = get_float_from_s_register(m); |
3111 double dm_value = get_double_from_d_register(vm); | 3206 float sd_value = sn_value * sm_value; |
3112 double dd_value = dn_value + dm_value; | 3207 sd_value = canonicalizeNaN(sd_value); |
3113 dd_value = canonicalizeNaN(dd_value); | 3208 set_s_register_from_float(d, sd_value); |
3114 set_d_register_from_double(vd, dd_value); | |
3115 } | 3209 } |
3116 } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) { | |
3117 // vmul | |
3118 if (instr->SzValue() != 0x1) { | |
3119 UNREACHABLE(); // Not used by V8. | |
3120 } | |
3121 | |
3122 double dn_value = get_double_from_d_register(vn); | |
3123 double dm_value = get_double_from_d_register(vm); | |
3124 double dd_value = dn_value * dm_value; | |
3125 dd_value = canonicalizeNaN(dd_value); | |
3126 set_d_register_from_double(vd, dd_value); | |
3127 } else if ((instr->Opc1Value() == 0x0)) { | 3210 } else if ((instr->Opc1Value() == 0x0)) { |
3128 // vmla, vmls | 3211 // vmla, vmls |
3129 const bool is_vmls = (instr->Opc3Value() & 0x1); | 3212 const bool is_vmls = (instr->Opc3Value() & 0x1); |
| 3213 if (instr->SzValue() == 0x1) { |
| 3214 const double dd_val = get_double_from_d_register(vd); |
| 3215 const double dn_val = get_double_from_d_register(vn); |
| 3216 const double dm_val = get_double_from_d_register(vm); |
3130 | 3217 |
3131 if (instr->SzValue() != 0x1) { | 3218 // Note: we do the mul and add/sub in separate steps to avoid getting a |
3132 UNREACHABLE(); // Not used by V8. | 3219 // result with too high precision. |
3133 } | 3220 set_d_register_from_double(vd, dn_val * dm_val); |
| 3221 if (is_vmls) { |
| 3222 set_d_register_from_double( |
| 3223 vd, canonicalizeNaN(dd_val - get_double_from_d_register(vd))); |
| 3224 } else { |
| 3225 set_d_register_from_double( |
| 3226 vd, canonicalizeNaN(dd_val + get_double_from_d_register(vd))); |
| 3227 } |
| 3228 } else { |
| 3229 const float sd_val = get_float_from_s_register(d); |
| 3230 const float sn_val = get_float_from_s_register(n); |
| 3231 const float sm_val = get_float_from_s_register(m); |
3134 | 3232 |
3135 const double dd_val = get_double_from_d_register(vd); | 3233 // Note: we do the mul and add/sub in separate steps to avoid getting a |
3136 const double dn_val = get_double_from_d_register(vn); | 3234 // result with too high precision. |
3137 const double dm_val = get_double_from_d_register(vm); | 3235 set_s_register_from_float(d, sn_val * sm_val); |
3138 | 3236 if (is_vmls) { |
3139 // Note: we do the mul and add/sub in separate steps to avoid getting a | 3237 set_s_register_from_float( |
3140 // result with too high precision. | 3238 d, canonicalizeNaN(sd_val - get_float_from_s_register(d))); |
3141 set_d_register_from_double(vd, dn_val * dm_val); | 3239 } else { |
3142 if (is_vmls) { | 3240 set_s_register_from_float( |
3143 set_d_register_from_double( | 3241 d, canonicalizeNaN(sd_val + get_float_from_s_register(d))); |
3144 vd, | 3242 } |
3145 canonicalizeNaN(dd_val - get_double_from_d_register(vd))); | |
3146 } else { | |
3147 set_d_register_from_double( | |
3148 vd, | |
3149 canonicalizeNaN(dd_val + get_double_from_d_register(vd))); | |
3150 } | 3243 } |
3151 } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) { | 3244 } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) { |
3152 // vdiv | 3245 // vdiv |
3153 if (instr->SzValue() != 0x1) { | 3246 if (instr->SzValue() == 0x1) { |
3154 UNREACHABLE(); // Not used by V8. | 3247 double dn_value = get_double_from_d_register(vn); |
| 3248 double dm_value = get_double_from_d_register(vm); |
| 3249 double dd_value = dn_value / dm_value; |
| 3250 div_zero_vfp_flag_ = (dm_value == 0); |
| 3251 dd_value = canonicalizeNaN(dd_value); |
| 3252 set_d_register_from_double(vd, dd_value); |
| 3253 } else { |
| 3254 float sn_value = get_float_from_s_register(n); |
| 3255 float sm_value = get_float_from_s_register(m); |
| 3256 float sd_value = sn_value / sm_value; |
| 3257 div_zero_vfp_flag_ = (sm_value == 0); |
| 3258 sd_value = canonicalizeNaN(sd_value); |
| 3259 set_s_register_from_float(d, sd_value); |
3155 } | 3260 } |
3156 | |
3157 double dn_value = get_double_from_d_register(vn); | |
3158 double dm_value = get_double_from_d_register(vm); | |
3159 double dd_value = dn_value / dm_value; | |
3160 div_zero_vfp_flag_ = (dm_value == 0); | |
3161 dd_value = canonicalizeNaN(dd_value); | |
3162 set_d_register_from_double(vd, dd_value); | |
3163 } else { | 3261 } else { |
3164 UNIMPLEMENTED(); // Not used by V8. | 3262 UNIMPLEMENTED(); // Not used by V8. |
3165 } | 3263 } |
3166 } else { | 3264 } else { |
3167 if ((instr->VCValue() == 0x0) && | 3265 if ((instr->VCValue() == 0x0) && |
3168 (instr->VAValue() == 0x0)) { | 3266 (instr->VAValue() == 0x0)) { |
3169 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); | 3267 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); |
3170 } else if ((instr->VLValue() == 0x0) && | 3268 } else if ((instr->VLValue() == 0x0) && |
3171 (instr->VCValue() == 0x1) && | 3269 (instr->VCValue() == 0x1) && |
3172 (instr->Bit(23) == 0x0)) { | 3270 (instr->Bit(23) == 0x0)) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3257 } | 3355 } |
3258 | 3356 |
3259 | 3357 |
3260 void Simulator::DecodeVCMP(Instruction* instr) { | 3358 void Simulator::DecodeVCMP(Instruction* instr) { |
3261 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); | 3359 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); |
3262 DCHECK(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && | 3360 DCHECK(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && |
3263 (instr->Opc3Value() & 0x1)); | 3361 (instr->Opc3Value() & 0x1)); |
3264 // Comparison. | 3362 // Comparison. |
3265 | 3363 |
3266 VFPRegPrecision precision = kSinglePrecision; | 3364 VFPRegPrecision precision = kSinglePrecision; |
3267 if (instr->SzValue() == 1) { | 3365 if (instr->SzValue() == 0x1) { |
3268 precision = kDoublePrecision; | 3366 precision = kDoublePrecision; |
3269 } | 3367 } |
3270 | 3368 |
3271 int d = instr->VFPDRegValue(precision); | 3369 int d = instr->VFPDRegValue(precision); |
3272 int m = 0; | 3370 int m = 0; |
3273 if (instr->Opc2Value() == 0x4) { | 3371 if (instr->Opc2Value() == 0x4) { |
3274 m = instr->VFPMRegValue(precision); | 3372 m = instr->VFPMRegValue(precision); |
3275 } | 3373 } |
3276 | 3374 |
3277 if (precision == kDoublePrecision) { | 3375 if (precision == kDoublePrecision) { |
3278 double dd_value = get_double_from_d_register(d); | 3376 double dd_value = get_double_from_d_register(d); |
3279 double dm_value = 0.0; | 3377 double dm_value = 0.0; |
3280 if (instr->Opc2Value() == 0x4) { | 3378 if (instr->Opc2Value() == 0x4) { |
3281 dm_value = get_double_from_d_register(m); | 3379 dm_value = get_double_from_d_register(m); |
3282 } | 3380 } |
3283 | 3381 |
3284 // Raise exceptions for quiet NaNs if necessary. | 3382 // Raise exceptions for quiet NaNs if necessary. |
3285 if (instr->Bit(7) == 1) { | 3383 if (instr->Bit(7) == 1) { |
3286 if (std::isnan(dd_value)) { | 3384 if (std::isnan(dd_value)) { |
3287 inv_op_vfp_flag_ = true; | 3385 inv_op_vfp_flag_ = true; |
3288 } | 3386 } |
3289 } | 3387 } |
3290 | 3388 |
3291 Compute_FPSCR_Flags(dd_value, dm_value); | 3389 Compute_FPSCR_Flags(dd_value, dm_value); |
3292 } else { | 3390 } else { |
3293 UNIMPLEMENTED(); // Not used by V8. | 3391 float sd_value = get_float_from_s_register(d); |
| 3392 float sm_value = 0.0; |
| 3393 if (instr->Opc2Value() == 0x4) { |
| 3394 sm_value = get_float_from_s_register(m); |
| 3395 } |
| 3396 |
| 3397 // Raise exceptions for quiet NaNs if necessary. |
| 3398 if (instr->Bit(7) == 1) { |
| 3399 if (std::isnan(sd_value)) { |
| 3400 inv_op_vfp_flag_ = true; |
| 3401 } |
| 3402 } |
| 3403 |
| 3404 Compute_FPSCR_Flags(sd_value, sm_value); |
3294 } | 3405 } |
3295 } | 3406 } |
3296 | 3407 |
3297 | 3408 |
3298 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) { | 3409 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) { |
3299 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); | 3410 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); |
3300 DCHECK((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)); | 3411 DCHECK((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)); |
3301 | 3412 |
3302 VFPRegPrecision dst_precision = kDoublePrecision; | 3413 VFPRegPrecision dst_precision = kDoublePrecision; |
3303 VFPRegPrecision src_precision = kSinglePrecision; | 3414 VFPRegPrecision src_precision = kSinglePrecision; |
(...skipping 715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4019 uintptr_t address = *stack_slot; | 4130 uintptr_t address = *stack_slot; |
4020 set_register(sp, current_sp + sizeof(uintptr_t)); | 4131 set_register(sp, current_sp + sizeof(uintptr_t)); |
4021 return address; | 4132 return address; |
4022 } | 4133 } |
4023 | 4134 |
4024 } } // namespace v8::internal | 4135 } } // namespace v8::internal |
4025 | 4136 |
4026 #endif // USE_SIMULATOR | 4137 #endif // USE_SIMULATOR |
4027 | 4138 |
4028 #endif // V8_TARGET_ARCH_ARM | 4139 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |