Index: runtime/vm/simulator_arm64.cc |
=================================================================== |
--- runtime/vm/simulator_arm64.cc (revision 36576) |
+++ runtime/vm/simulator_arm64.cc (working copy) |
@@ -2205,7 +2205,17 @@ |
const VRegister vd = instr->VdField(); |
const VRegister vn = instr->VnField(); |
- if ((Q == 1) && (op == 0) && (imm4 == 0)) { |
+ const Register rn = instr->RnField(); |
+ const Register rd = instr->RdField(); |
+ if ((op == 0) && (imm4 == 7)) { |
+ if (Q == 0) { |
+ // Format(instr, "vmovrs 'rd, 'vn'idx5"); |
+ set_wregister(rd, get_vregisters(vn, idx5), R31IsZR); |
+ } else { |
+ // Format(instr, "vmovrd 'rd, 'vn'idx5"); |
+ set_register(rd, get_vregisterd(vn, idx5), R31IsZR); |
+ } |
+ } else if ((Q == 1) && (op == 0) && (imm4 == 0)) { |
// Format(instr, "vdup'csz 'vd, 'vn'idx5"); |
if (element_bytes == 4) { |
for (int i = 0; i < 4; i++) { |
@@ -2219,6 +2229,29 @@ |
UnimplementedInstruction(instr); |
return; |
} |
+ } else if ((Q == 1) && (op == 0) && (imm4 == 3)) { |
+ // Format(instr, "vins'csz 'vd'idx5, 'rn"); |
+ if (element_bytes == 4) { |
+ set_vregisters(vd, idx5, get_wregister(rn, R31IsZR)); |
+ } else if (element_bytes == 8) { |
+ set_vregisterd(vd, idx5, get_register(rn, R31IsZR)); |
+ } else { |
+ UnimplementedInstruction(instr); |
+ } |
+ } else if ((Q == 1) && (op == 0) && (imm4 == 1)) { |
+ // Format(instr, "vdup'csz 'vd, 'rn"); |
+ if (element_bytes == 4) { |
+ for (int i = 0; i < 4; i++) { |
+ set_vregisters(vd, i, get_wregister(rn, R31IsZR)); |
+ } |
+ } else if (element_bytes == 8) { |
+ for (int i = 0; i < 2; i++) { |
+ set_vregisterd(vd, i, get_register(rn, R31IsZR)); |
+ } |
+ } else { |
+ UnimplementedInstruction(instr); |
+ return; |
+ } |
} else if ((Q == 1) && (op == 1)) { |
// Format(instr, "vins'csz 'vd'idx5, 'vn'idx4"); |
if (element_bytes == 4) { |
@@ -2250,64 +2283,159 @@ |
if (instr->Bit(22) == 0) { |
// f32 case. |
for (int idx = 0; idx < 4; idx++) { |
- const float vn_val = bit_cast<float, int32_t>(get_vregisters(vn, idx)); |
- const float vm_val = bit_cast<float, int32_t>(get_vregisters(vm, idx)); |
- float res = 0.0; |
- if ((U == 0) && (opcode == 0x1a)) { |
+ const int32_t vn_val = get_vregisters(vn, idx); |
+ const int32_t vm_val = get_vregisters(vm, idx); |
+ const float vn_flt = bit_cast<float, int32_t>(vn_val); |
+ const float vm_flt = bit_cast<float, int32_t>(vm_val); |
+ int32_t res = 0.0; |
+ if ((U == 0) && (opcode == 0x3)) { |
if (instr->Bit(23) == 0) { |
+ // Format(instr, "vand 'vd, 'vn, 'vm"); |
+ res = vn_val & vm_val; |
+ } else { |
+ // Format(instr, "vorr 'vd, 'vn, 'vm"); |
+ res = vn_val | vm_val; |
+ } |
+ } else if ((U == 1) && (opcode == 0x3)) { |
+ // Format(instr, "veor 'vd, 'vn, 'vm"); |
+ res = vn_val ^ vm_val; |
+ } else if ((U == 0) && (opcode == 0x10)) { |
+ // Format(instr, "vadd'vsz 'vd, 'vn, 'vm"); |
+ res = vn_val + vm_val; |
+ } else if ((U == 1) && (opcode == 0x10)) { |
+ // Format(instr, "vsub'vsz 'vd, 'vn, 'vm"); |
+ res = vn_val - vm_val; |
+ } else if ((U == 0) && (opcode == 0x1a)) { |
+ if (instr->Bit(23) == 0) { |
// Format(instr, "vadd'vsz 'vd, 'vn, 'vm"); |
- res = vn_val + vm_val; |
+ res = bit_cast<int32_t, float>(vn_flt + vm_flt); |
} else { |
// Format(instr, "vsub'vsz 'vd, 'vn, 'vm"); |
- res = vn_val - vm_val; |
+ res = bit_cast<int32_t, float>(vn_flt - vm_flt); |
} |
} else if ((U == 1) && (opcode == 0x1b)) { |
// Format(instr, "vmul'vsz 'vd, 'vn, 'vm"); |
- res = vn_val * vm_val; |
+ res = bit_cast<int32_t, float>(vn_flt * vm_flt); |
} else if ((U == 1) && (opcode == 0x1f)) { |
// Format(instr, "vdiv'vsz 'vd, 'vn, 'vm"); |
- res = vn_val / vm_val; |
+ res = bit_cast<int32_t, float>(vn_flt / vm_flt); |
} else { |
UnimplementedInstruction(instr); |
return; |
} |
- set_vregisters(vd, idx, bit_cast<int32_t, float>(res)); |
+ set_vregisters(vd, idx, res); |
} |
} else { |
// f64 case. |
for (int idx = 0; idx < 2; idx++) { |
- const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, idx)); |
- const double vm_val = bit_cast<double, int64_t>(get_vregisterd(vm, idx)); |
- double res = 0.0; |
- if ((U == 0) && (opcode == 0x1a)) { |
+ const int64_t vn_val = get_vregisterd(vn, idx); |
+ const int64_t vm_val = get_vregisterd(vm, idx); |
+ const double vn_dbl = bit_cast<double, int64_t>(vn_val); |
+ const double vm_dbl = bit_cast<double, int64_t>(vm_val); |
+ int64_t res = 0.0; |
+ if ((U == 0) && (opcode == 0x3)) { |
if (instr->Bit(23) == 0) { |
+ // Format(instr, "vand 'vd, 'vn, 'vm"); |
+ res = vn_val & vm_val; |
+ } else { |
+ // Format(instr, "vorr 'vd, 'vn, 'vm"); |
+ res = vn_val | vm_val; |
+ } |
+ } else if ((U == 1) && (opcode == 0x3)) { |
+ // Format(instr, "veor 'vd, 'vn, 'vm"); |
+ res = vn_val ^ vm_val; |
+ } else if ((U == 0) && (opcode == 0x10)) { |
+ // Format(instr, "vadd'vsz 'vd, 'vn, 'vm"); |
+ res = vn_val + vm_val; |
+ } else if ((U == 1) && (opcode == 0x10)) { |
+ // Format(instr, "vsub'vsz 'vd, 'vn, 'vm"); |
+ res = vn_val - vm_val; |
+ } else if ((U == 0) && (opcode == 0x1a)) { |
+ if (instr->Bit(23) == 0) { |
// Format(instr, "vadd'vsz 'vd, 'vn, 'vm"); |
- res = vn_val + vm_val; |
+ res = bit_cast<int64_t, double>(vn_dbl + vm_dbl); |
} else { |
// Format(instr, "vsub'vsz 'vd, 'vn, 'vm"); |
- res = vn_val - vm_val; |
+ res = bit_cast<int64_t, double>(vn_dbl - vm_dbl); |
} |
} else if ((U == 1) && (opcode == 0x1b)) { |
// Format(instr, "vmul'vsz 'vd, 'vn, 'vm"); |
- res = vn_val * vm_val; |
+ res = bit_cast<int64_t, double>(vn_dbl * vm_dbl); |
} else if ((U == 1) && (opcode == 0x1f)) { |
// Format(instr, "vdiv'vsz 'vd, 'vn, 'vm"); |
- res = vn_val / vm_val; |
+ res = bit_cast<int64_t, double>(vn_dbl / vm_dbl); |
} else { |
UnimplementedInstruction(instr); |
return; |
} |
- set_vregisterd(vd, idx, bit_cast<int64_t, double>(res)); |
+ set_vregisterd(vd, idx, res); |
} |
} |
} |
+void Simulator::DecodeSIMDTwoReg(Instr* instr) { |
+ const int32_t Q = instr->Bit(30); |
+ const int32_t U = instr->Bit(29); |
+ const int32_t op = instr->Bits(12, 5); |
+ const int32_t sz = instr->Bits(22, 2); |
+ const VRegister vd = instr->VdField(); |
+ const VRegister vn = instr->VnField(); |
+ |
+ if ((Q == 1) && (U == 1) && (op == 5)) { |
+ // Format(instr, "vnot 'vd, 'vn"); |
+ for (int i = 0; i < 2; i++) { |
+ set_vregisterd(vd, i, ~get_vregisterd(vn, i)); |
+ } |
+ } else if ((U == 0) && (op == 0xf)) { |
+ if (sz == 2) { |
+ // Format(instr, "vabss 'vd, 'vn"); |
+ for (int i = 0; i < 4; i++) { |
+ const int32_t vn_val = get_vregisters(vn, i); |
+ const float vn_flt = bit_cast<float, int32_t>(vn_val); |
+ set_vregisters(vd, i, bit_cast<int32_t, float>(fabsf(vn_flt))); |
+ } |
+ } else if (sz == 3) { |
+ // Format(instr, "vabsd 'vd, 'vn"); |
+ for (int i = 0; i < 2; i++) { |
+ const int64_t vn_val = get_vregisterd(vn, i); |
+ const double vn_dbl = bit_cast<double, int64_t>(vn_val); |
+ set_vregisterd(vd, i, bit_cast<int64_t, double>(fabs(vn_dbl))); |
+ } |
+ } else { |
+ UnimplementedInstruction(instr); |
+ } |
+ } else if ((U == 1) && (op == 0xf)) { |
+ if (sz == 2) { |
+ // Format(instr, "vnegs 'vd, 'vn"); |
+ for (int i = 0; i < 4; i++) { |
+ const int32_t vn_val = get_vregisters(vn, i); |
+ const float vn_flt = bit_cast<float, int32_t>(vn_val); |
+ set_vregisters(vd, i, bit_cast<int32_t, float>(-vn_flt)); |
+ } |
+ } else if (sz == 3) { |
+ // Format(instr, "vnegd 'vd, 'vn"); |
+ for (int i = 0; i < 2; i++) { |
+ const int64_t vn_val = get_vregisterd(vn, i); |
+ const double vn_dbl = bit_cast<double, int64_t>(vn_val); |
+ set_vregisterd(vd, i, bit_cast<int64_t, double>(-vn_dbl)); |
+ } |
+ } else { |
+ UnimplementedInstruction(instr); |
+ } |
+ } else { |
+ UnimplementedInstruction(instr); |
+ } |
+} |
+ |
+ |
void Simulator::DecodeDPSimd1(Instr* instr) { |
if (instr->IsSIMDCopyOp()) { |
DecodeSIMDCopy(instr); |
} else if (instr->IsSIMDThreeSameOp()) { |
DecodeSIMDThreeSame(instr); |
+ } else if (instr->IsSIMDTwoRegOp()) { |
+ DecodeSIMDTwoReg(instr); |
} else { |
UnimplementedInstruction(instr); |
} |