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