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