Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(579)

Side by Side Diff: src/arm/simulator-arm.cc

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

Powered by Google App Engine
This is Rietveld 408576698