diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp index bfefa3e28f..1324cb7761 100644 --- a/Source/Core/Common/Src/x64Emitter.cpp +++ b/Source/Core/Common/Src/x64Emitter.cpp @@ -936,6 +936,64 @@ namespace Gen void CMP (int bits, const OpArg &a1, const OpArg &a2) {WriteNormalOp(bits, nrmCMP, a1, a2);} void XCHG(int bits, const OpArg &a1, const OpArg &a2) {WriteNormalOp(bits, nrmXCHG, a1, a2);} + void IMUL(int bits, X64Reg regOp, OpArg a1, OpArg a2) + { + if (bits == 8) { + _assert_msg_(DYNA_REC, 0, "IMUL - illegal bit size!"); + return; + } + if (a1.IsImm()) { + _assert_msg_(DYNA_REC, 0, "IMUL - second arg cannot be imm!"); + return; + } + if (!a2.IsImm()) + { + _assert_msg_(DYNA_REC, 0, "IMUL - third arg must be imm!"); + return; + } + + if (bits == 16) + Write8(0x66); + a1.WriteRex(bits == 64, regOp); + + if (a2.GetImmBits() == 8) { + Write8(0x6B); + a1.WriteRest(1, regOp); + Write8((u8)a2.offset); + } else { + Write8(0x69); + if (a2.GetImmBits() == 16 && bits == 16) { + a1.WriteRest(2, regOp); + Write16((u16)a2.offset); + } else if (a2.GetImmBits() == 32 && + (bits == 32 || bits == 64)) { + a1.WriteRest(4, regOp); + Write32((u32)a2.offset); + } else { + _assert_msg_(DYNA_REC, 0, "IMUL - unhandled case!"); + } + } + } + + void IMUL(int bits, X64Reg regOp, OpArg a) + { + if (bits == 8) { + _assert_msg_(DYNA_REC, 0, "IMUL - illegal bit size!"); + return; + } + if (a.IsImm()) + { + IMUL(bits, regOp, R(regOp), a) ; + return ; + } + + if (bits == 16) + Write8(0x66); + a.WriteRex(bits == 64, regOp); + Write8(0x0F); + Write8(0xAF); + a.WriteRest(0, regOp); + } void WriteSSEOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes = 0) diff --git a/Source/Core/Common/Src/x64Emitter.h b/Source/Core/Common/Src/x64Emitter.h index 5126aa1d66..b62b24f786 100644 --- a/Source/Core/Common/Src/x64Emitter.h +++ b/Source/Core/Common/Src/x64Emitter.h @@ -282,7 +282,9 @@ namespace Gen void DIV(int bits, OpArg src); void IMUL(int bits, OpArg src); //SIGNED void IDIV(int bits, OpArg src); - //TODO: alternate IMUL forms + void IMUL(int bits, X64Reg regOp, OpArg src); + void IMUL(int bits, X64Reg regOp, OpArg src, OpArg imm); + void NEG(int bits, OpArg src); void NOT(int bits, OpArg src); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp index cdccc5abf2..0bee529785 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp @@ -486,19 +486,11 @@ namespace Jit64 #endif INSTRUCTION_START; int a = inst.RA, d = inst.RD; - gpr.FlushLockX(EDX); - gpr.Lock(a, d); - if (d != a) { - gpr.LoadToX64(d, false, true); - } else { - gpr.LoadToX64(d, true, true); - } - MOV(32, R(EAX), gpr.R(a)); - MOV(32, R(EDX), Imm32((u32)(s32)inst.SIMM_16)); - IMUL(32, R(EDX)); - MOV(32, gpr.R(d), R(EAX)); - gpr.UnlockAll(); - gpr.UnlockAllX(); + gpr.Lock(a, d); + gpr.LoadToX64(d, (d == a), true); + gpr.KillImmediate(a); + IMUL(32, gpr.RX(d), gpr.R(a), Imm32((u32)(s32)inst.SIMM_16)); + gpr.UnlockAll(); } void mullwx(UGeckoInstruction inst) @@ -509,21 +501,19 @@ namespace Jit64 #endif INSTRUCTION_START; int a = inst.RA, b = inst.RB, d = inst.RD; - gpr.FlushLockX(EDX); - gpr.Lock(a, b, d); - if (d != a && d != b) { - gpr.LoadToX64(d, false, true); + gpr.Lock(a, b, d); + gpr.LoadToX64(d, (d == a || d == b), true); + if (d == a) { + IMUL(32, gpr.RX(d), gpr.R(b)); + } else if (d == b) { + IMUL(32, gpr.RX(d), gpr.R(a)); } else { - gpr.LoadToX64(d, true, true); + MOV(32, gpr.R(d), gpr.R(b)); + IMUL(32, gpr.RX(d), gpr.R(a)); } - MOV(32, R(EAX), gpr.R(a)); - gpr.KillImmediate(b); - IMUL(32, gpr.R(b)); - MOV(32, gpr.R(d), R(EAX)); gpr.UnlockAll(); - gpr.UnlockAllX(); - // result is already in eax if (inst.Rc) { + MOV(32, R(EAX), gpr.R(d)); CALL((u8*)Asm::computeRc); } }