Index: runtime/vm/simulator_arm.cc |
=================================================================== |
--- runtime/vm/simulator_arm.cc (revision 24980) |
+++ runtime/vm/simulator_arm.cc (working copy) |
@@ -923,6 +923,21 @@ |
} |
+void Simulator::set_qregister(QRegister reg, simd_value_t value) { |
+ ASSERT((reg >= 0) && (reg < kNumberOfQRegisters)); |
+ qregisters_[reg].data_[0] = value.data_[0]; |
+ qregisters_[reg].data_[1] = value.data_[1]; |
+ qregisters_[reg].data_[2] = value.data_[2]; |
+ qregisters_[reg].data_[3] = value.data_[3]; |
+} |
+ |
+ |
+simd_value_t Simulator::get_qregister(QRegister reg) const { |
+ ASSERT((reg >= 0) && (reg < kNumberOfQRegisters)); |
+ return qregisters_[reg]; |
+} |
+ |
+ |
void Simulator::set_sregister_bits(SRegister reg, int32_t value) { |
ASSERT((reg >= 0) && (reg < kNumberOfSRegisters)); |
sregisters_[reg] = value; |
@@ -2884,6 +2899,69 @@ |
} |
+void Simulator::DecodeSIMDDataProcessing(Instr* instr) { |
+ ASSERT(instr->ConditionField() == kSpecialCondition); |
+ |
+ if (instr->Bit(6) == 1) { |
+ // Q = 1, Using 128-bit Q registers. |
+ const QRegister qd = instr->QdField(); |
+ const QRegister qn = instr->QnField(); |
+ const QRegister qm = instr->QmField(); |
+ simd_value_t s8d; |
+ simd_value_t s8n = get_qregister(qn); |
+ simd_value_t s8m = get_qregister(qm); |
+ int8_t* s8d_8 = reinterpret_cast<int8_t*>(&s8d); |
+ int8_t* s8n_8 = reinterpret_cast<int8_t*>(&s8n); |
+ int8_t* s8m_8 = reinterpret_cast<int8_t*>(&s8m); |
+ int16_t* s8d_16 = reinterpret_cast<int16_t*>(&s8d); |
+ int16_t* s8n_16 = reinterpret_cast<int16_t*>(&s8n); |
+ int16_t* s8m_16 = reinterpret_cast<int16_t*>(&s8m); |
+ int64_t* s8d_64 = reinterpret_cast<int64_t*>(&s8d); |
+ int64_t* s8n_64 = reinterpret_cast<int64_t*>(&s8n); |
+ int64_t* s8m_64 = reinterpret_cast<int64_t*>(&s8m); |
+ |
+ if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) && |
+ (instr->Bit(24) == 0)) { |
+ // Uses q registers. |
+ // Format(instr, "vadd.'sz 'qd, 'qn, 'qm"); |
+ const int size = instr->Bits(20, 2); |
+ if (size == 0) { |
+ for (int i = 0; i < 16; i++) { |
+ s8d_8[i] = s8n_8[i] + s8m_8[i]; |
+ } |
+ } else if (size == 1) { |
+ for (int i = 0; i < 8; i++) { |
+ s8d_16[i] = s8n_16[i] + s8m_16[i]; |
+ } |
+ } else if (size == 2) { |
+ for (int i = 0; i < 4; i++) { |
+ s8d.data_[i].u = s8n.data_[i].u + s8m.data_[i].u; |
+ } |
+ } else if (size == 3) { |
+ for (int i = 0; i < 2; i++) { |
+ s8d_64[i] = s8n_64[i] + s8m_64[i]; |
+ } |
+ } else { |
+ UNREACHABLE(); |
+ } |
+ } else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 0) && |
+ (instr->Bit(24) == 0)) { |
+ // Format(instr, "vadd.F32 'qd, 'qn, 'qm"); |
+ for (int i = 0; i < 4; i++) { |
+ s8d.data_[i].f = s8n.data_[i].f + s8m.data_[i].f; |
+ } |
+ } else { |
+ UnimplementedInstruction(instr); |
+ } |
+ |
+ set_qregister(qd, s8d); |
+ } else { |
+ // Q == 0, Uses 64-bit D registers. |
+ UnimplementedInstruction(instr); |
+ } |
+} |
+ |
+ |
// Executes the current instruction. |
void Simulator::InstructionDecode(Instr* instr) { |
pc_modified_ = false; |
@@ -2897,7 +2975,11 @@ |
// Format(instr, "clrex"); |
ClearExclusive(); |
} else { |
- UnimplementedInstruction(instr); |
+ if (instr->IsSIMDDataProcessing()) { |
+ DecodeSIMDDataProcessing(instr); |
+ } else { |
+ UnimplementedInstruction(instr); |
+ } |
} |
} else if (ConditionallyExecute(instr)) { |
switch (instr->TypeField()) { |