Index: src/arm/simulator-arm.cc |
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc |
index fae282207aac85f6133cb6d517d9c671cbfb0f9d..25d85789fcf04935f79035424cb3a9524fe553a4 100644 |
--- a/src/arm/simulator-arm.cc |
+++ b/src/arm/simulator-arm.cc |
@@ -3852,7 +3852,7 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { |
set_q_register(Vd, data); |
} else if (instr->Bits(11, 8) == 8) { |
// vadd/vtst |
- int size = static_cast<NeonSize>(instr->Bits(21, 20)); |
+ NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
int Vd = instr->VFPDRegValue(kSimd128Precision); |
int Vm = instr->VFPMRegValue(kSimd128Precision); |
int Vn = instr->VFPNRegValue(kSimd128Precision); |
@@ -3985,6 +3985,7 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { |
set_q_register(Vd, src1); |
} else if (instr->Bits(21, 20) == 0 && instr->Bits(11, 8) == 0xe && |
instr->Bit(4) == 0) { |
+ // vceq.f32 Qd, Qm, Qn |
int Vd = instr->VFPDRegValue(kSimd128Precision); |
int Vm = instr->VFPMRegValue(kSimd128Precision); |
int Vn = instr->VFPNRegValue(kSimd128Precision); |
@@ -3998,6 +3999,57 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { |
} |
set_q_register(Vd, src1); |
+ } else if (instr->Bits(11, 8) == 0x3) { |
+ // vcge/vcgt.s<size> Qd, Qm, Qn. |
+ bool ge = instr->Bit(4) == 1; |
+ NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
+ int Vd = instr->VFPDRegValue(kSimd128Precision); |
+ int Vm = instr->VFPMRegValue(kSimd128Precision); |
+ int Vn = instr->VFPNRegValue(kSimd128Precision); |
+ uint32_t src1[4], src2[4]; |
+ get_q_register(Vn, src1); |
+ get_q_register(Vm, src2); |
+ switch (size) { |
+ case Neon8: { |
+ int8_t* s1 = reinterpret_cast<int8_t*>(src1); |
martyn.capewell
2017/01/06 19:10:21
It's worth implementing some new get/set_q_registe
bbudge
2017/01/10 11:17:51
Yes, good idea. Done.
|
+ int8_t* s2 = reinterpret_cast<int8_t*>(src2); |
+ for (int i = 0; i < 16; i++) { |
+ if (ge) |
+ s1[i] = s1[i] >= s2[i] ? 0xFF : 0; |
+ else |
+ s1[i] = s1[i] > s2[i] ? 0xFF : 0; |
+ } |
+ break; |
+ } |
+ case Neon16: { |
+ int16_t s1[8], s2[8]; |
+ memcpy(s1, src1, sizeof(s1)); |
+ memcpy(s2, src2, sizeof(s2)); |
+ for (int i = 0; i < 8; i++) { |
+ if (ge) |
+ s1[i] = s1[i] >= s2[i] ? 0xffffu : 0; |
+ else |
+ s1[i] = s1[i] > s2[i] ? 0xffffu : 0; |
+ } |
+ memcpy(src1, s1, sizeof(src1)); |
+ break; |
+ } |
+ case Neon32: { |
+ int32_t* s1 = reinterpret_cast<int32_t*>(src1); |
+ int32_t* s2 = reinterpret_cast<int32_t*>(src2); |
+ for (int i = 0; i < 4; i++) { |
+ if (ge) |
+ s1[i] = s1[i] >= s2[i] ? 0xFFFFFFFF : 0; |
+ else |
+ s1[i] = s1[i] > s2[i] ? 0xFFFFFFFF : 0; |
+ } |
+ break; |
+ } |
+ default: |
+ UNREACHABLE(); |
+ break; |
+ } |
+ set_q_register(Vd, src1); |
} else { |
UNIMPLEMENTED(); |
} |
@@ -4050,7 +4102,7 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { |
case 6: |
if (instr->Bits(11, 8) == 8 && instr->Bit(4) == 0) { |
// vsub.size Qd, Qm, Qn. |
- int size = static_cast<NeonSize>(instr->Bits(21, 20)); |
+ NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
int Vd = instr->VFPDRegValue(kSimd128Precision); |
int Vm = instr->VFPMRegValue(kSimd128Precision); |
int Vn = instr->VFPNRegValue(kSimd128Precision); |
@@ -4089,7 +4141,7 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { |
set_q_register(Vd, src1); |
} else if (instr->Bits(11, 8) == 8 && instr->Bit(4) == 1) { |
// vceq.size Qd, Qm, Qn. |
- int size = static_cast<NeonSize>(instr->Bits(21, 20)); |
+ NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
int Vd = instr->VFPDRegValue(kSimd128Precision); |
int Vm = instr->VFPMRegValue(kSimd128Precision); |
int Vn = instr->VFPNRegValue(kSimd128Precision); |
@@ -4178,6 +4230,78 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { |
bit_cast<float>(src2[i])); |
} |
set_q_register(Vd, src1); |
+ } else if (instr->Bit(20) == 0 && instr->Bits(11, 8) == 0xe && |
+ instr->Bit(4) == 0) { |
+ // vcge/vcgt.f32 Qd, Qm, Qn |
+ bool ge = instr->Bit(21) == 0; |
+ int Vd = instr->VFPDRegValue(kSimd128Precision); |
+ int Vm = instr->VFPMRegValue(kSimd128Precision); |
+ int Vn = instr->VFPNRegValue(kSimd128Precision); |
+ uint32_t src1[4], src2[4]; |
+ get_q_register(Vn, src1); |
+ get_q_register(Vm, src2); |
+ for (int i = 0; i < 4; i++) { |
+ if (ge) { |
+ src1[i] = bit_cast<float>(src1[i]) >= bit_cast<float>(src2[i]) |
+ ? 0xFFFFFFFF |
+ : 0; |
+ } else { |
+ src1[i] = bit_cast<float>(src1[i]) > bit_cast<float>(src2[i]) |
+ ? 0xFFFFFFFF |
+ : 0; |
+ } |
+ } |
+ set_q_register(Vd, src1); |
+ |
+ } else if (instr->Bits(11, 8) == 0x3) { |
+ // vcge/vcgt.u<size> Qd, Qm, Qn. |
+ bool ge = instr->Bit(4) == 1; |
+ NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
+ int Vd = instr->VFPDRegValue(kSimd128Precision); |
+ int Vm = instr->VFPMRegValue(kSimd128Precision); |
+ int Vn = instr->VFPNRegValue(kSimd128Precision); |
+ uint32_t src1[4], src2[4]; |
+ get_q_register(Vn, src1); |
+ get_q_register(Vm, src2); |
+ switch (size) { |
+ case Neon8: { |
+ uint8_t* s1 = reinterpret_cast<uint8_t*>(src1); |
+ uint8_t* s2 = reinterpret_cast<uint8_t*>(src2); |
+ for (int i = 0; i < 16; i++) { |
+ if (ge) |
+ s1[i] = s1[i] >= s2[i] ? 0xFF : 0; |
+ else |
+ s1[i] = s1[i] > s2[i] ? 0xFF : 0; |
+ } |
+ break; |
+ } |
+ case Neon16: { |
+ uint16_t s1[8], s2[8]; |
+ memcpy(s1, src1, sizeof(s1)); |
+ memcpy(s2, src2, sizeof(s2)); |
+ for (int i = 0; i < 8; i++) { |
+ if (ge) |
+ s1[i] = s1[i] >= s2[i] ? 0xffffu : 0; |
+ else |
+ s1[i] = s1[i] > s2[i] ? 0xffffu : 0; |
+ } |
+ memcpy(src1, s1, sizeof(src1)); |
+ break; |
+ } |
+ case Neon32: { |
+ for (int i = 0; i < 4; i++) { |
+ if (ge) |
+ src1[i] = src1[i] >= src2[i] ? 0xFFFFFFFF : 0; |
+ else |
+ src1[i] = src1[i] > src2[i] ? 0xFFFFFFFF : 0; |
+ } |
+ break; |
+ } |
+ default: |
+ UNREACHABLE(); |
+ break; |
+ } |
+ set_q_register(Vd, src1); |
} else { |
UNIMPLEMENTED(); |
} |
@@ -4299,7 +4423,7 @@ 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. |
- int size = static_cast<NeonSize>(instr->Bits(19, 18)); |
+ NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18)); |
int Vd = instr->VFPDRegValue(kSimd128Precision); |
int Vm = instr->VFPMRegValue(kSimd128Precision); |
uint32_t src1[4], src2[4], dst1[4], dst2[4]; |
@@ -4352,7 +4476,7 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { |
// vrev<op>.size Qd, Qm |
int Vd = instr->VFPDRegValue(kSimd128Precision); |
int Vm = instr->VFPMRegValue(kSimd128Precision); |
- int size = static_cast<NeonSize>(instr->Bits(19, 18)); |
+ NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18)); |
NeonSize op = static_cast<NeonSize>(static_cast<int>(Neon64) - |
instr->Bits(8, 7)); |
uint32_t src[4]; |
@@ -4425,7 +4549,7 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { |
} else if (instr->Bits(17, 16) == 0x1 && instr->Bit(11) == 0) { |
int Vd = instr->VFPDRegValue(kSimd128Precision); |
int Vm = instr->VFPMRegValue(kSimd128Precision); |
- int size = static_cast<NeonSize>(instr->Bits(19, 18)); |
+ NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18)); |
uint32_t src[4]; |
get_q_register(Vm, src); |
if (instr->Bits(9, 6) == 0xd) { |