summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorRyan Houdek <Sonicadvance1@Gmail.com>2013-09-08 21:49:56 +0000
committerRyan Houdek <Sonicadvance1@Gmail.com>2013-09-08 21:56:17 +0000
commitc1aa80cefa0df06e858a5efe1e0084534ba683d7 (patch)
treedc4ce2e65fc234da651ea2c0fc6a95ffe267b9e0 /Source
parentf382a5350062cc04f1b31f950fa9f53ea8b71bcb (diff)
[ARM] Add support for double registers in VMOV(immediate). Add VEOR and VSTR1. Fix some minor encoding bugs.
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Common/Src/ArmEmitter.cpp32
-rw-r--r--Source/Core/Common/Src/ArmEmitter.h4
2 files changed, 32 insertions, 4 deletions
diff --git a/Source/Core/Common/Src/ArmEmitter.cpp b/Source/Core/Common/Src/ArmEmitter.cpp
index e0f02244a8..70a165d114 100644
--- a/Source/Core/Common/Src/ArmEmitter.cpp
+++ b/Source/Core/Common/Src/ArmEmitter.cpp
@@ -1077,7 +1077,8 @@ void ARMXEmitter::VMSR(ARMReg Rt) {
void ARMXEmitter::VMOV(ARMReg Dest, Operand2 op2)
{
_dbg_assert_msg_(DYNA_REC, cpu_info.bVFPv3, "VMOV #imm requires VFPv3");
- Write32(condition | (0xEB << 20) | EncodeVd(Dest) | (0xA << 8) | op2.Imm8VFP());
+ bool double_reg = Dest >= D0;
+ Write32(condition | (0xEB << 20) | EncodeVd(Dest) | (0x5 << 9) | (double_reg << 8) | op2.Imm8VFP());
}
void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src, bool high)
{
@@ -1234,7 +1235,7 @@ void NEONXEmitter::VABD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg 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) << 2) | (Vm & 0xF));
+ | ((Vm & 0x10) << 1) | (Vm & 0xF));
}
void NEONXEmitter::VADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
{
@@ -1265,7 +1266,7 @@ void NEONXEmitter::VSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
Write32((0xF3 << 24) | ((Vd & 0x10) << 18) | (encodedSize(Size) << 20) | ((Vn & 0xF) << 16) \
| ((Vd & 0xF) << 12) | (0x8 << 8) | ((Vn & 0x10) << 3) | (1 << 6) \
- | ((Vm & 0x10) << 2) | (Vm & 0xF));
+ | ((Vm & 0x10) << 1) | (Vm & 0xF));
}
void NEONXEmitter::VLD1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm)
@@ -1290,6 +1291,18 @@ void NEONXEmitter::VLD2(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignmen
| (align << 4) | Rm);
}
+void NEONXEmitter::VST1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm)
+{
+ u32 spacing = 0x7; // Single spaced registers
+ // Gets encoded as a double register
+ Vd = SubBase(Vd);
+
+ Write32((0xF4 << 24) | ((Vd & 0x10) << 18) | (Rn << 16)
+ | ((Vd & 0xF) << 12) | (spacing << 8) | (encodedSize(Size) << 6)
+ | (align << 4) | Rm);
+}
+
+
void NEONXEmitter::VREVX(u32 size, NEONElementType Size, ARMReg Vd, ARMReg Vm)
{
bool register_quad = Vd >= Q0;
@@ -1298,7 +1311,7 @@ void NEONXEmitter::VREVX(u32 size, NEONElementType Size, ARMReg Vd, ARMReg Vm)
Write32((0xF3 << 24) | (1 << 23) | ((Vd & 0x10) << 18) | (0x3 << 20)
| (encodedSize(Size) << 18) | ((Vd & 0xF) << 12) | (size << 7)
- | (register_quad << 6) | ((Vm & 0x10) << 2) | (Vm & 0xF));
+ | (register_quad << 6) | ((Vm & 0x10) << 1) | (Vm & 0xF));
}
void NEONXEmitter::VREV64(NEONElementType Size, ARMReg Vd, ARMReg Vm)
@@ -1316,5 +1329,16 @@ void NEONXEmitter::VREV16(NEONElementType Size, ARMReg Vd, ARMReg Vm)
VREVX(0, Size, Vd, Vm);
}
+void NEONXEmitter::VEOR(ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ bool register_quad = Vd >= Q0;
+ Vd = SubBase(Vd);
+ 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));
+}
+
}
diff --git a/Source/Core/Common/Src/ArmEmitter.h b/Source/Core/Common/Src/ArmEmitter.h
index 79121e832a..138780e836 100644
--- a/Source/Core/Common/Src/ArmEmitter.h
+++ b/Source/Core/Common/Src/ArmEmitter.h
@@ -630,8 +630,12 @@ public:
void VREV32(NEONElementType Size, ARMReg Vd, ARMReg Vm);
void VREV16(NEONElementType Size, ARMReg Vd, ARMReg Vm);
+ void VEOR(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+
void VLD1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC);
void VLD2(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC);
+
+ void VST1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC);
};
// Everything that needs to generate X86 code should inherit from this.