[sve2] Implement add/sub high and narrow
Implement add/sub high and narrow instructions, with and without rounding.
Change-Id: I3245d3f208031304fcd1f4d2edc601b2c5f2e555
diff --git a/src/aarch64/simulator-aarch64.cc b/src/aarch64/simulator-aarch64.cc
index 36a49fe..bf5ee0e 100644
--- a/src/aarch64/simulator-aarch64.cc
+++ b/src/aarch64/simulator-aarch64.cc
@@ -71,8 +71,8 @@
DEFAULT_FORM_TO_VISITOR_MAP(Simulator),
{"adclb_z_zzz", &Simulator::SimulateSVEAddSubCarry},
{"adclt_z_zzz", &Simulator::SimulateSVEAddSubCarry},
- {"addhnb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
- {"addhnt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
+ {"addhnb_z_zz", &Simulator::SimulateSVEAddSubHigh},
+ {"addhnt_z_zz", &Simulator::SimulateSVEAddSubHigh},
{"addp_z_p_zz", &Simulator::SimulateSVEIntArithPair},
{"bcax_z_zzz", &Simulator::Simulate_ZdnD_ZdnD_ZmD_ZkD},
{"bdep_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
@@ -142,12 +142,12 @@
{"pmul_z_zz", &Simulator::Simulate_ZdB_ZnB_ZmB},
{"pmullb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
{"pmullt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
- {"raddhnb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
- {"raddhnt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
+ {"raddhnb_z_zz", &Simulator::SimulateSVEAddSubHigh},
+ {"raddhnt_z_zz", &Simulator::SimulateSVEAddSubHigh},
{"rshrnb_z_zi", &Simulator::SimulateSVENarrow},
{"rshrnt_z_zi", &Simulator::SimulateSVENarrow},
- {"rsubhnb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
- {"rsubhnt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
+ {"rsubhnb_z_zz", &Simulator::SimulateSVEAddSubHigh},
+ {"rsubhnt_z_zz", &Simulator::SimulateSVEAddSubHigh},
{"saba_z_zzz", &Simulator::Simulate_ZdaT_ZnT_ZmT},
{"sabalb_z_zzz", &Simulator::SimulateSVEInterleavedArithLong},
{"sabalt_z_zzz", &Simulator::SimulateSVEInterleavedArithLong},
@@ -274,8 +274,8 @@
{"stnt1h_z_p_ar_s_x32_unscaled", &Simulator::Simulate_ZtS_Pg_ZnS_Xm},
{"stnt1w_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_Pg_ZnD_Xm},
{"stnt1w_z_p_ar_s_x32_unscaled", &Simulator::Simulate_ZtS_Pg_ZnS_Xm},
- {"subhnb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
- {"subhnt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
+ {"subhnb_z_zz", &Simulator::SimulateSVEAddSubHigh},
+ {"subhnt_z_zz", &Simulator::SimulateSVEAddSubHigh},
{"suqadd_z_p_zz", &Simulator::SimulateSVESaturatingArithmetic},
{"tbl_z_zz_2", &Simulator::Simulate_ZdT_Zn1T_Zn2T_ZmT},
{"tbx_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
@@ -2575,30 +2575,12 @@
USE(zn);
switch (form_hash_) {
- case Hash("addhnb_z_zz"):
- VIXL_UNIMPLEMENTED();
- break;
- case Hash("addhnt_z_zz"):
- VIXL_UNIMPLEMENTED();
- break;
case Hash("pmullb_z_zz"):
VIXL_UNIMPLEMENTED();
break;
case Hash("pmullt_z_zz"):
VIXL_UNIMPLEMENTED();
break;
- case Hash("raddhnb_z_zz"):
- VIXL_UNIMPLEMENTED();
- break;
- case Hash("raddhnt_z_zz"):
- VIXL_UNIMPLEMENTED();
- break;
- case Hash("rsubhnb_z_zz"):
- VIXL_UNIMPLEMENTED();
- break;
- case Hash("rsubhnt_z_zz"):
- VIXL_UNIMPLEMENTED();
- break;
case Hash("smullb_z_zz"):
VIXL_UNIMPLEMENTED();
break;
@@ -2611,12 +2593,6 @@
case Hash("sqdmullt_z_zz"):
VIXL_UNIMPLEMENTED();
break;
- case Hash("subhnb_z_zz"):
- VIXL_UNIMPLEMENTED();
- break;
- case Hash("subhnt_z_zz"):
- VIXL_UNIMPLEMENTED();
- break;
case Hash("umullb_z_zz"):
VIXL_UNIMPLEMENTED();
break;
@@ -2628,6 +2604,60 @@
}
}
+void Simulator::SimulateSVEAddSubHigh(const Instruction* instr) {
+ SimVRegister& zd = ReadVRegister(instr->GetRd());
+ SimVRegister& zm = ReadVRegister(instr->GetRm());
+ SimVRegister& zn = ReadVRegister(instr->GetRn());
+ SimVRegister result;
+ bool top = false;
+
+ VectorFormat vform_src = instr->GetSVEVectorFormat();
+ if (vform_src == kFormatVnB) {
+ VIXL_UNIMPLEMENTED();
+ }
+ VectorFormat vform = VectorFormatHalfWidth(vform_src);
+
+ switch (form_hash_) {
+ case Hash("addhnt_z_zz"):
+ top = true;
+ VIXL_FALLTHROUGH();
+ case Hash("addhnb_z_zz"):
+ addhn(vform, result, zn, zm);
+ break;
+ case Hash("raddhnt_z_zz"):
+ top = true;
+ VIXL_FALLTHROUGH();
+ case Hash("raddhnb_z_zz"):
+ raddhn(vform, result, zn, zm);
+ break;
+ case Hash("rsubhnt_z_zz"):
+ top = true;
+ VIXL_FALLTHROUGH();
+ case Hash("rsubhnb_z_zz"):
+ rsubhn(vform, result, zn, zm);
+ break;
+ case Hash("subhnt_z_zz"):
+ top = true;
+ VIXL_FALLTHROUGH();
+ case Hash("subhnb_z_zz"):
+ subhn(vform, result, zn, zm);
+ break;
+ default:
+ VIXL_UNIMPLEMENTED();
+ }
+
+ if (top) {
+ // Keep even elements, replace odd elements with the results.
+ xtn(vform, zd, zd);
+ zip1(vform, zd, zd, result);
+ } else {
+ // Zero odd elements, replace even elements with the results.
+ SimVRegister zero;
+ zero.Clear();
+ zip1(vform, zd, result, zero);
+ }
+}
+
void Simulator::SimulateSVEShiftLeftImm(const Instruction* instr) {
SimVRegister& zd = ReadVRegister(instr->GetRd());
SimVRegister& zn = ReadVRegister(instr->GetRn());