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 3074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3999 template <typename T> | 4010 template <typename T> |
4000 T Clamp(int64_t value) { | 4011 T Clamp(int64_t value) { |
4001 static_assert(sizeof(int64_t) > sizeof(T), "T must be int32_t or smaller"); | 4012 static_assert(sizeof(int64_t) > sizeof(T), "T must be int32_t or smaller"); |
4002 int64_t min = static_cast<int64_t>(std::numeric_limits<T>::min()); | 4013 int64_t min = static_cast<int64_t>(std::numeric_limits<T>::min()); |
4003 int64_t max = static_cast<int64_t>(std::numeric_limits<T>::max()); | 4014 int64_t max = static_cast<int64_t>(std::numeric_limits<T>::max()); |
4004 int64_t clamped = std::max(min, std::min(max, value)); | 4015 int64_t clamped = std::max(min, std::min(max, value)); |
4005 return static_cast<T>(clamped); | 4016 return static_cast<T>(clamped); |
4006 } | 4017 } |
4007 | 4018 |
4008 template <typename T> | 4019 template <typename T> |
| 4020 T MinMax(T a, T b, bool is_min) { |
| 4021 return is_min ? std::min(a, b) : std::max(a, b); |
| 4022 } |
| 4023 |
| 4024 template <typename T> |
4009 void AddSaturate(Simulator* simulator, int Vd, int Vm, int Vn) { | 4025 void AddSaturate(Simulator* simulator, int Vd, int Vm, int Vn) { |
4010 static const int kLanes = 16 / sizeof(T); | 4026 static const int kLanes = 16 / sizeof(T); |
4011 T src1[kLanes], src2[kLanes]; | 4027 T src1[kLanes], src2[kLanes]; |
4012 simulator->get_q_register(Vn, src1); | 4028 simulator->get_q_register(Vn, src1); |
4013 simulator->get_q_register(Vm, src2); | 4029 simulator->get_q_register(Vm, src2); |
4014 for (int i = 0; i < kLanes; i++) { | 4030 for (int i = 0; i < kLanes; i++) { |
4015 src1[i] = Clamp<T>(Widen(src1[i]) + Widen(src2[i])); | 4031 src1[i] = Clamp<T>(Widen(src1[i]) + Widen(src2[i])); |
4016 } | 4032 } |
4017 simulator->set_q_register(Vd, src1); | 4033 simulator->set_q_register(Vd, src1); |
4018 } | 4034 } |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4172 case 0x6: { | 4188 case 0x6: { |
4173 // vmin/vmax.s<size> Qd, Qm, Qn. | 4189 // vmin/vmax.s<size> Qd, Qm, Qn. |
4174 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); | 4190 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
4175 bool min = instr->Bit(4) != 0; | 4191 bool min = instr->Bit(4) != 0; |
4176 switch (size) { | 4192 switch (size) { |
4177 case Neon8: { | 4193 case Neon8: { |
4178 int8_t src1[16], src2[16]; | 4194 int8_t src1[16], src2[16]; |
4179 get_q_register(Vn, src1); | 4195 get_q_register(Vn, src1); |
4180 get_q_register(Vm, src2); | 4196 get_q_register(Vm, src2); |
4181 for (int i = 0; i < 16; i++) { | 4197 for (int i = 0; i < 16; i++) { |
4182 if (min) | 4198 src1[i] = MinMax(src1[i], src2[i], min); |
4183 src1[i] = std::min(src1[i], src2[i]); | |
4184 else | |
4185 src1[i] = std::max(src1[i], src2[i]); | |
4186 } | 4199 } |
4187 set_q_register(Vd, src1); | 4200 set_q_register(Vd, src1); |
4188 break; | 4201 break; |
4189 } | 4202 } |
4190 case Neon16: { | 4203 case Neon16: { |
4191 int16_t src1[8], src2[8]; | 4204 int16_t src1[8], src2[8]; |
4192 get_q_register(Vn, src1); | 4205 get_q_register(Vn, src1); |
4193 get_q_register(Vm, src2); | 4206 get_q_register(Vm, src2); |
4194 for (int i = 0; i < 8; i++) { | 4207 for (int i = 0; i < 8; i++) { |
4195 if (min) | 4208 src1[i] = MinMax(src1[i], src2[i], min); |
4196 src1[i] = std::min(src1[i], src2[i]); | |
4197 else | |
4198 src1[i] = std::max(src1[i], src2[i]); | |
4199 } | 4209 } |
4200 set_q_register(Vd, src1); | 4210 set_q_register(Vd, src1); |
4201 break; | 4211 break; |
4202 } | 4212 } |
4203 case Neon32: { | 4213 case Neon32: { |
4204 int32_t src1[4], src2[4]; | 4214 int32_t src1[4], src2[4]; |
4205 get_q_register(Vn, src1); | 4215 get_q_register(Vn, src1); |
4206 get_q_register(Vm, src2); | 4216 get_q_register(Vm, src2); |
4207 for (int i = 0; i < 4; i++) { | 4217 for (int i = 0; i < 4; i++) { |
4208 if (min) | 4218 src1[i] = MinMax(src1[i], src2[i], min); |
4209 src1[i] = std::min(src1[i], src2[i]); | |
4210 else | |
4211 src1[i] = std::max(src1[i], src2[i]); | |
4212 } | 4219 } |
4213 set_q_register(Vd, src1); | 4220 set_q_register(Vd, src1); |
4214 break; | 4221 break; |
4215 } | 4222 } |
4216 default: | 4223 default: |
4217 UNREACHABLE(); | 4224 UNREACHABLE(); |
4218 break; | 4225 break; |
4219 } | 4226 } |
4220 break; | 4227 break; |
4221 } | 4228 } |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4336 } | 4343 } |
4337 default: | 4344 default: |
4338 UNREACHABLE(); | 4345 UNREACHABLE(); |
4339 break; | 4346 break; |
4340 } | 4347 } |
4341 } else { | 4348 } else { |
4342 UNIMPLEMENTED(); | 4349 UNIMPLEMENTED(); |
4343 } | 4350 } |
4344 break; | 4351 break; |
4345 } | 4352 } |
| 4353 case 0xa: { |
| 4354 // vpmin/vpmax.s<size> Dd, Dm, Dn. |
| 4355 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
| 4356 bool min = instr->Bit(4) != 0; |
| 4357 switch (size) { |
| 4358 case Neon8: { |
| 4359 int8_t dst[8], src1[8], src2[8]; |
| 4360 get_d_register(Vn, src1); |
| 4361 get_d_register(Vm, src2); |
| 4362 for (int i = 0; i < 4; i++) { |
| 4363 dst[i + 0] = MinMax(src1[i * 2], src1[i * 2 + 1], min); |
| 4364 dst[i + 4] = MinMax(src2[i * 2], src2[i * 2 + 1], min); |
| 4365 } |
| 4366 set_d_register(Vd, dst); |
| 4367 break; |
| 4368 } |
| 4369 case Neon16: { |
| 4370 int16_t dst[4], src1[4], src2[4]; |
| 4371 get_d_register(Vn, src1); |
| 4372 get_d_register(Vm, src2); |
| 4373 for (int i = 0; i < 2; i++) { |
| 4374 dst[i + 0] = MinMax(src1[i * 2], src1[i * 2 + 1], min); |
| 4375 dst[i + 2] = MinMax(src2[i * 2], src2[i * 2 + 1], min); |
| 4376 } |
| 4377 set_d_register(Vd, dst); |
| 4378 break; |
| 4379 } |
| 4380 case Neon32: { |
| 4381 int32_t dst[2], src1[2], src2[2]; |
| 4382 get_d_register(Vn, src1); |
| 4383 get_d_register(Vm, src2); |
| 4384 dst[0] = MinMax(src1[0], src1[1], min); |
| 4385 dst[1] = MinMax(src2[0], src2[1], min); |
| 4386 set_d_register(Vd, dst); |
| 4387 break; |
| 4388 } |
| 4389 default: |
| 4390 UNREACHABLE(); |
| 4391 break; |
| 4392 } |
| 4393 break; |
| 4394 } |
4346 case 0xd: { | 4395 case 0xd: { |
4347 if (instr->Bit(4) == 0) { | 4396 if (instr->Bit(4) == 0) { |
4348 float src1[4], src2[4]; | 4397 float src1[4], src2[4]; |
4349 get_q_register(Vn, src1); | 4398 get_q_register(Vn, src1); |
4350 get_q_register(Vm, src2); | 4399 get_q_register(Vm, src2); |
4351 for (int i = 0; i < 4; i++) { | 4400 for (int i = 0; i < 4; i++) { |
4352 if (instr->Bit(21) == 0) { | 4401 if (instr->Bit(21) == 0) { |
4353 // vadd.f32 Qd, Qm, Qn. | 4402 // vadd.f32 Qd, Qm, Qn. |
4354 src1[i] = src1[i] + src2[i]; | 4403 src1[i] = src1[i] + src2[i]; |
4355 } else { | 4404 } else { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4390 for (int i = 0; i < 4; i++) { | 4439 for (int i = 0; i < 4; i++) { |
4391 src1[i] = 2.0f - src1[i] * src2[i]; | 4440 src1[i] = 2.0f - src1[i] * src2[i]; |
4392 } | 4441 } |
4393 } else { | 4442 } else { |
4394 // vrsqrts.f32 Qd, Qm, Qn. | 4443 // vrsqrts.f32 Qd, Qm, Qn. |
4395 for (int i = 0; i < 4; i++) { | 4444 for (int i = 0; i < 4; i++) { |
4396 src1[i] = (3.0f - src1[i] * src2[i]) * 0.5f; | 4445 src1[i] = (3.0f - src1[i] * src2[i]) * 0.5f; |
4397 } | 4446 } |
4398 } | 4447 } |
4399 } else { | 4448 } else { |
4400 if (instr->Bit(21) == 1) { | 4449 // vmin/vmax.f32 Qd, Qm, Qn. |
4401 // vmin.f32 Qd, Qm, Qn. | 4450 bool min = instr->Bit(21) == 1; |
4402 for (int i = 0; i < 4; i++) { | 4451 for (int i = 0; i < 4; i++) { |
4403 src1[i] = std::min(src1[i], src2[i]); | 4452 src1[i] = MinMax(src1[i], src2[i], min); |
4404 } | |
4405 } else { | |
4406 // vmax.f32 Qd, Qm, Qn. | |
4407 for (int i = 0; i < 4; i++) { | |
4408 src1[i] = std::max(src1[i], src2[i]); | |
4409 } | |
4410 } | 4453 } |
4411 } | 4454 } |
4412 set_q_register(Vd, src1); | 4455 set_q_register(Vd, src1); |
4413 } else { | 4456 } else { |
4414 UNIMPLEMENTED(); | 4457 UNIMPLEMENTED(); |
4415 } | 4458 } |
4416 break; | 4459 break; |
4417 } | 4460 } |
4418 default: | 4461 default: |
4419 UNIMPLEMENTED(); | 4462 UNIMPLEMENTED(); |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4685 case 0x6: { | 4728 case 0x6: { |
4686 // vmin/vmax.u<size> Qd, Qm, Qn. | 4729 // vmin/vmax.u<size> Qd, Qm, Qn. |
4687 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); | 4730 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
4688 bool min = instr->Bit(4) != 0; | 4731 bool min = instr->Bit(4) != 0; |
4689 switch (size) { | 4732 switch (size) { |
4690 case Neon8: { | 4733 case Neon8: { |
4691 uint8_t src1[16], src2[16]; | 4734 uint8_t src1[16], src2[16]; |
4692 get_q_register(Vn, src1); | 4735 get_q_register(Vn, src1); |
4693 get_q_register(Vm, src2); | 4736 get_q_register(Vm, src2); |
4694 for (int i = 0; i < 16; i++) { | 4737 for (int i = 0; i < 16; i++) { |
4695 if (min) | 4738 src1[i] = MinMax(src1[i], src2[i], min); |
4696 src1[i] = std::min(src1[i], src2[i]); | |
4697 else | |
4698 src1[i] = std::max(src1[i], src2[i]); | |
4699 } | 4739 } |
4700 set_q_register(Vd, src1); | 4740 set_q_register(Vd, src1); |
4701 break; | 4741 break; |
4702 } | 4742 } |
4703 case Neon16: { | 4743 case Neon16: { |
4704 uint16_t src1[8], src2[8]; | 4744 uint16_t src1[8], src2[8]; |
4705 get_q_register(Vn, src1); | 4745 get_q_register(Vn, src1); |
4706 get_q_register(Vm, src2); | 4746 get_q_register(Vm, src2); |
4707 for (int i = 0; i < 8; i++) { | 4747 for (int i = 0; i < 8; i++) { |
4708 if (min) | 4748 src1[i] = MinMax(src1[i], src2[i], min); |
4709 src1[i] = std::min(src1[i], src2[i]); | |
4710 else | |
4711 src1[i] = std::max(src1[i], src2[i]); | |
4712 } | 4749 } |
4713 set_q_register(Vd, src1); | 4750 set_q_register(Vd, src1); |
4714 break; | 4751 break; |
4715 } | 4752 } |
4716 case Neon32: { | 4753 case Neon32: { |
4717 uint32_t src1[4], src2[4]; | 4754 uint32_t src1[4], src2[4]; |
4718 get_q_register(Vn, src1); | 4755 get_q_register(Vn, src1); |
4719 get_q_register(Vm, src2); | 4756 get_q_register(Vm, src2); |
4720 for (int i = 0; i < 4; i++) { | 4757 for (int i = 0; i < 4; i++) { |
4721 if (min) | 4758 src1[i] = MinMax(src1[i], src2[i], min); |
4722 src1[i] = std::min(src1[i], src2[i]); | |
4723 else | |
4724 src1[i] = std::max(src1[i], src2[i]); | |
4725 } | 4759 } |
4726 set_q_register(Vd, src1); | 4760 set_q_register(Vd, src1); |
4727 break; | 4761 break; |
4728 } | 4762 } |
4729 default: | 4763 default: |
4730 UNREACHABLE(); | 4764 UNREACHABLE(); |
4731 break; | 4765 break; |
4732 } | 4766 } |
4733 break; | 4767 break; |
4734 } | 4768 } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4805 set_q_register(Vd, src1); | 4839 set_q_register(Vd, src1); |
4806 break; | 4840 break; |
4807 } | 4841 } |
4808 default: | 4842 default: |
4809 UNREACHABLE(); | 4843 UNREACHABLE(); |
4810 break; | 4844 break; |
4811 } | 4845 } |
4812 } | 4846 } |
4813 break; | 4847 break; |
4814 } | 4848 } |
| 4849 case 0xa: { |
| 4850 // vpmin/vpmax.u<size> Dd, Dm, Dn. |
| 4851 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
| 4852 bool min = instr->Bit(4) != 0; |
| 4853 switch (size) { |
| 4854 case Neon8: { |
| 4855 uint8_t dst[8], src1[8], src2[8]; |
| 4856 get_d_register(Vn, src1); |
| 4857 get_d_register(Vm, src2); |
| 4858 for (int i = 0; i < 4; i++) { |
| 4859 dst[i + 0] = MinMax(src1[i * 2], src1[i * 2 + 1], min); |
| 4860 dst[i + 4] = MinMax(src2[i * 2], src2[i * 2 + 1], min); |
| 4861 } |
| 4862 set_d_register(Vd, dst); |
| 4863 break; |
| 4864 } |
| 4865 case Neon16: { |
| 4866 uint16_t dst[4], src1[4], src2[4]; |
| 4867 get_d_register(Vn, src1); |
| 4868 get_d_register(Vm, src2); |
| 4869 for (int i = 0; i < 2; i++) { |
| 4870 dst[i + 0] = MinMax(src1[i * 2], src1[i * 2 + 1], min); |
| 4871 dst[i + 2] = MinMax(src2[i * 2], src2[i * 2 + 1], min); |
| 4872 } |
| 4873 set_d_register(Vd, dst); |
| 4874 break; |
| 4875 } |
| 4876 case Neon32: { |
| 4877 uint32_t dst[2], src1[2], src2[2]; |
| 4878 get_d_register(Vn, src1); |
| 4879 get_d_register(Vm, src2); |
| 4880 dst[0] = MinMax(src1[0], src1[1], min); |
| 4881 dst[1] = MinMax(src2[0], src2[1], min); |
| 4882 set_d_register(Vd, dst); |
| 4883 break; |
| 4884 } |
| 4885 default: |
| 4886 UNREACHABLE(); |
| 4887 break; |
| 4888 } |
| 4889 break; |
| 4890 } |
4815 case 0xd: { | 4891 case 0xd: { |
4816 if (instr->Bit(21) == 0 && instr->Bit(6) == 1 && instr->Bit(4) == 1) { | 4892 if (instr->Bit(21) == 0 && instr->Bit(6) == 1 && instr->Bit(4) == 1) { |
4817 // vmul.f32 Qd, Qn, Qm | 4893 // vmul.f32 Qd, Qn, Qm |
4818 float src1[4], src2[4]; | 4894 float src1[4], src2[4]; |
4819 get_q_register(Vn, src1); | 4895 get_q_register(Vn, src1); |
4820 get_q_register(Vm, src2); | 4896 get_q_register(Vm, src2); |
4821 for (int i = 0; i < 4; i++) { | 4897 for (int i = 0; i < 4; i++) { |
4822 src1[i] = src1[i] * src2[i]; | 4898 src1[i] = src1[i] * src2[i]; |
4823 } | 4899 } |
4824 set_q_register(Vd, src1); | 4900 set_q_register(Vd, src1); |
(...skipping 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5982 processor->prev_ = nullptr; | 6058 processor->prev_ = nullptr; |
5983 processor->next_ = nullptr; | 6059 processor->next_ = nullptr; |
5984 } | 6060 } |
5985 | 6061 |
5986 } // namespace internal | 6062 } // namespace internal |
5987 } // namespace v8 | 6063 } // namespace v8 |
5988 | 6064 |
5989 #endif // USE_SIMULATOR | 6065 #endif // USE_SIMULATOR |
5990 | 6066 |
5991 #endif // V8_TARGET_ARCH_ARM | 6067 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |