From 759263351a34e20285cf087f5f58a345eb2d6870 Mon Sep 17 00:00:00 2001 From: hrydgard Date: Wed, 10 Jun 2009 19:43:47 +0000 Subject: [PATCH] JITIL: Disable all load/store instructions in 64-bit mode. This actually makes a lot of games work - but slowly. Investigation needed. Reindent a bunch of code. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3405 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/PowerPC/Jit64IL/IR.h | 1026 ++++++++--------- Source/Core/Core/Src/PowerPC/Jit64IL/Jit.cpp | 538 ++++----- Source/Core/Core/Src/PowerPC/Jit64IL/Jit.h | 8 + .../Core/Src/PowerPC/Jit64IL/Jit_Branch.cpp | 269 +++-- .../Src/PowerPC/Jit64IL/Jit_FloatingPoint.cpp | 154 +-- .../Core/Src/PowerPC/Jit64IL/Jit_Integer.cpp | 936 +++++++-------- .../Src/PowerPC/Jit64IL/Jit_LoadStore.cpp | 10 + .../PowerPC/Jit64IL/Jit_LoadStoreFloating.cpp | 6 + .../PowerPC/Jit64IL/Jit_LoadStorePaired.cpp | 2 + .../Core/Src/PowerPC/Jit64IL/Jit_Paired.cpp | 354 +++--- 10 files changed, 1664 insertions(+), 1639 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h index e3f335228e..94c9c8e07c 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h @@ -22,534 +22,534 @@ #include namespace IREmitter { - enum Opcode { - Nop = 0, +enum Opcode { + Nop = 0, - // "Zero-operand" operators - // Register load operators - LoadGReg, - LoadLink, - LoadCR, - LoadCarry, - LoadCTR, - LoadMSR, - LoadGQR, + // "Zero-operand" operators + // Register load operators + LoadGReg, + LoadLink, + LoadCR, + LoadCarry, + LoadCTR, + LoadMSR, + LoadGQR, - // Unary operators - // Integer unary operators - SExt8, - SExt16, - BSwap32, - BSwap16, - Cntlzw, // Count leading zeros - Load8, // These loads zext - Load16, - Load32, - // Branches - BranchUncond, - // Register store operators - StoreGReg, - StoreCR, - StoreLink, - StoreCarry, - StoreCTR, - StoreMSR, - StoreFPRF, - StoreGQR, - StoreSRR, - // Arbitrary interpreter instruction - InterpreterFallback, + // Unary operators + // Integer unary operators + SExt8, + SExt16, + BSwap32, + BSwap16, + Cntlzw, // Count leading zeros + Load8, // These loads zext + Load16, + Load32, + // Branches + BranchUncond, + // Register store operators + StoreGReg, + StoreCR, + StoreLink, + StoreCarry, + StoreCTR, + StoreMSR, + StoreFPRF, + StoreGQR, + StoreSRR, + // Arbitrary interpreter instruction + InterpreterFallback, - // Binary operators - // Commutative integer operators - Add, - Mul, - And, - Or, - Xor, - // Non-commutative integer operators - Sub, - Shl, // Note that shifts ignore bits above the bottom 5 - Shrl, - Sarl, - Rol, - ICmpCRSigned, // CR for signed int compare - ICmpCRUnsigned, // CR for unsigned int compare - ICmpEq, // One if equal, zero otherwise - ICmpNe, - ICmpUgt, // One if op1 > op2, zero otherwise - ICmpUlt, - ICmpUge, - ICmpUle, - ICmpSgt, // One if op1 > op2, zero otherwise - ICmpSlt, - ICmpSge, - ICmpSle, // Opposite of sgt - // Memory store operators - Store8, - Store16, - Store32, - BranchCond, - // Floating-point - // There are three floating-point formats: single, double, - // and packed. For any operation where the format of the - // operand isn't known, the ForceTo* operations are used; - // these are folded into the appropriate conversion - // (or no conversion) depending on the type of the operand. - // The "mreg" format is a pair of doubles; this is the - // most general possible represenation which is used - // in the register state. - // This might seem like overkill, but the semantics require - // having the different formats. - // FIXME: Check the accuracy of the mapping: - // 1. Is paired arithmetic always rounded to single-precision - // first, or does it do double-to-single like the - // single-precision instructions? - // 2. The implementation of madd is slightly off, and - // the implementation of fmuls is very slightly off; - // likely nothing cares, though. - FResult_Start, - LoadSingle, - LoadDouble, - LoadPaired, // This handles quantizers itself - DoubleToSingle, - DupSingleToMReg, - DupSingleToPacked, - InsertDoubleInMReg, - ExpandPackedToMReg, - CompactMRegToPacked, - LoadFReg, - LoadFRegDENToZero, - FSMul, - FSAdd, - FSSub, - FSNeg, - FPAdd, - FPMul, - FPSub, - FPNeg, - FDMul, - FDAdd, - FDSub, - FDNeg, - FPMerge00, - FPMerge01, - FPMerge10, - FPMerge11, - FPDup0, - FPDup1, - FResult_End, - StorePaired, - StoreSingle, - StoreDouble, - StoreFReg, - FDCmpCR, + // Binary operators + // Commutative integer operators + Add, + Mul, + And, + Or, + Xor, + // Non-commutative integer operators + Sub, + Shl, // Note that shifts ignore bits above the bottom 5 + Shrl, + Sarl, + Rol, + ICmpCRSigned, // CR for signed int compare + ICmpCRUnsigned, // CR for unsigned int compare + ICmpEq, // One if equal, zero otherwise + ICmpNe, + ICmpUgt, // One if op1 > op2, zero otherwise + ICmpUlt, + ICmpUge, + ICmpUle, + ICmpSgt, // One if op1 > op2, zero otherwise + ICmpSlt, + ICmpSge, + ICmpSle, // Opposite of sgt + // Memory store operators + Store8, + Store16, + Store32, + BranchCond, + // Floating-point + // There are three floating-point formats: single, double, + // and packed. For any operation where the format of the + // operand isn't known, the ForceTo* operations are used; + // these are folded into the appropriate conversion + // (or no conversion) depending on the type of the operand. + // The "mreg" format is a pair of doubles; this is the + // most general possible represenation which is used + // in the register state. + // This might seem like overkill, but the semantics require + // having the different formats. + // FIXME: Check the accuracy of the mapping: + // 1. Is paired arithmetic always rounded to single-precision + // first, or does it do double-to-single like the + // single-precision instructions? + // 2. The implementation of madd is slightly off, and + // the implementation of fmuls is very slightly off; + // likely nothing cares, though. + FResult_Start, + LoadSingle, + LoadDouble, + LoadPaired, // This handles quantizers itself + DoubleToSingle, + DupSingleToMReg, + DupSingleToPacked, + InsertDoubleInMReg, + ExpandPackedToMReg, + CompactMRegToPacked, + LoadFReg, + LoadFRegDENToZero, + FSMul, + FSAdd, + FSSub, + FSNeg, + FPAdd, + FPMul, + FPSub, + FPNeg, + FDMul, + FDAdd, + FDSub, + FDNeg, + FPMerge00, + FPMerge01, + FPMerge10, + FPMerge11, + FPDup0, + FPDup1, + FResult_End, + StorePaired, + StoreSingle, + StoreDouble, + StoreFReg, + FDCmpCR, - // "Trinary" operators - // FIXME: Need to change representation! - //Select, // Equivalent to C "Op1 ? Op2 : Op3" + // "Trinary" operators + // FIXME: Need to change representation! + //Select, // Equivalent to C "Op1 ? Op2 : Op3" - // Integer constants - CInt16, - CInt32, + // Integer constants + CInt16, + CInt32, - // Funny PPC "branches" - SystemCall, - RFIExit, - InterpreterBranch, + // Funny PPC "branches" + SystemCall, + RFIExit, + InterpreterBranch, - //IdleLoop, // The "usual" idle loop, load+compare+branch - IdleBranch, // branch operation belonging to idle loop - ShortIdleLoop, // Idle loop seen in homebrew like wii mahjong, - // just a branch + //IdleLoop, // The "usual" idle loop, load+compare+branch + IdleBranch, // branch operation belonging to idle loop + ShortIdleLoop, // Idle loop seen in homebrew like wii mahjong, + // just a branch - // "Opcode" representing a register too far away to - // reference directly; this is a size optimization - Tramp, - // "Opcode"s representing the start and end - BlockStart, BlockEnd - }; + // "Opcode" representing a register too far away to + // reference directly; this is a size optimization + Tramp, + // "Opcode"s representing the start and end + BlockStart, BlockEnd +}; - typedef unsigned Inst; - typedef Inst* InstLoc; +typedef unsigned Inst; +typedef Inst* InstLoc; - unsigned inline getOpcode(Inst i) { - return i & 255; +unsigned inline getOpcode(Inst i) { + return i & 255; +} + +unsigned inline isImm(Inst i) { + return getOpcode(i) >= CInt16 && getOpcode(i) <= CInt32; +} + +unsigned inline isICmp(Inst i) { + return getOpcode(i) >= ICmpEq && getOpcode(i) <= ICmpSle; +} + +unsigned inline isFResult(Inst i) { + return getOpcode(i) > FResult_Start && + getOpcode(i) < FResult_End; +} + +InstLoc inline getOp1(InstLoc i) { + i = i - 1 - ((*i >> 8) & 255); + if (getOpcode(*i) == Tramp) { + i = i - 1 - (*i >> 8); + } + return i; +} + +InstLoc inline getOp2(InstLoc i) { + i = i - 1 - ((*i >> 16) & 255); + if (getOpcode(*i) == Tramp) { + i = i - 1 - (*i >> 8); + } + return i; +} + +class IRBuilder { +private: + InstLoc EmitZeroOp(unsigned Opcode, unsigned extra); + InstLoc EmitUOp(unsigned OpCode, InstLoc Op1, + unsigned extra = 0); + InstLoc EmitBiOp(unsigned OpCode, InstLoc Op1, InstLoc Op2, + unsigned extra = 0); + + InstLoc FoldAdd(InstLoc Op1, InstLoc Op2); + InstLoc FoldSub(InstLoc Op1, InstLoc Op2); + InstLoc FoldAnd(InstLoc Op1, InstLoc Op2); + InstLoc FoldOr(InstLoc Op1, InstLoc Op2); + InstLoc FoldRol(InstLoc Op1, InstLoc Op2); + InstLoc FoldShl(InstLoc Op1, InstLoc Op2); + InstLoc FoldShrl(InstLoc Op1, InstLoc Op2); + InstLoc FoldXor(InstLoc Op1, InstLoc Op2); + InstLoc FoldBranchCond(InstLoc Op1, InstLoc Op2); + InstLoc FoldIdleBranch(InstLoc Op1, InstLoc Op2); + InstLoc FoldICmp(unsigned Opcode, InstLoc Op1, InstLoc Op2); + InstLoc FoldICmpCRSigned(InstLoc Op1, InstLoc Op2); + InstLoc FoldICmpCRUnsigned(InstLoc Op1, InstLoc Op2); + InstLoc FoldDoubleBiOp(unsigned Opcode, InstLoc Op1, InstLoc Op2); + + InstLoc FoldInterpreterFallback(InstLoc Op1, InstLoc Op2); + + InstLoc FoldZeroOp(unsigned Opcode, unsigned extra); + InstLoc FoldUOp(unsigned OpCode, InstLoc Op1, + unsigned extra = 0); + InstLoc FoldBiOp(unsigned OpCode, InstLoc Op1, InstLoc Op2, + unsigned extra = 0); + + unsigned ComputeKnownZeroBits(InstLoc I); + +public: + InstLoc EmitIntConst(unsigned value); + InstLoc EmitStoreLink(InstLoc val) { + return FoldUOp(StoreLink, val); + } + InstLoc EmitBranchUncond(InstLoc val) { + return FoldUOp(BranchUncond, val); + } + InstLoc EmitBranchCond(InstLoc check, InstLoc dest) { + return FoldBiOp(BranchCond, check, dest); + } + InstLoc EmitIdleBranch(InstLoc check, InstLoc dest) { + return FoldBiOp(IdleBranch, check, dest); + } + InstLoc EmitLoadCR(unsigned crreg) { + return FoldZeroOp(LoadCR, crreg); + } + InstLoc EmitStoreCR(InstLoc value, unsigned crreg) { + return FoldUOp(StoreCR, value, crreg); + } + InstLoc EmitLoadLink() { + return FoldZeroOp(LoadLink, 0); + } + InstLoc EmitLoadMSR() { + return FoldZeroOp(LoadMSR, 0); + } + InstLoc EmitStoreMSR(InstLoc val) { + return FoldUOp(StoreMSR, val); + } + InstLoc EmitStoreFPRF(InstLoc value) { + return FoldUOp(StoreFPRF, value); + } + InstLoc EmitLoadGReg(unsigned reg) { + return FoldZeroOp(LoadGReg, reg); + } + InstLoc EmitStoreGReg(InstLoc value, unsigned reg) { + return FoldUOp(StoreGReg, value, reg); + } + InstLoc EmitAnd(InstLoc op1, InstLoc op2) { + return FoldBiOp(And, op1, op2); + } + InstLoc EmitXor(InstLoc op1, InstLoc op2) { + return FoldBiOp(Xor, op1, op2); + } + InstLoc EmitSub(InstLoc op1, InstLoc op2) { + return FoldBiOp(Sub, op1, op2); + } + InstLoc EmitOr(InstLoc op1, InstLoc op2) { + return FoldBiOp(Or, op1, op2); + } + InstLoc EmitAdd(InstLoc op1, InstLoc op2) { + return FoldBiOp(Add, op1, op2); + } + InstLoc EmitMul(InstLoc op1, InstLoc op2) { + return FoldBiOp(Mul, op1, op2); + } + InstLoc EmitRol(InstLoc op1, InstLoc op2) { + return FoldBiOp(Rol, op1, op2); + } + InstLoc EmitShl(InstLoc op1, InstLoc op2) { + return FoldBiOp(Shl, op1, op2); + } + InstLoc EmitShrl(InstLoc op1, InstLoc op2) { + return FoldBiOp(Shrl, op1, op2); + } + InstLoc EmitSarl(InstLoc op1, InstLoc op2) { + return FoldBiOp(Sarl, op1, op2); + } + InstLoc EmitLoadCTR() { + return FoldZeroOp(LoadCTR, 0); + } + InstLoc EmitStoreCTR(InstLoc op1) { + return FoldUOp(StoreCTR, op1); + } + InstLoc EmitICmpEq(InstLoc op1, InstLoc op2) { + return FoldBiOp(ICmpEq, op1, op2); + } + InstLoc EmitICmpNe(InstLoc op1, InstLoc op2) { + return FoldBiOp(ICmpNe, op1, op2); + } + InstLoc EmitICmpUgt(InstLoc op1, InstLoc op2) { + return FoldBiOp(ICmpUgt, op1, op2); + } + InstLoc EmitICmpUlt(InstLoc op1, InstLoc op2) { + return FoldBiOp(ICmpUlt, op1, op2); + } + InstLoc EmitICmpSgt(InstLoc op1, InstLoc op2) { + return FoldBiOp(ICmpSgt, op1, op2); + } + InstLoc EmitICmpSlt(InstLoc op1, InstLoc op2) { + return FoldBiOp(ICmpSlt, op1, op2); + } + InstLoc EmitICmpSge(InstLoc op1, InstLoc op2) { + return FoldBiOp(ICmpSge, op1, op2); + } + InstLoc EmitICmpSle(InstLoc op1, InstLoc op2) { + return FoldBiOp(ICmpSle, op1, op2); + } + InstLoc EmitLoad8(InstLoc op1) { + return FoldUOp(Load8, op1); + } + InstLoc EmitLoad16(InstLoc op1) { + return FoldUOp(Load16, op1); + } + InstLoc EmitLoad32(InstLoc op1) { + return FoldUOp(Load32, op1); + } + InstLoc EmitStore8(InstLoc op1, InstLoc op2) { + return FoldBiOp(Store8, op1, op2); + } + InstLoc EmitStore16(InstLoc op1, InstLoc op2) { + return FoldBiOp(Store16, op1, op2); + } + InstLoc EmitStore32(InstLoc op1, InstLoc op2) { + return FoldBiOp(Store32, op1, op2); + } + InstLoc EmitSExt16(InstLoc op1) { + return FoldUOp(SExt16, op1); + } + InstLoc EmitSExt8(InstLoc op1) { + return FoldUOp(SExt8, op1); + } + InstLoc EmitCntlzw(InstLoc op1) { + return FoldUOp(Cntlzw, op1); + } + InstLoc EmitICmpCRSigned(InstLoc op1, InstLoc op2) { + return FoldBiOp(ICmpCRSigned, op1, op2); + } + InstLoc EmitICmpCRUnsigned(InstLoc op1, InstLoc op2) { + return FoldBiOp(ICmpCRUnsigned, op1, op2); + } + InstLoc EmitInterpreterFallback(InstLoc op1, InstLoc op2) { + return FoldBiOp(InterpreterFallback, op1, op2); + } + InstLoc EmitInterpreterBranch() { + return FoldZeroOp(InterpreterBranch, 0); + } + InstLoc EmitLoadCarry() { + return FoldZeroOp(LoadCarry, 0); + } + InstLoc EmitStoreCarry(InstLoc op1) { + return FoldUOp(StoreCarry, op1); + } + InstLoc EmitSystemCall(InstLoc pc) { + return FoldUOp(SystemCall, pc); + } + InstLoc EmitRFIExit() { + return FoldZeroOp(RFIExit, 0); + } + InstLoc EmitShortIdleLoop(InstLoc pc) { + return FoldUOp(ShortIdleLoop, pc); + } + InstLoc EmitLoadSingle(InstLoc addr) { + return FoldUOp(LoadSingle, addr); + } + InstLoc EmitLoadDouble(InstLoc addr) { + return FoldUOp(LoadDouble, addr); + } + InstLoc EmitLoadPaired(InstLoc addr, unsigned quantReg) { + return FoldUOp(LoadPaired, addr, quantReg); + } + InstLoc EmitStoreSingle(InstLoc value, InstLoc addr) { + return FoldBiOp(StoreSingle, value, addr); + } + InstLoc EmitStoreDouble(InstLoc value, InstLoc addr) { + return FoldBiOp(StoreDouble, value, addr); + } + InstLoc EmitStorePaired(InstLoc value, InstLoc addr, unsigned quantReg) { + return FoldBiOp(StorePaired, value, addr, quantReg); + } + InstLoc EmitLoadFReg(unsigned freg) { + return FoldZeroOp(LoadFReg, freg); + } + InstLoc EmitLoadFRegDENToZero(unsigned freg) { + return FoldZeroOp(LoadFRegDENToZero, freg); + } + InstLoc EmitStoreFReg(InstLoc val, unsigned freg) { + return FoldUOp(StoreFReg, val, freg); + } + InstLoc EmitDupSingleToMReg(InstLoc val) { + return FoldUOp(DupSingleToMReg, val); + } + InstLoc EmitDupSingleToPacked(InstLoc val) { + return FoldUOp(DupSingleToPacked, val); + } + InstLoc EmitInsertDoubleInMReg(InstLoc val, InstLoc reg) { + return FoldBiOp(InsertDoubleInMReg, val, reg); + } + InstLoc EmitExpandPackedToMReg(InstLoc val) { + return FoldUOp(ExpandPackedToMReg, val); + } + InstLoc EmitCompactMRegToPacked(InstLoc val) { + return FoldUOp(CompactMRegToPacked, val); + } + InstLoc EmitFSMul(InstLoc op1, InstLoc op2) { + return FoldBiOp(FSMul, op1, op2); + } + InstLoc EmitFSAdd(InstLoc op1, InstLoc op2) { + return FoldBiOp(FSAdd, op1, op2); + } + InstLoc EmitFSSub(InstLoc op1, InstLoc op2) { + return FoldBiOp(FSSub, op1, op2); + } + InstLoc EmitFSNeg(InstLoc op1) { + return FoldUOp(FSNeg, op1); + } + InstLoc EmitFDMul(InstLoc op1, InstLoc op2) { + return FoldBiOp(FDMul, op1, op2); + } + InstLoc EmitFDAdd(InstLoc op1, InstLoc op2) { + return FoldBiOp(FDAdd, op1, op2); + } + InstLoc EmitFDSub(InstLoc op1, InstLoc op2) { + return FoldBiOp(FDSub, op1, op2); + } + InstLoc EmitFDNeg(InstLoc op1) { + return FoldUOp(FDNeg, op1); + } + InstLoc EmitFPAdd(InstLoc op1, InstLoc op2) { + return FoldBiOp(FPAdd, op1, op2); + } + InstLoc EmitFPMul(InstLoc op1, InstLoc op2) { + return FoldBiOp(FPMul, op1, op2); + } + InstLoc EmitFPSub(InstLoc op1, InstLoc op2) { + return FoldBiOp(FPSub, op1, op2); + } + InstLoc EmitFPMerge00(InstLoc op1, InstLoc op2) { + return FoldBiOp(FPMerge00, op1, op2); + } + InstLoc EmitFPMerge01(InstLoc op1, InstLoc op2) { + return FoldBiOp(FPMerge01, op1, op2); + } + InstLoc EmitFPMerge10(InstLoc op1, InstLoc op2) { + return FoldBiOp(FPMerge10, op1, op2); + } + InstLoc EmitFPMerge11(InstLoc op1, InstLoc op2) { + return FoldBiOp(FPMerge11, op1, op2); + } + InstLoc EmitFPDup0(InstLoc op1) { + return FoldUOp(FPDup0, op1); + } + InstLoc EmitFPDup1(InstLoc op1) { + return FoldUOp(FPDup1, op1); + } + InstLoc EmitFPNeg(InstLoc op1) { + return FoldUOp(FPNeg, op1); + } + InstLoc EmitDoubleToSingle(InstLoc op1) { + return FoldUOp(DoubleToSingle, op1); + } + InstLoc EmitFDCmpCR(InstLoc op1, InstLoc op2) { + return FoldBiOp(FDCmpCR, op1, op2); + } + InstLoc EmitLoadGQR(unsigned gqr) { + return FoldZeroOp(LoadGQR, gqr); + } + InstLoc EmitStoreGQR(InstLoc op1, unsigned gqr) { + return FoldUOp(StoreGQR, op1, gqr); + } + InstLoc EmitStoreSRR(InstLoc op1, unsigned srr) { + return FoldUOp(StoreSRR, op1, srr); } - unsigned inline isImm(Inst i) { - return getOpcode(i) >= CInt16 && getOpcode(i) <= CInt32; - } - - unsigned inline isICmp(Inst i) { - return getOpcode(i) >= ICmpEq && getOpcode(i) <= ICmpSle; + void StartBackPass() { curReadPtr = &InstList[InstList.size()]; } + void StartForwardPass() { curReadPtr = &InstList[0]; } + InstLoc ReadForward() { return curReadPtr++; } + InstLoc ReadBackward() { return --curReadPtr; } + InstLoc getFirstInst() { return &InstList[0]; } + unsigned int getNumInsts() { return (unsigned int)InstList.size(); } + unsigned int ReadInst(InstLoc I) { return *I; } + unsigned int GetImmValue(InstLoc I); + + void Reset() { + InstList.clear(); + InstList.reserve(100000); + for (unsigned i = 0; i < 32; i++) { + GRegCache[i] = 0; + GRegCacheStore[i] = 0; + FRegCache[i] = 0; + FRegCacheStore[i] = 0; + } + CarryCache = 0; + CarryCacheStore = 0; + for (unsigned i = 0; i < 8; i++) { + CRCache[i] = 0; + CRCacheStore[i] = 0; + } + CTRCache = 0; + CTRCacheStore = 0; } - unsigned inline isFResult(Inst i) { - return getOpcode(i) > FResult_Start && - getOpcode(i) < FResult_End; - } + IRBuilder() { Reset(); } - InstLoc inline getOp1(InstLoc i) { - i = i - 1 - ((*i >> 8) & 255); - if (getOpcode(*i) == Tramp) { - i = i - 1 - (*i >> 8); - } - return i; - } - - InstLoc inline getOp2(InstLoc i) { - i = i - 1 - ((*i >> 16) & 255); - if (getOpcode(*i) == Tramp) { - i = i - 1 - (*i >> 8); - } - return i; - } - - class IRBuilder { - private: - InstLoc EmitZeroOp(unsigned Opcode, unsigned extra); - InstLoc EmitUOp(unsigned OpCode, InstLoc Op1, - unsigned extra = 0); - InstLoc EmitBiOp(unsigned OpCode, InstLoc Op1, InstLoc Op2, - unsigned extra = 0); - - InstLoc FoldAdd(InstLoc Op1, InstLoc Op2); - InstLoc FoldSub(InstLoc Op1, InstLoc Op2); - InstLoc FoldAnd(InstLoc Op1, InstLoc Op2); - InstLoc FoldOr(InstLoc Op1, InstLoc Op2); - InstLoc FoldRol(InstLoc Op1, InstLoc Op2); - InstLoc FoldShl(InstLoc Op1, InstLoc Op2); - InstLoc FoldShrl(InstLoc Op1, InstLoc Op2); - InstLoc FoldXor(InstLoc Op1, InstLoc Op2); - InstLoc FoldBranchCond(InstLoc Op1, InstLoc Op2); - InstLoc FoldIdleBranch(InstLoc Op1, InstLoc Op2); - InstLoc FoldICmp(unsigned Opcode, InstLoc Op1, InstLoc Op2); - InstLoc FoldICmpCRSigned(InstLoc Op1, InstLoc Op2); - InstLoc FoldICmpCRUnsigned(InstLoc Op1, InstLoc Op2); - InstLoc FoldDoubleBiOp(unsigned Opcode, InstLoc Op1, InstLoc Op2); - - InstLoc FoldInterpreterFallback(InstLoc Op1, InstLoc Op2); - - InstLoc FoldZeroOp(unsigned Opcode, unsigned extra); - InstLoc FoldUOp(unsigned OpCode, InstLoc Op1, - unsigned extra = 0); - InstLoc FoldBiOp(unsigned OpCode, InstLoc Op1, InstLoc Op2, - unsigned extra = 0); - - unsigned ComputeKnownZeroBits(InstLoc I); - - public: - InstLoc EmitIntConst(unsigned value); - InstLoc EmitStoreLink(InstLoc val) { - return FoldUOp(StoreLink, val); - } - InstLoc EmitBranchUncond(InstLoc val) { - return FoldUOp(BranchUncond, val); - } - InstLoc EmitBranchCond(InstLoc check, InstLoc dest) { - return FoldBiOp(BranchCond, check, dest); - } - InstLoc EmitIdleBranch(InstLoc check, InstLoc dest) { - return FoldBiOp(IdleBranch, check, dest); - } - InstLoc EmitLoadCR(unsigned crreg) { - return FoldZeroOp(LoadCR, crreg); - } - InstLoc EmitStoreCR(InstLoc value, unsigned crreg) { - return FoldUOp(StoreCR, value, crreg); - } - InstLoc EmitLoadLink() { - return FoldZeroOp(LoadLink, 0); - } - InstLoc EmitLoadMSR() { - return FoldZeroOp(LoadMSR, 0); - } - InstLoc EmitStoreMSR(InstLoc val) { - return FoldUOp(StoreMSR, val); - } - InstLoc EmitStoreFPRF(InstLoc value) { - return FoldUOp(StoreFPRF, value); - } - InstLoc EmitLoadGReg(unsigned reg) { - return FoldZeroOp(LoadGReg, reg); - } - InstLoc EmitStoreGReg(InstLoc value, unsigned reg) { - return FoldUOp(StoreGReg, value, reg); - } - InstLoc EmitAnd(InstLoc op1, InstLoc op2) { - return FoldBiOp(And, op1, op2); - } - InstLoc EmitXor(InstLoc op1, InstLoc op2) { - return FoldBiOp(Xor, op1, op2); - } - InstLoc EmitSub(InstLoc op1, InstLoc op2) { - return FoldBiOp(Sub, op1, op2); - } - InstLoc EmitOr(InstLoc op1, InstLoc op2) { - return FoldBiOp(Or, op1, op2); - } - InstLoc EmitAdd(InstLoc op1, InstLoc op2) { - return FoldBiOp(Add, op1, op2); - } - InstLoc EmitMul(InstLoc op1, InstLoc op2) { - return FoldBiOp(Mul, op1, op2); - } - InstLoc EmitRol(InstLoc op1, InstLoc op2) { - return FoldBiOp(Rol, op1, op2); - } - InstLoc EmitShl(InstLoc op1, InstLoc op2) { - return FoldBiOp(Shl, op1, op2); - } - InstLoc EmitShrl(InstLoc op1, InstLoc op2) { - return FoldBiOp(Shrl, op1, op2); - } - InstLoc EmitSarl(InstLoc op1, InstLoc op2) { - return FoldBiOp(Sarl, op1, op2); - } - InstLoc EmitLoadCTR() { - return FoldZeroOp(LoadCTR, 0); - } - InstLoc EmitStoreCTR(InstLoc op1) { - return FoldUOp(StoreCTR, op1); - } - InstLoc EmitICmpEq(InstLoc op1, InstLoc op2) { - return FoldBiOp(ICmpEq, op1, op2); - } - InstLoc EmitICmpNe(InstLoc op1, InstLoc op2) { - return FoldBiOp(ICmpNe, op1, op2); - } - InstLoc EmitICmpUgt(InstLoc op1, InstLoc op2) { - return FoldBiOp(ICmpUgt, op1, op2); - } - InstLoc EmitICmpUlt(InstLoc op1, InstLoc op2) { - return FoldBiOp(ICmpUlt, op1, op2); - } - InstLoc EmitICmpSgt(InstLoc op1, InstLoc op2) { - return FoldBiOp(ICmpSgt, op1, op2); - } - InstLoc EmitICmpSlt(InstLoc op1, InstLoc op2) { - return FoldBiOp(ICmpSlt, op1, op2); - } - InstLoc EmitICmpSge(InstLoc op1, InstLoc op2) { - return FoldBiOp(ICmpSge, op1, op2); - } - InstLoc EmitICmpSle(InstLoc op1, InstLoc op2) { - return FoldBiOp(ICmpSle, op1, op2); - } - InstLoc EmitLoad8(InstLoc op1) { - return FoldUOp(Load8, op1); - } - InstLoc EmitLoad16(InstLoc op1) { - return FoldUOp(Load16, op1); - } - InstLoc EmitLoad32(InstLoc op1) { - return FoldUOp(Load32, op1); - } - InstLoc EmitStore8(InstLoc op1, InstLoc op2) { - return FoldBiOp(Store8, op1, op2); - } - InstLoc EmitStore16(InstLoc op1, InstLoc op2) { - return FoldBiOp(Store16, op1, op2); - } - InstLoc EmitStore32(InstLoc op1, InstLoc op2) { - return FoldBiOp(Store32, op1, op2); - } - InstLoc EmitSExt16(InstLoc op1) { - return FoldUOp(SExt16, op1); - } - InstLoc EmitSExt8(InstLoc op1) { - return FoldUOp(SExt8, op1); - } - InstLoc EmitCntlzw(InstLoc op1) { - return FoldUOp(Cntlzw, op1); - } - InstLoc EmitICmpCRSigned(InstLoc op1, InstLoc op2) { - return FoldBiOp(ICmpCRSigned, op1, op2); - } - InstLoc EmitICmpCRUnsigned(InstLoc op1, InstLoc op2) { - return FoldBiOp(ICmpCRUnsigned, op1, op2); - } - InstLoc EmitInterpreterFallback(InstLoc op1, InstLoc op2) { - return FoldBiOp(InterpreterFallback, op1, op2); - } - InstLoc EmitInterpreterBranch() { - return FoldZeroOp(InterpreterBranch, 0); - } - InstLoc EmitLoadCarry() { - return FoldZeroOp(LoadCarry, 0); - } - InstLoc EmitStoreCarry(InstLoc op1) { - return FoldUOp(StoreCarry, op1); - } - InstLoc EmitSystemCall(InstLoc pc) { - return FoldUOp(SystemCall, pc); - } - InstLoc EmitRFIExit() { - return FoldZeroOp(RFIExit, 0); - } - InstLoc EmitShortIdleLoop(InstLoc pc) { - return FoldUOp(ShortIdleLoop, pc); - } - InstLoc EmitLoadSingle(InstLoc addr) { - return FoldUOp(LoadSingle, addr); - } - InstLoc EmitLoadDouble(InstLoc addr) { - return FoldUOp(LoadDouble, addr); - } - InstLoc EmitLoadPaired(InstLoc addr, unsigned quantReg) { - return FoldUOp(LoadPaired, addr, quantReg); - } - InstLoc EmitStoreSingle(InstLoc value, InstLoc addr) { - return FoldBiOp(StoreSingle, value, addr); - } - InstLoc EmitStoreDouble(InstLoc value, InstLoc addr) { - return FoldBiOp(StoreDouble, value, addr); - } - InstLoc EmitStorePaired(InstLoc value, InstLoc addr, unsigned quantReg) { - return FoldBiOp(StorePaired, value, addr, quantReg); - } - InstLoc EmitLoadFReg(unsigned freg) { - return FoldZeroOp(LoadFReg, freg); - } - InstLoc EmitLoadFRegDENToZero(unsigned freg) { - return FoldZeroOp(LoadFRegDENToZero, freg); - } - InstLoc EmitStoreFReg(InstLoc val, unsigned freg) { - return FoldUOp(StoreFReg, val, freg); - } - InstLoc EmitDupSingleToMReg(InstLoc val) { - return FoldUOp(DupSingleToMReg, val); - } - InstLoc EmitDupSingleToPacked(InstLoc val) { - return FoldUOp(DupSingleToPacked, val); - } - InstLoc EmitInsertDoubleInMReg(InstLoc val, InstLoc reg) { - return FoldBiOp(InsertDoubleInMReg, val, reg); - } - InstLoc EmitExpandPackedToMReg(InstLoc val) { - return FoldUOp(ExpandPackedToMReg, val); - } - InstLoc EmitCompactMRegToPacked(InstLoc val) { - return FoldUOp(CompactMRegToPacked, val); - } - InstLoc EmitFSMul(InstLoc op1, InstLoc op2) { - return FoldBiOp(FSMul, op1, op2); - } - InstLoc EmitFSAdd(InstLoc op1, InstLoc op2) { - return FoldBiOp(FSAdd, op1, op2); - } - InstLoc EmitFSSub(InstLoc op1, InstLoc op2) { - return FoldBiOp(FSSub, op1, op2); - } - InstLoc EmitFSNeg(InstLoc op1) { - return FoldUOp(FSNeg, op1); - } - InstLoc EmitFDMul(InstLoc op1, InstLoc op2) { - return FoldBiOp(FDMul, op1, op2); - } - InstLoc EmitFDAdd(InstLoc op1, InstLoc op2) { - return FoldBiOp(FDAdd, op1, op2); - } - InstLoc EmitFDSub(InstLoc op1, InstLoc op2) { - return FoldBiOp(FDSub, op1, op2); - } - InstLoc EmitFDNeg(InstLoc op1) { - return FoldUOp(FDNeg, op1); - } - InstLoc EmitFPAdd(InstLoc op1, InstLoc op2) { - return FoldBiOp(FPAdd, op1, op2); - } - InstLoc EmitFPMul(InstLoc op1, InstLoc op2) { - return FoldBiOp(FPMul, op1, op2); - } - InstLoc EmitFPSub(InstLoc op1, InstLoc op2) { - return FoldBiOp(FPSub, op1, op2); - } - InstLoc EmitFPMerge00(InstLoc op1, InstLoc op2) { - return FoldBiOp(FPMerge00, op1, op2); - } - InstLoc EmitFPMerge01(InstLoc op1, InstLoc op2) { - return FoldBiOp(FPMerge01, op1, op2); - } - InstLoc EmitFPMerge10(InstLoc op1, InstLoc op2) { - return FoldBiOp(FPMerge10, op1, op2); - } - InstLoc EmitFPMerge11(InstLoc op1, InstLoc op2) { - return FoldBiOp(FPMerge11, op1, op2); - } - InstLoc EmitFPDup0(InstLoc op1) { - return FoldUOp(FPDup0, op1); - } - InstLoc EmitFPDup1(InstLoc op1) { - return FoldUOp(FPDup1, op1); - } - InstLoc EmitFPNeg(InstLoc op1) { - return FoldUOp(FPNeg, op1); - } - InstLoc EmitDoubleToSingle(InstLoc op1) { - return FoldUOp(DoubleToSingle, op1); - } - InstLoc EmitFDCmpCR(InstLoc op1, InstLoc op2) { - return FoldBiOp(FDCmpCR, op1, op2); - } - InstLoc EmitLoadGQR(unsigned gqr) { - return FoldZeroOp(LoadGQR, gqr); - } - InstLoc EmitStoreGQR(InstLoc op1, unsigned gqr) { - return FoldUOp(StoreGQR, op1, gqr); - } - InstLoc EmitStoreSRR(InstLoc op1, unsigned srr) { - return FoldUOp(StoreSRR, op1, srr); - } - - void StartBackPass() { curReadPtr = &InstList[InstList.size()]; } - void StartForwardPass() { curReadPtr = &InstList[0]; } - InstLoc ReadForward() { return curReadPtr++; } - InstLoc ReadBackward() { return --curReadPtr; } - InstLoc getFirstInst() { return &InstList[0]; } - unsigned int getNumInsts() { return (unsigned int)InstList.size(); } - unsigned int ReadInst(InstLoc I) { return *I; } - unsigned int GetImmValue(InstLoc I); - - void Reset() { - InstList.clear(); - InstList.reserve(100000); - for (unsigned i = 0; i < 32; i++) { - GRegCache[i] = 0; - GRegCacheStore[i] = 0; - FRegCache[i] = 0; - FRegCacheStore[i] = 0; - } - CarryCache = 0; - CarryCacheStore = 0; - for (unsigned i = 0; i < 8; i++) { - CRCache[i] = 0; - CRCacheStore[i] = 0; - } - CTRCache = 0; - CTRCacheStore = 0; - } - - IRBuilder() { Reset(); } - - private: - IRBuilder(IRBuilder&); // DO NOT IMPLEMENT - std::vector InstList; // FIXME: We must ensure this is - // continuous! - std::vector ConstList; - InstLoc curReadPtr; - InstLoc GRegCache[32]; - InstLoc GRegCacheStore[32]; - InstLoc FRegCache[32]; - InstLoc FRegCacheStore[32]; - InstLoc CarryCache; - InstLoc CarryCacheStore; - InstLoc CTRCache; - InstLoc CTRCacheStore; - InstLoc CRCache[8]; - InstLoc CRCacheStore[8]; - }; +private: + IRBuilder(IRBuilder&); // DO NOT IMPLEMENT + std::vector InstList; // FIXME: We must ensure this is + // continuous! + std::vector ConstList; + InstLoc curReadPtr; + InstLoc GRegCache[32]; + InstLoc GRegCacheStore[32]; + InstLoc FRegCache[32]; + InstLoc FRegCacheStore[32]; + InstLoc CarryCache; + InstLoc CarryCacheStore; + InstLoc CTRCache; + InstLoc CTRCacheStore; + InstLoc CRCache[8]; + InstLoc CRCacheStore[8]; +}; }; diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit.cpp index 9cf158194f..bb9a58a3bd 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit.cpp @@ -170,314 +170,314 @@ namespace CPUCompare extern u32 m_BlockStart; } - void Jit(u32 em_address) - { - jit.Jit(em_address); - } +void Jit(u32 em_address) +{ + jit.Jit(em_address); +} - void Jit64::Init() - { - asm_routines.compareEnabled = ::Core::g_CoreStartupParameter.bRunCompareClient; - if (Core::g_CoreStartupParameter.bJITUnlimitedCache) - CODE_SIZE = 1024*1024*8*8; +void Jit64::Init() +{ + asm_routines.compareEnabled = ::Core::g_CoreStartupParameter.bRunCompareClient; + if (Core::g_CoreStartupParameter.bJITUnlimitedCache) + CODE_SIZE = 1024*1024*8*8; - jo.optimizeStack = true; - jo.enableBlocklink = true; // Speed boost, but not 100% safe + jo.optimizeStack = true; + jo.enableBlocklink = true; // Speed boost, but not 100% safe #ifdef _M_X64 #ifdef JITTEST - jo.enableFastMem = false; + jo.enableFastMem = false; #else - jo.enableFastMem = Core::GetStartupParameter().bUseFastMem; + jo.enableFastMem = Core::GetStartupParameter().bUseFastMem; #endif #else - jo.enableFastMem = false; + jo.enableFastMem = false; #endif - jo.assumeFPLoadFromMem = true; - jo.fpAccurateFlags = true; - jo.optimizeGatherPipe = true; - jo.fastInterrupts = false; - jo.accurateSinglePrecision = false; + jo.assumeFPLoadFromMem = true; + jo.fpAccurateFlags = true; + jo.optimizeGatherPipe = true; + jo.fastInterrupts = false; + jo.accurateSinglePrecision = false; - gpr.SetEmitter(this); - fpr.SetEmitter(this); + gpr.SetEmitter(this); + fpr.SetEmitter(this); - trampolines.Init(); - AllocCodeSpace(CODE_SIZE); + trampolines.Init(); + AllocCodeSpace(CODE_SIZE); - blocks.Init(); - asm_routines.Init(); - } + blocks.Init(); + asm_routines.Init(); +} - void Jit64::ClearCache() +void Jit64::ClearCache() +{ + blocks.Clear(); + trampolines.ClearCodeSpace(); + ClearCodeSpace(); +} + +void Jit64::Shutdown() +{ + FreeCodeSpace(); + + blocks.Shutdown(); + trampolines.Shutdown(); + asm_routines.Shutdown(); +} + + +void Jit64::WriteCallInterpreter(UGeckoInstruction inst) +{ + gpr.Flush(FLUSH_ALL); + fpr.Flush(FLUSH_ALL); + if (js.isLastInstruction) { - blocks.Clear(); - trampolines.ClearCodeSpace(); - ClearCodeSpace(); + MOV(32, M(&PC), Imm32(js.compilerPC)); + MOV(32, M(&NPC), Imm32(js.compilerPC + 4)); } - - void Jit64::Shutdown() + Interpreter::_interpreterInstruction instr = GetInterpreterOp(inst); + ABI_CallFunctionC((void*)instr, inst.hex); + if (js.isLastInstruction) { - FreeCodeSpace(); - - blocks.Shutdown(); - trampolines.Shutdown(); - asm_routines.Shutdown(); - } - - - void Jit64::WriteCallInterpreter(UGeckoInstruction inst) - { - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); - if (js.isLastInstruction) - { - MOV(32, M(&PC), Imm32(js.compilerPC)); - MOV(32, M(&NPC), Imm32(js.compilerPC + 4)); - } - Interpreter::_interpreterInstruction instr = GetInterpreterOp(inst); - ABI_CallFunctionC((void*)instr, inst.hex); - if (js.isLastInstruction) - { - MOV(32, R(EAX), M(&NPC)); - WriteRfiExitDestInEAX(); - } - } - - void Jit64::unknown_instruction(UGeckoInstruction inst) - { - // CCPU::Break(); - PanicAlert("unknown_instruction %08x - Fix me ;)", inst.hex); - } - - void Jit64::Default(UGeckoInstruction _inst) - { - ibuild.EmitInterpreterFallback( - ibuild.EmitIntConst(_inst.hex), - ibuild.EmitIntConst(js.compilerPC)); - } - - void Jit64::HLEFunction(UGeckoInstruction _inst) - { - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); - ABI_CallFunctionCC((void*)&HLE::Execute, js.compilerPC, _inst.hex); MOV(32, R(EAX), M(&NPC)); - WriteExitDestInEAX(0); + WriteRfiExitDestInEAX(); } +} - void Jit64::DoNothing(UGeckoInstruction _inst) +void Jit64::unknown_instruction(UGeckoInstruction inst) +{ + // CCPU::Break(); + PanicAlert("unknown_instruction %08x - Fix me ;)", inst.hex); +} + +void Jit64::Default(UGeckoInstruction _inst) +{ + ibuild.EmitInterpreterFallback( + ibuild.EmitIntConst(_inst.hex), + ibuild.EmitIntConst(js.compilerPC)); +} + +void Jit64::HLEFunction(UGeckoInstruction _inst) +{ + gpr.Flush(FLUSH_ALL); + fpr.Flush(FLUSH_ALL); + ABI_CallFunctionCC((void*)&HLE::Execute, js.compilerPC, _inst.hex); + MOV(32, R(EAX), M(&NPC)); + WriteExitDestInEAX(0); +} + +void Jit64::DoNothing(UGeckoInstruction _inst) +{ + // Yup, just don't do anything. +} + +void Jit64::NotifyBreakpoint(u32 em_address, bool set) +{ + int block_num = blocks.GetBlockNumberFromStartAddress(em_address); + if (block_num >= 0) { - // Yup, just don't do anything. + blocks.DestroyBlock(block_num, false); } +} - void Jit64::NotifyBreakpoint(u32 em_address, bool set) - { - int block_num = blocks.GetBlockNumberFromStartAddress(em_address); - if (block_num >= 0) +static const bool ImHereDebug = false; +static const bool ImHereLog = false; +static std::map been_here; + +void ImHere() +{ + static FILE *f = 0; + if (ImHereLog) { + if (!f) { - blocks.DestroyBlock(block_num, false); - } - } - - static const bool ImHereDebug = false; - static const bool ImHereLog = false; - static std::map been_here; - - void ImHere() - { - static FILE *f = 0; - if (ImHereLog) { - if (!f) - { #ifdef _M_X64 - f = fopen("log64.txt", "w"); + f = fopen("log64.txt", "w"); #else - f = fopen("log32.txt", "w"); + f = fopen("log32.txt", "w"); #endif - } - fprintf(f, "%08x\n", PC); } - if (been_here.find(PC) != been_here.end()) { - been_here.find(PC)->second++; - if ((been_here.find(PC)->second) & 1023) - return; - } - DEBUG_LOG(DYNA_REC, "I'm here - PC = %08x , LR = %08x", PC, LR); - // printf("I'm here - PC = %08x , LR = %08x", PC, LR); - been_here[PC] = 1; + fprintf(f, "%08x\n", PC); } - - void Jit64::Cleanup() - { - if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0) - ABI_CallFunction((void *)&GPFifo::CheckGatherPipe); + if (been_here.find(PC) != been_here.end()) { + been_here.find(PC)->second++; + if ((been_here.find(PC)->second) & 1023) + return; } + DEBUG_LOG(DYNA_REC, "I'm here - PC = %08x , LR = %08x", PC, LR); + // printf("I'm here - PC = %08x , LR = %08x", PC, LR); + been_here[PC] = 1; +} - void Jit64::WriteExit(u32 destination, int exit_num) +void Jit64::Cleanup() +{ + if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0) + ABI_CallFunction((void *)&GPFifo::CheckGatherPipe); +} + +void Jit64::WriteExit(u32 destination, int exit_num) +{ + Cleanup(); + SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); + + //If nobody has taken care of this yet (this can be removed when all branches are done) + JitBlock *b = js.curBlock; + b->exitAddress[exit_num] = destination; + b->exitPtrs[exit_num] = GetWritableCodePtr(); + + // Link opportunity! + int block = blocks.GetBlockNumberFromStartAddress(destination); + if (block >= 0 && jo.enableBlocklink) { - Cleanup(); - SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); - - //If nobody has taken care of this yet (this can be removed when all branches are done) - JitBlock *b = js.curBlock; - b->exitAddress[exit_num] = destination; - b->exitPtrs[exit_num] = GetWritableCodePtr(); - - // Link opportunity! - int block = blocks.GetBlockNumberFromStartAddress(destination); - if (block >= 0 && jo.enableBlocklink) - { - // It exists! Joy of joy! - JMP(blocks.GetBlock(block)->checkedEntry, true); - b->linkStatus[exit_num] = true; - } - else - { - MOV(32, M(&PC), Imm32(destination)); - JMP(asm_routines.dispatcher, true); - } + // It exists! Joy of joy! + JMP(blocks.GetBlock(block)->checkedEntry, true); + b->linkStatus[exit_num] = true; } - - void Jit64::WriteExitDestInEAX(int exit_num) + else { - MOV(32, M(&PC), R(EAX)); - Cleanup(); - SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); + MOV(32, M(&PC), Imm32(destination)); JMP(asm_routines.dispatcher, true); } +} - void Jit64::WriteRfiExitDestInEAX() - { - MOV(32, M(&PC), R(EAX)); - Cleanup(); - SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); - JMP(asm_routines.testExceptions, true); - } +void Jit64::WriteExitDestInEAX(int exit_num) +{ + MOV(32, M(&PC), R(EAX)); + Cleanup(); + SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); + JMP(asm_routines.dispatcher, true); +} - void Jit64::WriteExceptionExit(u32 exception) +void Jit64::WriteRfiExitDestInEAX() +{ + MOV(32, M(&PC), R(EAX)); + Cleanup(); + SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); + JMP(asm_routines.testExceptions, true); +} + +void Jit64::WriteExceptionExit(u32 exception) +{ + Cleanup(); + OR(32, M(&PowerPC::ppcState.Exceptions), Imm32(exception)); + MOV(32, M(&PC), Imm32(js.compilerPC + 4)); + JMP(asm_routines.testExceptions, true); +} + +void STACKALIGN Jit64::Run() +{ + CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode; + pExecAddr(); + //Will return when PowerPC::state changes +} + +void Jit64::SingleStep() +{ + // NOT USED, NOT TESTED, PROBABLY NOT WORKING YET + // PanicAlert("Single"); + /* + JitBlock temp_block; + PPCAnalyst::CodeBuffer temp_codebuffer(1); // Only room for one instruction! Single step! + const u8 *code = DoJit(PowerPC::ppcState.pc, &temp_codebuffer, &temp_block); + CompiledCode pExecAddr = (CompiledCode)code; + pExecAddr();*/ +} + +void STACKALIGN Jit64::Jit(u32 em_address) +{ + if (GetSpaceLeft() < 0x10000 || blocks.IsFull()) { - Cleanup(); - OR(32, M(&PowerPC::ppcState.Exceptions), Imm32(exception)); - MOV(32, M(&PC), Imm32(js.compilerPC + 4)); - JMP(asm_routines.testExceptions, true); + INFO_LOG(DYNA_REC, "JIT cache full - clearing.") + if (Core::g_CoreStartupParameter.bJITUnlimitedCache) + { + ERROR_LOG(DYNA_REC, "What? JIT cache still full - clearing."); + PanicAlert("What? JIT cache still full - clearing."); + } + ClearCache(); } + int block_num = blocks.AllocateBlock(em_address); + JitBlock *b = blocks.GetBlock(block_num); + blocks.FinalizeBlock(block_num, jo.enableBlocklink, DoJit(em_address, &code_buffer, b)); +} + +const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buffer, JitBlock *b) +{ + if (em_address == 0) + PanicAlert("ERROR : Trying to compile at 0. LR=%08x", LR); + + int size; + js.isLastInstruction = false; + js.blockStart = em_address; + js.fifoBytesThisBlock = 0; + js.curBlock = b; + js.blockSetsQuantizers = false; + js.block_flags = 0; + js.cancel = false; + + //Analyze the block, collect all instructions it is made of (including inlining, + //if that is enabled), reorder instructions for optimal performance, and join joinable instructions. + PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, code_buffer); + PPCAnalyst::CodeOp *ops = code_buffer->codebuffer; + + const u8 *start = AlignCode4(); //TODO: Test if this or AlignCode16 make a difference from GetCodePtr + b->checkedEntry = start; + b->runCount = 0; + + // Downcount flag check. The last block decremented downcounter, and the flag should still be available. + FixupBranch skip = J_CC(CC_NBE); + MOV(32, M(&PC), Imm32(js.blockStart)); + JMP(asm_routines.doTiming, true); // downcount hit zero - go doTiming. + SetJumpTarget(skip); + + const u8 *normalEntry = GetCodePtr(); + b->normalEntry = normalEntry; - void STACKALIGN Jit64::Run() + if (ImHereDebug) + ABI_CallFunction((void *)&ImHere); //Used to get a trace of the last few blocks before a crash, sometimes VERY useful + + if (js.fpa.any) { - CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode; - pExecAddr(); - //Will return when PowerPC::state changes - } - - void Jit64::SingleStep() - { - // NOT USED, NOT TESTED, PROBABLY NOT WORKING YET - // PanicAlert("Single"); - /* - JitBlock temp_block; - PPCAnalyst::CodeBuffer temp_codebuffer(1); // Only room for one instruction! Single step! - const u8 *code = DoJit(PowerPC::ppcState.pc, &temp_codebuffer, &temp_block); - CompiledCode pExecAddr = (CompiledCode)code; - pExecAddr();*/ - } - - void STACKALIGN Jit64::Jit(u32 em_address) - { - if (GetSpaceLeft() < 0x10000 || blocks.IsFull()) - { - INFO_LOG(DYNA_REC, "JIT cache full - clearing.") - if (Core::g_CoreStartupParameter.bJITUnlimitedCache) - { - ERROR_LOG(DYNA_REC, "What? JIT cache still full - clearing."); - PanicAlert("What? JIT cache still full - clearing."); - } - ClearCache(); - } - int block_num = blocks.AllocateBlock(em_address); - JitBlock *b = blocks.GetBlock(block_num); - blocks.FinalizeBlock(block_num, jo.enableBlocklink, DoJit(em_address, &code_buffer, b)); - } - - const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buffer, JitBlock *b) - { - if (em_address == 0) - PanicAlert("ERROR : Trying to compile at 0. LR=%08x", LR); - - int size; - js.isLastInstruction = false; - js.blockStart = em_address; - js.fifoBytesThisBlock = 0; - js.curBlock = b; - js.blockSetsQuantizers = false; - js.block_flags = 0; - js.cancel = false; - - //Analyze the block, collect all instructions it is made of (including inlining, - //if that is enabled), reorder instructions for optimal performance, and join joinable instructions. - PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, code_buffer); - PPCAnalyst::CodeOp *ops = code_buffer->codebuffer; - - const u8 *start = AlignCode4(); //TODO: Test if this or AlignCode16 make a difference from GetCodePtr - b->checkedEntry = start; - b->runCount = 0; - - // Downcount flag check. The last block decremented downcounter, and the flag should still be available. - FixupBranch skip = J_CC(CC_NBE); + //This block uses FPU - needs to add FP exception bailout + TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); //Test FP enabled bit + FixupBranch b1 = J_CC(CC_NZ); MOV(32, M(&PC), Imm32(js.blockStart)); - JMP(asm_routines.doTiming, true); // downcount hit zero - go doTiming. - SetJumpTarget(skip); - - const u8 *normalEntry = GetCodePtr(); - b->normalEntry = normalEntry; - - if (ImHereDebug) - ABI_CallFunction((void *)&ImHere); //Used to get a trace of the last few blocks before a crash, sometimes VERY useful - - if (js.fpa.any) - { - //This block uses FPU - needs to add FP exception bailout - TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); //Test FP enabled bit - FixupBranch b1 = J_CC(CC_NZ); - MOV(32, M(&PC), Imm32(js.blockStart)); - JMP(asm_routines.fpException, true); - SetJumpTarget(b1); - } - - js.rewriteStart = (u8*)GetCodePtr(); - - // Start up IR builder (structure that collects the - // instruction processed by the JIT routines) - ibuild.Reset(); - - js.downcountAmount = js.st.numCycles + PatchEngine::GetSpeedhackCycles(em_address); - js.blockSize = size; - // Translate instructions - for (int i = 0; i < (int)size; i++) - { - js.compilerPC = ops[i].address; - js.op = &ops[i]; - js.instructionNumber = i; - if (i == (int)size - 1) - { - js.isLastInstruction = true; - js.next_inst = 0; - } - else - { - // help peephole optimizations - js.next_inst = ops[i + 1].inst; - js.next_compilerPC = ops[i + 1].address; - } - - if (!ops[i].skip) - PPCTables::CompileInstruction(ops[i].inst); - } - - // Perform actual code generation - WriteCode(); - - b->flags = js.block_flags; - b->codeSize = (u32)(GetCodePtr() - normalEntry); - b->originalSize = size; - return normalEntry; + JMP(asm_routines.fpException, true); + SetJumpTarget(b1); } + + js.rewriteStart = (u8*)GetCodePtr(); + + // Start up IR builder (structure that collects the + // instruction processed by the JIT routines) + ibuild.Reset(); + + js.downcountAmount = js.st.numCycles + PatchEngine::GetSpeedhackCycles(em_address); + js.blockSize = size; + // Translate instructions + for (int i = 0; i < (int)size; i++) + { + js.compilerPC = ops[i].address; + js.op = &ops[i]; + js.instructionNumber = i; + if (i == (int)size - 1) + { + js.isLastInstruction = true; + js.next_inst = 0; + } + else + { + // help peephole optimizations + js.next_inst = ops[i + 1].inst; + js.next_compilerPC = ops[i + 1].address; + } + + if (!ops[i].skip) + PPCTables::CompileInstruction(ops[i].inst); + } + + // Perform actual code generation + WriteCode(); + + b->flags = js.block_flags; + b->codeSize = (u32)(GetCodePtr() - normalEntry); + b->originalSize = size; + return normalEntry; +} diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit.h index 3488d77b6e..02a8c5bc6b 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit.h +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit.h @@ -71,6 +71,14 @@ struct CONTEXT Core::g_CoreStartupParameter.bJIT##type##Off) \ {Default(inst); return;} +#ifdef _M_X64 +#define DISABLE64 \ + {Default(inst); return;} +#else +#define DISABLE64 +#endif + + class TrampolineCache : public Gen::XCodeBlock { public: diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Branch.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Branch.cpp index 2bc5dd8db3..bfd7035acc 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Branch.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Branch.cpp @@ -45,150 +45,149 @@ using namespace Gen; - void Jit64::sc(UGeckoInstruction inst) - { - ibuild.EmitSystemCall(ibuild.EmitIntConst(js.compilerPC)); +void Jit64::sc(UGeckoInstruction inst) +{ + ibuild.EmitSystemCall(ibuild.EmitIntConst(js.compilerPC)); +} + +void Jit64::rfi(UGeckoInstruction inst) +{ + ibuild.EmitRFIExit(); +} + +void Jit64::bx(UGeckoInstruction inst) +{ + NORMALBRANCH_START + INSTRUCTION_START; + + if (inst.LK) + ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4)); + + u32 destination; + if (inst.AA) + destination = SignExt26(inst.LI << 2); + else + destination = js.compilerPC + SignExt26(inst.LI << 2); + + if (destination == js.compilerPC) { + ibuild.EmitShortIdleLoop(ibuild.EmitIntConst(js.compilerPC)); + return; } - void Jit64::rfi(UGeckoInstruction inst) + ibuild.EmitBranchUncond(ibuild.EmitIntConst(destination)); +} + +static IREmitter::InstLoc TestBranch(IREmitter::IRBuilder& ibuild, UGeckoInstruction inst) { + IREmitter::InstLoc CRTest = 0, CTRTest = 0; + if ((inst.BO & 16) == 0) // Test a CR bit { - ibuild.EmitRFIExit(); + IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2); + IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3)); + CRTest = ibuild.EmitAnd(CRReg, CRCmp); + if (!(inst.BO & 8)) + CRTest = ibuild.EmitXor(CRTest, CRCmp); } - void Jit64::bx(UGeckoInstruction inst) - { - NORMALBRANCH_START - INSTRUCTION_START; - - if (inst.LK) - ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4)); - - u32 destination; - if (inst.AA) - destination = SignExt26(inst.LI << 2); - else - destination = js.compilerPC + SignExt26(inst.LI << 2); - - if (destination == js.compilerPC) { - ibuild.EmitShortIdleLoop(ibuild.EmitIntConst(js.compilerPC)); - return; - } - - ibuild.EmitBranchUncond(ibuild.EmitIntConst(destination)); - } - - static IREmitter::InstLoc TestBranch(IREmitter::IRBuilder& ibuild, UGeckoInstruction inst) { - IREmitter::InstLoc CRTest = 0, CTRTest = 0; - if ((inst.BO & 16) == 0) // Test a CR bit - { - IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2); - IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3)); - CRTest = ibuild.EmitAnd(CRReg, CRCmp); - if (!(inst.BO & 8)) - CRTest = ibuild.EmitXor(CRTest, CRCmp); - } - - if ((inst.BO & 4) == 0) { - IREmitter::InstLoc c = ibuild.EmitLoadCTR(); - c = ibuild.EmitSub(c, ibuild.EmitIntConst(1)); - ibuild.EmitStoreCTR(c); - if (inst.BO & 2) { - CTRTest = ibuild.EmitICmpEq(c, - ibuild.EmitIntConst(0)); - } else { - CTRTest = c; - } - } - - IREmitter::InstLoc Test = CRTest; - if (CTRTest) { - if (Test) - Test = ibuild.EmitAnd(Test, CTRTest); - else - Test = CTRTest; - } - - if (!Test) { - Test = ibuild.EmitIntConst(1); - } - return Test; - } - - void Jit64::bcx(UGeckoInstruction inst) - { - NORMALBRANCH_START - if (inst.LK) - ibuild.EmitStoreLink( - ibuild.EmitIntConst(js.compilerPC + 4)); - - IREmitter::InstLoc Test = TestBranch(ibuild, inst); - - u32 destination; - if(inst.AA) - destination = SignExt16(inst.BD << 2); - else - destination = js.compilerPC + SignExt16(inst.BD << 2); - - if (Core::GetStartupParameter().bSkipIdle && - inst.hex == 0x4182fff8 && - (Memory::ReadUnchecked_U32(js.compilerPC - 8) & 0xFFFF0000) == 0x800D0000 && - (Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x28000000 || - (Core::GetStartupParameter().bWii && Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x2C000000)) - ) - { - ibuild.EmitIdleBranch(Test, ibuild.EmitIntConst(destination)); - } - else - { - ibuild.EmitBranchCond(Test, ibuild.EmitIntConst(destination)); - } - ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4)); - } - - void Jit64::bcctrx(UGeckoInstruction inst) - { - NORMALBRANCH_START - if ((inst.BO & 4) == 0) { - IREmitter::InstLoc c = ibuild.EmitLoadCTR(); - c = ibuild.EmitSub(c, ibuild.EmitIntConst(1)); - ibuild.EmitStoreCTR(c); - } - IREmitter::InstLoc test; - if ((inst.BO & 16) == 0) // Test a CR bit - { - IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2); - IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3)); - test = ibuild.EmitAnd(CRReg, CRCmp); - if (!(inst.BO & 8)) - test = ibuild.EmitXor(test, CRCmp); + if ((inst.BO & 4) == 0) { + IREmitter::InstLoc c = ibuild.EmitLoadCTR(); + c = ibuild.EmitSub(c, ibuild.EmitIntConst(1)); + ibuild.EmitStoreCTR(c); + if (inst.BO & 2) { + CTRTest = ibuild.EmitICmpEq(c, + ibuild.EmitIntConst(0)); } else { - test = ibuild.EmitIntConst(1); + CTRTest = c; } - test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0)); - ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4)); - - IREmitter::InstLoc destination = ibuild.EmitLoadCTR(); - destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4)); - if (inst.LK) - ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4)); - ibuild.EmitBranchUncond(destination); } - void Jit64::bclrx(UGeckoInstruction inst) + IREmitter::InstLoc Test = CRTest; + if (CTRTest) { + if (Test) + Test = ibuild.EmitAnd(Test, CTRTest); + else + Test = CTRTest; + } + + if (!Test) { + Test = ibuild.EmitIntConst(1); + } + return Test; +} + +void Jit64::bcx(UGeckoInstruction inst) +{ + NORMALBRANCH_START + if (inst.LK) + ibuild.EmitStoreLink( + ibuild.EmitIntConst(js.compilerPC + 4)); + + IREmitter::InstLoc Test = TestBranch(ibuild, inst); + + u32 destination; + if(inst.AA) + destination = SignExt16(inst.BD << 2); + else + destination = js.compilerPC + SignExt16(inst.BD << 2); + + if (Core::GetStartupParameter().bSkipIdle && + inst.hex == 0x4182fff8 && + (Memory::ReadUnchecked_U32(js.compilerPC - 8) & 0xFFFF0000) == 0x800D0000 && + (Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x28000000 || + (Core::GetStartupParameter().bWii && Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x2C000000)) + ) + { + ibuild.EmitIdleBranch(Test, ibuild.EmitIntConst(destination)); + } + else { - NORMALBRANCH_START - if (inst.hex == 0x4e800020) { - ibuild.EmitBranchUncond(ibuild.EmitLoadLink()); - return; - } - IREmitter::InstLoc test = TestBranch(ibuild, inst); - test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0)); - ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4)); - - IREmitter::InstLoc destination = ibuild.EmitLoadLink(); - destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4)); - if (inst.LK) - ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4)); - ibuild.EmitBranchUncond(destination); + ibuild.EmitBranchCond(Test, ibuild.EmitIntConst(destination)); } + ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4)); +} +void Jit64::bcctrx(UGeckoInstruction inst) +{ + NORMALBRANCH_START + if ((inst.BO & 4) == 0) { + IREmitter::InstLoc c = ibuild.EmitLoadCTR(); + c = ibuild.EmitSub(c, ibuild.EmitIntConst(1)); + ibuild.EmitStoreCTR(c); + } + IREmitter::InstLoc test; + if ((inst.BO & 16) == 0) // Test a CR bit + { + IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2); + IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3)); + test = ibuild.EmitAnd(CRReg, CRCmp); + if (!(inst.BO & 8)) + test = ibuild.EmitXor(test, CRCmp); + } else { + test = ibuild.EmitIntConst(1); + } + test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0)); + ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4)); + + IREmitter::InstLoc destination = ibuild.EmitLoadCTR(); + destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4)); + if (inst.LK) + ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4)); + ibuild.EmitBranchUncond(destination); +} + +void Jit64::bclrx(UGeckoInstruction inst) +{ + NORMALBRANCH_START + if (inst.hex == 0x4e800020) { + ibuild.EmitBranchUncond(ibuild.EmitLoadLink()); + return; + } + IREmitter::InstLoc test = TestBranch(ibuild, inst); + test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0)); + ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4)); + + IREmitter::InstLoc destination = ibuild.EmitLoadLink(); + destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4)); + if (inst.LK) + ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4)); + ibuild.EmitBranchUncond(destination); +} diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_FloatingPoint.cpp index 9fe28e2dd9..61aedcc90a 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_FloatingPoint.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_FloatingPoint.cpp @@ -28,86 +28,86 @@ //#define INSTRUCTION_START Default(inst); return; #define INSTRUCTION_START - void Jit64::fp_arith_s(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(FloatingPoint) - if (inst.Rc || (inst.SUBOP5 != 25 && inst.SUBOP5 != 20 && inst.SUBOP5 != 21)) { - Default(inst); return; - } - IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA); - switch (inst.SUBOP5) - { - case 25: //mul - val = ibuild.EmitFDMul(val, ibuild.EmitLoadFReg(inst.FC)); - break; - case 18: //div - case 20: //sub - val = ibuild.EmitFDSub(val, ibuild.EmitLoadFReg(inst.FB)); - break; - case 21: //add - val = ibuild.EmitFDAdd(val, ibuild.EmitLoadFReg(inst.FB)); - break; - case 23: //sel - case 24: //res - default: - _assert_msg_(DYNA_REC, 0, "fp_arith_s WTF!!!"); - } - - if (inst.OPCD == 59) { - val = ibuild.EmitDoubleToSingle(val); - val = ibuild.EmitDupSingleToMReg(val); - } else { - val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD)); - } - ibuild.EmitStoreFReg(val, inst.FD); +void Jit64::fp_arith_s(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(FloatingPoint) + if (inst.Rc || (inst.SUBOP5 != 25 && inst.SUBOP5 != 20 && inst.SUBOP5 != 21)) { + Default(inst); return; } - - void Jit64::fmaddXX(UGeckoInstruction inst) + IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA); + switch (inst.SUBOP5) { - INSTRUCTION_START - JITDISABLE(FloatingPoint) - if (inst.Rc) { - Default(inst); return; - } - - IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA); + case 25: //mul val = ibuild.EmitFDMul(val, ibuild.EmitLoadFReg(inst.FC)); - if (inst.SUBOP5 & 1) - val = ibuild.EmitFDAdd(val, ibuild.EmitLoadFReg(inst.FB)); - else - val = ibuild.EmitFDSub(val, ibuild.EmitLoadFReg(inst.FB)); - if (inst.SUBOP5 & 2) - val = ibuild.EmitFDNeg(val); - if (inst.OPCD == 59) { - val = ibuild.EmitDoubleToSingle(val); - val = ibuild.EmitDupSingleToMReg(val); - } else { - val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD)); - } - ibuild.EmitStoreFReg(val, inst.FD); - } - - void Jit64::fmrx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(FloatingPoint) - if (inst.Rc) { - Default(inst); return; - } - IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FB); - val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD)); - ibuild.EmitStoreFReg(val, inst.FD); + break; + case 18: //div + case 20: //sub + val = ibuild.EmitFDSub(val, ibuild.EmitLoadFReg(inst.FB)); + break; + case 21: //add + val = ibuild.EmitFDAdd(val, ibuild.EmitLoadFReg(inst.FB)); + break; + case 23: //sel + case 24: //res + default: + _assert_msg_(DYNA_REC, 0, "fp_arith_s WTF!!!"); } - void Jit64::fcmpx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(FloatingPoint) - IREmitter::InstLoc lhs, rhs, res; - lhs = ibuild.EmitLoadFRegDENToZero(inst.FA); - rhs = ibuild.EmitLoadFRegDENToZero(inst.FB); - res = ibuild.EmitFDCmpCR(lhs, rhs); - ibuild.EmitStoreFPRF(res); - ibuild.EmitStoreCR(res, inst.CRFD); + if (inst.OPCD == 59) { + val = ibuild.EmitDoubleToSingle(val); + val = ibuild.EmitDupSingleToMReg(val); + } else { + val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD)); } + ibuild.EmitStoreFReg(val, inst.FD); +} + +void Jit64::fmaddXX(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(FloatingPoint) + if (inst.Rc) { + Default(inst); return; + } + + IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA); + val = ibuild.EmitFDMul(val, ibuild.EmitLoadFReg(inst.FC)); + if (inst.SUBOP5 & 1) + val = ibuild.EmitFDAdd(val, ibuild.EmitLoadFReg(inst.FB)); + else + val = ibuild.EmitFDSub(val, ibuild.EmitLoadFReg(inst.FB)); + if (inst.SUBOP5 & 2) + val = ibuild.EmitFDNeg(val); + if (inst.OPCD == 59) { + val = ibuild.EmitDoubleToSingle(val); + val = ibuild.EmitDupSingleToMReg(val); + } else { + val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD)); + } + ibuild.EmitStoreFReg(val, inst.FD); +} + +void Jit64::fmrx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(FloatingPoint) + if (inst.Rc) { + Default(inst); return; + } + IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FB); + val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD)); + ibuild.EmitStoreFReg(val, inst.FD); +} + +void Jit64::fcmpx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(FloatingPoint) + IREmitter::InstLoc lhs, rhs, res; + lhs = ibuild.EmitLoadFRegDENToZero(inst.FA); + rhs = ibuild.EmitLoadFRegDENToZero(inst.FB); + res = ibuild.EmitFDCmpCR(lhs, rhs); + ibuild.EmitStoreFPRF(res); + ibuild.EmitStoreCR(res, inst.CRFD); +} diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Integer.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Integer.cpp index a3693d207a..ec2e201387 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Integer.cpp @@ -31,514 +31,514 @@ //#define INSTRUCTION_START Default(inst); return; #define INSTRUCTION_START - static void ComputeRC(IREmitter::IRBuilder& ibuild, - IREmitter::InstLoc val) { - IREmitter::InstLoc res = - ibuild.EmitICmpCRSigned(val, ibuild.EmitIntConst(0)); - ibuild.EmitStoreCR(res, 0); - } +static void ComputeRC(IREmitter::IRBuilder& ibuild, + IREmitter::InstLoc val) { + IREmitter::InstLoc res = + ibuild.EmitICmpCRSigned(val, ibuild.EmitIntConst(0)); + ibuild.EmitStoreCR(res, 0); +} - void Jit64::reg_imm(UGeckoInstruction inst) +void Jit64::reg_imm(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + int d = inst.RD, a = inst.RA, s = inst.RS; + IREmitter::InstLoc val, test, c; + switch (inst.OPCD) { - INSTRUCTION_START - JITDISABLE(Integer) - int d = inst.RD, a = inst.RA, s = inst.RS; - IREmitter::InstLoc val, test, c; - switch (inst.OPCD) - { - case 14: //addi - val = ibuild.EmitIntConst(inst.SIMM_16); - if (a) - val = ibuild.EmitAdd(ibuild.EmitLoadGReg(a), val); - ibuild.EmitStoreGReg(val, d); - break; - case 15: //addis - val = ibuild.EmitIntConst(inst.SIMM_16 << 16); - if (a) - val = ibuild.EmitAdd(ibuild.EmitLoadGReg(a), val); - ibuild.EmitStoreGReg(val, d); - break; - case 24: //ori - val = ibuild.EmitIntConst(inst.UIMM); - val = ibuild.EmitOr(ibuild.EmitLoadGReg(s), val); - ibuild.EmitStoreGReg(val, a); - break; - case 25: //oris - val = ibuild.EmitIntConst(inst.UIMM << 16); - val = ibuild.EmitOr(ibuild.EmitLoadGReg(s), val); - ibuild.EmitStoreGReg(val, a); - break; - case 28: //andi - val = ibuild.EmitIntConst(inst.UIMM); - val = ibuild.EmitAnd(ibuild.EmitLoadGReg(s), val); - ibuild.EmitStoreGReg(val, a); + case 14: //addi + val = ibuild.EmitIntConst(inst.SIMM_16); + if (a) + val = ibuild.EmitAdd(ibuild.EmitLoadGReg(a), val); + ibuild.EmitStoreGReg(val, d); + break; + case 15: //addis + val = ibuild.EmitIntConst(inst.SIMM_16 << 16); + if (a) + val = ibuild.EmitAdd(ibuild.EmitLoadGReg(a), val); + ibuild.EmitStoreGReg(val, d); + break; + case 24: //ori + val = ibuild.EmitIntConst(inst.UIMM); + val = ibuild.EmitOr(ibuild.EmitLoadGReg(s), val); + ibuild.EmitStoreGReg(val, a); + break; + case 25: //oris + val = ibuild.EmitIntConst(inst.UIMM << 16); + val = ibuild.EmitOr(ibuild.EmitLoadGReg(s), val); + ibuild.EmitStoreGReg(val, a); + break; + case 28: //andi + val = ibuild.EmitIntConst(inst.UIMM); + val = ibuild.EmitAnd(ibuild.EmitLoadGReg(s), val); + ibuild.EmitStoreGReg(val, a); + ComputeRC(ibuild, val); + break; + case 29: //andis + val = ibuild.EmitIntConst(inst.UIMM << 16); + val = ibuild.EmitAnd(ibuild.EmitLoadGReg(s), val); + ibuild.EmitStoreGReg(val, a); + ComputeRC(ibuild, val); + break; + case 26: //xori + val = ibuild.EmitIntConst(inst.UIMM); + val = ibuild.EmitXor(ibuild.EmitLoadGReg(s), val); + ibuild.EmitStoreGReg(val, a); + break; + case 27: //xoris + val = ibuild.EmitIntConst(inst.UIMM << 16); + val = ibuild.EmitXor(ibuild.EmitLoadGReg(s), val); + ibuild.EmitStoreGReg(val, a); + break; + case 12: //addic + case 13: //addic_rc + c = ibuild.EmitIntConst(inst.SIMM_16); + val = ibuild.EmitAdd(ibuild.EmitLoadGReg(a), c); + ibuild.EmitStoreGReg(val, d); + test = ibuild.EmitICmpUgt(c, val); + ibuild.EmitStoreCarry(test); + if (inst.OPCD == 13) ComputeRC(ibuild, val); - break; - case 29: //andis - val = ibuild.EmitIntConst(inst.UIMM << 16); - val = ibuild.EmitAnd(ibuild.EmitLoadGReg(s), val); - ibuild.EmitStoreGReg(val, a); - ComputeRC(ibuild, val); - break; - case 26: //xori - val = ibuild.EmitIntConst(inst.UIMM); - val = ibuild.EmitXor(ibuild.EmitLoadGReg(s), val); - ibuild.EmitStoreGReg(val, a); - break; - case 27: //xoris - val = ibuild.EmitIntConst(inst.UIMM << 16); - val = ibuild.EmitXor(ibuild.EmitLoadGReg(s), val); - ibuild.EmitStoreGReg(val, a); - break; - case 12: //addic - case 13: //addic_rc - c = ibuild.EmitIntConst(inst.SIMM_16); - val = ibuild.EmitAdd(ibuild.EmitLoadGReg(a), c); - ibuild.EmitStoreGReg(val, d); - test = ibuild.EmitICmpUgt(c, val); - ibuild.EmitStoreCarry(test); - if (inst.OPCD == 13) - ComputeRC(ibuild, val); - break; - default: - Default(inst); - break; - } + break; + default: + Default(inst); + break; } +} - void Jit64::cmpXX(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc lhs, rhs, res; - lhs = ibuild.EmitLoadGReg(inst.RA); - if (inst.OPCD == 31) { - rhs = ibuild.EmitLoadGReg(inst.RB); - if (inst.SUBOP10 == 32) { - res = ibuild.EmitICmpCRUnsigned(lhs, rhs); - } else { - res = ibuild.EmitICmpCRSigned(lhs, rhs); - } - } else if (inst.OPCD == 10) { - rhs = ibuild.EmitIntConst(inst.UIMM); +void Jit64::cmpXX(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc lhs, rhs, res; + lhs = ibuild.EmitLoadGReg(inst.RA); + if (inst.OPCD == 31) { + rhs = ibuild.EmitLoadGReg(inst.RB); + if (inst.SUBOP10 == 32) { res = ibuild.EmitICmpCRUnsigned(lhs, rhs); - } else { // inst.OPCD == 11 - rhs = ibuild.EmitIntConst(inst.SIMM_16); + } else { res = ibuild.EmitICmpCRSigned(lhs, rhs); } - - ibuild.EmitStoreCR(res, inst.CRFD); + } else if (inst.OPCD == 10) { + rhs = ibuild.EmitIntConst(inst.UIMM); + res = ibuild.EmitICmpCRUnsigned(lhs, rhs); + } else { // inst.OPCD == 11 + rhs = ibuild.EmitIntConst(inst.SIMM_16); + res = ibuild.EmitICmpCRSigned(lhs, rhs); } - - void Jit64::orx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RB); - val = ibuild.EmitOr(ibuild.EmitLoadGReg(inst.RS), val); - ibuild.EmitStoreGReg(val, inst.RA); - if (inst.Rc) - ComputeRC(ibuild, val); - } - - // m_GPR[_inst.RA] = m_GPR[_inst.RS] ^ m_GPR[_inst.RB]; - void Jit64::xorx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RB); - val = ibuild.EmitXor(ibuild.EmitLoadGReg(inst.RS), val); - ibuild.EmitStoreGReg(val, inst.RA); - if (inst.Rc) - ComputeRC(ibuild, val); - } + ibuild.EmitStoreCR(res, inst.CRFD); +} - void Jit64::andx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RB); - val = ibuild.EmitAnd(ibuild.EmitLoadGReg(inst.RS), val); - ibuild.EmitStoreGReg(val, inst.RA); - if (inst.Rc) - ComputeRC(ibuild, val); - } +void Jit64::orx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RB); + val = ibuild.EmitOr(ibuild.EmitLoadGReg(inst.RS), val); + ibuild.EmitStoreGReg(val, inst.RA); + if (inst.Rc) + ComputeRC(ibuild, val); +} - void Jit64::extsbx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS); - val = ibuild.EmitSExt8(val); - ibuild.EmitStoreGReg(val, inst.RA); - if (inst.Rc) - ComputeRC(ibuild, val); - } - void Jit64::extshx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS); - val = ibuild.EmitSExt16(val); - ibuild.EmitStoreGReg(val, inst.RA); - if (inst.Rc) - ComputeRC(ibuild, val); - } +// m_GPR[_inst.RA] = m_GPR[_inst.RS] ^ m_GPR[_inst.RB]; +void Jit64::xorx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RB); + val = ibuild.EmitXor(ibuild.EmitLoadGReg(inst.RS), val); + ibuild.EmitStoreGReg(val, inst.RA); + if (inst.Rc) + ComputeRC(ibuild, val); +} - void Jit64::subfic(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc nota, lhs, val, test; - nota = ibuild.EmitXor(ibuild.EmitLoadGReg(inst.RA), - ibuild.EmitIntConst(-1)); - if (inst.SIMM_16 == -1) { - val = nota; - test = ibuild.EmitIntConst(1); - } else { - lhs = ibuild.EmitIntConst(inst.SIMM_16 + 1); - val = ibuild.EmitAdd(nota, lhs); - test = ibuild.EmitICmpUgt(lhs, val); - } - ibuild.EmitStoreGReg(val, inst.RD); - ibuild.EmitStoreCarry(test); - } +void Jit64::andx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RB); + val = ibuild.EmitAnd(ibuild.EmitLoadGReg(inst.RS), val); + ibuild.EmitStoreGReg(val, inst.RA); + if (inst.Rc) + ComputeRC(ibuild, val); +} - void Jit64::subfcx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - if (inst.OE) PanicAlert("OE: subfcx"); - IREmitter::InstLoc val, test, lhs, rhs; - lhs = ibuild.EmitLoadGReg(inst.RB); - rhs = ibuild.EmitLoadGReg(inst.RA); - val = ibuild.EmitSub(lhs, rhs); - ibuild.EmitStoreGReg(val, inst.RD); - test = ibuild.EmitICmpEq(rhs, ibuild.EmitIntConst(0)); - test = ibuild.EmitOr(test, ibuild.EmitICmpUgt(lhs, val)); - ibuild.EmitStoreCarry(test); - if (inst.Rc) - ComputeRC(ibuild, val); - } +void Jit64::extsbx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS); + val = ibuild.EmitSExt8(val); + ibuild.EmitStoreGReg(val, inst.RA); + if (inst.Rc) + ComputeRC(ibuild, val); +} - void Jit64::subfex(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - if (inst.OE) PanicAlert("OE: subfex"); - IREmitter::InstLoc val, test, lhs, rhs, carry; - rhs = ibuild.EmitLoadGReg(inst.RA); - carry = ibuild.EmitLoadCarry(); - rhs = ibuild.EmitXor(rhs, ibuild.EmitIntConst(-1)); - rhs = ibuild.EmitAdd(rhs, carry); - test = ibuild.EmitICmpEq(rhs, ibuild.EmitIntConst(0)); - test = ibuild.EmitAnd(test, carry); - lhs = ibuild.EmitLoadGReg(inst.RB); - val = ibuild.EmitAdd(lhs, rhs); - ibuild.EmitStoreGReg(val, inst.RD); - test = ibuild.EmitOr(test, ibuild.EmitICmpUgt(lhs, val)); - ibuild.EmitStoreCarry(test); - if (inst.Rc) - ComputeRC(ibuild, val); - } +void Jit64::extshx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS); + val = ibuild.EmitSExt16(val); + ibuild.EmitStoreGReg(val, inst.RA); + if (inst.Rc) + ComputeRC(ibuild, val); +} - void Jit64::subfx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - if (inst.OE) PanicAlert("OE: subfx"); - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RB); - val = ibuild.EmitSub(val, ibuild.EmitLoadGReg(inst.RA)); - ibuild.EmitStoreGReg(val, inst.RD); - if (inst.Rc) - ComputeRC(ibuild, val); +void Jit64::subfic(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc nota, lhs, val, test; + nota = ibuild.EmitXor(ibuild.EmitLoadGReg(inst.RA), + ibuild.EmitIntConst(-1)); + if (inst.SIMM_16 == -1) { + val = nota; + test = ibuild.EmitIntConst(1); + } else { + lhs = ibuild.EmitIntConst(inst.SIMM_16 + 1); + val = ibuild.EmitAdd(nota, lhs); + test = ibuild.EmitICmpUgt(lhs, val); } + ibuild.EmitStoreGReg(val, inst.RD); + ibuild.EmitStoreCarry(test); +} - void Jit64::mulli(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RA); - val = ibuild.EmitMul(val, ibuild.EmitIntConst(inst.SIMM_16)); - ibuild.EmitStoreGReg(val, inst.RD); - } +void Jit64::subfcx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + if (inst.OE) PanicAlert("OE: subfcx"); + IREmitter::InstLoc val, test, lhs, rhs; + lhs = ibuild.EmitLoadGReg(inst.RB); + rhs = ibuild.EmitLoadGReg(inst.RA); + val = ibuild.EmitSub(lhs, rhs); + ibuild.EmitStoreGReg(val, inst.RD); + test = ibuild.EmitICmpEq(rhs, ibuild.EmitIntConst(0)); + test = ibuild.EmitOr(test, ibuild.EmitICmpUgt(lhs, val)); + ibuild.EmitStoreCarry(test); + if (inst.Rc) + ComputeRC(ibuild, val); +} - void Jit64::mullwx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RB); - val = ibuild.EmitMul(ibuild.EmitLoadGReg(inst.RA), val); - ibuild.EmitStoreGReg(val, inst.RD); - if (inst.Rc) - ComputeRC(ibuild, val); - } +void Jit64::subfex(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + if (inst.OE) PanicAlert("OE: subfex"); + IREmitter::InstLoc val, test, lhs, rhs, carry; + rhs = ibuild.EmitLoadGReg(inst.RA); + carry = ibuild.EmitLoadCarry(); + rhs = ibuild.EmitXor(rhs, ibuild.EmitIntConst(-1)); + rhs = ibuild.EmitAdd(rhs, carry); + test = ibuild.EmitICmpEq(rhs, ibuild.EmitIntConst(0)); + test = ibuild.EmitAnd(test, carry); + lhs = ibuild.EmitLoadGReg(inst.RB); + val = ibuild.EmitAdd(lhs, rhs); + ibuild.EmitStoreGReg(val, inst.RD); + test = ibuild.EmitOr(test, ibuild.EmitICmpUgt(lhs, val)); + ibuild.EmitStoreCarry(test); + if (inst.Rc) + ComputeRC(ibuild, val); +} - void Jit64::mulhwux(UGeckoInstruction inst) - { - Default(inst); return; +void Jit64::subfx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + if (inst.OE) PanicAlert("OE: subfx"); + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RB); + val = ibuild.EmitSub(val, ibuild.EmitLoadGReg(inst.RA)); + ibuild.EmitStoreGReg(val, inst.RD); + if (inst.Rc) + ComputeRC(ibuild, val); +} + +void Jit64::mulli(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RA); + val = ibuild.EmitMul(val, ibuild.EmitIntConst(inst.SIMM_16)); + ibuild.EmitStoreGReg(val, inst.RD); +} + +void Jit64::mullwx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RB); + val = ibuild.EmitMul(ibuild.EmitLoadGReg(inst.RA), val); + ibuild.EmitStoreGReg(val, inst.RD); + if (inst.Rc) + ComputeRC(ibuild, val); +} + +void Jit64::mulhwux(UGeckoInstruction inst) +{ + Default(inst); return; #if 0 - if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff) - {Default(inst); return;} // turn off from debugger + if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff) + {Default(inst); return;} // turn off from debugger - 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); - } else { - gpr.LoadToX64(d, true, true); - } - if (gpr.RX(d) == EDX) - PanicAlert("mulhwux : WTF"); - MOV(32, R(EAX), gpr.R(a)); - gpr.KillImmediate(b); - MUL(32, gpr.R(b)); - gpr.UnlockAll(); - gpr.UnlockAllX(); - if (inst.Rc) { - MOV(32, R(EAX), R(EDX)); - MOV(32, gpr.R(d), R(EDX)); - // result is already in eax - CALL((u8*)asm_routines.computeRc); - } else { - MOV(32, gpr.R(d), R(EDX)); - } -#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); + } else { + gpr.LoadToX64(d, true, true); } + if (gpr.RX(d) == EDX) + PanicAlert("mulhwux : WTF"); + MOV(32, R(EAX), gpr.R(a)); + gpr.KillImmediate(b); + MUL(32, gpr.R(b)); + gpr.UnlockAll(); + gpr.UnlockAllX(); + if (inst.Rc) { + MOV(32, R(EAX), R(EDX)); + MOV(32, gpr.R(d), R(EDX)); + // result is already in eax + CALL((u8*)asm_routines.computeRc); + } else { + MOV(32, gpr.R(d), R(EDX)); + } +#endif +} - // skipped some of the special handling in here - if we get crashes, let the interpreter handle this op - void Jit64::divwux(UGeckoInstruction inst) { - Default(inst); return; +// skipped some of the special handling in here - if we get crashes, let the interpreter handle this op +void Jit64::divwux(UGeckoInstruction inst) { + Default(inst); return; #if 0 - 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); - } else { - gpr.LoadToX64(d, true, true); - } - MOV(32, R(EAX), gpr.R(a)); - XOR(32, R(EDX), R(EDX)); - gpr.KillImmediate(b); - DIV(32, gpr.R(b)); - MOV(32, gpr.R(d), R(EAX)); - gpr.UnlockAll(); - gpr.UnlockAllX(); - if (inst.Rc) { - CALL((u8*)asm_routines.computeRc); - } + 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); + } else { + gpr.LoadToX64(d, true, true); + } + MOV(32, R(EAX), gpr.R(a)); + XOR(32, R(EDX), R(EDX)); + gpr.KillImmediate(b); + DIV(32, gpr.R(b)); + MOV(32, gpr.R(d), R(EAX)); + gpr.UnlockAll(); + gpr.UnlockAllX(); + if (inst.Rc) { + CALL((u8*)asm_routines.computeRc); + } #endif - } +} - u32 Helper_Mask(u8 mb, u8 me) - { - return (((mb > me) ? - ~(((u32)-1 >> mb) ^ ((me >= 31) ? 0 : (u32) -1 >> (me + 1))) - : - (((u32)-1 >> mb) ^ ((me >= 31) ? 0 : (u32) -1 >> (me + 1)))) - ); - } +u32 Helper_Mask(u8 mb, u8 me) +{ + return (((mb > me) ? + ~(((u32)-1 >> mb) ^ ((me >= 31) ? 0 : (u32) -1 >> (me + 1))) + : + (((u32)-1 >> mb) ^ ((me >= 31) ? 0 : (u32) -1 >> (me + 1)))) + ); +} - void Jit64::addx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RB); - val = ibuild.EmitAdd(ibuild.EmitLoadGReg(inst.RA), val); - ibuild.EmitStoreGReg(val, inst.RD); - if (inst.Rc) - ComputeRC(ibuild, val); - } +void Jit64::addx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RB); + val = ibuild.EmitAdd(ibuild.EmitLoadGReg(inst.RA), val); + ibuild.EmitStoreGReg(val, inst.RD); + if (inst.Rc) + ComputeRC(ibuild, val); +} - void Jit64::addzex(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc lhs = ibuild.EmitLoadGReg(inst.RA), - val, newcarry; - val = ibuild.EmitAdd(lhs, ibuild.EmitLoadCarry()); - ibuild.EmitStoreGReg(val, inst.RD); - newcarry = ibuild.EmitICmpUlt(val, lhs); - ibuild.EmitStoreCarry(newcarry); - if (inst.Rc) - ComputeRC(ibuild, val); - } - // This can be optimized - void Jit64::addex(UGeckoInstruction inst) - { - Default(inst); return; +void Jit64::addzex(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc lhs = ibuild.EmitLoadGReg(inst.RA), + val, newcarry; + val = ibuild.EmitAdd(lhs, ibuild.EmitLoadCarry()); + ibuild.EmitStoreGReg(val, inst.RD); + newcarry = ibuild.EmitICmpUlt(val, lhs); + ibuild.EmitStoreCarry(newcarry); + if (inst.Rc) + ComputeRC(ibuild, val); +} +// This can be optimized +void Jit64::addex(UGeckoInstruction inst) +{ + Default(inst); return; #if 0 - // USES_XER - if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff) - {Default(inst); return;} // turn off from debugger + // USES_XER + if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff) + {Default(inst); return;} // turn off from debugger - INSTRUCTION_START; - 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); - else - gpr.LoadToX64(d, true); - MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); - SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag - MOV(32, R(EAX), gpr.R(a)); - ADC(32, R(EAX), gpr.R(b)); - MOV(32, gpr.R(d), R(EAX)); - //GenerateCarry(ECX); - gpr.UnlockAll(); - gpr.UnlockAllX(); - if (inst.Rc) - { - CALL((u8*)asm_routines.computeRc); - } + INSTRUCTION_START; + 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); + else + gpr.LoadToX64(d, true); + MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); + SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + MOV(32, R(EAX), gpr.R(a)); + ADC(32, R(EAX), gpr.R(b)); + MOV(32, gpr.R(d), R(EAX)); + //GenerateCarry(ECX); + gpr.UnlockAll(); + gpr.UnlockAllX(); + if (inst.Rc) + { + CALL((u8*)asm_routines.computeRc); + } #endif - } +} - void Jit64::rlwinmx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - unsigned mask = Helper_Mask(inst.MB, inst.ME); - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS); - val = ibuild.EmitRol(val, ibuild.EmitIntConst(inst.SH)); - val = ibuild.EmitAnd(val, ibuild.EmitIntConst(mask)); - ibuild.EmitStoreGReg(val, inst.RA); - if (inst.Rc) - ComputeRC(ibuild, val); - } +void Jit64::rlwinmx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + unsigned mask = Helper_Mask(inst.MB, inst.ME); + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS); + val = ibuild.EmitRol(val, ibuild.EmitIntConst(inst.SH)); + val = ibuild.EmitAnd(val, ibuild.EmitIntConst(mask)); + ibuild.EmitStoreGReg(val, inst.RA); + if (inst.Rc) + ComputeRC(ibuild, val); +} - void Jit64::rlwimix(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - unsigned mask = Helper_Mask(inst.MB, inst.ME); - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS); - val = ibuild.EmitRol(val, ibuild.EmitIntConst(inst.SH)); - val = ibuild.EmitAnd(val, ibuild.EmitIntConst(mask)); - IREmitter::InstLoc ival = ibuild.EmitLoadGReg(inst.RA); - ival = ibuild.EmitAnd(ival, ibuild.EmitIntConst(~mask)); - val = ibuild.EmitOr(ival, val); - ibuild.EmitStoreGReg(val, inst.RA); - if (inst.Rc) - ComputeRC(ibuild, val); - } +void Jit64::rlwimix(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + unsigned mask = Helper_Mask(inst.MB, inst.ME); + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS); + val = ibuild.EmitRol(val, ibuild.EmitIntConst(inst.SH)); + val = ibuild.EmitAnd(val, ibuild.EmitIntConst(mask)); + IREmitter::InstLoc ival = ibuild.EmitLoadGReg(inst.RA); + ival = ibuild.EmitAnd(ival, ibuild.EmitIntConst(~mask)); + val = ibuild.EmitOr(ival, val); + ibuild.EmitStoreGReg(val, inst.RA); + if (inst.Rc) + ComputeRC(ibuild, val); +} - void Jit64::rlwnmx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - unsigned int mask = Helper_Mask(inst.MB, inst.ME); - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS); - val = ibuild.EmitRol(val, ibuild.EmitLoadGReg(inst.RB)); - val = ibuild.EmitAnd(val, ibuild.EmitIntConst(mask)); - ibuild.EmitStoreGReg(val, inst.RA); - if (inst.Rc) - ComputeRC(ibuild, val); - } +void Jit64::rlwnmx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + unsigned int mask = Helper_Mask(inst.MB, inst.ME); + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS); + val = ibuild.EmitRol(val, ibuild.EmitLoadGReg(inst.RB)); + val = ibuild.EmitAnd(val, ibuild.EmitIntConst(mask)); + ibuild.EmitStoreGReg(val, inst.RA); + if (inst.Rc) + ComputeRC(ibuild, val); +} - void Jit64::negx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RA); - val = ibuild.EmitSub(ibuild.EmitIntConst(0), val); - ibuild.EmitStoreGReg(val, inst.RD); - if (inst.Rc) - ComputeRC(ibuild, val); - } +void Jit64::negx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RA); + val = ibuild.EmitSub(ibuild.EmitIntConst(0), val); + ibuild.EmitStoreGReg(val, inst.RD); + if (inst.Rc) + ComputeRC(ibuild, val); +} - void Jit64::srwx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS), - samt = ibuild.EmitLoadGReg(inst.RB), - corr; - // FIXME: We can do better with a cmov - // FIXME: We can do better on 64-bit - val = ibuild.EmitShrl(val, samt); - corr = ibuild.EmitShl(samt, ibuild.EmitIntConst(26)); - corr = ibuild.EmitSarl(corr, ibuild.EmitIntConst(31)); - corr = ibuild.EmitXor(corr, ibuild.EmitIntConst(-1)); - val = ibuild.EmitAnd(corr, val); - ibuild.EmitStoreGReg(val, inst.RA); - if (inst.Rc) - ComputeRC(ibuild, val); - } +void Jit64::srwx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS), + samt = ibuild.EmitLoadGReg(inst.RB), + corr; + // FIXME: We can do better with a cmov + // FIXME: We can do better on 64-bit + val = ibuild.EmitShrl(val, samt); + corr = ibuild.EmitShl(samt, ibuild.EmitIntConst(26)); + corr = ibuild.EmitSarl(corr, ibuild.EmitIntConst(31)); + corr = ibuild.EmitXor(corr, ibuild.EmitIntConst(-1)); + val = ibuild.EmitAnd(corr, val); + ibuild.EmitStoreGReg(val, inst.RA); + if (inst.Rc) + ComputeRC(ibuild, val); +} - void Jit64::slwx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS), - samt = ibuild.EmitLoadGReg(inst.RB), - corr; - // FIXME: We can do better with a cmov - // FIXME: We can do better on 64-bit - val = ibuild.EmitShl(val, samt); - corr = ibuild.EmitShl(samt, ibuild.EmitIntConst(26)); - corr = ibuild.EmitSarl(corr, ibuild.EmitIntConst(31)); - corr = ibuild.EmitXor(corr, ibuild.EmitIntConst(-1)); - val = ibuild.EmitAnd(corr, val); - ibuild.EmitStoreGReg(val, inst.RA); - if (inst.Rc) - ComputeRC(ibuild, val); - } +void Jit64::slwx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS), + samt = ibuild.EmitLoadGReg(inst.RB), + corr; + // FIXME: We can do better with a cmov + // FIXME: We can do better on 64-bit + val = ibuild.EmitShl(val, samt); + corr = ibuild.EmitShl(samt, ibuild.EmitIntConst(26)); + corr = ibuild.EmitSarl(corr, ibuild.EmitIntConst(31)); + corr = ibuild.EmitXor(corr, ibuild.EmitIntConst(-1)); + val = ibuild.EmitAnd(corr, val); + ibuild.EmitStoreGReg(val, inst.RA); + if (inst.Rc) + ComputeRC(ibuild, val); +} - void Jit64::srawx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - // FIXME: We can do a lot better on 64-bit - IREmitter::InstLoc val, samt, mask, mask2, test; - val = ibuild.EmitLoadGReg(inst.RS); - samt = ibuild.EmitLoadGReg(inst.RB); - mask = ibuild.EmitIntConst(-1); - val = ibuild.EmitSarl(val, samt); - mask = ibuild.EmitShl(mask, samt); - samt = ibuild.EmitShl(samt, ibuild.EmitIntConst(26)); - samt = ibuild.EmitSarl(samt, ibuild.EmitIntConst(31)); - samt = ibuild.EmitAnd(samt, ibuild.EmitIntConst(31)); - val = ibuild.EmitSarl(val, samt); - ibuild.EmitStoreGReg(val, inst.RA); - mask = ibuild.EmitShl(mask, samt); - mask2 = ibuild.EmitAnd(mask, ibuild.EmitIntConst(0x7FFFFFFF)); - test = ibuild.EmitOr(val, mask2); - test = ibuild.EmitICmpUgt(test, mask); - ibuild.EmitStoreCarry(test); - } +void Jit64::srawx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + // FIXME: We can do a lot better on 64-bit + IREmitter::InstLoc val, samt, mask, mask2, test; + val = ibuild.EmitLoadGReg(inst.RS); + samt = ibuild.EmitLoadGReg(inst.RB); + mask = ibuild.EmitIntConst(-1); + val = ibuild.EmitSarl(val, samt); + mask = ibuild.EmitShl(mask, samt); + samt = ibuild.EmitShl(samt, ibuild.EmitIntConst(26)); + samt = ibuild.EmitSarl(samt, ibuild.EmitIntConst(31)); + samt = ibuild.EmitAnd(samt, ibuild.EmitIntConst(31)); + val = ibuild.EmitSarl(val, samt); + ibuild.EmitStoreGReg(val, inst.RA); + mask = ibuild.EmitShl(mask, samt); + mask2 = ibuild.EmitAnd(mask, ibuild.EmitIntConst(0x7FFFFFFF)); + test = ibuild.EmitOr(val, mask2); + test = ibuild.EmitICmpUgt(test, mask); + ibuild.EmitStoreCarry(test); +} - void Jit64::srawix(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS), test; - val = ibuild.EmitSarl(val, ibuild.EmitIntConst(inst.SH)); - ibuild.EmitStoreGReg(val, inst.RA); - unsigned int mask = -1u << inst.SH; - test = ibuild.EmitOr(val, ibuild.EmitIntConst(mask & 0x7FFFFFFF)); - test = ibuild.EmitICmpUgt(test, ibuild.EmitIntConst(mask)); - - ibuild.EmitStoreCarry(test); - if (inst.Rc) - ComputeRC(ibuild, val); - } +void Jit64::srawix(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS), test; + val = ibuild.EmitSarl(val, ibuild.EmitIntConst(inst.SH)); + ibuild.EmitStoreGReg(val, inst.RA); + unsigned int mask = -1u << inst.SH; + test = ibuild.EmitOr(val, ibuild.EmitIntConst(mask & 0x7FFFFFFF)); + test = ibuild.EmitICmpUgt(test, ibuild.EmitIntConst(mask)); + + ibuild.EmitStoreCarry(test); + if (inst.Rc) + ComputeRC(ibuild, val); +} - // count leading zeroes - void Jit64::cntlzwx(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Integer) - IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS); - val = ibuild.EmitCntlzw(val); - ibuild.EmitStoreGReg(val, inst.RA); - if (inst.Rc) - ComputeRC(ibuild, val); - } +// count leading zeroes +void Jit64::cntlzwx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS); + val = ibuild.EmitCntlzw(val); + ibuild.EmitStoreGReg(val, inst.RA); + if (inst.Rc) + ComputeRC(ibuild, val); +} diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStore.cpp index 34bf12ec51..4e98ad9dff 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStore.cpp @@ -41,6 +41,7 @@ void Jit64::lhax(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStore) IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB); if (inst.RA) @@ -53,6 +54,7 @@ void Jit64::lhax(UGeckoInstruction inst) void Jit64::lXz(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStore) IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16); if (inst.RA) @@ -73,6 +75,7 @@ void Jit64::lXz(UGeckoInstruction inst) void Jit64::lha(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStore) IREmitter::InstLoc addr = ibuild.EmitIntConst((s32)(s16)inst.SIMM_16); @@ -86,6 +89,7 @@ void Jit64::lha(UGeckoInstruction inst) void Jit64::lXzx(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStore) IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB); if (inst.RA) { @@ -108,6 +112,8 @@ void Jit64::lXzx(UGeckoInstruction inst) void Jit64::dcbz(UGeckoInstruction inst) { Default(inst); return; + + // TODO! #if 0 if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreOff) {Default(inst); return;} // turn off from debugger @@ -131,6 +137,7 @@ void Jit64::dcbz(UGeckoInstruction inst) void Jit64::stX(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStore) IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16), value = ibuild.EmitLoadGReg(inst.RS); @@ -150,6 +157,7 @@ void Jit64::stX(UGeckoInstruction inst) void Jit64::stXx(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStore) IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB), value = ibuild.EmitLoadGReg(inst.RS); @@ -169,6 +177,7 @@ void Jit64::stXx(UGeckoInstruction inst) void Jit64::lmw(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStore) IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16); if (inst.RA) @@ -184,6 +193,7 @@ void Jit64::lmw(UGeckoInstruction inst) void Jit64::stmw(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStore) IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16); if (inst.RA) diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStoreFloating.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStoreFloating.cpp index c1b1afa4fa..ff7f08ecb4 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStoreFloating.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStoreFloating.cpp @@ -45,6 +45,7 @@ void Jit64::lfs(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStoreFloating) IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16), val; if (inst.RA) @@ -58,6 +59,7 @@ void Jit64::lfs(UGeckoInstruction inst) void Jit64::lfd(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStoreFloating) IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16), val; if (inst.RA) @@ -72,6 +74,7 @@ void Jit64::lfd(UGeckoInstruction inst) void Jit64::stfd(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStoreFloating) IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16), val = ibuild.EmitLoadFReg(inst.RS); @@ -87,6 +90,7 @@ void Jit64::stfd(UGeckoInstruction inst) void Jit64::stfs(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStoreFloating) IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16), val = ibuild.EmitLoadFReg(inst.RS); @@ -103,6 +107,7 @@ void Jit64::stfs(UGeckoInstruction inst) void Jit64::stfsx(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStoreFloating) IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB), val = ibuild.EmitLoadFReg(inst.RS); @@ -117,6 +122,7 @@ void Jit64::stfsx(UGeckoInstruction inst) void Jit64::lfsx(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStoreFloating) IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB), val; if (inst.RA) diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStorePaired.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStorePaired.cpp index 04fe73f6ed..102fe399a5 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStorePaired.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStorePaired.cpp @@ -44,6 +44,7 @@ void Jit64::psq_st(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStorePaired) if (inst.W || !Core::GetStartupParameter().bOptimizeQuantizers) {Default(inst); return;} IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_12), val; @@ -59,6 +60,7 @@ void Jit64::psq_st(UGeckoInstruction inst) void Jit64::psq_l(UGeckoInstruction inst) { INSTRUCTION_START + DISABLE64 JITDISABLE(LoadStorePaired) if (inst.W || !Core::GetStartupParameter().bOptimizeQuantizers) {Default(inst); return;} IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_12), val; diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Paired.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Paired.cpp index 34fc75d406..4db88a0972 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Paired.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Paired.cpp @@ -26,193 +26,193 @@ #include "Jit.h" #include "JitRegCache.h" - void Jit64::ps_mr(UGeckoInstruction inst) - { +void Jit64::ps_mr(UGeckoInstruction inst) +{ + Default(inst); return; +} + +void Jit64::ps_sel(UGeckoInstruction inst) +{ + Default(inst); return; +} + +void Jit64::ps_sign(UGeckoInstruction inst) +{ + Default(inst); return; +} + +void Jit64::ps_rsqrte(UGeckoInstruction inst) +{ + Default(inst); return; +} + +void Jit64::ps_arith(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Paired) + if (inst.Rc || (inst.SUBOP5 != 21 && inst.SUBOP5 != 20 && inst.SUBOP5 != 25)) { Default(inst); return; } - - void Jit64::ps_sel(UGeckoInstruction inst) + IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), rhs; + if (inst.SUBOP5 == 25) + rhs = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); + else + rhs = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); + val = ibuild.EmitCompactMRegToPacked(val); + + switch (inst.SUBOP5) { - Default(inst); return; - } - - void Jit64::ps_sign(UGeckoInstruction inst) - { - Default(inst); return; - } - - void Jit64::ps_rsqrte(UGeckoInstruction inst) - { - Default(inst); return; - } - - void Jit64::ps_arith(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Paired) - if (inst.Rc || (inst.SUBOP5 != 21 && inst.SUBOP5 != 20 && inst.SUBOP5 != 25)) { - Default(inst); return; - } - IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), rhs; - if (inst.SUBOP5 == 25) - rhs = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); - else - rhs = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); - val = ibuild.EmitCompactMRegToPacked(val); - - switch (inst.SUBOP5) - { - case 20: - val = ibuild.EmitFPSub(val, rhs); - break; - case 21: - val = ibuild.EmitFPAdd(val, rhs); - break; - case 25: - val = ibuild.EmitFPMul(val, rhs); - } - val = ibuild.EmitExpandPackedToMReg(val); - ibuild.EmitStoreFReg(val, inst.FD); - } - - void Jit64::ps_sum(UGeckoInstruction inst) - { - // FIXME: This operation strikes me as a bit strange... - // perhaps we can optimize it depending on the users? - INSTRUCTION_START - JITDISABLE(Paired) - if (inst.Rc || inst.SUBOP5 != 10) { - Default(inst); return; - } - IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), temp; - val = ibuild.EmitCompactMRegToPacked(val); - val = ibuild.EmitFPDup0(val); - temp = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); - val = ibuild.EmitFPAdd(val, temp); - temp = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); - val = ibuild.EmitFPMerge11(val, temp); - val = ibuild.EmitExpandPackedToMReg(val); - ibuild.EmitStoreFReg(val, inst.FD); - } - - - void Jit64::ps_muls(UGeckoInstruction inst) - { - INSTRUCTION_START - JITDISABLE(Paired) - if (inst.Rc) { - Default(inst); return; - } - IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), - rhs = ibuild.EmitLoadFReg(inst.FC); - - val = ibuild.EmitCompactMRegToPacked(val); - rhs = ibuild.EmitCompactMRegToPacked(rhs); - - if (inst.SUBOP5 == 12) - rhs = ibuild.EmitFPDup0(rhs); - else - rhs = ibuild.EmitFPDup1(rhs); - + case 20: + val = ibuild.EmitFPSub(val, rhs); + break; + case 21: + val = ibuild.EmitFPAdd(val, rhs); + break; + case 25: val = ibuild.EmitFPMul(val, rhs); - val = ibuild.EmitExpandPackedToMReg(val); - ibuild.EmitStoreFReg(val, inst.FD); + } + val = ibuild.EmitExpandPackedToMReg(val); + ibuild.EmitStoreFReg(val, inst.FD); +} + +void Jit64::ps_sum(UGeckoInstruction inst) +{ + // FIXME: This operation strikes me as a bit strange... + // perhaps we can optimize it depending on the users? + INSTRUCTION_START + JITDISABLE(Paired) + if (inst.Rc || inst.SUBOP5 != 10) { + Default(inst); return; + } + IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), temp; + val = ibuild.EmitCompactMRegToPacked(val); + val = ibuild.EmitFPDup0(val); + temp = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); + val = ibuild.EmitFPAdd(val, temp); + temp = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); + val = ibuild.EmitFPMerge11(val, temp); + val = ibuild.EmitExpandPackedToMReg(val); + ibuild.EmitStoreFReg(val, inst.FD); +} + + +void Jit64::ps_muls(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Paired) + if (inst.Rc) { + Default(inst); return; + } + IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), + rhs = ibuild.EmitLoadFReg(inst.FC); + + val = ibuild.EmitCompactMRegToPacked(val); + rhs = ibuild.EmitCompactMRegToPacked(rhs); + + if (inst.SUBOP5 == 12) + rhs = ibuild.EmitFPDup0(rhs); + else + rhs = ibuild.EmitFPDup1(rhs); + + val = ibuild.EmitFPMul(val, rhs); + val = ibuild.EmitExpandPackedToMReg(val); + ibuild.EmitStoreFReg(val, inst.FD); +} + + +//TODO: find easy cases and optimize them, do a breakout like ps_arith +void Jit64::ps_mergeXX(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Paired) + if (inst.Rc) { + Default(inst); return; } + IREmitter::InstLoc val = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FA)), + rhs = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); - //TODO: find easy cases and optimize them, do a breakout like ps_arith - void Jit64::ps_mergeXX(UGeckoInstruction inst) + switch (inst.SUBOP10) { - INSTRUCTION_START - JITDISABLE(Paired) - if (inst.Rc) { - Default(inst); return; - } - - IREmitter::InstLoc val = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FA)), - rhs = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); - - switch (inst.SUBOP10) - { - case 528: - val = ibuild.EmitFPMerge00(val, rhs); - break; //00 - case 560: - val = ibuild.EmitFPMerge01(val, rhs); - break; //01 - case 592: - val = ibuild.EmitFPMerge10(val, rhs); - break; //10 - case 624: - val = ibuild.EmitFPMerge11(val, rhs); - break; //11 - default: - _assert_msg_(DYNA_REC, 0, "ps_merge - invalid op"); - } - val = ibuild.EmitExpandPackedToMReg(val); - ibuild.EmitStoreFReg(val, inst.FD); + case 528: + val = ibuild.EmitFPMerge00(val, rhs); + break; //00 + case 560: + val = ibuild.EmitFPMerge01(val, rhs); + break; //01 + case 592: + val = ibuild.EmitFPMerge10(val, rhs); + break; //10 + case 624: + val = ibuild.EmitFPMerge11(val, rhs); + break; //11 + default: + _assert_msg_(DYNA_REC, 0, "ps_merge - invalid op"); } + val = ibuild.EmitExpandPackedToMReg(val); + ibuild.EmitStoreFReg(val, inst.FD); +} - void Jit64::ps_maddXX(UGeckoInstruction inst) +void Jit64::ps_maddXX(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Paired) + if (inst.Rc) { + Default(inst); return; + } + + IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), op2, op3; + val = ibuild.EmitCompactMRegToPacked(val); + switch (inst.SUBOP5) { - INSTRUCTION_START - JITDISABLE(Paired) - if (inst.Rc) { - Default(inst); return; - } - - IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), op2, op3; - val = ibuild.EmitCompactMRegToPacked(val); - switch (inst.SUBOP5) - { - case 14: {//madds0 - op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); - op2 = ibuild.EmitFPDup0(op2); - val = ibuild.EmitFPMul(val, op2); - op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); - val = ibuild.EmitFPAdd(val, op3); - break; - } - case 15: {//madds1 - op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); - op2 = ibuild.EmitFPDup1(op2); - val = ibuild.EmitFPMul(val, op2); - op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); - val = ibuild.EmitFPAdd(val, op3); - break; - } - case 28: {//msub - op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); - val = ibuild.EmitFPMul(val, op2); - op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); - val = ibuild.EmitFPSub(val, op3); - break; - } - case 29: {//madd - op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); - val = ibuild.EmitFPMul(val, op2); - op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); - val = ibuild.EmitFPAdd(val, op3); - break; - } - case 30: {//nmsub - op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); - val = ibuild.EmitFPMul(val, op2); - op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); - val = ibuild.EmitFPSub(val, op3); - val = ibuild.EmitFPNeg(val); - break; - } - case 31: {//nmadd - op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); - val = ibuild.EmitFPMul(val, op2); - op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); - val = ibuild.EmitFPAdd(val, op3); - val = ibuild.EmitFPNeg(val); - break; - } - } - val = ibuild.EmitExpandPackedToMReg(val); - ibuild.EmitStoreFReg(val, inst.FD); + case 14: {//madds0 + op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); + op2 = ibuild.EmitFPDup0(op2); + val = ibuild.EmitFPMul(val, op2); + op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); + val = ibuild.EmitFPAdd(val, op3); + break; } + case 15: {//madds1 + op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); + op2 = ibuild.EmitFPDup1(op2); + val = ibuild.EmitFPMul(val, op2); + op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); + val = ibuild.EmitFPAdd(val, op3); + break; + } + case 28: {//msub + op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); + val = ibuild.EmitFPMul(val, op2); + op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); + val = ibuild.EmitFPSub(val, op3); + break; + } + case 29: {//madd + op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); + val = ibuild.EmitFPMul(val, op2); + op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); + val = ibuild.EmitFPAdd(val, op3); + break; + } + case 30: {//nmsub + op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); + val = ibuild.EmitFPMul(val, op2); + op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); + val = ibuild.EmitFPSub(val, op3); + val = ibuild.EmitFPNeg(val); + break; + } + case 31: {//nmadd + op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC)); + val = ibuild.EmitFPMul(val, op2); + op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB)); + val = ibuild.EmitFPAdd(val, op3); + val = ibuild.EmitFPNeg(val); + break; + } + } + val = ibuild.EmitExpandPackedToMReg(val); + ibuild.EmitStoreFReg(val, inst.FD); +}