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