Index: src/arm/simulator-arm.cc |
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc |
index e2bcd952a6c08df63c8bc3565c5e7c38a170d8d4..d3247f7ac64f224436fa6adb275bdca7ce2c4fde 100644 |
--- a/src/arm/simulator-arm.cc |
+++ b/src/arm/simulator-arm.cc |
@@ -5046,57 +5046,109 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { |
} |
} |
set_d_register(vd, &result); |
- } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 6) == 0x7) { |
- // vzip.<size> Qd, Qm. |
+ } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 8) == 0x1 && |
+ instr->Bit(6) == 1) { |
NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18)); |
int Vd = instr->VFPDRegValue(kSimd128Precision); |
int Vm = instr->VFPMRegValue(kSimd128Precision); |
- switch (size) { |
- case Neon8: { |
- uint8_t src1[16], src2[16], dst1[16], dst2[16]; |
- get_q_register(Vd, src1); |
- get_q_register(Vm, src2); |
- for (int i = 0; i < 8; i++) { |
- dst1[i * 2] = src1[i]; |
- dst1[i * 2 + 1] = src2[i]; |
- dst2[i * 2] = src1[i + 8]; |
- dst2[i * 2 + 1] = src2[i + 8]; |
+ if (instr->Bit(7) == 1) { |
+ // vzip.<size> Qd, Qm. |
+ switch (size) { |
+ case Neon8: { |
+ uint8_t src1[16], src2[16], dst1[16], dst2[16]; |
+ get_q_register(Vd, src1); |
+ get_q_register(Vm, src2); |
+ for (int i = 0; i < 8; i++) { |
+ dst1[i * 2] = src1[i]; |
+ dst1[i * 2 + 1] = src2[i]; |
+ dst2[i * 2] = src1[i + 8]; |
+ dst2[i * 2 + 1] = src2[i + 8]; |
+ } |
+ set_q_register(Vd, dst1); |
+ set_q_register(Vm, dst2); |
+ break; |
} |
- set_q_register(Vd, dst1); |
- set_q_register(Vm, dst2); |
- break; |
- } |
- case Neon16: { |
- uint16_t src1[8], src2[8], dst1[8], dst2[8]; |
- get_q_register(Vd, src1); |
- get_q_register(Vm, src2); |
- for (int i = 0; i < 8; i += 2) { |
- dst1[i] = src1[i / 2]; |
- dst1[i + 1] = src2[i / 2]; |
- dst2[i] = src1[i / 2 + 4]; |
- dst2[i + 1] = src2[i / 2 + 4]; |
+ case Neon16: { |
+ uint16_t src1[8], src2[8], dst1[8], dst2[8]; |
+ get_q_register(Vd, src1); |
+ get_q_register(Vm, src2); |
+ for (int i = 0; i < 4; i++) { |
+ dst1[i * 2] = src1[i]; |
+ dst1[i * 2 + 1] = src2[i]; |
+ dst2[i * 2] = src1[i + 4]; |
+ dst2[i * 2 + 1] = src2[i + 4]; |
+ } |
+ set_q_register(Vd, dst1); |
+ set_q_register(Vm, dst2); |
+ break; |
} |
- set_q_register(Vd, dst1); |
- set_q_register(Vm, dst2); |
- break; |
+ case Neon32: { |
+ uint32_t src1[4], src2[4], dst1[4], dst2[4]; |
+ get_q_register(Vd, src1); |
+ get_q_register(Vm, src2); |
+ for (int i = 0; i < 2; i++) { |
+ dst1[i * 2] = src1[i]; |
+ dst1[i * 2 + 1] = src2[i]; |
+ dst2[i * 2] = src1[i + 2]; |
+ dst2[i * 2 + 1] = src2[i + 2]; |
+ } |
+ set_q_register(Vd, dst1); |
+ set_q_register(Vm, dst2); |
+ break; |
+ } |
+ default: |
+ UNREACHABLE(); |
+ break; |
} |
- case Neon32: { |
- uint32_t src1[4], src2[4], dst1[4], dst2[4]; |
- get_q_register(Vd, src1); |
- get_q_register(Vm, src2); |
- for (int i = 0; i < 2; i++) { |
- dst1[i * 2] = src1[i]; |
- dst1[i * 2 + 1] = src2[i]; |
- dst2[i * 2] = src1[i + 2]; |
- dst2[i * 2 + 1] = src2[i + 2]; |
+ } else { |
+ // vuzp.<size> Qd, Qm. |
+ switch (size) { |
+ case Neon8: { |
+ uint8_t src1[16], src2[16], dst1[16], dst2[16]; |
+ get_q_register(Vd, src1); |
+ get_q_register(Vm, src2); |
+ for (int i = 0; i < 8; i++) { |
+ dst1[i] = src1[i * 2]; |
+ dst1[i + 8] = src2[i * 2]; |
+ dst2[i] = src1[i * 2 + 1]; |
+ dst2[i + 8] = src2[i * 2 + 1]; |
+ } |
+ set_q_register(Vd, dst1); |
+ set_q_register(Vm, dst2); |
+ break; |
} |
- set_q_register(Vd, dst1); |
- set_q_register(Vm, dst2); |
- break; |
+ case Neon16: { |
+ uint16_t src1[8], src2[8], dst1[8], dst2[8]; |
+ get_q_register(Vd, src1); |
+ get_q_register(Vm, src2); |
+ for (int i = 0; i < 4; i++) { |
+ dst1[i] = src1[i * 2]; |
+ dst1[i + 4] = src2[i * 2]; |
+ dst2[i] = src1[i * 2 + 1]; |
+ dst2[i + 4] = src2[i * 2 + 1]; |
+ } |
+ set_q_register(Vd, dst1); |
+ set_q_register(Vm, dst2); |
+ break; |
+ } |
+ case Neon32: { |
+ uint32_t src1[4], src2[4], dst1[4], dst2[4]; |
+ get_q_register(Vd, src1); |
+ get_q_register(Vm, src2); |
+ for (int i = 0; i < 2; i++) { |
+ dst1[i] = src1[i * 2]; |
+ dst1[i + 2] = src2[i * 2]; |
+ dst2[i] = src1[i * 2 + 1]; |
+ dst2[i + 2] = src2[i * 2 + 1]; |
+ } |
+ set_q_register(Vd, dst1); |
+ set_q_register(Vm, dst2); |
+ break; |
+ } |
+ default: |
+ UNREACHABLE(); |
+ break; |
} |
- default: |
- UNREACHABLE(); |
- break; |
} |
} else if (instr->Bits(17, 16) == 0 && instr->Bits(11, 9) == 0) { |
// vrev<op>.size Qd, Qm |
@@ -5183,6 +5235,49 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { |
UNREACHABLE(); |
break; |
} |
+ } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 6) == 0x3) { |
+ int Vd = instr->VFPDRegValue(kSimd128Precision); |
+ int Vm = instr->VFPMRegValue(kSimd128Precision); |
+ NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18)); |
+ // vtrn.<size> Qd, Qm. |
+ switch (size) { |
+ case Neon8: { |
+ uint8_t src[16], dst[16]; |
+ get_q_register(Vd, dst); |
+ get_q_register(Vm, src); |
+ for (int i = 0; i < 8; i++) { |
+ std::swap(dst[2 * i + 1], src[2 * i]); |
+ } |
+ set_q_register(Vd, dst); |
+ set_q_register(Vm, src); |
+ break; |
+ } |
+ case Neon16: { |
+ uint16_t src[8], dst[8]; |
+ get_q_register(Vd, dst); |
+ get_q_register(Vm, src); |
+ for (int i = 0; i < 4; i++) { |
+ std::swap(dst[2 * i + 1], src[2 * i]); |
+ } |
+ set_q_register(Vd, dst); |
+ set_q_register(Vm, src); |
+ break; |
+ } |
+ case Neon32: { |
+ uint32_t src[4], dst[4]; |
+ get_q_register(Vd, dst); |
+ get_q_register(Vm, src); |
+ for (int i = 0; i < 2; i++) { |
+ std::swap(dst[2 * i + 1], src[2 * i]); |
+ } |
+ set_q_register(Vd, dst); |
+ set_q_register(Vm, src); |
+ break; |
+ } |
+ default: |
+ UNREACHABLE(); |
+ break; |
+ } |
} else if (instr->Bits(17, 16) == 0x1 && instr->Bit(11) == 0) { |
int Vd = instr->VFPDRegValue(kSimd128Precision); |
int Vm = instr->VFPMRegValue(kSimd128Precision); |