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 3970 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3981 HandleVList(instr); | 3981 HandleVList(instr); |
3982 break; | 3982 break; |
3983 default: | 3983 default: |
3984 UNIMPLEMENTED(); // Not used by V8. | 3984 UNIMPLEMENTED(); // Not used by V8. |
3985 } | 3985 } |
3986 } else { | 3986 } else { |
3987 UNIMPLEMENTED(); // Not used by V8. | 3987 UNIMPLEMENTED(); // Not used by V8. |
3988 } | 3988 } |
3989 } | 3989 } |
3990 | 3990 |
| 3991 // Templated operations for NEON instructions. |
| 3992 // TODO(bbudge) Add more templates for use in DecodeSpecialCondition. |
| 3993 template <typename T> |
| 3994 int64_t Widen(T value) { |
| 3995 static_assert(sizeof(int64_t) > sizeof(T), "T must be int32_t or smaller"); |
| 3996 return static_cast<int64_t>(value); |
| 3997 } |
| 3998 |
| 3999 template <typename T> |
| 4000 T Clamp(int64_t value) { |
| 4001 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()); |
| 4003 int64_t max = static_cast<int64_t>(std::numeric_limits<T>::max()); |
| 4004 int64_t clamped = std::max(min, std::min(max, value)); |
| 4005 return static_cast<T>(clamped); |
| 4006 } |
| 4007 |
| 4008 template <typename T> |
| 4009 void AddSaturate(Simulator* simulator, int Vd, int Vm, int Vn) { |
| 4010 static const int kLanes = 16 / sizeof(T); |
| 4011 T src1[kLanes], src2[kLanes]; |
| 4012 simulator->get_q_register(Vn, src1); |
| 4013 simulator->get_q_register(Vm, src2); |
| 4014 for (int i = 0; i < kLanes; i++) { |
| 4015 src1[i] = Clamp<T>(Widen(src1[i]) + Widen(src2[i])); |
| 4016 } |
| 4017 simulator->set_q_register(Vd, src1); |
| 4018 } |
| 4019 |
| 4020 template <typename T> |
| 4021 void SubSaturate(Simulator* simulator, int Vd, int Vm, int Vn) { |
| 4022 static const int kLanes = 16 / sizeof(T); |
| 4023 T src1[kLanes], src2[kLanes]; |
| 4024 simulator->get_q_register(Vn, src1); |
| 4025 simulator->get_q_register(Vm, src2); |
| 4026 for (int i = 0; i < kLanes; i++) { |
| 4027 src1[i] = Clamp<T>(Widen(src1[i]) - Widen(src2[i])); |
| 4028 } |
| 4029 simulator->set_q_register(Vd, src1); |
| 4030 } |
| 4031 |
3991 void Simulator::DecodeSpecialCondition(Instruction* instr) { | 4032 void Simulator::DecodeSpecialCondition(Instruction* instr) { |
3992 switch (instr->SpecialValue()) { | 4033 switch (instr->SpecialValue()) { |
3993 case 4: | 4034 case 4: { |
3994 if (instr->Bits(11, 8) == 1 && instr->Bits(21, 20) == 2 && | 4035 int Vd, Vm, Vn; |
3995 instr->Bit(4) == 1) { | 4036 if (instr->Bit(6) == 0) { |
3996 // vmov Qd, Qm. | 4037 Vd = instr->VFPDRegValue(kDoublePrecision); |
3997 // vorr, Qd, Qm, Qn. | 4038 Vm = instr->VFPMRegValue(kDoublePrecision); |
3998 int Vd = instr->VFPDRegValue(kSimd128Precision); | 4039 Vn = instr->VFPNRegValue(kDoublePrecision); |
3999 int Vm = instr->VFPMRegValue(kSimd128Precision); | 4040 } else { |
4000 int Vn = instr->VFPNRegValue(kSimd128Precision); | 4041 Vd = instr->VFPDRegValue(kSimd128Precision); |
4001 uint32_t src1[4]; | 4042 Vm = instr->VFPMRegValue(kSimd128Precision); |
4002 get_q_register(Vm, src1); | 4043 Vn = instr->VFPNRegValue(kSimd128Precision); |
4003 if (Vm != Vn) { | 4044 } |
4004 uint32_t src2[4]; | 4045 switch (instr->Bits(11, 8)) { |
4005 get_q_register(Vn, src2); | 4046 case 0x0: { |
4006 for (int i = 0; i < 4; i++) { | 4047 if (instr->Bit(4) == 1) { |
4007 src1[i] = src1[i] | src2[i]; | 4048 // vqadd.s<size> Qd, Qm, Qn. |
| 4049 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
| 4050 switch (size) { |
| 4051 case Neon8: |
| 4052 AddSaturate<int8_t>(this, Vd, Vm, Vn); |
| 4053 break; |
| 4054 case Neon16: |
| 4055 AddSaturate<int16_t>(this, Vd, Vm, Vn); |
| 4056 break; |
| 4057 case Neon32: |
| 4058 AddSaturate<int32_t>(this, Vd, Vm, Vn); |
| 4059 break; |
| 4060 default: |
| 4061 UNREACHABLE(); |
| 4062 break; |
| 4063 } |
| 4064 } else { |
| 4065 UNIMPLEMENTED(); |
4008 } | 4066 } |
| 4067 break; |
4009 } | 4068 } |
4010 set_q_register(Vd, src1); | 4069 case 0x1: { |
4011 } else if (instr->Bits(11, 8) == 8) { | 4070 if (instr->Bits(21, 20) == 2 && instr->Bit(6) == 1 && |
4012 // vadd/vtst | 4071 instr->Bit(4) == 1) { |
4013 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); | 4072 // vmov Qd, Qm. |
4014 int Vd = instr->VFPDRegValue(kSimd128Precision); | 4073 // vorr, Qd, Qm, Qn. |
4015 int Vm = instr->VFPMRegValue(kSimd128Precision); | 4074 uint32_t src1[4]; |
4016 int Vn = instr->VFPNRegValue(kSimd128Precision); | 4075 get_q_register(Vm, src1); |
4017 if (instr->Bit(4) == 0) { | 4076 if (Vm != Vn) { |
4018 // vadd.i<size> Qd, Qm, Qn. | 4077 uint32_t src2[4]; |
| 4078 get_q_register(Vn, src2); |
| 4079 for (int i = 0; i < 4; i++) { |
| 4080 src1[i] = src1[i] | src2[i]; |
| 4081 } |
| 4082 } |
| 4083 set_q_register(Vd, src1); |
| 4084 } else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 && |
| 4085 instr->Bit(4) == 1) { |
| 4086 // vand Qd, Qm, Qn. |
| 4087 uint32_t src1[4], src2[4]; |
| 4088 get_q_register(Vn, src1); |
| 4089 get_q_register(Vm, src2); |
| 4090 for (int i = 0; i < 4; i++) { |
| 4091 src1[i] = src1[i] & src2[i]; |
| 4092 } |
| 4093 set_q_register(Vd, src1); |
| 4094 } else { |
| 4095 UNIMPLEMENTED(); |
| 4096 } |
| 4097 break; |
| 4098 } |
| 4099 case 0x2: { |
| 4100 if (instr->Bit(4) == 1) { |
| 4101 // vqsub.s<size> Qd, Qm, Qn. |
| 4102 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
| 4103 switch (size) { |
| 4104 case Neon8: |
| 4105 SubSaturate<int8_t>(this, Vd, Vm, Vn); |
| 4106 break; |
| 4107 case Neon16: |
| 4108 SubSaturate<int16_t>(this, Vd, Vm, Vn); |
| 4109 break; |
| 4110 case Neon32: |
| 4111 SubSaturate<int32_t>(this, Vd, Vm, Vn); |
| 4112 break; |
| 4113 default: |
| 4114 UNREACHABLE(); |
| 4115 break; |
| 4116 } |
| 4117 } else { |
| 4118 UNIMPLEMENTED(); |
| 4119 } |
| 4120 break; |
| 4121 } |
| 4122 case 0x3: { |
| 4123 // vcge/vcgt.s<size> Qd, Qm, Qn. |
| 4124 bool ge = instr->Bit(4) == 1; |
| 4125 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
4019 switch (size) { | 4126 switch (size) { |
4020 case Neon8: { | 4127 case Neon8: { |
4021 uint8_t src1[16], src2[16]; | 4128 int8_t src1[16], src2[16]; |
4022 get_q_register(Vn, src1); | 4129 get_q_register(Vn, src1); |
4023 get_q_register(Vm, src2); | 4130 get_q_register(Vm, src2); |
4024 for (int i = 0; i < 16; i++) { | 4131 for (int i = 0; i < 16; i++) { |
4025 src1[i] += src2[i]; | 4132 if (ge) |
| 4133 src1[i] = src1[i] >= src2[i] ? 0xFF : 0; |
| 4134 else |
| 4135 src1[i] = src1[i] > src2[i] ? 0xFF : 0; |
4026 } | 4136 } |
4027 set_q_register(Vd, src1); | 4137 set_q_register(Vd, src1); |
4028 break; | 4138 break; |
4029 } | 4139 } |
4030 case Neon16: { | 4140 case Neon16: { |
4031 uint16_t src1[8], src2[8]; | 4141 int16_t src1[8], src2[8]; |
4032 get_q_register(Vn, src1); | 4142 get_q_register(Vn, src1); |
4033 get_q_register(Vm, src2); | 4143 get_q_register(Vm, src2); |
4034 for (int i = 0; i < 8; i++) { | 4144 for (int i = 0; i < 8; i++) { |
4035 src1[i] += src2[i]; | 4145 if (ge) |
| 4146 src1[i] = src1[i] >= src2[i] ? 0xFFFF : 0; |
| 4147 else |
| 4148 src1[i] = src1[i] > src2[i] ? 0xFFFF : 0; |
4036 } | 4149 } |
4037 set_q_register(Vd, src1); | 4150 set_q_register(Vd, src1); |
4038 break; | 4151 break; |
4039 } | 4152 } |
4040 case Neon32: { | 4153 case Neon32: { |
4041 uint32_t src1[4], src2[4]; | 4154 int32_t src1[4], src2[4]; |
4042 get_q_register(Vn, src1); | 4155 get_q_register(Vn, src1); |
4043 get_q_register(Vm, src2); | 4156 get_q_register(Vm, src2); |
4044 for (int i = 0; i < 4; i++) { | 4157 for (int i = 0; i < 4; i++) { |
4045 src1[i] += src2[i]; | 4158 if (ge) |
| 4159 src1[i] = src1[i] >= src2[i] ? 0xFFFFFFFF : 0; |
| 4160 else |
| 4161 src1[i] = src1[i] > src2[i] ? 0xFFFFFFFF : 0; |
4046 } | 4162 } |
4047 set_q_register(Vd, src1); | 4163 set_q_register(Vd, src1); |
4048 break; | 4164 break; |
4049 } | 4165 } |
4050 default: | 4166 default: |
4051 UNREACHABLE(); | 4167 UNREACHABLE(); |
4052 break; | 4168 break; |
4053 } | 4169 } |
4054 } else { | 4170 break; |
4055 // vtst.i<size> Qd, Qm, Qn. | 4171 } |
| 4172 case 0x6: { |
| 4173 // vmin/vmax.s<size> Qd, Qm, Qn. |
| 4174 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
| 4175 bool min = instr->Bit(4) != 0; |
4056 switch (size) { | 4176 switch (size) { |
4057 case Neon8: { | 4177 case Neon8: { |
4058 uint8_t src1[16], src2[16]; | 4178 int8_t src1[16], src2[16]; |
4059 get_q_register(Vn, src1); | 4179 get_q_register(Vn, src1); |
4060 get_q_register(Vm, src2); | 4180 get_q_register(Vm, src2); |
4061 for (int i = 0; i < 16; i++) { | 4181 for (int i = 0; i < 16; i++) { |
4062 src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFu : 0; | 4182 if (min) |
| 4183 src1[i] = std::min(src1[i], src2[i]); |
| 4184 else |
| 4185 src1[i] = std::max(src1[i], src2[i]); |
4063 } | 4186 } |
4064 set_q_register(Vd, src1); | 4187 set_q_register(Vd, src1); |
4065 break; | 4188 break; |
4066 } | 4189 } |
4067 case Neon16: { | 4190 case Neon16: { |
4068 uint16_t src1[8], src2[8]; | 4191 int16_t src1[8], src2[8]; |
4069 get_q_register(Vn, src1); | 4192 get_q_register(Vn, src1); |
4070 get_q_register(Vm, src2); | 4193 get_q_register(Vm, src2); |
4071 for (int i = 0; i < 8; i++) { | 4194 for (int i = 0; i < 8; i++) { |
4072 src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFFFu : 0; | 4195 if (min) |
| 4196 src1[i] = std::min(src1[i], src2[i]); |
| 4197 else |
| 4198 src1[i] = std::max(src1[i], src2[i]); |
4073 } | 4199 } |
4074 set_q_register(Vd, src1); | 4200 set_q_register(Vd, src1); |
4075 break; | 4201 break; |
4076 } | 4202 } |
4077 case Neon32: { | 4203 case Neon32: { |
4078 uint32_t src1[4], src2[4]; | 4204 int32_t src1[4], src2[4]; |
4079 get_q_register(Vn, src1); | 4205 get_q_register(Vn, src1); |
4080 get_q_register(Vm, src2); | 4206 get_q_register(Vm, src2); |
4081 for (int i = 0; i < 4; i++) { | 4207 for (int i = 0; i < 4; i++) { |
4082 src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFFFFFFFu : 0; | 4208 if (min) |
| 4209 src1[i] = std::min(src1[i], src2[i]); |
| 4210 else |
| 4211 src1[i] = std::max(src1[i], src2[i]); |
4083 } | 4212 } |
4084 set_q_register(Vd, src1); | 4213 set_q_register(Vd, src1); |
4085 break; | 4214 break; |
4086 } | 4215 } |
4087 default: | 4216 default: |
4088 UNREACHABLE(); | 4217 UNREACHABLE(); |
4089 break; | 4218 break; |
4090 } | 4219 } |
4091 } | 4220 break; |
4092 } else if (instr->Bits(11, 8) == 0xd && instr->Bit(20) == 0 && | 4221 } |
4093 instr->Bit(4) == 0) { | 4222 case 0x8: { |
4094 int Vd = instr->VFPDRegValue(kSimd128Precision); | 4223 // vadd/vtst |
4095 int Vm = instr->VFPMRegValue(kSimd128Precision); | 4224 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
4096 int Vn = instr->VFPNRegValue(kSimd128Precision); | 4225 if (instr->Bit(4) == 0) { |
4097 float src1[4], src2[4]; | 4226 // vadd.i<size> Qd, Qm, Qn. |
4098 get_q_register(Vn, src1); | 4227 switch (size) { |
4099 get_q_register(Vm, src2); | 4228 case Neon8: { |
4100 for (int i = 0; i < 4; i++) { | 4229 uint8_t src1[16], src2[16]; |
4101 if (instr->Bit(21) == 0) { | 4230 get_q_register(Vn, src1); |
4102 // vadd.f32 Qd, Qm, Qn. | 4231 get_q_register(Vm, src2); |
4103 src1[i] = src1[i] + src2[i]; | 4232 for (int i = 0; i < 16; i++) { |
4104 } else { | 4233 src1[i] += src2[i]; |
4105 // vsub.f32 Qd, Qm, Qn. | 4234 } |
4106 src1[i] = src1[i] - src2[i]; | 4235 set_q_register(Vd, src1); |
4107 } | 4236 break; |
4108 } | 4237 } |
4109 set_q_register(Vd, src1); | 4238 case Neon16: { |
4110 } else if (instr->Bits(11, 8) == 0x9 && instr->Bit(6) == 1 && | 4239 uint16_t src1[8], src2[8]; |
4111 instr->Bit(4) == 1) { | 4240 get_q_register(Vn, src1); |
4112 // vmul.i<size> Qd, Qm, Qn. | 4241 get_q_register(Vm, src2); |
4113 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); | 4242 for (int i = 0; i < 8; i++) { |
4114 int Vd = instr->VFPDRegValue(kSimd128Precision); | 4243 src1[i] += src2[i]; |
4115 int Vm = instr->VFPMRegValue(kSimd128Precision); | 4244 } |
4116 int Vn = instr->VFPNRegValue(kSimd128Precision); | 4245 set_q_register(Vd, src1); |
4117 switch (size) { | 4246 break; |
4118 case Neon8: { | 4247 } |
4119 uint8_t src1[16], src2[16]; | 4248 case Neon32: { |
4120 get_q_register(Vn, src1); | 4249 uint32_t src1[4], src2[4]; |
4121 get_q_register(Vm, src2); | 4250 get_q_register(Vn, src1); |
4122 for (int i = 0; i < 16; i++) { | 4251 get_q_register(Vm, src2); |
4123 src1[i] *= src2[i]; | 4252 for (int i = 0; i < 4; i++) { |
4124 } | 4253 src1[i] += src2[i]; |
4125 set_q_register(Vd, src1); | 4254 } |
4126 break; | 4255 set_q_register(Vd, src1); |
4127 } | 4256 break; |
4128 case Neon16: { | 4257 } |
4129 uint16_t src1[8], src2[8]; | 4258 default: |
4130 get_q_register(Vn, src1); | 4259 UNREACHABLE(); |
4131 get_q_register(Vm, src2); | 4260 break; |
4132 for (int i = 0; i < 8; i++) { | 4261 } |
4133 src1[i] *= src2[i]; | 4262 } else { |
4134 } | 4263 // vtst.i<size> Qd, Qm, Qn. |
4135 set_q_register(Vd, src1); | 4264 switch (size) { |
4136 break; | 4265 case Neon8: { |
4137 } | 4266 uint8_t src1[16], src2[16]; |
4138 case Neon32: { | 4267 get_q_register(Vn, src1); |
4139 uint32_t src1[4], src2[4]; | 4268 get_q_register(Vm, src2); |
| 4269 for (int i = 0; i < 16; i++) { |
| 4270 src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFu : 0; |
| 4271 } |
| 4272 set_q_register(Vd, src1); |
| 4273 break; |
| 4274 } |
| 4275 case Neon16: { |
| 4276 uint16_t src1[8], src2[8]; |
| 4277 get_q_register(Vn, src1); |
| 4278 get_q_register(Vm, src2); |
| 4279 for (int i = 0; i < 8; i++) { |
| 4280 src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFFFu : 0; |
| 4281 } |
| 4282 set_q_register(Vd, src1); |
| 4283 break; |
| 4284 } |
| 4285 case Neon32: { |
| 4286 uint32_t src1[4], src2[4]; |
| 4287 get_q_register(Vn, src1); |
| 4288 get_q_register(Vm, src2); |
| 4289 for (int i = 0; i < 4; i++) { |
| 4290 src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFFFFFFFu : 0; |
| 4291 } |
| 4292 set_q_register(Vd, src1); |
| 4293 break; |
| 4294 } |
| 4295 default: |
| 4296 UNREACHABLE(); |
| 4297 break; |
| 4298 } |
| 4299 } |
| 4300 break; |
| 4301 } |
| 4302 case 0x9: { |
| 4303 if (instr->Bit(6) == 1 && instr->Bit(4) == 1) { |
| 4304 // vmul.i<size> Qd, Qm, Qn. |
| 4305 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
| 4306 switch (size) { |
| 4307 case Neon8: { |
| 4308 uint8_t src1[16], src2[16]; |
| 4309 get_q_register(Vn, src1); |
| 4310 get_q_register(Vm, src2); |
| 4311 for (int i = 0; i < 16; i++) { |
| 4312 src1[i] *= src2[i]; |
| 4313 } |
| 4314 set_q_register(Vd, src1); |
| 4315 break; |
| 4316 } |
| 4317 case Neon16: { |
| 4318 uint16_t src1[8], src2[8]; |
| 4319 get_q_register(Vn, src1); |
| 4320 get_q_register(Vm, src2); |
| 4321 for (int i = 0; i < 8; i++) { |
| 4322 src1[i] *= src2[i]; |
| 4323 } |
| 4324 set_q_register(Vd, src1); |
| 4325 break; |
| 4326 } |
| 4327 case Neon32: { |
| 4328 uint32_t src1[4], src2[4]; |
| 4329 get_q_register(Vn, src1); |
| 4330 get_q_register(Vm, src2); |
| 4331 for (int i = 0; i < 4; i++) { |
| 4332 src1[i] *= src2[i]; |
| 4333 } |
| 4334 set_q_register(Vd, src1); |
| 4335 break; |
| 4336 } |
| 4337 default: |
| 4338 UNREACHABLE(); |
| 4339 break; |
| 4340 } |
| 4341 } else { |
| 4342 UNIMPLEMENTED(); |
| 4343 } |
| 4344 break; |
| 4345 } |
| 4346 case 0xd: { |
| 4347 if (instr->Bit(4) == 0) { |
| 4348 float src1[4], src2[4]; |
4140 get_q_register(Vn, src1); | 4349 get_q_register(Vn, src1); |
4141 get_q_register(Vm, src2); | 4350 get_q_register(Vm, src2); |
4142 for (int i = 0; i < 4; i++) { | 4351 for (int i = 0; i < 4; i++) { |
4143 src1[i] *= src2[i]; | 4352 if (instr->Bit(21) == 0) { |
| 4353 // vadd.f32 Qd, Qm, Qn. |
| 4354 src1[i] = src1[i] + src2[i]; |
| 4355 } else { |
| 4356 // vsub.f32 Qd, Qm, Qn. |
| 4357 src1[i] = src1[i] - src2[i]; |
| 4358 } |
4144 } | 4359 } |
4145 set_q_register(Vd, src1); | 4360 set_q_register(Vd, src1); |
4146 break; | 4361 } else { |
4147 } | 4362 UNIMPLEMENTED(); |
4148 default: | 4363 } |
4149 UNIMPLEMENTED(); | 4364 break; |
4150 break; | 4365 } |
4151 } | 4366 case 0xe: { |
4152 } else if (instr->Bits(11, 8) == 0xe && instr->Bits(21, 20) == 0 && | 4367 if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 0) { |
4153 instr->Bit(4) == 0) { | 4368 // vceq.f32. |
4154 // vceq.f32. | 4369 float src1[4], src2[4]; |
4155 int Vd = instr->VFPDRegValue(kSimd128Precision); | |
4156 int Vm = instr->VFPMRegValue(kSimd128Precision); | |
4157 int Vn = instr->VFPNRegValue(kSimd128Precision); | |
4158 float src1[4], src2[4]; | |
4159 get_q_register(Vn, src1); | |
4160 get_q_register(Vm, src2); | |
4161 uint32_t dst[4]; | |
4162 for (int i = 0; i < 4; i++) { | |
4163 dst[i] = (src1[i] == src2[i]) ? 0xFFFFFFFF : 0; | |
4164 } | |
4165 set_q_register(Vd, dst); | |
4166 } else if (instr->Bits(11, 8) == 1 && instr->Bits(21, 20) == 0 && | |
4167 instr->Bit(6) == 1 && instr->Bit(4) == 1) { | |
4168 int Vd = instr->VFPDRegValue(kSimd128Precision); | |
4169 int Vm = instr->VFPMRegValue(kSimd128Precision); | |
4170 int Vn = instr->VFPNRegValue(kSimd128Precision); | |
4171 // vand Qd, Qm, Qn. | |
4172 uint32_t src1[4], src2[4]; | |
4173 get_q_register(Vn, src1); | |
4174 get_q_register(Vm, src2); | |
4175 for (int i = 0; i < 4; i++) { | |
4176 src1[i] = src1[i] & src2[i]; | |
4177 } | |
4178 set_q_register(Vd, src1); | |
4179 } else if (instr->Bits(11, 8) == 0x3) { | |
4180 // vcge/vcgt.s<size> Qd, Qm, Qn. | |
4181 bool ge = instr->Bit(4) == 1; | |
4182 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); | |
4183 int Vd = instr->VFPDRegValue(kSimd128Precision); | |
4184 int Vm = instr->VFPMRegValue(kSimd128Precision); | |
4185 int Vn = instr->VFPNRegValue(kSimd128Precision); | |
4186 switch (size) { | |
4187 case Neon8: { | |
4188 int8_t src1[16], src2[16]; | |
4189 get_q_register(Vn, src1); | 4370 get_q_register(Vn, src1); |
4190 get_q_register(Vm, src2); | 4371 get_q_register(Vm, src2); |
4191 for (int i = 0; i < 16; i++) { | 4372 uint32_t dst[4]; |
4192 if (ge) | 4373 for (int i = 0; i < 4; i++) { |
4193 src1[i] = src1[i] >= src2[i] ? 0xFF : 0; | 4374 dst[i] = (src1[i] == src2[i]) ? 0xFFFFFFFF : 0; |
4194 else | 4375 } |
4195 src1[i] = src1[i] > src2[i] ? 0xFF : 0; | 4376 set_q_register(Vd, dst); |
4196 } | 4377 } else { |
4197 set_q_register(Vd, src1); | 4378 UNIMPLEMENTED(); |
4198 break; | 4379 } |
4199 } | 4380 break; |
4200 case Neon16: { | 4381 } |
4201 int16_t src1[8], src2[8]; | 4382 case 0xf: { |
| 4383 if (instr->Bit(20) == 0 && instr->Bit(6) == 1) { |
| 4384 float src1[4], src2[4]; |
4202 get_q_register(Vn, src1); | 4385 get_q_register(Vn, src1); |
4203 get_q_register(Vm, src2); | 4386 get_q_register(Vm, src2); |
4204 for (int i = 0; i < 8; i++) { | 4387 if (instr->Bit(4) == 1) { |
4205 if (ge) | 4388 if (instr->Bit(21) == 0) { |
4206 src1[i] = src1[i] >= src2[i] ? 0xFFFF : 0; | 4389 // vrecps.f32 Qd, Qm, Qn. |
4207 else | 4390 for (int i = 0; i < 4; i++) { |
4208 src1[i] = src1[i] > src2[i] ? 0xFFFF : 0; | 4391 src1[i] = 2.0f - src1[i] * src2[i]; |
| 4392 } |
| 4393 } else { |
| 4394 // vrsqrts.f32 Qd, Qm, Qn. |
| 4395 for (int i = 0; i < 4; i++) { |
| 4396 src1[i] = (3.0f - src1[i] * src2[i]) * 0.5f; |
| 4397 } |
| 4398 } |
| 4399 } else { |
| 4400 if (instr->Bit(21) == 1) { |
| 4401 // vmin.f32 Qd, Qm, Qn. |
| 4402 for (int i = 0; i < 4; i++) { |
| 4403 src1[i] = std::min(src1[i], src2[i]); |
| 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 } |
4209 } | 4411 } |
4210 set_q_register(Vd, src1); | 4412 set_q_register(Vd, src1); |
4211 break; | 4413 } else { |
4212 } | 4414 UNIMPLEMENTED(); |
4213 case Neon32: { | 4415 } |
4214 int32_t src1[4], src2[4]; | 4416 break; |
4215 get_q_register(Vn, src1); | 4417 } |
4216 get_q_register(Vm, src2); | 4418 default: |
4217 for (int i = 0; i < 4; i++) { | 4419 UNIMPLEMENTED(); |
4218 if (ge) | 4420 break; |
4219 src1[i] = src1[i] >= src2[i] ? 0xFFFFFFFF : 0; | |
4220 else | |
4221 src1[i] = src1[i] > src2[i] ? 0xFFFFFFFF : 0; | |
4222 } | |
4223 set_q_register(Vd, src1); | |
4224 break; | |
4225 } | |
4226 default: | |
4227 UNREACHABLE(); | |
4228 break; | |
4229 } | |
4230 } else if (instr->Bits(11, 8) == 0xf && instr->Bit(20) == 0 && | |
4231 instr->Bit(6) == 1) { | |
4232 int Vd = instr->VFPDRegValue(kSimd128Precision); | |
4233 int Vm = instr->VFPMRegValue(kSimd128Precision); | |
4234 int Vn = instr->VFPNRegValue(kSimd128Precision); | |
4235 float src1[4], src2[4]; | |
4236 get_q_register(Vn, src1); | |
4237 get_q_register(Vm, src2); | |
4238 if (instr->Bit(4) == 1) { | |
4239 if (instr->Bit(21) == 0) { | |
4240 // vrecps.f32 Qd, Qm, Qn. | |
4241 for (int i = 0; i < 4; i++) { | |
4242 src1[i] = 2.0f - src1[i] * src2[i]; | |
4243 } | |
4244 } else { | |
4245 // vrsqrts.f32 Qd, Qm, Qn. | |
4246 for (int i = 0; i < 4; i++) { | |
4247 src1[i] = (3.0f - src1[i] * src2[i]) * 0.5f; | |
4248 } | |
4249 } | |
4250 } else { | |
4251 if (instr->Bit(21) == 1) { | |
4252 // vmin.f32 Qd, Qm, Qn. | |
4253 for (int i = 0; i < 4; i++) { | |
4254 src1[i] = std::min(src1[i], src2[i]); | |
4255 } | |
4256 } else { | |
4257 // vmax.f32 Qd, Qm, Qn. | |
4258 for (int i = 0; i < 4; i++) { | |
4259 src1[i] = std::max(src1[i], src2[i]); | |
4260 } | |
4261 } | |
4262 } | |
4263 set_q_register(Vd, src1); | |
4264 } else if (instr->Bits(11, 8) == 0x6) { | |
4265 // vmin/vmax.s<size> Qd, Qm, Qn. | |
4266 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); | |
4267 int Vd = instr->VFPDRegValue(kSimd128Precision); | |
4268 int Vm = instr->VFPMRegValue(kSimd128Precision); | |
4269 int Vn = instr->VFPNRegValue(kSimd128Precision); | |
4270 bool min = instr->Bit(4) != 0; | |
4271 switch (size) { | |
4272 case Neon8: { | |
4273 int8_t src1[16], src2[16]; | |
4274 get_q_register(Vn, src1); | |
4275 get_q_register(Vm, src2); | |
4276 for (int i = 0; i < 16; i++) { | |
4277 if (min) | |
4278 src1[i] = std::min(src1[i], src2[i]); | |
4279 else | |
4280 src1[i] = std::max(src1[i], src2[i]); | |
4281 } | |
4282 set_q_register(Vd, src1); | |
4283 break; | |
4284 } | |
4285 case Neon16: { | |
4286 int16_t src1[8], src2[8]; | |
4287 get_q_register(Vn, src1); | |
4288 get_q_register(Vm, src2); | |
4289 for (int i = 0; i < 8; i++) { | |
4290 if (min) | |
4291 src1[i] = std::min(src1[i], src2[i]); | |
4292 else | |
4293 src1[i] = std::max(src1[i], src2[i]); | |
4294 } | |
4295 set_q_register(Vd, src1); | |
4296 break; | |
4297 } | |
4298 case Neon32: { | |
4299 int32_t src1[4], src2[4]; | |
4300 get_q_register(Vn, src1); | |
4301 get_q_register(Vm, src2); | |
4302 for (int i = 0; i < 4; i++) { | |
4303 if (min) | |
4304 src1[i] = std::min(src1[i], src2[i]); | |
4305 else | |
4306 src1[i] = std::max(src1[i], src2[i]); | |
4307 } | |
4308 set_q_register(Vd, src1); | |
4309 break; | |
4310 } | |
4311 default: | |
4312 UNREACHABLE(); | |
4313 break; | |
4314 } | |
4315 } else { | |
4316 UNIMPLEMENTED(); | |
4317 } | 4421 } |
4318 break; | 4422 break; |
| 4423 } |
4319 case 5: | 4424 case 5: |
4320 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && | 4425 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && |
4321 (instr->Bit(4) == 1)) { | 4426 (instr->Bit(4) == 1)) { |
4322 // vmovl signed | 4427 // vmovl signed |
4323 if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED(); | 4428 if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED(); |
4324 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); | 4429 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); |
4325 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); | 4430 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); |
4326 int imm3 = instr->Bits(21, 19); | 4431 int imm3 = instr->Bits(21, 19); |
4327 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED(); | 4432 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED(); |
4328 int esize = 8 * imm3; | 4433 int esize = 8 * imm3; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4429 break; | 4534 break; |
4430 } | 4535 } |
4431 default: | 4536 default: |
4432 UNREACHABLE(); | 4537 UNREACHABLE(); |
4433 break; | 4538 break; |
4434 } | 4539 } |
4435 } else { | 4540 } else { |
4436 UNIMPLEMENTED(); | 4541 UNIMPLEMENTED(); |
4437 } | 4542 } |
4438 break; | 4543 break; |
4439 case 6: | 4544 case 6: { |
4440 if (instr->Bits(11, 8) == 8 && instr->Bit(4) == 0) { | 4545 int Vd, Vm, Vn; |
4441 // vsub.size Qd, Qm, Qn. | 4546 if (instr->Bit(6) == 0) { |
4442 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); | 4547 Vd = instr->VFPDRegValue(kDoublePrecision); |
4443 int Vd = instr->VFPDRegValue(kSimd128Precision); | 4548 Vm = instr->VFPMRegValue(kDoublePrecision); |
4444 int Vm = instr->VFPMRegValue(kSimd128Precision); | 4549 Vn = instr->VFPNRegValue(kDoublePrecision); |
4445 int Vn = instr->VFPNRegValue(kSimd128Precision); | 4550 } else { |
4446 switch (size) { | 4551 Vd = instr->VFPDRegValue(kSimd128Precision); |
4447 case Neon8: { | 4552 Vm = instr->VFPMRegValue(kSimd128Precision); |
4448 uint8_t src1[16], src2[16]; | 4553 Vn = instr->VFPNRegValue(kSimd128Precision); |
4449 get_q_register(Vn, src1); | 4554 } |
4450 get_q_register(Vm, src2); | 4555 switch (instr->Bits(11, 8)) { |
4451 for (int i = 0; i < 16; i++) { | 4556 case 0x0: { |
4452 src1[i] -= src2[i]; | 4557 if (instr->Bit(4) == 1) { |
4453 } | 4558 // vqadd.u<size> Qd, Qm, Qn. |
4454 set_q_register(Vd, src1); | 4559 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
4455 break; | 4560 switch (size) { |
4456 } | 4561 case Neon8: |
4457 case Neon16: { | 4562 AddSaturate<uint8_t>(this, Vd, Vm, Vn); |
4458 uint16_t src1[8], src2[8]; | 4563 break; |
4459 get_q_register(Vn, src1); | 4564 case Neon16: |
4460 get_q_register(Vm, src2); | 4565 AddSaturate<uint16_t>(this, Vd, Vm, Vn); |
4461 for (int i = 0; i < 8; i++) { | 4566 break; |
4462 src1[i] -= src2[i]; | 4567 case Neon32: |
4463 } | 4568 AddSaturate<uint32_t>(this, Vd, Vm, Vn); |
4464 set_q_register(Vd, src1); | 4569 break; |
4465 break; | 4570 default: |
4466 } | 4571 UNREACHABLE(); |
4467 case Neon32: { | 4572 break; |
4468 uint32_t src1[4], src2[4]; | 4573 } |
| 4574 } else { |
| 4575 UNIMPLEMENTED(); |
| 4576 } |
| 4577 break; |
| 4578 } |
| 4579 case 0x1: { |
| 4580 if (instr->Bits(21, 20) == 1 && instr->Bit(4) == 1) { |
| 4581 // vbsl.size Qd, Qm, Qn. |
| 4582 uint32_t dst[4], src1[4], src2[4]; |
| 4583 get_q_register(Vd, dst); |
4469 get_q_register(Vn, src1); | 4584 get_q_register(Vn, src1); |
4470 get_q_register(Vm, src2); | 4585 get_q_register(Vm, src2); |
4471 for (int i = 0; i < 4; i++) { | 4586 for (int i = 0; i < 4; i++) { |
4472 src1[i] -= src2[i]; | 4587 dst[i] = (dst[i] & src1[i]) | (~dst[i] & src2[i]); |
4473 } | 4588 } |
4474 set_q_register(Vd, src1); | 4589 set_q_register(Vd, dst); |
4475 break; | 4590 } else if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 1) { |
4476 } | 4591 if (instr->Bit(6) == 0) { |
4477 default: | 4592 // veor Dd, Dn, Dm |
4478 UNREACHABLE(); | 4593 uint64_t src1, src2; |
4479 break; | 4594 get_d_register(Vn, &src1); |
4480 } | 4595 get_d_register(Vm, &src2); |
4481 } else if (instr->Bits(11, 8) == 8 && instr->Bit(4) == 1) { | 4596 src1 ^= src2; |
4482 // vceq.size Qd, Qm, Qn. | 4597 set_d_register(Vd, &src1); |
4483 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); | 4598 |
4484 int Vd = instr->VFPDRegValue(kSimd128Precision); | 4599 } else { |
4485 int Vm = instr->VFPMRegValue(kSimd128Precision); | 4600 // veor Qd, Qn, Qm |
4486 int Vn = instr->VFPNRegValue(kSimd128Precision); | 4601 uint32_t src1[4], src2[4]; |
4487 switch (size) { | 4602 get_q_register(Vn, src1); |
4488 case Neon8: { | 4603 get_q_register(Vm, src2); |
4489 uint8_t src1[16], src2[16]; | 4604 for (int i = 0; i < 4; i++) src1[i] ^= src2[i]; |
4490 get_q_register(Vn, src1); | 4605 set_q_register(Vd, src1); |
4491 get_q_register(Vm, src2); | 4606 } |
4492 for (int i = 0; i < 16; i++) { | 4607 } else { |
4493 src1[i] = (src1[i] == src2[i]) ? 0xFFu : 0; | 4608 UNIMPLEMENTED(); |
4494 } | 4609 } |
4495 set_q_register(Vd, src1); | 4610 break; |
4496 break; | 4611 } |
4497 } | 4612 case 0x2: { |
4498 case Neon16: { | 4613 if (instr->Bit(4) == 1) { |
4499 uint16_t src1[8], src2[8]; | 4614 // vqsub.u<size> Qd, Qm, Qn. |
4500 get_q_register(Vn, src1); | 4615 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
4501 get_q_register(Vm, src2); | 4616 switch (size) { |
4502 for (int i = 0; i < 8; i++) { | 4617 case Neon8: |
4503 src1[i] = (src1[i] == src2[i]) ? 0xFFFFu : 0; | 4618 SubSaturate<uint8_t>(this, Vd, Vm, Vn); |
4504 } | 4619 break; |
4505 set_q_register(Vd, src1); | 4620 case Neon16: |
4506 break; | 4621 SubSaturate<uint16_t>(this, Vd, Vm, Vn); |
4507 } | 4622 break; |
4508 case Neon32: { | 4623 case Neon32: |
4509 uint32_t src1[4], src2[4]; | 4624 SubSaturate<uint32_t>(this, Vd, Vm, Vn); |
| 4625 break; |
| 4626 default: |
| 4627 UNREACHABLE(); |
| 4628 break; |
| 4629 } |
| 4630 } else { |
| 4631 UNIMPLEMENTED(); |
| 4632 } |
| 4633 break; |
| 4634 } |
| 4635 case 0x3: { |
| 4636 // vcge/vcgt.u<size> Qd, Qm, Qn. |
| 4637 bool ge = instr->Bit(4) == 1; |
| 4638 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
| 4639 switch (size) { |
| 4640 case Neon8: { |
| 4641 uint8_t src1[16], src2[16]; |
| 4642 get_q_register(Vn, src1); |
| 4643 get_q_register(Vm, src2); |
| 4644 for (int i = 0; i < 16; i++) { |
| 4645 if (ge) |
| 4646 src1[i] = src1[i] >= src2[i] ? 0xFFu : 0; |
| 4647 else |
| 4648 src1[i] = src1[i] > src2[i] ? 0xFFu : 0; |
| 4649 } |
| 4650 set_q_register(Vd, src1); |
| 4651 break; |
| 4652 } |
| 4653 case Neon16: { |
| 4654 uint16_t src1[8], src2[8]; |
| 4655 get_q_register(Vn, src1); |
| 4656 get_q_register(Vm, src2); |
| 4657 for (int i = 0; i < 8; i++) { |
| 4658 if (ge) |
| 4659 src1[i] = src1[i] >= src2[i] ? 0xFFFFu : 0; |
| 4660 else |
| 4661 src1[i] = src1[i] > src2[i] ? 0xFFFFu : 0; |
| 4662 } |
| 4663 set_q_register(Vd, src1); |
| 4664 break; |
| 4665 } |
| 4666 case Neon32: { |
| 4667 uint32_t src1[4], src2[4]; |
| 4668 get_q_register(Vn, src1); |
| 4669 get_q_register(Vm, src2); |
| 4670 for (int i = 0; i < 4; i++) { |
| 4671 if (ge) |
| 4672 src1[i] = src1[i] >= src2[i] ? 0xFFFFFFFFu : 0; |
| 4673 else |
| 4674 src1[i] = src1[i] > src2[i] ? 0xFFFFFFFFu : 0; |
| 4675 } |
| 4676 set_q_register(Vd, src1); |
| 4677 break; |
| 4678 } |
| 4679 default: |
| 4680 UNREACHABLE(); |
| 4681 break; |
| 4682 } |
| 4683 break; |
| 4684 } |
| 4685 case 0x6: { |
| 4686 // vmin/vmax.u<size> Qd, Qm, Qn. |
| 4687 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
| 4688 bool min = instr->Bit(4) != 0; |
| 4689 switch (size) { |
| 4690 case Neon8: { |
| 4691 uint8_t src1[16], src2[16]; |
| 4692 get_q_register(Vn, src1); |
| 4693 get_q_register(Vm, src2); |
| 4694 for (int i = 0; i < 16; i++) { |
| 4695 if (min) |
| 4696 src1[i] = std::min(src1[i], src2[i]); |
| 4697 else |
| 4698 src1[i] = std::max(src1[i], src2[i]); |
| 4699 } |
| 4700 set_q_register(Vd, src1); |
| 4701 break; |
| 4702 } |
| 4703 case Neon16: { |
| 4704 uint16_t src1[8], src2[8]; |
| 4705 get_q_register(Vn, src1); |
| 4706 get_q_register(Vm, src2); |
| 4707 for (int i = 0; i < 8; i++) { |
| 4708 if (min) |
| 4709 src1[i] = std::min(src1[i], src2[i]); |
| 4710 else |
| 4711 src1[i] = std::max(src1[i], src2[i]); |
| 4712 } |
| 4713 set_q_register(Vd, src1); |
| 4714 break; |
| 4715 } |
| 4716 case Neon32: { |
| 4717 uint32_t src1[4], src2[4]; |
| 4718 get_q_register(Vn, src1); |
| 4719 get_q_register(Vm, src2); |
| 4720 for (int i = 0; i < 4; i++) { |
| 4721 if (min) |
| 4722 src1[i] = std::min(src1[i], src2[i]); |
| 4723 else |
| 4724 src1[i] = std::max(src1[i], src2[i]); |
| 4725 } |
| 4726 set_q_register(Vd, src1); |
| 4727 break; |
| 4728 } |
| 4729 default: |
| 4730 UNREACHABLE(); |
| 4731 break; |
| 4732 } |
| 4733 break; |
| 4734 } |
| 4735 case 0x8: { |
| 4736 if (instr->Bit(4) == 0) { |
| 4737 // vsub.size Qd, Qm, Qn. |
| 4738 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
| 4739 switch (size) { |
| 4740 case Neon8: { |
| 4741 uint8_t src1[16], src2[16]; |
| 4742 get_q_register(Vn, src1); |
| 4743 get_q_register(Vm, src2); |
| 4744 for (int i = 0; i < 16; i++) { |
| 4745 src1[i] -= src2[i]; |
| 4746 } |
| 4747 set_q_register(Vd, src1); |
| 4748 break; |
| 4749 } |
| 4750 case Neon16: { |
| 4751 uint16_t src1[8], src2[8]; |
| 4752 get_q_register(Vn, src1); |
| 4753 get_q_register(Vm, src2); |
| 4754 for (int i = 0; i < 8; i++) { |
| 4755 src1[i] -= src2[i]; |
| 4756 } |
| 4757 set_q_register(Vd, src1); |
| 4758 break; |
| 4759 } |
| 4760 case Neon32: { |
| 4761 uint32_t src1[4], src2[4]; |
| 4762 get_q_register(Vn, src1); |
| 4763 get_q_register(Vm, src2); |
| 4764 for (int i = 0; i < 4; i++) { |
| 4765 src1[i] -= src2[i]; |
| 4766 } |
| 4767 set_q_register(Vd, src1); |
| 4768 break; |
| 4769 } |
| 4770 default: |
| 4771 UNREACHABLE(); |
| 4772 break; |
| 4773 } |
| 4774 } else { |
| 4775 // vceq.size Qd, Qm, Qn. |
| 4776 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
| 4777 switch (size) { |
| 4778 case Neon8: { |
| 4779 uint8_t src1[16], src2[16]; |
| 4780 get_q_register(Vn, src1); |
| 4781 get_q_register(Vm, src2); |
| 4782 for (int i = 0; i < 16; i++) { |
| 4783 src1[i] = (src1[i] == src2[i]) ? 0xFFu : 0; |
| 4784 } |
| 4785 set_q_register(Vd, src1); |
| 4786 break; |
| 4787 } |
| 4788 case Neon16: { |
| 4789 uint16_t src1[8], src2[8]; |
| 4790 get_q_register(Vn, src1); |
| 4791 get_q_register(Vm, src2); |
| 4792 for (int i = 0; i < 8; i++) { |
| 4793 src1[i] = (src1[i] == src2[i]) ? 0xFFFFu : 0; |
| 4794 } |
| 4795 set_q_register(Vd, src1); |
| 4796 break; |
| 4797 } |
| 4798 case Neon32: { |
| 4799 uint32_t src1[4], src2[4]; |
| 4800 get_q_register(Vn, src1); |
| 4801 get_q_register(Vm, src2); |
| 4802 for (int i = 0; i < 4; i++) { |
| 4803 src1[i] = (src1[i] == src2[i]) ? 0xFFFFFFFFu : 0; |
| 4804 } |
| 4805 set_q_register(Vd, src1); |
| 4806 break; |
| 4807 } |
| 4808 default: |
| 4809 UNREACHABLE(); |
| 4810 break; |
| 4811 } |
| 4812 } |
| 4813 break; |
| 4814 } |
| 4815 case 0xd: { |
| 4816 if (instr->Bit(21) == 0 && instr->Bit(6) == 1 && instr->Bit(4) == 1) { |
| 4817 // vmul.f32 Qd, Qn, Qm |
| 4818 float src1[4], src2[4]; |
4510 get_q_register(Vn, src1); | 4819 get_q_register(Vn, src1); |
4511 get_q_register(Vm, src2); | 4820 get_q_register(Vm, src2); |
4512 for (int i = 0; i < 4; i++) { | 4821 for (int i = 0; i < 4; i++) { |
4513 src1[i] = (src1[i] == src2[i]) ? 0xFFFFFFFFu : 0; | 4822 src1[i] = src1[i] * src2[i]; |
4514 } | 4823 } |
4515 set_q_register(Vd, src1); | 4824 set_q_register(Vd, src1); |
4516 break; | 4825 } else { |
4517 } | 4826 UNIMPLEMENTED(); |
4518 default: | 4827 } |
4519 UNREACHABLE(); | 4828 break; |
4520 break; | 4829 } |
4521 } | 4830 case 0xe: { |
4522 } else if (instr->Bits(11, 8) == 1 && instr->Bits(21, 20) == 1 && | 4831 if (instr->Bit(20) == 0 && instr->Bit(4) == 0) { |
4523 instr->Bit(4) == 1) { | 4832 // vcge/vcgt.f32 Qd, Qm, Qn |
4524 // vbsl.size Qd, Qm, Qn. | 4833 bool ge = instr->Bit(21) == 0; |
4525 int Vd = instr->VFPDRegValue(kSimd128Precision); | 4834 float src1[4], src2[4]; |
4526 int Vm = instr->VFPMRegValue(kSimd128Precision); | |
4527 int Vn = instr->VFPNRegValue(kSimd128Precision); | |
4528 uint32_t dst[4], src1[4], src2[4]; | |
4529 get_q_register(Vd, dst); | |
4530 get_q_register(Vn, src1); | |
4531 get_q_register(Vm, src2); | |
4532 for (int i = 0; i < 4; i++) { | |
4533 dst[i] = (dst[i] & src1[i]) | (~dst[i] & src2[i]); | |
4534 } | |
4535 set_q_register(Vd, dst); | |
4536 } else if (instr->Bits(11, 8) == 1 && instr->Bits(21, 20) == 0 && | |
4537 instr->Bit(4) == 1) { | |
4538 if (instr->Bit(6) == 0) { | |
4539 // veor Dd, Dn, Dm | |
4540 int Vd = instr->VFPDRegValue(kDoublePrecision); | |
4541 int Vn = instr->VFPNRegValue(kDoublePrecision); | |
4542 int Vm = instr->VFPMRegValue(kDoublePrecision); | |
4543 uint64_t src1, src2; | |
4544 get_d_register(Vn, &src1); | |
4545 get_d_register(Vm, &src2); | |
4546 src1 ^= src2; | |
4547 set_d_register(Vd, &src1); | |
4548 | |
4549 } else { | |
4550 // veor Qd, Qn, Qm | |
4551 int Vd = instr->VFPDRegValue(kSimd128Precision); | |
4552 int Vn = instr->VFPNRegValue(kSimd128Precision); | |
4553 int Vm = instr->VFPMRegValue(kSimd128Precision); | |
4554 uint32_t src1[4], src2[4]; | |
4555 get_q_register(Vn, src1); | |
4556 get_q_register(Vm, src2); | |
4557 for (int i = 0; i < 4; i++) src1[i] ^= src2[i]; | |
4558 set_q_register(Vd, src1); | |
4559 } | |
4560 } else if (instr->Bits(11, 8) == 0xd && instr->Bit(21) == 0 && | |
4561 instr->Bit(6) == 1 && instr->Bit(4) == 1) { | |
4562 // vmul.f32 Qd, Qn, Qm | |
4563 int Vd = instr->VFPDRegValue(kSimd128Precision); | |
4564 int Vn = instr->VFPNRegValue(kSimd128Precision); | |
4565 int Vm = instr->VFPMRegValue(kSimd128Precision); | |
4566 float src1[4], src2[4]; | |
4567 get_q_register(Vn, src1); | |
4568 get_q_register(Vm, src2); | |
4569 for (int i = 0; i < 4; i++) { | |
4570 src1[i] = src1[i] * src2[i]; | |
4571 } | |
4572 set_q_register(Vd, src1); | |
4573 } else if (instr->Bits(11, 8) == 0xe && instr->Bit(20) == 0 && | |
4574 instr->Bit(4) == 0) { | |
4575 // vcge/vcgt.f32 Qd, Qm, Qn | |
4576 bool ge = instr->Bit(21) == 0; | |
4577 int Vd = instr->VFPDRegValue(kSimd128Precision); | |
4578 int Vm = instr->VFPMRegValue(kSimd128Precision); | |
4579 int Vn = instr->VFPNRegValue(kSimd128Precision); | |
4580 float src1[4], src2[4]; | |
4581 get_q_register(Vn, src1); | |
4582 get_q_register(Vm, src2); | |
4583 uint32_t dst[4]; | |
4584 for (int i = 0; i < 4; i++) { | |
4585 if (ge) { | |
4586 dst[i] = src1[i] >= src2[i] ? 0xFFFFFFFFu : 0; | |
4587 } else { | |
4588 dst[i] = src1[i] > src2[i] ? 0xFFFFFFFFu : 0; | |
4589 } | |
4590 } | |
4591 set_q_register(Vd, dst); | |
4592 } else if (instr->Bits(11, 8) == 0x3) { | |
4593 // vcge/vcgt.u<size> Qd, Qm, Qn. | |
4594 bool ge = instr->Bit(4) == 1; | |
4595 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); | |
4596 int Vd = instr->VFPDRegValue(kSimd128Precision); | |
4597 int Vm = instr->VFPMRegValue(kSimd128Precision); | |
4598 int Vn = instr->VFPNRegValue(kSimd128Precision); | |
4599 switch (size) { | |
4600 case Neon8: { | |
4601 uint8_t src1[16], src2[16]; | |
4602 get_q_register(Vn, src1); | 4835 get_q_register(Vn, src1); |
4603 get_q_register(Vm, src2); | 4836 get_q_register(Vm, src2); |
4604 for (int i = 0; i < 16; i++) { | 4837 uint32_t dst[4]; |
4605 if (ge) | |
4606 src1[i] = src1[i] >= src2[i] ? 0xFFu : 0; | |
4607 else | |
4608 src1[i] = src1[i] > src2[i] ? 0xFFu : 0; | |
4609 } | |
4610 set_q_register(Vd, src1); | |
4611 break; | |
4612 } | |
4613 case Neon16: { | |
4614 uint16_t src1[8], src2[8]; | |
4615 get_q_register(Vn, src1); | |
4616 get_q_register(Vm, src2); | |
4617 for (int i = 0; i < 8; i++) { | |
4618 if (ge) | |
4619 src1[i] = src1[i] >= src2[i] ? 0xFFFFu : 0; | |
4620 else | |
4621 src1[i] = src1[i] > src2[i] ? 0xFFFFu : 0; | |
4622 } | |
4623 set_q_register(Vd, src1); | |
4624 break; | |
4625 } | |
4626 case Neon32: { | |
4627 uint32_t src1[4], src2[4]; | |
4628 get_q_register(Vn, src1); | |
4629 get_q_register(Vm, src2); | |
4630 for (int i = 0; i < 4; i++) { | 4838 for (int i = 0; i < 4; i++) { |
4631 if (ge) | 4839 if (ge) { |
4632 src1[i] = src1[i] >= src2[i] ? 0xFFFFFFFFu : 0; | 4840 dst[i] = src1[i] >= src2[i] ? 0xFFFFFFFFu : 0; |
4633 else | 4841 } else { |
4634 src1[i] = src1[i] > src2[i] ? 0xFFFFFFFFu : 0; | 4842 dst[i] = src1[i] > src2[i] ? 0xFFFFFFFFu : 0; |
4635 } | 4843 } |
4636 set_q_register(Vd, src1); | 4844 } |
4637 break; | 4845 set_q_register(Vd, dst); |
4638 } | 4846 } else { |
4639 default: | 4847 UNIMPLEMENTED(); |
4640 UNREACHABLE(); | 4848 } |
4641 break; | 4849 break; |
4642 } | 4850 } |
4643 } else if (instr->Bits(11, 8) == 0x6) { | 4851 default: |
4644 // vmin/vmax.u<size> Qd, Qm, Qn. | 4852 UNREACHABLE(); |
4645 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); | 4853 break; |
4646 int Vd = instr->VFPDRegValue(kSimd128Precision); | |
4647 int Vm = instr->VFPMRegValue(kSimd128Precision); | |
4648 int Vn = instr->VFPNRegValue(kSimd128Precision); | |
4649 bool min = instr->Bit(4) != 0; | |
4650 switch (size) { | |
4651 case Neon8: { | |
4652 uint8_t src1[16], src2[16]; | |
4653 get_q_register(Vn, src1); | |
4654 get_q_register(Vm, src2); | |
4655 for (int i = 0; i < 16; i++) { | |
4656 if (min) | |
4657 src1[i] = std::min(src1[i], src2[i]); | |
4658 else | |
4659 src1[i] = std::max(src1[i], src2[i]); | |
4660 } | |
4661 set_q_register(Vd, src1); | |
4662 break; | |
4663 } | |
4664 case Neon16: { | |
4665 uint16_t src1[8], src2[8]; | |
4666 get_q_register(Vn, src1); | |
4667 get_q_register(Vm, src2); | |
4668 for (int i = 0; i < 8; i++) { | |
4669 if (min) | |
4670 src1[i] = std::min(src1[i], src2[i]); | |
4671 else | |
4672 src1[i] = std::max(src1[i], src2[i]); | |
4673 } | |
4674 set_q_register(Vd, src1); | |
4675 break; | |
4676 } | |
4677 case Neon32: { | |
4678 uint32_t src1[4], src2[4]; | |
4679 get_q_register(Vn, src1); | |
4680 get_q_register(Vm, src2); | |
4681 for (int i = 0; i < 4; i++) { | |
4682 if (min) | |
4683 src1[i] = std::min(src1[i], src2[i]); | |
4684 else | |
4685 src1[i] = std::max(src1[i], src2[i]); | |
4686 } | |
4687 set_q_register(Vd, src1); | |
4688 break; | |
4689 } | |
4690 default: | |
4691 UNREACHABLE(); | |
4692 break; | |
4693 } | |
4694 } else { | |
4695 UNIMPLEMENTED(); | |
4696 } | 4854 } |
4697 break; | 4855 break; |
| 4856 } |
4698 case 7: | 4857 case 7: |
4699 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && | 4858 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && |
4700 (instr->Bit(4) == 1)) { | 4859 (instr->Bit(4) == 1)) { |
4701 // vmovl unsigned | 4860 // vmovl unsigned |
4702 if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED(); | 4861 if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED(); |
4703 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); | 4862 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); |
4704 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); | 4863 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); |
4705 int imm3 = instr->Bits(21, 19); | 4864 int imm3 = instr->Bits(21, 19); |
4706 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED(); | 4865 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED(); |
4707 int esize = 8 * imm3; | 4866 int esize = 8 * imm3; |
(...skipping 1115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5823 processor->prev_ = nullptr; | 5982 processor->prev_ = nullptr; |
5824 processor->next_ = nullptr; | 5983 processor->next_ = nullptr; |
5825 } | 5984 } |
5826 | 5985 |
5827 } // namespace internal | 5986 } // namespace internal |
5828 } // namespace v8 | 5987 } // namespace v8 |
5829 | 5988 |
5830 #endif // USE_SIMULATOR | 5989 #endif // USE_SIMULATOR |
5831 | 5990 |
5832 #endif // V8_TARGET_ARCH_ARM | 5991 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |