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 // 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 #if V8_TARGET_ARCH_ARM | 9 #if V8_TARGET_ARCH_ARM |
| 10 | 10 |
| (...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 893 memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value) * 2); | 893 memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value) * 2); |
| 894 } | 894 } |
| 895 | 895 |
| 896 | 896 |
| 897 void Simulator::set_d_register(int dreg, const uint32_t* value) { | 897 void Simulator::set_d_register(int dreg, const uint32_t* value) { |
| 898 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); | 898 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); |
| 899 memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value) * 2); | 899 memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value) * 2); |
| 900 } | 900 } |
| 901 | 901 |
| 902 template <typename T> | 902 template <typename T> |
| 903 void Simulator::get_d_register(int dreg, T* value) { | |
| 904 DCHECK((dreg >= 0) && (dreg < num_d_registers)); | |
| 905 memcpy(value, vfp_registers_ + dreg * 2, kDoubleSize); | |
| 906 } | |
| 907 | |
| 908 template <typename T> | |
| 909 void Simulator::set_d_register(int dreg, const T* value) { | |
| 910 DCHECK((dreg >= 0) && (dreg < num_d_registers)); | |
| 911 memcpy(vfp_registers_ + dreg * 2, value, kDoubleSize); | |
| 912 } | |
| 913 | |
| 914 template <typename T> | |
| 903 void Simulator::get_q_register(int qreg, T* value) { | 915 void Simulator::get_q_register(int qreg, T* value) { |
| 904 DCHECK((qreg >= 0) && (qreg < num_q_registers)); | 916 DCHECK((qreg >= 0) && (qreg < num_q_registers)); |
| 905 memcpy(value, vfp_registers_ + qreg * 4, kSimd128Size); | 917 memcpy(value, vfp_registers_ + qreg * 4, kSimd128Size); |
| 906 } | 918 } |
| 907 | 919 |
| 908 template <typename T> | 920 template <typename T> |
| 909 void Simulator::set_q_register(int qreg, const T* value) { | 921 void Simulator::set_q_register(int qreg, const T* value) { |
| 910 DCHECK((qreg >= 0) && (qreg < num_q_registers)); | 922 DCHECK((qreg >= 0) && (qreg < num_q_registers)); |
| 911 memcpy(vfp_registers_ + qreg * 4, value, kSimd128Size); | 923 memcpy(vfp_registers_ + qreg * 4, value, kSimd128Size); |
| 912 } | 924 } |
| 913 | 925 |
| 914 | |
| 915 // Raw access to the PC register. | 926 // Raw access to the PC register. |
| 916 void Simulator::set_pc(int32_t value) { | 927 void Simulator::set_pc(int32_t value) { |
| 917 pc_modified_ = true; | 928 pc_modified_ = true; |
| 918 registers_[pc] = value; | 929 registers_[pc] = value; |
| 919 } | 930 } |
| 920 | 931 |
| 921 | 932 |
| 922 bool Simulator::has_bad_pc() const { | 933 bool Simulator::has_bad_pc() const { |
| 923 return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc)); | 934 return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc)); |
| 924 } | 935 } |
| (...skipping 3411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4336 } | 4347 } |
| 4337 default: | 4348 default: |
| 4338 UNREACHABLE(); | 4349 UNREACHABLE(); |
| 4339 break; | 4350 break; |
| 4340 } | 4351 } |
| 4341 } else { | 4352 } else { |
| 4342 UNIMPLEMENTED(); | 4353 UNIMPLEMENTED(); |
| 4343 } | 4354 } |
| 4344 break; | 4355 break; |
| 4345 } | 4356 } |
| 4357 case 0xa: { | |
| 4358 // vpmin/vpmax.s<size> Dd, Dm, Dn. | |
| 4359 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); | |
| 4360 bool min = instr->Bit(4) != 0; | |
| 4361 switch (size) { | |
| 4362 case Neon8: { | |
| 4363 int8_t dst[8], src1[8], src2[8]; | |
| 4364 get_d_register(Vn, src1); | |
| 4365 get_d_register(Vm, src2); | |
| 4366 for (int i = 0; i < 4; i++) { | |
| 4367 if (min) { | |
|
martyn.capewell
2017/02/28 15:45:24
How about a templated minmax helper?
template <typ
bbudge
2017/02/28 17:39:35
That does look nicer. Done.
| |
| 4368 dst[i + 0] = std::min(src1[i * 2], src1[i * 2 + 1]); | |
| 4369 dst[i + 4] = std::min(src2[i * 2], src2[i * 2 + 1]); | |
| 4370 } else { | |
| 4371 dst[i + 0] = std::max(src1[i * 2], src1[i * 2 + 1]); | |
| 4372 dst[i + 4] = std::max(src2[i * 2], src2[i * 2 + 1]); | |
| 4373 } | |
| 4374 } | |
| 4375 set_d_register(Vd, dst); | |
| 4376 break; | |
| 4377 } | |
| 4378 case Neon16: { | |
| 4379 int16_t dst[4], src1[4], src2[4]; | |
| 4380 get_d_register(Vn, src1); | |
| 4381 get_d_register(Vm, src2); | |
| 4382 for (int i = 0; i < 2; i++) { | |
| 4383 if (min) { | |
| 4384 dst[i + 0] = std::min(src1[i * 2], src1[i * 2 + 1]); | |
| 4385 dst[i + 2] = std::min(src2[i * 2], src2[i * 2 + 1]); | |
| 4386 } else { | |
| 4387 dst[i + 0] = std::max(src1[i * 2], src1[i * 2 + 1]); | |
| 4388 dst[i + 2] = std::max(src2[i * 2], src2[i * 2 + 1]); | |
| 4389 } | |
| 4390 } | |
| 4391 set_d_register(Vd, dst); | |
| 4392 break; | |
| 4393 } | |
| 4394 case Neon32: { | |
| 4395 int32_t dst[2], src1[2], src2[2]; | |
| 4396 get_d_register(Vn, src1); | |
| 4397 get_d_register(Vm, src2); | |
| 4398 if (min) { | |
| 4399 dst[0] = std::min(src1[0], src1[1]); | |
| 4400 dst[1] = std::min(src2[0], src2[1]); | |
| 4401 } else { | |
| 4402 dst[0] = std::max(src1[0], src1[1]); | |
| 4403 dst[1] = std::max(src2[0], src2[1]); | |
| 4404 } | |
| 4405 set_d_register(Vd, dst); | |
| 4406 break; | |
| 4407 } | |
| 4408 default: | |
| 4409 UNREACHABLE(); | |
| 4410 break; | |
| 4411 } | |
| 4412 break; | |
| 4413 } | |
| 4346 case 0xd: { | 4414 case 0xd: { |
| 4347 if (instr->Bit(4) == 0) { | 4415 if (instr->Bit(4) == 0) { |
| 4348 float src1[4], src2[4]; | 4416 float src1[4], src2[4]; |
| 4349 get_q_register(Vn, src1); | 4417 get_q_register(Vn, src1); |
| 4350 get_q_register(Vm, src2); | 4418 get_q_register(Vm, src2); |
| 4351 for (int i = 0; i < 4; i++) { | 4419 for (int i = 0; i < 4; i++) { |
| 4352 if (instr->Bit(21) == 0) { | 4420 if (instr->Bit(21) == 0) { |
| 4353 // vadd.f32 Qd, Qm, Qn. | 4421 // vadd.f32 Qd, Qm, Qn. |
| 4354 src1[i] = src1[i] + src2[i]; | 4422 src1[i] = src1[i] + src2[i]; |
| 4355 } else { | 4423 } else { |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4805 set_q_register(Vd, src1); | 4873 set_q_register(Vd, src1); |
| 4806 break; | 4874 break; |
| 4807 } | 4875 } |
| 4808 default: | 4876 default: |
| 4809 UNREACHABLE(); | 4877 UNREACHABLE(); |
| 4810 break; | 4878 break; |
| 4811 } | 4879 } |
| 4812 } | 4880 } |
| 4813 break; | 4881 break; |
| 4814 } | 4882 } |
| 4883 case 0xa: { | |
| 4884 // vpmin/vpmax.u<size> Dd, Dm, Dn. | |
| 4885 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); | |
| 4886 bool min = instr->Bit(4) != 0; | |
| 4887 switch (size) { | |
| 4888 case Neon8: { | |
| 4889 uint8_t dst[8], src1[8], src2[8]; | |
| 4890 get_d_register(Vn, src1); | |
| 4891 get_d_register(Vm, src2); | |
| 4892 for (int i = 0; i < 4; i++) { | |
| 4893 if (min) { | |
| 4894 dst[i + 0] = std::min(src1[i * 2], src1[i * 2 + 1]); | |
| 4895 dst[i + 4] = std::min(src2[i * 2], src2[i * 2 + 1]); | |
| 4896 } else { | |
| 4897 dst[i + 0] = std::max(src1[i * 2], src1[i * 2 + 1]); | |
| 4898 dst[i + 4] = std::max(src2[i * 2], src2[i * 2 + 1]); | |
| 4899 } | |
| 4900 } | |
| 4901 set_d_register(Vd, dst); | |
| 4902 break; | |
| 4903 } | |
| 4904 case Neon16: { | |
| 4905 uint16_t dst[4], src1[4], src2[4]; | |
| 4906 get_d_register(Vn, src1); | |
| 4907 get_d_register(Vm, src2); | |
| 4908 for (int i = 0; i < 2; i++) { | |
| 4909 if (min) { | |
| 4910 dst[i + 0] = std::min(src1[i * 2], src1[i * 2 + 1]); | |
| 4911 dst[i + 2] = std::min(src2[i * 2], src2[i * 2 + 1]); | |
| 4912 } else { | |
| 4913 dst[i + 0] = std::max(src1[i * 2], src1[i * 2 + 1]); | |
| 4914 dst[i + 2] = std::max(src2[i * 2], src2[i * 2 + 1]); | |
| 4915 } | |
| 4916 } | |
| 4917 set_d_register(Vd, dst); | |
| 4918 break; | |
| 4919 } | |
| 4920 case Neon32: { | |
| 4921 uint32_t dst[2], src1[2], src2[2]; | |
| 4922 get_d_register(Vn, src1); | |
| 4923 get_d_register(Vm, src2); | |
| 4924 if (min) { | |
| 4925 dst[0] = std::min(src1[0], src1[1]); | |
| 4926 dst[1] = std::min(src2[0], src2[1]); | |
| 4927 } else { | |
| 4928 dst[0] = std::max(src1[0], src1[1]); | |
| 4929 dst[1] = std::max(src2[0], src2[1]); | |
| 4930 } | |
| 4931 set_d_register(Vd, dst); | |
| 4932 break; | |
| 4933 } | |
| 4934 default: | |
| 4935 UNREACHABLE(); | |
| 4936 break; | |
| 4937 } | |
| 4938 break; | |
| 4939 } | |
| 4815 case 0xd: { | 4940 case 0xd: { |
| 4816 if (instr->Bit(21) == 0 && instr->Bit(6) == 1 && instr->Bit(4) == 1) { | 4941 if (instr->Bit(21) == 0 && instr->Bit(6) == 1 && instr->Bit(4) == 1) { |
| 4817 // vmul.f32 Qd, Qn, Qm | 4942 // vmul.f32 Qd, Qn, Qm |
| 4818 float src1[4], src2[4]; | 4943 float src1[4], src2[4]; |
| 4819 get_q_register(Vn, src1); | 4944 get_q_register(Vn, src1); |
| 4820 get_q_register(Vm, src2); | 4945 get_q_register(Vm, src2); |
| 4821 for (int i = 0; i < 4; i++) { | 4946 for (int i = 0; i < 4; i++) { |
| 4822 src1[i] = src1[i] * src2[i]; | 4947 src1[i] = src1[i] * src2[i]; |
| 4823 } | 4948 } |
| 4824 set_q_register(Vd, src1); | 4949 set_q_register(Vd, src1); |
| (...skipping 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5982 processor->prev_ = nullptr; | 6107 processor->prev_ = nullptr; |
| 5983 processor->next_ = nullptr; | 6108 processor->next_ = nullptr; |
| 5984 } | 6109 } |
| 5985 | 6110 |
| 5986 } // namespace internal | 6111 } // namespace internal |
| 5987 } // namespace v8 | 6112 } // namespace v8 |
| 5988 | 6113 |
| 5989 #endif // USE_SIMULATOR | 6114 #endif // USE_SIMULATOR |
| 5990 | 6115 |
| 5991 #endif // V8_TARGET_ARCH_ARM | 6116 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |