summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Common/Src/x64Emitter.cpp58
-rw-r--r--Source/Core/Common/Src/x64Emitter.h4
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp38
3 files changed, 75 insertions, 25 deletions
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);
}
}