summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorRyan Houdek <Sonicadvance1@gmail.com>2015-02-12 18:47:06 -0600
committerRyan Houdek <Sonicadvance1@gmail.com>2015-02-13 12:16:06 -0600
commit814aaaf5381e79230beedc3a76a14ae2baf17857 (patch)
tree9e47c93e6247425c4a6228a1fac08135645522b0 /Source/Core
parent0252bbb33f6288c74466c364e50fb77b0afed273 (diff)
[AArch64] Implement a couple of emitter instructions.
These will be used with the vertex loader JIT recompiler.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Common/Arm64Emitter.cpp52
-rw-r--r--Source/Core/Common/Arm64Emitter.h10
2 files changed, 60 insertions, 2 deletions
diff --git a/Source/Core/Common/Arm64Emitter.cpp b/Source/Core/Common/Arm64Emitter.cpp
index 57ad0b3215..741bdf8620 100644
--- a/Source/Core/Common/Arm64Emitter.cpp
+++ b/Source/Core/Common/Arm64Emitter.cpp
@@ -1006,6 +1006,10 @@ void ARM64XEmitter::SMADDL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra)
{
EncodeData3SrcInst(2, Rd, Rn, Rm, Ra);
}
+void ARM64XEmitter::SMULL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
+{
+ SMADDL(Rd, Rn, Rm, SP);
+}
void ARM64XEmitter::SMSUBL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra)
{
EncodeData3SrcInst(3, Rd, Rn, Rm, Ra);
@@ -1850,6 +1854,18 @@ void ARM64FloatEmitter::EmitScalar1Source(bool M, bool S, u32 type, u32 opcode,
(opcode << 15) | (1 << 14) | (Rn << 5) | Rd);
}
+void ARM64FloatEmitter::EmitVectorxElement(bool U, u32 size, bool L, u32 opcode, bool H, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
+{
+ bool quad = IsQuad(Rd);
+
+ Rd = DecodeReg(Rd);
+ Rn = DecodeReg(Rn);
+ Rm = DecodeReg(Rm);
+
+ Write32((quad << 30) | (U << 29) | (0b01111 << 24) | (size << 22) | (L << 21) | \
+ (Rm << 16) | (opcode << 12) | (H << 11) | (Rn << 5) | Rd);
+}
+
void ARM64FloatEmitter::LDR(u8 size, IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
{
EmitLoadStoreImmediate(size, 1, type, Rt, Rn, imm);
@@ -2092,6 +2108,21 @@ void ARM64FloatEmitter::LD1(u8 size, u8 count, ARM64Reg Rt, ARM64Reg Rn)
opcode = 0b0010;
EmitLoadStoreMultipleStructure(size, 1, opcode, Rt, Rn);
}
+void ARM64FloatEmitter::ST1(u8 size, u8 count, ARM64Reg Rt, ARM64Reg Rn)
+{
+ _assert_msg_(DYNA_REC, !(count == 0 || count > 4), "%s must have a count of 1 to 4 registers!", __FUNCTION__);
+ u32 opcode = 0;
+ if (count == 1)
+ opcode = 0b111;
+ else if (count == 2)
+ opcode = 0b1010;
+ else if (count == 3)
+ opcode = 0b0110;
+ else if (count == 4)
+ opcode = 0b0010;
+ EmitLoadStoreMultipleStructure(size, 0, opcode, Rt, Rn);
+}
+
// Scalar - 1 Source
void ARM64FloatEmitter::FABS(ARM64Reg Rd, ARM64Reg Rn)
{
@@ -2581,6 +2612,27 @@ void ARM64FloatEmitter::UXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn)
USHLL(src_size, Rd, Rn, 0);
}
+// vector x indexed element
+void ARM64FloatEmitter::FMUL(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u8 index)
+{
+ _assert_msg_(DYNA_REC, size == 32 || size == 64, "%s only supports 32bit or 64bit size!", __FUNCTION__);
+
+ bool L = false;
+ bool H = false;
+
+ if (size == 32)
+ {
+ L = index & 1;
+ H = (index >> 1) & 1;
+ }
+ else if (size == 64)
+ {
+ H = index == 1;
+ }
+
+ EmitVectorxElement(0, 2 | (size >> 6), L, 0b1001, H, Rd, Rn, Rm);
+}
+
void ARM64FloatEmitter::ABI_PushRegisters(BitSet32 registers)
{
for (auto it : registers)
diff --git a/Source/Core/Common/Arm64Emitter.h b/Source/Core/Common/Arm64Emitter.h
index b94e306612..7bcbe4a45a 100644
--- a/Source/Core/Common/Arm64Emitter.h
+++ b/Source/Core/Common/Arm64Emitter.h
@@ -78,8 +78,8 @@ enum ARM64Reg
};
inline bool Is64Bit(ARM64Reg reg) { return reg & 0x20; }
-inline bool IsSingle(ARM64Reg reg) { return reg & 0x40; }
-inline bool IsDouble(ARM64Reg reg) { return reg & 0x80; }
+inline bool IsSingle(ARM64Reg reg) { return (reg & 0xC0) == 0x40; }
+inline bool IsDouble(ARM64Reg reg) { return (reg & 0xC0) == 0x80; }
inline bool IsQuad(ARM64Reg reg) { return (reg & 0xC0) == 0xC0; }
inline bool IsVector(ARM64Reg reg) { return (reg & 0xC0) != 0; }
inline ARM64Reg DecodeReg(ARM64Reg reg) { return (ARM64Reg)(reg & 0x1F); }
@@ -479,6 +479,7 @@ public:
void MADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra);
void MSUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra);
void SMADDL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra);
+ void SMULL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
void SMSUBL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra);
void SMULH(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
void UMADDL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra);
@@ -641,6 +642,7 @@ public:
// Loadstore multiple structure
void LD1(u8 size, u8 count, ARM64Reg Rt, ARM64Reg Rn);
+ void ST1(u8 size, u8 count, ARM64Reg Rt, ARM64Reg Rn);
// Scalar - 1 Source
void FABS(ARM64Reg Rd, ARM64Reg Rn);
@@ -725,6 +727,9 @@ public:
void SXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn);
void UXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn);
+ // vector x indexed element
+ void FMUL(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u8 index);
+
// ABI related
void ABI_PushRegisters(BitSet32 registers);
void ABI_PopRegisters(BitSet32 registers, BitSet32 ignore_mask = BitSet32(0));
@@ -750,6 +755,7 @@ private:
void EmitShiftImm(bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd, ARM64Reg Rn);
void EmitLoadStoreMultipleStructure(u32 size, bool L, u32 opcode, ARM64Reg Rt, ARM64Reg Rn);
void EmitScalar1Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn);
+ void EmitVectorxElement(bool U, u32 size, bool L, u32 opcode, bool H, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
};
class ARM64CodeBlock : public CodeBlock<ARM64XEmitter>