Chromium Code Reviews| Index: src/arm/simulator-arm.cc |
| diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc |
| index 3a3a90225bf0af1fa7ba72f454fca9fd8487eb42..a4659de3c689aa419ee989e625b3066b0dea838f 100644 |
| --- a/src/arm/simulator-arm.cc |
| +++ b/src/arm/simulator-arm.cc |
| @@ -900,6 +900,18 @@ void Simulator::set_d_register(int dreg, const uint32_t* value) { |
| } |
| template <typename T> |
| +void Simulator::get_d_register(int dreg, T* value) { |
| + DCHECK((dreg >= 0) && (dreg < num_d_registers)); |
| + memcpy(value, vfp_registers_ + dreg * 2, kDoubleSize); |
| +} |
| + |
| +template <typename T> |
| +void Simulator::set_d_register(int dreg, const T* value) { |
| + DCHECK((dreg >= 0) && (dreg < num_d_registers)); |
| + memcpy(vfp_registers_ + dreg * 2, value, kDoubleSize); |
| +} |
| + |
| +template <typename T> |
| void Simulator::get_q_register(int qreg, T* value) { |
| DCHECK((qreg >= 0) && (qreg < num_q_registers)); |
| memcpy(value, vfp_registers_ + qreg * 4, kSimd128Size); |
| @@ -911,7 +923,6 @@ void Simulator::set_q_register(int qreg, const T* value) { |
| memcpy(vfp_registers_ + qreg * 4, value, kSimd128Size); |
| } |
| - |
| // Raw access to the PC register. |
| void Simulator::set_pc(int32_t value) { |
| pc_modified_ = true; |
| @@ -4343,6 +4354,63 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { |
| } |
| break; |
| } |
| + case 0xa: { |
| + // vpmin/vpmax.s<size> Dd, Dm, Dn. |
| + NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
| + bool min = instr->Bit(4) != 0; |
| + switch (size) { |
| + case Neon8: { |
| + int8_t dst[8], src1[8], src2[8]; |
| + get_d_register(Vn, src1); |
| + get_d_register(Vm, src2); |
| + for (int i = 0; i < 4; i++) { |
| + if (min) { |
|
martyn.capewell
2017/02/28 15:45:24
How about a templated minmax helper?
template <typ
bbudge
2017/02/28 17:39:35
That does look nicer. Done.
|
| + dst[i + 0] = std::min(src1[i * 2], src1[i * 2 + 1]); |
| + dst[i + 4] = std::min(src2[i * 2], src2[i * 2 + 1]); |
| + } else { |
| + dst[i + 0] = std::max(src1[i * 2], src1[i * 2 + 1]); |
| + dst[i + 4] = std::max(src2[i * 2], src2[i * 2 + 1]); |
| + } |
| + } |
| + set_d_register(Vd, dst); |
| + break; |
| + } |
| + case Neon16: { |
| + int16_t dst[4], src1[4], src2[4]; |
| + get_d_register(Vn, src1); |
| + get_d_register(Vm, src2); |
| + for (int i = 0; i < 2; i++) { |
| + if (min) { |
| + dst[i + 0] = std::min(src1[i * 2], src1[i * 2 + 1]); |
| + dst[i + 2] = std::min(src2[i * 2], src2[i * 2 + 1]); |
| + } else { |
| + dst[i + 0] = std::max(src1[i * 2], src1[i * 2 + 1]); |
| + dst[i + 2] = std::max(src2[i * 2], src2[i * 2 + 1]); |
| + } |
| + } |
| + set_d_register(Vd, dst); |
| + break; |
| + } |
| + case Neon32: { |
| + int32_t dst[2], src1[2], src2[2]; |
| + get_d_register(Vn, src1); |
| + get_d_register(Vm, src2); |
| + if (min) { |
| + dst[0] = std::min(src1[0], src1[1]); |
| + dst[1] = std::min(src2[0], src2[1]); |
| + } else { |
| + dst[0] = std::max(src1[0], src1[1]); |
| + dst[1] = std::max(src2[0], src2[1]); |
| + } |
| + set_d_register(Vd, dst); |
| + break; |
| + } |
| + default: |
| + UNREACHABLE(); |
| + break; |
| + } |
| + break; |
| + } |
| case 0xd: { |
| if (instr->Bit(4) == 0) { |
| float src1[4], src2[4]; |
| @@ -4812,6 +4880,63 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { |
| } |
| break; |
| } |
| + case 0xa: { |
| + // vpmin/vpmax.u<size> Dd, Dm, Dn. |
| + NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); |
| + bool min = instr->Bit(4) != 0; |
| + switch (size) { |
| + case Neon8: { |
| + uint8_t dst[8], src1[8], src2[8]; |
| + get_d_register(Vn, src1); |
| + get_d_register(Vm, src2); |
| + for (int i = 0; i < 4; i++) { |
| + if (min) { |
| + dst[i + 0] = std::min(src1[i * 2], src1[i * 2 + 1]); |
| + dst[i + 4] = std::min(src2[i * 2], src2[i * 2 + 1]); |
| + } else { |
| + dst[i + 0] = std::max(src1[i * 2], src1[i * 2 + 1]); |
| + dst[i + 4] = std::max(src2[i * 2], src2[i * 2 + 1]); |
| + } |
| + } |
| + set_d_register(Vd, dst); |
| + break; |
| + } |
| + case Neon16: { |
| + uint16_t dst[4], src1[4], src2[4]; |
| + get_d_register(Vn, src1); |
| + get_d_register(Vm, src2); |
| + for (int i = 0; i < 2; i++) { |
| + if (min) { |
| + dst[i + 0] = std::min(src1[i * 2], src1[i * 2 + 1]); |
| + dst[i + 2] = std::min(src2[i * 2], src2[i * 2 + 1]); |
| + } else { |
| + dst[i + 0] = std::max(src1[i * 2], src1[i * 2 + 1]); |
| + dst[i + 2] = std::max(src2[i * 2], src2[i * 2 + 1]); |
| + } |
| + } |
| + set_d_register(Vd, dst); |
| + break; |
| + } |
| + case Neon32: { |
| + uint32_t dst[2], src1[2], src2[2]; |
| + get_d_register(Vn, src1); |
| + get_d_register(Vm, src2); |
| + if (min) { |
| + dst[0] = std::min(src1[0], src1[1]); |
| + dst[1] = std::min(src2[0], src2[1]); |
| + } else { |
| + dst[0] = std::max(src1[0], src1[1]); |
| + dst[1] = std::max(src2[0], src2[1]); |
| + } |
| + set_d_register(Vd, dst); |
| + break; |
| + } |
| + default: |
| + UNREACHABLE(); |
| + break; |
| + } |
| + break; |
| + } |
| case 0xd: { |
| if (instr->Bit(21) == 0 && instr->Bit(6) == 1 && instr->Bit(4) == 1) { |
| // vmul.f32 Qd, Qn, Qm |