| 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 |