summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorRyan Houdek <Sonicadvance1@Gmail.com>2013-10-08 10:16:42 +0000
committerRyan Houdek <Sonicadvance1@Gmail.com>2013-10-08 10:17:01 +0000
commit7dd8deecece2055500a207ea4fa0e573158dede5 (patch)
tree0a3ee3536b7a47b139ecc3ee8359ea9d224077a9 /Source/Core
parent4a0745799f4688c54764fe341cb362b85fd24e2a (diff)
[ARM] Update the ArmEmitter with a bunch of NEON emitters. This adds around 47 instruction emitters if I counted correctly. None well tested at this point. On going to add all the NEON emitters.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Common/Src/ArmEmitter.cpp569
-rw-r--r--Source/Core/Common/Src/ArmEmitter.h59
2 files changed, 550 insertions, 78 deletions
diff --git a/Source/Core/Common/Src/ArmEmitter.cpp b/Source/Core/Common/Src/ArmEmitter.cpp
index f7864c4978..c579306217 100644
--- a/Source/Core/Common/Src/ArmEmitter.cpp
+++ b/Source/Core/Common/Src/ArmEmitter.cpp
@@ -883,7 +883,7 @@ void ARMXEmitter::LDMFD(ARMReg dest, bool WriteBack, const int Regnum, ...)
WriteRegStoreOp(0x89, dest, WriteBack, RegList);
}
-ARMReg ARMXEmitter::SubBase(ARMReg Reg)
+ARMReg SubBase(ARMReg Reg)
{
if (Reg >= S0)
{
@@ -898,44 +898,7 @@ ARMReg ARMXEmitter::SubBase(ARMReg Reg)
return Reg;
}
-// Double/single, Neon
-extern const VFPEnc VFPOps[16][2] = {
- {{0xE0, 0xA0}, {0x20, 0xD1}}, // 0: VMLA
- {{0xE1, 0xA4}, { -1, -1}}, // 1: VNMLA
- {{0xE0, 0xA4}, {0x22, 0xD1}}, // 2: VMLS
- {{0xE1, 0xA0}, { -1, -1}}, // 3: VNMLS
- {{0xE3, 0xA0}, {0x20, 0xD0}}, // 4: VADD
- {{0xE3, 0xA4}, {0x22, 0xD0}}, // 5: VSUB
- {{0xE2, 0xA0}, {0x30, 0xD1}}, // 6: VMUL
- {{0xE2, 0xA4}, { -1, -1}}, // 7: VNMUL
- {{0xEB, 0xAC}, { -1 /* 0x3B */, -1 /* 0x70 */}}, // 8: VABS(Vn(0x0) used for encoding)
- {{0xE8, 0xA0}, { -1, -1}}, // 9: VDIV
- {{0xEB, 0xA4}, { -1 /* 0x3B */, -1 /* 0x78 */}}, // 10: VNEG(Vn(0x1) used for encoding)
- {{0xEB, 0xAC}, { -1, -1}}, // 11: VSQRT (Vn(0x1) used for encoding)
- {{0xEB, 0xA4}, { -1, -1}}, // 12: VCMP (Vn(0x4 | #0 ? 1 : 0) used for encoding)
- {{0xEB, 0xAC}, { -1, -1}}, // 13: VCMPE (Vn(0x4 | #0 ? 1 : 0) used for encoding)
- {{ -1, -1}, {0x3B, 0x30}}, // 14: VABSi
- };
-
-const char *VFPOpNames[16] = {
- "VMLA",
- "VNMLA",
- "VMLS",
- "VNMLS",
- "VADD",
- "VSUB",
- "VMUL",
- "VNMUL",
- "VABS",
- "VDIV",
- "VNEG",
- "VSQRT",
- "VCMP",
- "VCMPE",
- "VABSi",
-};
-
-u32 ARMXEmitter::EncodeVd(ARMReg Vd)
+u32 EncodeVd(ARMReg Vd)
{
bool quad_reg = Vd >= Q0;
bool double_reg = Vd >= D0;
@@ -950,7 +913,7 @@ u32 ARMXEmitter::EncodeVd(ARMReg Vd)
else
return ((Reg & 0x1) << 22) | ((Reg & 0x1E) << 11);
}
-u32 ARMXEmitter::EncodeVn(ARMReg Vn)
+u32 EncodeVn(ARMReg Vn)
{
bool quad_reg = Vn >= Q0;
bool double_reg = Vn >= D0;
@@ -964,7 +927,7 @@ u32 ARMXEmitter::EncodeVn(ARMReg Vn)
else
return ((Reg & 0x1E) << 15) | ((Reg & 0x1) << 7);
}
-u32 ARMXEmitter::EncodeVm(ARMReg Vm)
+u32 EncodeVm(ARMReg Vm)
{
bool quad_reg = Vm >= Q0;
bool double_reg = Vm >= D0;
@@ -980,6 +943,43 @@ u32 ARMXEmitter::EncodeVm(ARMReg Vm)
return ((Reg & 0x1) << 5) | (Reg >> 1);
}
+// Double/single, Neon
+extern const VFPEnc VFPOps[16][2] = {
+ {{0xE0, 0xA0}, {0x20, 0xD1}}, // 0: VMLA
+ {{0xE1, 0xA4}, { -1, -1}}, // 1: VNMLA
+ {{0xE0, 0xA4}, {0x22, 0xD1}}, // 2: VMLS
+ {{0xE1, 0xA0}, { -1, -1}}, // 3: VNMLS
+ {{0xE3, 0xA0}, {0x20, 0xD0}}, // 4: VADD
+ {{0xE3, 0xA4}, {0x22, 0xD0}}, // 5: VSUB
+ {{0xE2, 0xA0}, {0x30, 0xD1}}, // 6: VMUL
+ {{0xE2, 0xA4}, { -1, -1}}, // 7: VNMUL
+ {{0xEB, 0xAC}, { -1 /* 0x3B */, -1 /* 0x70 */}}, // 8: VABS(Vn(0x0) used for encoding)
+ {{0xE8, 0xA0}, { -1, -1}}, // 9: VDIV
+ {{0xEB, 0xA4}, { -1 /* 0x3B */, -1 /* 0x78 */}}, // 10: VNEG(Vn(0x1) used for encoding)
+ {{0xEB, 0xAC}, { -1, -1}}, // 11: VSQRT (Vn(0x1) used for encoding)
+ {{0xEB, 0xA4}, { -1, -1}}, // 12: VCMP (Vn(0x4 | #0 ? 1 : 0) used for encoding)
+ {{0xEB, 0xAC}, { -1, -1}}, // 13: VCMPE (Vn(0x4 | #0 ? 1 : 0) used for encoding)
+ {{ -1, -1}, {0x3B, 0x30}}, // 14: VABSi
+ };
+
+const char *VFPOpNames[16] = {
+ "VMLA",
+ "VNMLA",
+ "VMLS",
+ "VNMLS",
+ "VADD",
+ "VSUB",
+ "VMUL",
+ "VNMUL",
+ "VABS",
+ "VDIV",
+ "VNEG",
+ "VSQRT",
+ "VCMP",
+ "VCMPE",
+ "VABSi",
+};
+
void ARMXEmitter::WriteVFPDataOp(u32 Op, ARMReg Vd, ARMReg Vn, ARMReg Vm)
{
bool quad_reg = Vd >= Q0;
@@ -1244,38 +1244,480 @@ void ARMXEmitter::VCVT(ARMReg Dest, ARMReg Source, int flags)
}
}
+void NEONXEmitter::VABA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+ bool register_quad = Vd >= Q0;
+
+ Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | EncodeVn(Vn) \
+ | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x71 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+
+void NEONXEmitter::VABAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, Vn >= D0 && Vn < Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, Vm >= D0 && Vm < Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+
+ Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (1 << 23) | EncodeVn(Vn) \
+ | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x50 << 4) | EncodeVm(Vm));
+}
+
void NEONXEmitter::VABD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
{
- _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to VABD(float)");
- _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use VABD(float) when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
bool register_quad = Vd >= Q0;
- // Gets encoded as a double register
- Vd = SubBase(Vd);
- Vn = SubBase(Vn);
- Vm = SubBase(Vm);
+ if (Size & F_32)
+ Write32((0xF3 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | (0xD << 8) | EncodeVm(Vm));
+ else
+ Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | EncodeVn(Vn) \
+ | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x70 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
- Write32((0xF3 << 24) | ((Vd & 0x10) << 18) | (encodedSize(Size) << 20) | ((Vn & 0xF) << 16) \
- | ((Vd & 0xF) << 12) | (0xD << 8) | ((Vn & 0x10) << 3) | (register_quad << 6) \
- | ((Vm & 0x10) << 1) | (Vm & 0xF));
+void NEONXEmitter::VABDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, Vn >= D0 && Vn < Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, Vm >= D0 && Vm < Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+
+ Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (1 << 23) | EncodeVn(Vn) \
+ | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x70 << 4) | EncodeVm(Vm));
}
+
+void NEONXEmitter::VABS(NEONElementType Size, ARMReg Vd, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ bool register_quad = Vd >= Q0;
+
+ Write32((0xF3 << 24) | (0xB1 << 16) | (encodedSize(Size) << 18) | EncodeVd(Vd) \
+ | ((Size & F_32 ? 1 : 0) << 10) | (0x30 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+
+void NEONXEmitter::VACGE(ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ // Only Float
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ bool register_quad = Vd >= Q0;
+
+ Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) \
+ | (0xD1 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+
+void NEONXEmitter::VACGT(ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ // Only Float
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ bool register_quad = Vd >= Q0;
+
+ Write32((0xF3 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) \
+ | (0xD1 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+
+void NEONXEmitter::VACLE(ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ VACGE(Vd, Vm, Vn);
+}
+
+void NEONXEmitter::VACLT(ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ VACGT(Vd, Vn, Vm);
+}
+
void NEONXEmitter::VADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
{
- _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to VADD(integer)");
- _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use VADD(integer) when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
bool register_quad = Vd >= Q0;
- // Gets encoded as a double register
+ if (Size & F_32)
+ Write32((0xF2 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xD0 << 4) | (register_quad << 6) | EncodeVm(Vm));
+ else
+ Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) \
+ | (0x8 << 8) | (register_quad << 6) | EncodeVm(Vm));
+}
+
+void NEONXEmitter::VADDHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd < Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, Vn >= Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, Vm >= Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+
+ Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) \
+ | EncodeVd(Vd) | (0x80 << 4) | EncodeVm(Vm));
+}
+
+void NEONXEmitter::VADDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, Vn >= D0 && Vn < Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, Vm >= D0 && Vm < Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+
+ Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) \
+ | EncodeVd(Vd) | EncodeVm(Vm));
+}
+void NEONXEmitter::VADDW(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, Vn >= Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, Vm >= D0 && Vm < Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+
+ Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) \
+ | EncodeVd(Vd) | (1 << 8) | EncodeVm(Vm));
+}
+void NEONXEmitter::VAND(ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+ bool register_quad = Vd >= Q0;
+
+ Write32((0xF2 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VBIC(ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+ bool register_quad = Vd >= Q0;
+
+ Write32((0xF2 << 24) | (1 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VBIF(ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+ bool register_quad = Vd >= Q0;
+
+ Write32((0xF3 << 24) | (3 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VBIT(ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+ bool register_quad = Vd >= Q0;
+
+ Write32((0xF3 << 24) | (2 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VBSL(ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+ bool register_quad = Vd >= Q0;
+
+ Write32((0xF3 << 24) | (1 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+ if (Size & F_32)
+ Write32((0xF2 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xE0 << 4) | (register_quad << 6) | EncodeVm(Vm));
+ else
+ Write32((0xF3 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) \
+ | (0x81 << 4) | (register_quad << 6) | EncodeVm(Vm));
+
+}
+void NEONXEmitter::VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+
+ Write32((0xF2 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 16) \
+ | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (0x10 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+ if (Size & F_32)
+ Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xE0 << 4) | (register_quad << 6) | EncodeVm(Vm));
+ else
+ Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) \
+ | (0x31 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+ Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 16) \
+ | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (0x8 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+ if (Size & F_32)
+ Write32((0xF3 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | (0xE0 << 4) | (register_quad << 6) | EncodeVm(Vm));
+ else
+ Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) \
+ | (0x30 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+ Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) | (1 << 16) \
+ | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VCLE(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ VCGE(Size, Vd, Vm, Vn);
+}
+void NEONXEmitter::VCLE(NEONElementType Size, ARMReg Vd, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+ Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) | (1 << 16) \
+ | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (3 << 7) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VCLS(NEONElementType Size, ARMReg Vd, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+
+ bool register_quad = Vd >= Q0;
+ Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) \
+ | EncodeVd(Vd) | (1 << 10) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VCLT(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ VCGT(Size, Vd, Vm, Vn);
+}
+void NEONXEmitter::VCLT(NEONElementType Size, ARMReg Vd, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+ Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) | (1 << 16) \
+ | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (0x20 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VCLZ(NEONElementType Size, ARMReg Vd, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+ Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) \
+ | EncodeVd(Vd) | (0x48 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VCNT(NEONElementType Size, ARMReg Vd, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, Size & I_8, "Can only use I_8 with " __FUNCTION__);
+
+ bool register_quad = Vd >= Q0;
+ Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) \
+ | EncodeVd(Vd) | (0x90 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VDUP(NEONElementType Size, ARMReg Vd, ARMReg Vm, u8 index)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+ u32 sizeEncoded = 0, indexEncoded = 0;
+ if (Size & I_8)
+ sizeEncoded = 1;
+ else if (Size & I_16)
+ sizeEncoded = 2;
+ else if (Size & I_32)
+ sizeEncoded = 4;
+ if (Size & I_8)
+ indexEncoded <<= 1;
+ else if (Size & I_16)
+ indexEncoded <<= 2;
+ else if (Size & I_32)
+ indexEncoded <<= 3;
+ Write32((0xF3 << 24) | (0xD << 20) | (sizeEncoded << 16) | (indexEncoded << 16) \
+ | EncodeVd(Vd) | (0xC0 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VDUP(NEONElementType Size, ARMReg Vd, ARMReg Rt)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, Rt < D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
Vd = SubBase(Vd);
- Vn = SubBase(Vn);
- Vm = SubBase(Vm);
+ u8 sizeEncoded = 0;
+ if (Size & I_8)
+ sizeEncoded = 2;
+ else if (Size & I_16)
+ sizeEncoded = 1;
+ else if (Size & I_32)
+ sizeEncoded = 0;
- Write32((0xF2 << 24) | ((Vd & 0x10) << 18) | (encodedSize(Size) << 20) | ((Vn & 0xF) << 16) \
- | ((Vd & 0xF) << 12) | (0x8 << 8) | ((Vn & 0x10) << 3) | (register_quad << 6) \
- | ((Vm & 0x10) << 1) | (Vm & 0xF));
+ Write32((0xEE << 24) | (0x8 << 20) | ((sizeEncoded & 2) << 21) | (register_quad << 21) \
+ | ((Vd & 0xF) << 16) | (Rt << 12) | (0xD1 << 4) | ((Vd & 0x10) << 3) | (1 << 4));
+}
+void NEONXEmitter::VEOR(ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ bool register_quad = Vd >= Q0;
+
+ Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VEXT(ARMReg Vd, ARMReg Vn, ARMReg Vm, u8 index)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ bool register_quad = Vd >= Q0;
+
+ Write32((0xF2 << 24) | (0xB << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (index & 0xF) \
+ | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VFMA(ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bVFPv4, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ bool register_quad = Vd >= Q0;
+
+ Write32((0xF2 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xC1 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VFMS(ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bVFPv4, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ bool register_quad = Vd >= Q0;
+ Write32((0xF2 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | (0xC1 << 4) | (register_quad << 6) | EncodeVm(Vm));
}
+void NEONXEmitter::VHADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+
+ bool register_quad = Vd >= Q0;
+
+ Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \
+ | EncodeVn(Vn) | EncodeVd(Vd) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VHSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+
+ bool register_quad = Vd >= Q0;
+
+ Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \
+ | EncodeVn(Vn) | EncodeVd(Vd) | (1 << 9) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VMAX(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+
+ if (Size & F_32)
+ Write32((0xF2 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xF0 << 4) | (register_quad << 6) | EncodeVm(Vm));
+ else
+ Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \
+ | EncodeVn(Vn) | EncodeVd(Vd) | (0x60 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VMIN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+
+ if (Size & F_32)
+ Write32((0xF2 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | (0xF0 << 4) | (register_quad << 6) | EncodeVm(Vm));
+ else
+ Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \
+ | EncodeVn(Vn) | EncodeVd(Vd) | (0x61 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VMLA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+
+ if (Size & F_32)
+ Write32((0xF2 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xD1 << 4) | (register_quad << 6) | EncodeVm(Vm));
+ else
+ Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x90 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VMLS(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+
+ if (Size & F_32)
+ Write32((0xF2 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | (0xD1 << 4) | (register_quad << 6) | EncodeVm(Vm));
+ else
+ Write32((0xF2 << 24) | (1 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x90 << 4) | (register_quad << 6) | EncodeVm(Vm));
+}
+void NEONXEmitter::VMLAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, Vn >= Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, Vm >= D0 && Vm < Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+
+ Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) \
+ | EncodeVn(Vn) | EncodeVd(Vd) | (0x80 << 4) | EncodeVm(Vm));
+}
+void NEONXEmitter::VMLSL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, Vn >= Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, Vm >= D0 && Vm < Q0, "Pass invalid register to " __FUNCTION__);
+ _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it");
+ _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float.");
+
+ Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) \
+ | EncodeVn(Vn) | EncodeVd(Vd) | (0xA0 << 4) | EncodeVm(Vm));
+}
+
void NEONXEmitter::VSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
{
_dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to VSUB(integer)");
@@ -1362,17 +1804,6 @@ void NEONXEmitter::VRSQRTE(NEONElementType Size, ARMReg Vd, ARMReg Vm)
| ((Vm & 0x10) << 1) | (Vm & 0xF));
}
-void NEONXEmitter::VEOR(ARMReg Vd, ARMReg Vn, ARMReg Vm)
-{
- bool register_quad = Vd >= Q0;
- Vd = SubBase(Vd);
- Vn = SubBase(Vn);
- Vm = SubBase(Vm);
-
- Write32((0xF3 << 24) | ((Vd & 0x10) << 18) | ((Vn & 0xF) << 16)
- | ((Vd & 0xF) << 12) | (1 << 8) | ((Vn & 0x10) << 3)
- | (register_quad << 6) | ((Vm & 0x10) << 1) | (1 << 4) | (Vm & 0xF));
-}
void NEONXEmitter::VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm)
{
bool register_quad = Vd >= Q0;
diff --git a/Source/Core/Common/Src/ArmEmitter.h b/Source/Core/Common/Src/ArmEmitter.h
index 71597bbfd6..2d21743a10 100644
--- a/Source/Core/Common/Src/ArmEmitter.h
+++ b/Source/Core/Common/Src/ArmEmitter.h
@@ -339,6 +339,12 @@ struct LiteralPool
typedef const u8* JumpTarget;
+u32 EncodeVd(ARMReg Vd);
+u32 EncodeVn(ARMReg Vn);
+u32 EncodeVm(ARMReg Vm);
+// Subtracts the base from the register to give us the real one
+ARMReg SubBase(ARMReg Reg);
+
class ARMXEmitter
{
friend struct OpArg; // for Write8 etc
@@ -355,9 +361,6 @@ private:
void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2);
void WriteSignedMultiply(u32 Op, u32 Op2, u32 Op3, ARMReg dest, ARMReg r1, ARMReg r2);
- u32 EncodeVd(ARMReg Vd);
- u32 EncodeVn(ARMReg Vn);
- u32 EncodeVm(ARMReg Vm);
void WriteVFPDataOp(u32 Op, ARMReg Vd, ARMReg Vn, ARMReg Vm);
void WriteVFPDataOp6bit(u32 Op, ARMReg Vd, ARMReg Vn, ARMReg Vm, u32 bit6);
@@ -530,9 +533,6 @@ public:
// None of these will be created with conditional since ARM
// is deprecating conditional execution of ASIMD instructions.
// ASIMD instructions don't even have a conditional encoding.
-
- // Subtracts the base from the register to give us the real one
- ARMReg SubBase(ARMReg Reg);
// VFP Only
void VLDR(ARMReg Dest, ARMReg Base, s16 offset);
@@ -603,7 +603,6 @@ class NEONXEmitter
{
private:
ARMXEmitter *_emit;
- ARMReg SubBase(ARMReg Reg) { return _emit->SubBase(Reg); }
inline void Write32(u32 value) { _emit->Write32(value); }
inline u32 encodedSize(u32 value)
@@ -612,7 +611,7 @@ private:
return 0;
else if (value & I_16)
return 1;
- else if (value & I_32)
+ else if ((value & I_32) || (value & F_32))
return 2;
else if (value & I_64)
return 3;
@@ -628,8 +627,51 @@ public:
: _emit(emit)
{}
+ void VABA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VABAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VABD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VABDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VABS(NEONElementType Size, ARMReg Vd, ARMReg Vm);
+ void VACGE(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VACGT(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VACLE(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VACLT(ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VADDHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VADDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VADDW(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VAND(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VBIC(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VBIF(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VBIT(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VBSL(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vm);
+ void VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vm);
+ void VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vm);
+ void VCLE(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VCLE(NEONElementType Size, ARMReg Vd, ARMReg Vm);
+ void VCLS(NEONElementType Size, ARMReg Vd, ARMReg Vm);
+ void VCLT(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VCLT(NEONElementType Size, ARMReg Vd, ARMReg Vm);
+ void VCLZ(NEONElementType Size, ARMReg Vd, ARMReg Vm);
+ void VCNT(NEONElementType Size, ARMReg Vd, ARMReg Vm);
+ void VDUP(NEONElementType Size, ARMReg Vd, ARMReg Vm, u8 index);
+ void VDUP(NEONElementType Size, ARMReg Vd, ARMReg Rt);
+ void VEOR(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VEXT(ARMReg Vd, ARMReg Vn, ARMReg Vm, u8 index);
+ void VFMA(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VFMS(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VHADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VHSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VMAX(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VMIN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VMLA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VMLS(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VMLAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VMLSL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VREV64(NEONElementType Size, ARMReg Vd, ARMReg Vm);
void VREV32(NEONElementType Size, ARMReg Vd, ARMReg Vm);
@@ -637,7 +679,6 @@ public:
void VRSQRTE(NEONElementType Size, ARMReg Vd, ARMReg Vm);
- void VEOR(ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VLD1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC);