Chromium Code Reviews| 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 |