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 |