Index: Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h =================================================================== --- Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h (revision 5178) +++ Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h (working copy) @@ -46,6 +46,7 @@ const u8 *fpException; const u8 *computeRc; + const u8 *computeCr; const u8 *testExceptions; const u8 *dispatchPcInEAX; const u8 *doTiming; Index: Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp =================================================================== --- Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp (revision 5178) +++ Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp (working copy) @@ -24,15 +24,6 @@ #include "JitRegCache.h" #include "JitAsm.h" -// Assumes that the flags were just set through an addition. -void Jit64::GenerateCarry(Gen::X64Reg temp_reg) { - // USES_XER - SETcc(CC_C, R(temp_reg)); - AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~(1 << 29))); - SHL(32, R(temp_reg), Imm8(29)); - OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), R(temp_reg)); -} - u32 Add(u32 a, u32 b) {return a + b;} u32 Or (u32 a, u32 b) {return a | b;} u32 And(u32 a, u32 b) {return a & b;} @@ -55,7 +46,13 @@ gpr.LoadToX64(d, false); (this->*op)(32, gpr.R(d), Imm32(value)); //m_GPR[d] = m_GPR[_inst.RA] + _inst.SIMM_16; if (carry) - GenerateCarry(EAX); + { + // USES_XER + SETcc(CC_C, R(EAX)); + AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~(1 << 29))); + SHL(32, R(EAX), Imm8(29)); + OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), R(EAX)); + } } } else @@ -64,7 +61,13 @@ MOV(32, gpr.R(d), gpr.R(a)); (this->*op)(32, gpr.R(d), Imm32(value)); //m_GPR[d] = m_GPR[_inst.RA] + _inst.SIMM_16; if (carry) - GenerateCarry(EAX); + { + // USES_XER + SETcc(CC_C, R(EAX)); + AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~(1 << 29))); + SHL(32, R(EAX), Imm8(29)); + OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), R(EAX)); + } } } else if (doop == Add) @@ -79,8 +82,11 @@ if (Rc) { // Todo - special case immediates. + //if (gpr.R(d).IsImm()) + // gpr.LoadToX64(d, false); MOV(32, R(EAX), gpr.R(d)); CALL((u8*)asm_routines.computeRc); + CALL((u8*)asm_routines.computeCr); } gpr.UnlockAll(); } @@ -116,8 +122,8 @@ case 29: regimmop(a, s, true, inst.UIMM << 16, And, &XEmitter::AND, true); break; case 26: regimmop(a, s, true, inst.UIMM, Xor, &XEmitter::XOR, false); break; //xori case 27: regimmop(a, s, true, inst.UIMM << 16, Xor, &XEmitter::XOR, false); break; //xoris - case 12: //regimmop(d, a, false, (u32)(s32)inst.SIMM_16, Add, XEmitter::ADD, false, true); //addic - case 13: //regimmop(d, a, true, (u32)(s32)inst.SIMM_16, Add, XEmitter::ADD, true, true); //addic_rc + case 12: regimmop(d, a, false, (u32)(s32)inst.SIMM_16, Add, &XEmitter::ADD, false, true);break; //addic + case 13: regimmop(d, a, true, (u32)(s32)inst.SIMM_16, Add, &XEmitter::ADD, true, false);break; //addic_rc default: Default(inst); break; @@ -379,7 +385,13 @@ NOT(32, R(EAX)); ADD(32, R(EAX), Imm32(imm + 1)); MOV(32, gpr.R(d), R(EAX)); - GenerateCarry(ECX); + // + // USES_XER + SETcc(CC_C, R(ECX)); + AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~(1 << 29))); + SHL(32, R(ECX), Imm8(29)); + OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), R(ECX)); + // gpr.UnlockAll(); gpr.UnlockAllX(); // This instruction has no RC flag @@ -388,17 +400,70 @@ void Jit64::subfcx(UGeckoInstruction inst) { INSTRUCTION_START; - Default(inst); - return; - /* - u32 a = m_GPR[_inst.RA]; - u32 b = m_GPR[_inst.RB]; - m_GPR[_inst.RD] = b - a; - SetCarry(a == 0 || Helper_Carry(b, 0-a)); - - if (_inst.OE) PanicAlert("OE: subfcx"); - if (_inst.Rc) Helper_UpdateCR0(m_GPR[_inst.RD]); - */ + JITDISABLE(Integer) + int a = inst.RA, b = inst.RB, d = inst.RD; + gpr.FlushLockX(ECX); + gpr.Lock(a, b, d); + + if(d != a && d != b) + gpr.LoadToX64(d, false, true); + else + gpr.LoadToX64(d, true, true); + + MOV(32, R(EAX), gpr.R(b)); + SUB(32, R(EAX), gpr.R(a)); + MOV(32, gpr.R(d), R(EAX)); + + MOV(32, R(EAX), gpr.R(a)); + MOV(32, R(ECX), gpr.R(b)); + + CMP(32, R(EAX), Imm8(0)); + FixupBranch cpLesser = J_CC(CC_L); + FixupBranch cpGreater = J_CC(CC_G); + + // Equal + JitSetCA(); + FixupBranch continue3 = J(); + + // Lesser and greater + SetJumpTarget(cpGreater); + SetJumpTarget(cpLesser); + + NEG(32, R(EAX)); + NOT(32, R(ECX)); + + CMP(32, R(EAX), R(ECX)); + FixupBranch pLesser = J_CC(CC_L); + FixupBranch pGreater = J_CC(CC_G); + + // Equal + JitClearCA(); + FixupBranch continue1 = J(); + + // Greater + SetJumpTarget(pGreater); + JitSetCA(); + FixupBranch continue2 = J(); + + // Less than + SetJumpTarget(pLesser); + JitClearCA(); + + SetJumpTarget(continue1); + SetJumpTarget(continue2); + SetJumpTarget(continue3); + + //SetCarry(a == 0 || Helper_Carry(b, 0-a)); + //return -a > (~b); + + gpr.UnlockAll(); + gpr.UnlockAllX(); + if (inst.OE) PanicAlert("OE: subfcx"); + if (inst.Rc) { + MOV(32, R(EAX), gpr.R(d)); + CALL((u8*)asm_routines.computeRc); + CALL((u8*)asm_routines.computeCr); + } } void Jit64::subfex(UGeckoInstruction inst) @@ -599,7 +664,13 @@ MOV(32, R(EAX), gpr.R(a)); ADC(32, R(EAX), gpr.R(b)); MOV(32, gpr.R(d), R(EAX)); - GenerateCarry(ECX); + // + // USES_XER + SETcc(CC_C, R(ECX)); + AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~(1 << 29))); + SHL(32, R(ECX), Imm8(29)); + OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), R(ECX)); + // gpr.UnlockAll(); gpr.UnlockAllX(); if (inst.Rc) Index: Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp =================================================================== --- Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp (revision 5178) +++ Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp (working copy) @@ -216,15 +216,44 @@ CMP(32, R(EAX), Imm8(0)); FixupBranch pLesser = J_CC(CC_L); FixupBranch pGreater = J_CC(CC_G); + MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x2)); // _x86Reg == 0 RET(); + SetJumpTarget(pGreater); MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x4)); // _x86Reg > 0 RET(); + SetJumpTarget(pLesser); MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x8)); // _x86Reg < 0 RET(); + computeCr = AlignCode16(); + //MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); + + //AND(32, R(EAX), Imm32( 1 << 31 )); + //MOVSX(32, 8, ECX, M(&PowerPC::ppcState.cr_fast[0])); + //OR(32, R(ECX), R(EAX)); + //MOV(8, M(&PowerPC::ppcState.cr_fast[0]), R(ECX)); + //WriteToConstRamAddress(8, R(ECX), (u32)&PowerPC::ppcState.cr_fast[0]); + RET(); + + // Do the OR here + + /*[02:40:00] mov eax, spr_xer + [02:40:00] and eax, 1 + [02:40:00] mov ecx, cr_fast[0] + [02:40:00] or ecx, eax + [02:40:00] mov cr_fast[0], ecx*/ + + + /*MOV(32, R(EAX), M(&(PowerPC::ppcState.spr[SPR_XER]))); + SHR(32, R(EAX), Imm8( 31 )); + AND(32, R(EAX), Imm8( 1 << 4 )); + + OR(8, M(&(PowerPC::ppcState.cr_fast[0])), R(EAX));*/ + //RET(); + fifoDirectWrite8 = AlignCode4(); GenFifoWrite(8); fifoDirectWrite16 = AlignCode4(); Index: Source/Core/Core/Src/PowerPC/Jit64/Jit.h =================================================================== --- Source/Core/Core/Src/PowerPC/Jit64/Jit.h (revision 5178) +++ Source/Core/Core/Src/PowerPC/Jit64/Jit.h (working copy) @@ -137,8 +137,6 @@ void WriteCallInterpreter(UGeckoInstruction _inst); void Cleanup(); - void GenerateCarry(Gen::X64Reg temp_reg); - void tri_op(int d, int a, int b, bool reversible, void (XEmitter::*op)(Gen::X64Reg, Gen::OpArg)); typedef u32 (*Operation)(u32 a, u32 b); void regimmop(int d, int a, bool binary, u32 value, Operation doop, void (XEmitter::*op)(int, const Gen::OpArg&, const Gen::OpArg&), bool Rc = false, bool carry = false);