diff options
| author | Ryan Houdek <Sonicadvance1@Gmail.com> | 2013-09-08 21:49:56 +0000 |
|---|---|---|
| committer | Ryan Houdek <Sonicadvance1@Gmail.com> | 2013-09-08 21:56:17 +0000 |
| commit | c1aa80cefa0df06e858a5efe1e0084534ba683d7 (patch) | |
| tree | dc4ce2e65fc234da651ea2c0fc6a95ffe267b9e0 /Source | |
| parent | f382a5350062cc04f1b31f950fa9f53ea8b71bcb (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.cpp | 32 | ||||
| -rw-r--r-- | Source/Core/Common/Src/ArmEmitter.h | 4 |
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. |
