From a1ec735f6c1902ecddfa05eaf4123f5d6e1097f4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 26 Jan 2017 14:22:51 +0100 Subject: [PATCH] ARM64Emitter: Implement instructions to move data to/from SP --- Common/Arm64Emitter.cpp | 9 +++++++++ Common/Arm64Emitter.h | 4 ++++ Common/x64Emitter.h | 2 +- Core/MemMap.cpp | 1 + Core/Util/DisArm64.cpp | 6 +++++- unittest/TestArm64Emitter.cpp | 5 +++++ 6 files changed, 25 insertions(+), 2 deletions(-) diff --git a/Common/Arm64Emitter.cpp b/Common/Arm64Emitter.cpp index 4b4dbaefda..a8c7984584 100644 --- a/Common/Arm64Emitter.cpp +++ b/Common/Arm64Emitter.cpp @@ -1464,6 +1464,15 @@ void ARM64XEmitter::MOV(ARM64Reg Rd, ARM64Reg Rm) _assert_msg_(JIT, false, "Non-GPRs not supported in MOV"); } } + +void ARM64XEmitter::MOVfromSP(ARM64Reg Rd) { + ADD(Rd, ARM64Reg::SP, 0, false); +} + +void ARM64XEmitter::MOVtoSP(ARM64Reg Rn) { + ADD(ARM64Reg::SP, Rn, 0, false); +} + void ARM64XEmitter::MVN(ARM64Reg Rd, ARM64Reg Rm) { ORN(Rd, Is64Bit(Rd) ? ZR : WZR, Rm, ArithOption(Rm, ST_LSL, 0)); diff --git a/Common/Arm64Emitter.h b/Common/Arm64Emitter.h index fc1814bae0..df4c78f3d8 100644 --- a/Common/Arm64Emitter.h +++ b/Common/Arm64Emitter.h @@ -566,6 +566,10 @@ public: void MOV(ARM64Reg Rd, ARM64Reg Rm); void MVN(ARM64Reg Rd, ARM64Reg Rm); + // Wrapper around ADD reg, reg, imm. + void MOVfromSP(ARM64Reg Rd); + void MOVtoSP(ARM64Reg Rn); + // TODO: These are "slow" as they use arith+shift, should be replaced with UBFM/EXTR variants. void LSR(ARM64Reg Rd, ARM64Reg Rm, int shift); void LSL(ARM64Reg Rd, ARM64Reg Rm, int shift); diff --git a/Common/x64Emitter.h b/Common/x64Emitter.h index 056500775a..38dfe9c586 100644 --- a/Common/x64Emitter.h +++ b/Common/x64Emitter.h @@ -391,6 +391,7 @@ public: // INC and DEC are slow on Intel Core, but not on AMD. They create a // false flag dependency because they only update a subset of the flags. // XCHG is SLOW and should be avoided. + // Actually, REP MOVSB has gotten fast again on recent CPU generations, though it's not all that useful anyway. // Debug breakpoint void INT3(); @@ -410,7 +411,6 @@ public: void LAHF(); // 3 cycle vector path void SAHF(); // direct path fast - // Stack control void PUSH(X64Reg reg); void POP(X64Reg reg); diff --git a/Core/MemMap.cpp b/Core/MemMap.cpp index 26125c0874..be7e7d0e57 100644 --- a/Core/MemMap.cpp +++ b/Core/MemMap.cpp @@ -253,6 +253,7 @@ void MemoryMap_Shutdown(u32 flags) { void Init() { // On some 32 bit platforms, you can only map < 32 megs at a time. + // TODO: Wait, wtf? What platforms are those? This seems bad. const static int MAX_MMAP_SIZE = 31 * 1024 * 1024; _dbg_assert_msg_(MEMMAP, g_MemorySize < MAX_MMAP_SIZE * 3, "ACK - too much memory for three mmap views."); for (size_t i = 0; i < ARRAY_SIZE(views); i++) { diff --git a/Core/Util/DisArm64.cpp b/Core/Util/DisArm64.cpp index dc4ca3e80d..fd17c54412 100644 --- a/Core/Util/DisArm64.cpp +++ b/Core/Util/DisArm64.cpp @@ -159,11 +159,15 @@ static void DataProcessingImmediate(uint32_t w, uint64_t addr, Instruction *inst // Add/subtract immediate value int op = (w >> 30) & 1; int imm = ((w >> 10) & 0xFFF); - int shift = ((w >> 22) & 0x3) * 16; + int shift = ((w >> 22) & 0x1) * 12; int s = ((w >> 29) & 1); imm <<= shift; if (s && Rd == 31) { snprintf(instr->text, sizeof(instr->text), "cmp %c%d, #%d", r, Rn, imm); + } else if (!shift && Rn == 31 && imm == 0) { + snprintf(instr->text, sizeof(instr->text), "mov %c%d, sp", r, Rd); + } else if (!shift && Rd == 31 && imm == 0) { + snprintf(instr->text, sizeof(instr->text), "mov sp, %c%d", r, Rn); } else { snprintf(instr->text, sizeof(instr->text), "%s%s %c%d, %c%d, #%d", op == 0 ? "add" : "sub", s ? "s" : "", r, Rd, r, Rn, imm); } diff --git a/unittest/TestArm64Emitter.cpp b/unittest/TestArm64Emitter.cpp index 6aea74f0dc..2efeb77847 100644 --- a/unittest/TestArm64Emitter.cpp +++ b/unittest/TestArm64Emitter.cpp @@ -41,6 +41,11 @@ bool TestArm64Emitter() { ARM64XEmitter emitter((u8 *)code); ARM64FloatEmitter fp(&emitter); + emitter.MOVfromSP(X3); + RET(CheckLast(emitter, "910003e3 mov x3, sp")); + emitter.MOVtoSP(X11); + RET(CheckLast(emitter, "9100017f mov sp, x11")); + fp.EOR(Q0, Q1, Q2); RET(CheckLast(emitter, "6e221c20 eor q0, q1, q2")); fp.EOR(D0, D1, D2);