diff --git a/Source/Core/Core/DSP/DSPEmitter.h b/Source/Core/Core/DSP/DSPEmitter.h index e392fbf42d..c0dfa6aedf 100644 --- a/Source/Core/Core/DSP/DSPEmitter.h +++ b/Source/Core/Core/DSP/DSPEmitter.h @@ -41,8 +41,7 @@ public: // CC Util void Update_SR_Register64(Gen::X64Reg val = Gen::EAX); - void Update_SR_Register64_Carry(Gen::X64Reg val, Gen::X64Reg carry_ovfl); - void Update_SR_Register64_Carry2(Gen::X64Reg val, Gen::X64Reg carry_ovfl); + void Update_SR_Register64_Carry(Gen::X64Reg val, Gen::X64Reg carry_ovfl, bool carry_eq = false); void Update_SR_Register16(Gen::X64Reg val = Gen::EAX); void Update_SR_Register16_OverS32(Gen::X64Reg val = Gen::EAX); diff --git a/Source/Core/Core/DSP/Jit/DSPJitArithmetic.cpp b/Source/Core/Core/DSP/Jit/DSPJitArithmetic.cpp index 2e1a88890b..a56d75a5b1 100644 --- a/Source/Core/Core/DSP/Jit/DSPJitArithmetic.cpp +++ b/Source/Core/Core/DSP/Jit/DSPJitArithmetic.cpp @@ -179,7 +179,7 @@ void DSPEmitter::cmp(const UDSPInstruction opc) SUB(64, R(RAX), R(RDX)); // Update_SR_Register64(res, isCarry2(acc0, res), isOverflow(acc0, -acc1, res)); // CF -> influence on ABS/0xa100 NEG(64, R(RDX)); - Update_SR_Register64_Carry2(EAX, tmp1); + Update_SR_Register64_Carry(EAX, tmp1, true); gpr.putXReg(tmp1); } } @@ -210,7 +210,7 @@ void DSPEmitter::cmpar(const UDSPInstruction opc) SUB(64, R(RAX), R(RDX)); // Update_SR_Register64(res, isCarry2(sr, res), isOverflow(sr, -rr, res)); NEG(64, R(RDX)); - Update_SR_Register64_Carry2(EAX, tmp1); + Update_SR_Register64_Carry(EAX, tmp1, true); gpr.putXReg(tmp1); } } @@ -239,7 +239,7 @@ void DSPEmitter::cmpi(const UDSPInstruction opc) SUB(64, R(RAX), R(RDX)); // Update_SR_Register64(res, isCarry2(val, res), isOverflow(val, -imm, res)); NEG(64, R(RDX)); - Update_SR_Register64_Carry2(EAX, tmp1); + Update_SR_Register64_Carry(EAX, tmp1, true); gpr.putXReg(tmp1); } } @@ -268,7 +268,7 @@ void DSPEmitter::cmpis(const UDSPInstruction opc) SUB(64, R(RAX), R(RDX)); // Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -val, res)); NEG(64, R(RDX)); - Update_SR_Register64_Carry2(EAX, tmp1); + Update_SR_Register64_Carry(EAX, tmp1, true); gpr.putXReg(tmp1); } } @@ -862,7 +862,7 @@ void DSPEmitter::subr(const UDSPInstruction opc) NEG(64, R(RDX)); MOV(64, R(RCX), R(RAX)); set_long_acc(dreg, RCX); - Update_SR_Register64_Carry2(EAX, tmp1); + Update_SR_Register64_Carry(EAX, tmp1, true); } else { @@ -898,7 +898,7 @@ void DSPEmitter::subax(const UDSPInstruction opc) NEG(64, R(RDX)); MOV(64, R(RCX), R(RAX)); set_long_acc(dreg, RCX); - Update_SR_Register64_Carry2(EAX, tmp1); + Update_SR_Register64_Carry(EAX, tmp1, true); } else { @@ -932,7 +932,7 @@ void DSPEmitter::sub(const UDSPInstruction opc) NEG(64, R(RDX)); MOV(64, R(RCX), R(RAX)); set_long_acc(dreg, RCX); - Update_SR_Register64_Carry2(EAX, tmp1); + Update_SR_Register64_Carry(EAX, tmp1, true); } else { @@ -966,7 +966,7 @@ void DSPEmitter::subp(const UDSPInstruction opc) NEG(64, R(RDX)); MOV(64, R(RCX), R(RAX)); set_long_acc(dreg, RCX); - Update_SR_Register64_Carry2(EAX, tmp1); + Update_SR_Register64_Carry(EAX, tmp1, true); } else { @@ -999,7 +999,7 @@ void DSPEmitter::decm(const UDSPInstruction opc) MOV(64, R(RDX), Imm64(-subtract)); MOV(64, R(RCX), R(RAX)); set_long_acc(dreg, RCX); - Update_SR_Register64_Carry2(EAX, tmp1); + Update_SR_Register64_Carry(EAX, tmp1, true); } else { @@ -1031,7 +1031,7 @@ void DSPEmitter::dec(const UDSPInstruction opc) MOV(64, R(RDX), Imm64(-1)); MOV(64, R(RCX), R(RAX)); set_long_acc(dreg, RCX); - Update_SR_Register64_Carry2(EAX, tmp1); + Update_SR_Register64_Carry(EAX, tmp1, true); } else { diff --git a/Source/Core/Core/DSP/Jit/DSPJitCCUtil.cpp b/Source/Core/Core/DSP/Jit/DSPJitCCUtil.cpp index 8e9d86aed8..00e641328e 100644 --- a/Source/Core/Core/DSP/Jit/DSPJitCCUtil.cpp +++ b/Source/Core/Core/DSP/Jit/DSPJitCCUtil.cpp @@ -17,14 +17,14 @@ void DSPEmitter::Update_SR_Register(Gen::X64Reg val) gpr.getReg(DSP_REG_SR,sr_reg); // // 0x04 // if (_Value == 0) g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO; - CMP(64, R(val), Imm8(0)); + TEST(64, R(val), R(val)); FixupBranch notZero = J_CC(CC_NZ); - OR(16, sr_reg, Imm16(SR_ARITH_ZERO)); + OR(16, sr_reg, Imm16(SR_ARITH_ZERO | SR_TOP2BITS)); + FixupBranch end = J(); SetJumpTarget(notZero); // // 0x08 // if (_Value < 0) g_dsp.r[DSP_REG_SR] |= SR_SIGN; - CMP(64, R(val), Imm8(0)); FixupBranch greaterThanEqual = J_CC(CC_GE); OR(16, sr_reg, Imm16(SR_SIGN)); SetJumpTarget(greaterThanEqual); @@ -39,15 +39,16 @@ void DSPEmitter::Update_SR_Register(Gen::X64Reg val) // // 0x20 - Checks if top bits of m are equal // if (((_Value & 0xc0000000) == 0) || ((_Value & 0xc0000000) == 0xc0000000)) - AND(32, R(val), Imm32(0xc0000000)); - CMP(32, R(val), Imm32(0)); - FixupBranch zeroC = J_CC(CC_E); - CMP(32, R(val), Imm32(0xc0000000)); + MOV(32, R(RDX), Imm32(0xc0000000)); + AND(32, R(val), R(RDX)); + FixupBranch zeroC = J_CC(CC_Z); + CMP(32, R(val), R(RDX)); FixupBranch cC = J_CC(CC_NE); SetJumpTarget(zeroC); // g_dsp.r[DSP_REG_SR] |= SR_TOP2BITS; OR(16, sr_reg, Imm16(SR_TOP2BITS)); SetJumpTarget(cC); + SetJumpTarget(end); gpr.putReg(DSP_REG_SR); } @@ -66,7 +67,7 @@ void DSPEmitter::Update_SR_Register64(Gen::X64Reg val) // In: (val): s64 _Value // In: (carry_ovfl): 1 = carry, 2 = overflow // Clobbers RDX -void DSPEmitter::Update_SR_Register64_Carry(X64Reg val, X64Reg carry_ovfl) +void DSPEmitter::Update_SR_Register64_Carry(X64Reg val, X64Reg carry_ovfl, bool carry_eq) { OpArg sr_reg; gpr.getReg(DSP_REG_SR,sr_reg); @@ -78,7 +79,8 @@ void DSPEmitter::Update_SR_Register64_Carry(X64Reg val, X64Reg carry_ovfl) // 0x01 // g_dsp.r[DSP_REG_SR] |= SR_CARRY; // Carry = (acc>res) - FixupBranch noCarry = J_CC(CC_BE); + // Carry2 = (acc>=res) + FixupBranch noCarry = J_CC(carry_eq ? CC_B : CC_BE); OR(16, sr_reg, Imm16(SR_CARRY)); SetJumpTarget(noCarry); @@ -88,53 +90,23 @@ void DSPEmitter::Update_SR_Register64_Carry(X64Reg val, X64Reg carry_ovfl) // Overflow = ((acc ^ res) & (ax ^ res)) < 0 XOR(64, R(carry_ovfl), R(val)); XOR(64, R(RDX), R(val)); - AND(64, R(carry_ovfl), R(RDX)); - CMP(64, R(carry_ovfl), Imm8(0)); + TEST(64, R(carry_ovfl), R(RDX)); FixupBranch noOverflow = J_CC(CC_GE); OR(16, sr_reg, Imm16(SR_OVERFLOW | SR_OVERFLOW_STICKY)); SetJumpTarget(noOverflow); gpr.putReg(DSP_REG_SR); - Update_SR_Register(val); -} - -// In: (val): s64 _Value -// In: (carry_ovfl): 1 = carry, 2 = overflow -// Clobbers RDX -void DSPEmitter::Update_SR_Register64_Carry2(X64Reg val, X64Reg carry_ovfl) -{ - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - // g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK; - AND(16, sr_reg, Imm16(~SR_CMP_MASK)); - - CMP(64, R(carry_ovfl), R(val)); - - // 0x01 - // g_dsp.r[DSP_REG_SR] |= SR_CARRY; - // Carry2 = (acc>=res) - FixupBranch noCarry2 = J_CC(CC_B); - OR(16, sr_reg, Imm16(SR_CARRY)); - SetJumpTarget(noCarry2); - - // 0x02 and 0x80 - // g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW; - // g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW_STICKY; - // Overflow = ((acc ^ res) & (ax ^ res)) < 0 - XOR(64, R(carry_ovfl), R(val)); - XOR(64, R(RDX), R(val)); - AND(64, R(carry_ovfl), R(RDX)); - CMP(64, R(carry_ovfl), Imm8(0)); - FixupBranch noOverflow = J_CC(CC_GE); - OR(16, sr_reg, Imm16(SR_OVERFLOW | SR_OVERFLOW_STICKY)); - SetJumpTarget(noOverflow); - gpr.putReg(DSP_REG_SR); - - Update_SR_Register(); + if (carry_eq) + { + Update_SR_Register(); + } + else + { + Update_SR_Register(val); + } } // In: RAX: s64 _Value -// Clobbers RDX void DSPEmitter::Update_SR_Register16(X64Reg val) { OpArg sr_reg; @@ -143,38 +115,35 @@ void DSPEmitter::Update_SR_Register16(X64Reg val) // // 0x04 // if (_Value == 0) g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO; - CMP(64, R(val), Imm8(0)); + TEST(64, R(val), R(val)); FixupBranch notZero = J_CC(CC_NZ); - OR(16, sr_reg, Imm16(SR_ARITH_ZERO)); + OR(16, sr_reg, Imm16(SR_ARITH_ZERO | SR_TOP2BITS)); + FixupBranch end = J(); SetJumpTarget(notZero); // // 0x08 // if (_Value < 0) g_dsp.r[DSP_REG_SR] |= SR_SIGN; - CMP(64, R(val), Imm8(0)); FixupBranch greaterThanEqual = J_CC(CC_GE); OR(16, sr_reg, Imm16(SR_SIGN)); SetJumpTarget(greaterThanEqual); // // 0x20 - Checks if top bits of m are equal // if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3)) - //AND(32, R(val), Imm32(0xc0000000)); SHR(16, R(val), Imm8(14)); - CMP(16, R(val), Imm16(0)); - FixupBranch nZero = J_CC(CC_NE); - OR(16, sr_reg, Imm16(SR_TOP2BITS)); - FixupBranch cC = J(); - SetJumpTarget(nZero); + TEST(16, R(val), R(val)); + FixupBranch isZero = J_CC(CC_Z); CMP(16, R(val), Imm16(3)); FixupBranch notThree = J_CC(CC_NE); + SetJumpTarget(isZero); // g_dsp.r[DSP_REG_SR] |= SR_TOP2BITS; OR(16, sr_reg, Imm16(SR_TOP2BITS)); SetJumpTarget(notThree); - SetJumpTarget(cC); + SetJumpTarget(end); gpr.putReg(DSP_REG_SR); } // In: RAX: s64 _Value -// Clobbers RDX +// Clobbers RCX void DSPEmitter::Update_SR_Register16_OverS32(Gen::X64Reg val) { OpArg sr_reg;