diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp index 7583ef0fc3..00c58a0fbc 100644 --- a/Source/Core/Common/Src/x64Emitter.cpp +++ b/Source/Core/Common/Src/x64Emitter.cpp @@ -867,6 +867,69 @@ void XEmitter::BTS(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, void XEmitter::BTR(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 6);} void XEmitter::BTC(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 7);} +//shift can be either imm8 or cl +void XEmitter::SHRD(int bits, OpArg dest, OpArg src, OpArg shift) +{ + bool writeImm = false; + if (dest.IsImm()) + { + _assert_msg_(DYNA_REC, 0, "SHRD - can't use imms as destination"); + } + if (!src.IsSimpleReg()) + { + _assert_msg_(DYNA_REC, 0, "SHRD - must use simple register as source"); + } + if ((shift.IsSimpleReg() && shift.GetSimpleReg() != ECX) || (shift.IsImm() && shift.GetImmBits() != 8)) + { + _assert_msg_(DYNA_REC, 0, "SHRD - illegal shift"); + } + if (bits == 16) Write8(0x66); + X64Reg operand = src.GetSimpleReg(); + dest.WriteRex(this, bits, bits, operand); + if (shift.GetImmBits() == 8) + { + Write8(0x0F); Write8(0xAC); + dest.WriteRest(this, 1, operand); + Write8((u8)shift.offset); + } + else + { + Write8(0x0F); Write8(0xAD); + dest.WriteRest(this, 0, operand); + } +} + +void XEmitter::SHLD(int bits, OpArg dest, OpArg src, OpArg shift) +{ + bool writeImm = false; + if (dest.IsImm()) + { + _assert_msg_(DYNA_REC, 0, "SHLD - can't use imms as destination"); + } + if (!src.IsSimpleReg()) + { + _assert_msg_(DYNA_REC, 0, "SHLD - must use simple register as source"); + } + if ((shift.IsSimpleReg() && shift.GetSimpleReg() != ECX) || (shift.IsImm() && shift.GetImmBits() != 8)) + { + _assert_msg_(DYNA_REC, 0, "SHLD - illegal shift"); + } + if (bits == 16) Write8(0x66); + X64Reg operand = src.GetSimpleReg(); + dest.WriteRex(this, bits, bits, operand); + if (shift.GetImmBits() == 8) + { + Write8(0x0F); Write8(0xA4); + dest.WriteRest(this, 1, operand); + Write8((u8)shift.offset); + } + else + { + Write8(0x0F); Write8(0xA5); + dest.WriteRest(this, 0, operand); + } +} + void OpArg::WriteSingleByteOp(XEmitter *emit, u8 op, X64Reg _operandReg, int bits) { if (bits == 16) diff --git a/Source/Core/Common/Src/x64Emitter.h b/Source/Core/Common/Src/x64Emitter.h index 6bd9291eea..3b699c81a0 100644 --- a/Source/Core/Common/Src/x64Emitter.h +++ b/Source/Core/Common/Src/x64Emitter.h @@ -381,6 +381,10 @@ public: void BTR(int bits, OpArg dest, OpArg index); void BTC(int bits, OpArg dest, OpArg index); + // Double-Precision Shift + void SHRD(int bits, OpArg dest, OpArg src, OpArg shift); + void SHLD(int bits, OpArg dest, OpArg src, OpArg shift); + // Extend EAX into EDX in various ways void CWD(int bits = 16); inline void CDQ() {CWD(32);} diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp index 8df9853781..21ae8908c8 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp @@ -1758,10 +1758,9 @@ void Jit64::srawx(UGeckoInstruction inst) MOV(32, gpr.R(a), gpr.R(s)); TEST(32, R(ECX), Imm32(32)); FixupBranch topBitSet = J_CC(CC_NZ); - LEA(32, EAX, MComplex(gpr.RX(a), gpr.RX(a), 1, 0)); + XOR(32, R(EAX), R(EAX)); + SHRD(32, R(EAX), gpr.R(a), R(ECX)); SAR(32, gpr.R(a), R(ECX)); - NOT(32, R(ECX)); - SHL(32, R(EAX), R(ECX)); TEST(32, R(EAX), gpr.R(a)); FixupBranch nocarry1 = J_CC(CC_Z); JitSetCA();