diff --git a/Common/ArmEmitter.cpp b/Common/ArmEmitter.cpp index ad7651d968..1ca0d36429 100644 --- a/Common/ArmEmitter.cpp +++ b/Common/ArmEmitter.cpp @@ -29,6 +29,33 @@ namespace ArmGen { +inline u32 RotR(u32 a, int amount) { + return (a >> amount) | (a << (31 - amount)); +} + +bool TryMakeOperand2(u32 imm, Operand2 &op2) { + // Just brute force it. + for (int i = 0; i < 16; i++) { + if ((imm & 0xFF) == imm) { + op2 = Operand2((u8)imm, (u8)i); + return true; + } + imm = RotR(imm, 2); + } + return false; +} + +bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse) +{ + if (!TryMakeOperand2(imm, op2)) { + *inverse = true; + return TryMakeOperand2(~imm, op2); + } else { + *inverse = false; + return true; + } +} + void ARMXEmitter::SetCodePtr(u8 *ptr) { code = ptr; diff --git a/Common/ArmEmitter.h b/Common/ArmEmitter.h index d865aeba52..b3a8a1b613 100644 --- a/Common/ArmEmitter.h +++ b/Common/ArmEmitter.h @@ -112,7 +112,6 @@ enum OpType TYPE_MEM }; - // This is no longer a proper operand2 class. Need to split up. class Operand2 { @@ -298,6 +297,12 @@ public: }; + + +bool TryMakeOperand2(u32 imm, Operand2 &op2); +bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse); + + inline Operand2 R(ARMReg Reg) { return Operand2(Reg, TYPE_REG); } inline Operand2 IMM(u32 Imm) { return Operand2(Imm, TYPE_IMM); } inline Operand2 Mem(void *ptr) { return Operand2((u32)ptr, TYPE_IMM); } @@ -401,7 +406,7 @@ public: void LSLS(ARMReg dest, ARMReg src, ARMReg op2); void SBC (ARMReg dest, ARMReg src, Operand2 op2); void SBCS(ARMReg dest, ARMReg src, Operand2 op2); - void REV (ARMReg dest, ARMReg src ); + void REV (ARMReg dest, ARMReg src); void RSC (ARMReg dest, ARMReg src, Operand2 op2); void RSCS(ARMReg dest, ARMReg src, Operand2 op2); void TST ( ARMReg src, Operand2 op2); @@ -429,9 +434,9 @@ public: void SXTB(ARMReg dest, ARMReg op2); void SXTH(ARMReg dest, ARMReg op2, u8 rotation = 0); void SXTAH(ARMReg dest, ARMReg src, ARMReg op2, u8 rotation = 0); - // Using just MSR here messes with our defines on the PPC side of stuff + // Using just MSR here messes with our defines on the PPC side of stuff (when this code was in dolphin...) // Just need to put an underscore here, bit annoying. - void _MSR (bool nzcvq, bool g, Operand2 op2); + void _MSR (bool nzcvq, bool g, Operand2 op2); void _MSR (bool nzcvq, bool g, ARMReg src ); void MRS (ARMReg dest); diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index 6c1f57b92b..f5c81ff5ec 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -718,7 +718,7 @@ u32 sceMpegUnRegistStream(u32 mpeg, int streamUid) return -1; } - StreamInfo info; + StreamInfo info = {0}; switch (info.type) { case MPEG_AVC_STREAM: @@ -1051,9 +1051,10 @@ u32 sceMpegChangeGetAuMode(u32 mpeg, int streamUid, int mode) return -1; } - StreamInfo info; + // NOTE: Where is the info supposed to come from? + StreamInfo info = {0}; info.sid = streamUid; - if (info.sid) { + if (info.sid) { switch (info.type) { case MPEG_AVC_STREAM: if(mode == MPEG_AU_MODE_DECODE) { diff --git a/Core/MIPS/ARM/ArmCompALU.cpp b/Core/MIPS/ARM/ArmCompALU.cpp index 28236a77e3..281c027cde 100644 --- a/Core/MIPS/ARM/ArmCompALU.cpp +++ b/Core/MIPS/ARM/ArmCompALU.cpp @@ -34,20 +34,25 @@ using namespace MIPSAnalyst; namespace MIPSComp { - /* - void Jit::CompImmLogic(u32 op, void (ARMXEmitter::*arith)(ARMReg dst, ARMReg src, Operand2 op2)) + u32 EvalOR(u32 a, u32 b) { return a | b; } + u32 EvalXOR(u32 a, u32 b) { return a ^ b; } + u32 EvalAND(u32 a, u32 b) { return a & b; } + + + void Jit::CompImmLogic(int rs, int rt, u32 uimm, void (ARMXEmitter::*arith)(ARMReg dst, ARMReg src, Operand2 op2), u32 (*eval)(u32 a, u32 b)) { - u32 uimm = (u16)(op & 0xFFFF); - gpr.SpillLock() - int rt = _RT; - int rs = _RS; - gpr.Lock(rt, rs); - gpr.BindToRegister(rt, rt == rs, true); - if (rt != rs) - MOV(32, gpr.R(rt), gpr.R(rs)); - (this->*arith)(32, gpr.R(rt), Imm32(uimm)); - gpr.UnlockAll(); - }*/ + if (gpr.IsImm(rs)) { + gpr.SetImm(rt, (*eval)(gpr.GetImm(rs), uimm)); + } else { + gpr.SpillLock(rs, rt); + gpr.MapReg(rt, MAP_INITVAL | MAP_DIRTY); + gpr.MapReg(rs, MAP_INITVAL); + gpr.ReleaseSpillLocks(); + // TODO: Special case when uimm can be represented as an Operand2 + ARMABI_MOVI2R(R0, (u32)uimm); + (this->*arith)(gpr.R(rt), gpr.R(rs), R0); + } + } void Jit::Comp_IType(u32 op) { @@ -59,26 +64,31 @@ namespace MIPSComp switch (op >> 26) { - /* case 8: // same as addiu? case 9: //R(rt) = R(rs) + simm; break; //addiu { - if (gpr.IsImm(rs)) - { + if (gpr.IsImm(rs)) { gpr.SetImm(rt, gpr.GetImm(rs) + simm); - break; - } else if (rs == 0) { + }/* else if (rs == 0) { gpr.SetImm(rt, simm); } else { gpr.SpillLock(rs, rt); gpr.MapReg(rs, MAP_INITVAL); gpr.MapReg(rt, MAP_INITVAL | MAP_DIRTY); - ARMABI_MOVI2R(R0, (u32)simm); - ADD(gpr.R(rt), gpr.R(rs), R0); + Operand2 op2; + if (false && TryMakeOperand2(simm, op2)) { + ADD(gpr.R(rt), gpr.R(rs), op2); + } else { + ARMABI_MOVI2R(R0, (u32)simm); + ADD(gpr.R(rt), gpr.R(rs), R0); + } gpr.ReleaseSpillLocks(); + }*/ + else { + Comp_Generic(op); } break; - }*/ + } /* case 13: // OR { diff --git a/Core/MIPS/ARM/ArmCompBranch.cpp b/Core/MIPS/ARM/ArmCompBranch.cpp index 8485a0c1a3..7a4deaed8d 100644 --- a/Core/MIPS/ARM/ArmCompBranch.cpp +++ b/Core/MIPS/ARM/ArmCompBranch.cpp @@ -63,7 +63,6 @@ void Jit::BranchRSRTComp(u32 op, ArmGen::CCFlags cc, bool likely) } // The delay slot being nice doesn't really matter though... - /* if (rt == 0) { gpr.MapReg(rs, MAP_INITVAL); @@ -74,9 +73,7 @@ void Jit::BranchRSRTComp(u32 op, ArmGen::CCFlags cc, bool likely) gpr.MapReg(rt, MAP_INITVAL); CMP(gpr.R(rt), Operand2(0)); } - else - */ { gpr.SpillLock(rs, rt); gpr.MapReg(rs, MAP_INITVAL); diff --git a/Core/MIPS/ARM/ArmCompFPU.cpp b/Core/MIPS/ARM/ArmCompFPU.cpp index d008d2308b..9b3dee1bc4 100644 --- a/Core/MIPS/ARM/ArmCompFPU.cpp +++ b/Core/MIPS/ARM/ArmCompFPU.cpp @@ -115,6 +115,7 @@ void Jit::Comp_FPULS(u32 op) void Jit::Comp_FPU2op(u32 op) { + OLDD int fs = _FS; int fd = _FD; @@ -173,6 +174,7 @@ void Jit::Comp_FPU2op(u32 op) void Jit::Comp_mxc1(u32 op) { + OLDD int fs = _FS; int rt = _RT; diff --git a/Core/MIPS/ARM/ArmJit.cpp b/Core/MIPS/ARM/ArmJit.cpp index 671112c24b..7ff148aa1c 100644 --- a/Core/MIPS/ARM/ArmJit.cpp +++ b/Core/MIPS/ARM/ArmJit.cpp @@ -127,7 +127,11 @@ const u8 *Jit::DoJit(u32 em_address, ArmJitBlock *b) int numInstructions = 0; int cycles = 0; -// #define LOGASM + + static int logBlocks = 20; + if (logBlocks > 0) logBlocks--; + +#define LOGASM #ifdef LOGASM char temp[256]; #endif @@ -135,8 +139,10 @@ const u8 *Jit::DoJit(u32 em_address, ArmJitBlock *b) { u32 inst = Memory::Read_Instruction(js.compilerPC); #ifdef LOGASM - MIPSDisAsm(inst, js.compilerPC, temp, true); - INFO_LOG(DYNA_REC, "M: %08x %s", js.compilerPC, temp); + if (logBlocks > 0) { + MIPSDisAsm(inst, js.compilerPC, temp, true); + INFO_LOG(DYNA_REC, "M: %08x %s", js.compilerPC, temp); + } #endif js.downcountAmount += MIPSGetInstructionCycleEstimate(inst); @@ -146,14 +152,19 @@ const u8 *Jit::DoJit(u32 em_address, ArmJitBlock *b) numInstructions++; } #ifdef LOGASM - MIPSDisAsm(Memory::Read_Instruction(js.compilerPC), js.compilerPC, temp, true); - INFO_LOG(DYNA_REC, "M: %08x %s", js.compilerPC, temp); + if (logBlocks > 0) { + MIPSDisAsm(Memory::Read_Instruction(js.compilerPC), js.compilerPC, temp, true); + INFO_LOG(DYNA_REC, "M: %08x %s", js.compilerPC, temp); + } #endif b->codeSize = GetCodePtr() - b->normalEntry; #ifdef LOGASM - DisassembleArm(b->checkedEntry, GetCodePtr() - b->checkedEntry); + if (logBlocks > 0) { + INFO_LOG(DYNA_REC, "=============== ARM ==============="); + DisassembleArm(b->normalEntry, GetCodePtr() - b->normalEntry); + } #endif AlignCode16(); diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index 4f70ea53ed..805f44da1b 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -110,8 +110,8 @@ private: void BranchRSRTComp(u32 op, ArmGen::CCFlags cc, bool likely); // Utilities to reduce duplicated code + void CompImmLogic(int rs, int rt, u32 uimm, void (ARMXEmitter::*arith)(ARMReg dst, ARMReg src, Operand2 op2), u32 (*eval)(u32 a, u32 b)); /* - void CompImmLogic(u32 op, void (ARMXEmitter::*arith)(ARMReg dst, ARMReg src, Operand2 op2)); void CompImmLogic(u32 op, void (ARMXEmitter::*arith)(int, const OpArg &, const OpArg &)); void CompTriArith(u32 op, void (ARMXEmitter::*arith)(int, const OpArg &, const OpArg &)); void CompShiftImm(u32 op, void (ARMXEmitter::*shift)(int, OpArg, OpArg)); diff --git a/Core/MIPS/ARM/ArmRegCache.cpp b/Core/MIPS/ARM/ArmRegCache.cpp index 538e269cc2..7c34066b83 100644 --- a/Core/MIPS/ARM/ArmRegCache.cpp +++ b/Core/MIPS/ARM/ArmRegCache.cpp @@ -57,17 +57,20 @@ static const ARMReg *GetMIPSAllocationOrder(int &count) { } ARMReg ArmRegCache::MapReg(MIPSReg mipsReg, int mapFlags) { - // Let's see if it's already mapped. - for (int i = 0; i < NUM_ARMREG; i++) { - if (ar[i].mipsReg == mipsReg) { - if (mapFlags & MAP_DIRTY) - ar[i].isDirty = true; - // Already mapped, no need to do anything more. - return (ARMReg)i; + // Let's see if it's already mapped. If so we just need to update the dirty flag. + // We don't need to check for ML_INITVAL because we assume that anyone who maps + // with that flag immediately writes a "known" value to the register. + if (mr[mipsReg].loc == ML_ARMREG) { + if (ar[mr[mipsReg].reg].mipsReg != mipsReg) { + ERROR_LOG(HLE, "Mapping out of sync! %i", mipsReg); } + if (mapFlags & MAP_DIRTY) { + ar[mr[mipsReg].reg].isDirty = true; + } + return mr[mipsReg].reg; } - // Okay, so we need to allocate one. + // Okay, not mapped, so we need to allocate an ARM register. int allocCount; const ARMReg *allocOrder = GetMIPSAllocationOrder(allocCount); @@ -114,6 +117,7 @@ void ArmRegCache::FlushArmReg(ARMReg r) { if (ar[r].mipsReg != -1) { if (ar[r].isDirty && mr[ar[r].mipsReg].loc == ML_ARMREG) emit->STR(CTXREG, r, 4 * ar[r].mipsReg); + // IMMs won't be in an ARM reg. mr[ar[r].mipsReg].loc = ML_MEM; } else { ERROR_LOG(HLE, "Dirty but no mipsreg?"); @@ -151,11 +155,12 @@ void ArmRegCache::FlushAll() { } void ArmRegCache::SetImm(MIPSReg r, u32 immVal) { - // Zap existing value + // Zap existing value if cached in a reg if (mr[r].loc == ML_ARMREG) ar[mr[r].reg].mipsReg = -1; mr[r].loc = ML_IMM; mr[r].imm = immVal; + mr[r].reg = INVALID_REG; } bool ArmRegCache::IsImm(MIPSReg r) const { @@ -163,7 +168,9 @@ bool ArmRegCache::IsImm(MIPSReg r) const { } u32 ArmRegCache::GetImm(MIPSReg r) const { - // TODO: Check. + if (mr[r].loc != ML_IMM) { + ERROR_LOG(JIT, "Trying to get imm from non-imm register %i", r); + } return mr[r].imm; } @@ -176,8 +183,8 @@ int ArmRegCache::GetMipsRegOffset(MIPSReg r) { case MIPSREG_LO: return offsetof(MIPSState, lo); } - _dbg_assert_msg_(JIT, false, "bad mips register %i", (int)r); - return -999; // boom! + ERROR_LOG(JIT, "bad mips register %i", r); + return 0; // or what? } void ArmRegCache::SpillLock(MIPSReg r1, MIPSReg r2, MIPSReg r3) { @@ -187,7 +194,7 @@ void ArmRegCache::SpillLock(MIPSReg r1, MIPSReg r2, MIPSReg r3) { } void ArmRegCache::ReleaseSpillLocks() { - for (int i = 0; i < 16; i++) { + for (int i = 0; i < NUM_ARMREG; i++) { ar[i].spillLock = false; } } diff --git a/Core/MIPS/MIPS.h b/Core/MIPS/MIPS.h index 4f769301fe..701c1afdbc 100644 --- a/Core/MIPS/MIPS.h +++ b/Core/MIPS/MIPS.h @@ -113,6 +113,7 @@ public: void Reset(); void DoState(PointerWrap &p); + // MUST start with r! u32 r[32]; float f[32]; float v[128];