Merge pull request #4543 from unknownbrackets/cpu-minor

Minor cpu correctness adjustments
This commit is contained in:
Henrik Rydgård 2013-11-15 01:44:49 -08:00
commit 49f53a7ecd
13 changed files with 77 additions and 60 deletions

View File

@ -520,7 +520,7 @@ public:
virtual void DoState(PointerWrap &p)
{
auto s = p.Section("Thread", 1, 2);
auto s = p.Section("Thread", 1, 3);
if (!s)
return;
@ -531,6 +531,11 @@ public:
p.Do(currentMipscallId);
p.Do(currentCallbackId);
p.Do(context);
if (s <= 2)
{
context.other[4] = context.other[5];
context.other[3] = context.other[4];
}
p.Do(callbacks);
@ -1928,8 +1933,7 @@ void ThreadContext::reset()
vfpuCtrl[VFPU_CTRL_RCX6] = 0x3f800000;
vfpuCtrl[VFPU_CTRL_RCX7] = 0x3f800000;
fpcond = 0;
fcr0 = 0;
fcr31 = 0;
fcr31 = 0x00000e00;
hi = 0xDEADBEEF;
lo = 0xDEADBEEF;
}

View File

@ -132,7 +132,6 @@ struct ThreadContext
u32 hi;
u32 lo;
u32 fcr0;
u32 fcr31;
u32 fpcond;
};

View File

@ -159,7 +159,7 @@ void Jit::GenerateFixedCode()
LDR(R0, CTXREG, offsetof(MIPSState, pc));
BIC(R0, R0, Operand2(0xC0, 4)); // &= 0x3FFFFFFF
LDR(R0, R11, R0);
LDR(R0, MEMBASEREG, R0);
AND(R1, R0, Operand2(0xFC, 4)); // rotation is to the right, in 2-bit increments.
BIC(R0, R0, Operand2(0xFC, 4));
CMP(R1, Operand2(MIPS_EMUHACK_OPCODE >> 24, 4));

View File

@ -461,23 +461,28 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
}
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
bool andLink = (op & 0x3f) == 9;
MIPSOpcode delaySlotOp = Memory::Read_Instruction(js.compilerPC + 4);
bool delaySlotIsNice = IsDelaySlotNiceReg(op, delaySlotOp, rs);
if (andLink && rs == rd)
delaySlotIsNice = false;
CONDITIONAL_NICE_DELAYSLOT;
ARMReg destReg = R8;
if (IsSyscall(delaySlotOp)) {
_dbg_assert_msg_(JIT, (op & 0x3f) == 8, "jalr followed by syscall not supported.");
gpr.MapReg(rs);
MovToPC(gpr.R(rs)); // For syscall to be able to return.
if (andLink)
gpr.SetImm(rd, js.compilerPC + 8);
CompileDelaySlot(DELAYSLOT_FLUSH);
return; // Syscall wrote exit code.
} else if (delaySlotIsNice) {
if (andLink)
gpr.SetImm(rd, js.compilerPC + 8);
CompileDelaySlot(DELAYSLOT_NICE);
if (rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) {
if (!andLink && rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) {
// According to the MIPS ABI, there are some regs we don't need to preserve.
// Let's discard them so we don't need to write them back.
// NOTE: Not all games follow the MIPS ABI! Tekken 6, for example, will crash
@ -492,9 +497,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
if (jo.continueJumps && gpr.IsImm(rs) && js.numInstructions < jo.continueMaxInstructions) {
// Account for the increment in the loop.
js.compilerPC = gpr.GetImm(rs) - 4;
if ((op & 0x3f) == 9) {
gpr.SetImm(rd, js.compilerPC + 8);
}
// In case the delay slot was a break or something.
js.compiling = true;
return;
@ -507,6 +509,8 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
// Delay slot - this case is very rare, might be able to free up R8.
gpr.MapReg(rs);
MOV(R8, gpr.R(rs));
if (andLink)
gpr.SetImm(rd, js.compilerPC + 8);
CompileDelaySlot(DELAYSLOT_NICE);
FlushAll();
}
@ -516,8 +520,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
case 8: //jr
break;
case 9: //jalr
gpr.SetRegImm(R0, js.compilerPC + 8);
STR(R0, CTXREG, (int)rd * 4);
break;
default:
_dbg_assert_msg_(CPU,0,"Trying to compile instruction that can't be compiled");

View File

@ -117,7 +117,7 @@ void Jit::Comp_FPULS(MIPSOpcode op)
SetCCAndR0ForSafeAddress(rs, offset, R1);
doCheck = true;
}
ADD(R0, R0, R11);
ADD(R0, R0, MEMBASEREG);
}
#ifdef __ARM_ARCH_7S__
FixupBranch skip;
@ -161,7 +161,7 @@ void Jit::Comp_FPULS(MIPSOpcode op)
SetCCAndR0ForSafeAddress(rs, offset, R1);
doCheck = true;
}
ADD(R0, R0, R11);
ADD(R0, R0, MEMBASEREG);
}
#ifdef __ARM_ARCH_7S__
FixupBranch skip2;
@ -339,8 +339,7 @@ void Jit::Comp_mxc1(MIPSOpcode op)
return;
case 2: //cfc1
if (fs == 31)
{
if (fs == 31) {
gpr.MapDirtyIn(rt, MIPS_REG_FPCOND);
LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31));
#ifdef HAVE_ARMV7
@ -350,11 +349,11 @@ void Jit::Comp_mxc1(MIPSOpcode op)
ANDI2R(gpr.R(rt), gpr.R(rt), ~(0x1 << 23), R1); // R1 won't be used, this turns into a simple BIC.
ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, 23));
#endif
}
else if (fs == 0)
{
gpr.MapReg(rt, MAP_DIRTY | MAP_NOINIT);
LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr0));
} else if (fs == 0) {
gpr.SetImm(rt, MIPSState::FCR0_VALUE);
} else {
// Unsupported regs are always 0.
gpr.SetImm(rt, 0);
}
return;
@ -386,6 +385,7 @@ void Jit::Comp_mxc1(MIPSOpcode op)
VMSR(R1);
*/
// Update MIPS state
// TODO: Technically, should mask by 0x0181FFFF. Maybe just put all of FCR31 in the reg?
STR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31));
#ifdef HAVE_ARMV7
UBFX(gpr.R(MIPS_REG_FPCOND), gpr.R(rt), 23, 1);

View File

@ -162,31 +162,31 @@ namespace MIPSComp
switch (o) {
case 34: // lwl
LDR(R0, R11, R0);
LDR(R0, MEMBASEREG, R0);
ANDI2R(gpr.R(rt), gpr.R(rt), 0x00ffffff >> shift, R1);
ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, 24 - shift));
break;
case 38: // lwr
LDR(R0, R11, R0);
LDR(R0, MEMBASEREG, R0);
ANDI2R(gpr.R(rt), gpr.R(rt), 0xffffff00 << (24 - shift), R1);
ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSR, shift));
break;
case 42: // swl
LDR(R1, R11, R0);
LDR(R1, MEMBASEREG, R0);
// Don't worry, can't use temporary.
ANDI2R(R1, R1, 0xffffff00 << shift, R0);
ORR(R1, R1, Operand2(gpr.R(rt), ST_LSR, 24 - shift));
STR(R1, R11, R0);
STR(R1, MEMBASEREG, R0);
break;
case 46: // swr
LDR(R1, R11, R0);
LDR(R1, MEMBASEREG, R0);
// Don't worry, can't use temporary.
ANDI2R(R1, R1, 0x00ffffff >> (24 - shift), R0);
ORR(R1, R1, Operand2(gpr.R(rt), ST_LSL, shift));
STR(R1, R11, R0);
STR(R1, MEMBASEREG, R0);
break;
}
return;
@ -223,7 +223,7 @@ namespace MIPSComp
switch (o) {
case 34: // lwl
MOVI2R(R10, 0x00ffffff);
LDR(R0, R11, R0);
LDR(R0, MEMBASEREG, R0);
AND(gpr.R(rt), gpr.R(rt), Operand2(R10, ST_LSR, R1));
RSB(R1, R1, 24);
ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, R1));
@ -231,7 +231,7 @@ namespace MIPSComp
case 38: // lwr
MOVI2R(R10, 0xffffff00);
LDR(R0, R11, R0);
LDR(R0, MEMBASEREG, R0);
LSR(R0, R0, R1);
RSB(R1, R1, 24);
AND(gpr.R(rt), gpr.R(rt), Operand2(R10, ST_LSL, R1));
@ -240,21 +240,21 @@ namespace MIPSComp
case 42: // swl
MOVI2R(R10, 0xffffff00);
LDR(R9, R11, R0);
LDR(R9, MEMBASEREG, R0);
AND(R9, R9, Operand2(R10, ST_LSL, R1));
RSB(R1, R1, 24);
ORR(R9, R9, Operand2(gpr.R(rt), ST_LSR, R1));
STR(R9, R11, R0);
STR(R9, MEMBASEREG, R0);
break;
case 46: // swr
MOVI2R(R10, 0x00ffffff);
LDR(R9, R11, R0);
LDR(R9, MEMBASEREG, R0);
RSB(R1, R1, 24);
AND(R9, R9, Operand2(R10, ST_LSR, R1));
RSB(R1, R1, 24);
ORR(R9, R9, Operand2(gpr.R(rt), ST_LSL, R1));
STR(R9, R11, R0);
STR(R9, MEMBASEREG, R0);
break;
}
@ -353,15 +353,15 @@ namespace MIPSComp
switch (o)
{
// Load
case 35: LDR (gpr.R(rt), R11, addrReg); break;
case 37: LDRH (gpr.R(rt), R11, addrReg); break;
case 33: LDRSH(gpr.R(rt), R11, addrReg); break;
case 36: LDRB (gpr.R(rt), R11, addrReg); break;
case 32: LDRSB(gpr.R(rt), R11, addrReg); break;
case 35: LDR (gpr.R(rt), MEMBASEREG, addrReg); break;
case 37: LDRH (gpr.R(rt), MEMBASEREG, addrReg); break;
case 33: LDRSH(gpr.R(rt), MEMBASEREG, addrReg); break;
case 36: LDRB (gpr.R(rt), MEMBASEREG, addrReg); break;
case 32: LDRSB(gpr.R(rt), MEMBASEREG, addrReg); break;
// Store
case 43: STR (gpr.R(rt), R11, addrReg); break;
case 41: STRH (gpr.R(rt), R11, addrReg); break;
case 40: STRB (gpr.R(rt), R11, addrReg); break;
case 43: STR (gpr.R(rt), MEMBASEREG, addrReg); break;
case 41: STRH (gpr.R(rt), MEMBASEREG, addrReg); break;
case 40: STRB (gpr.R(rt), MEMBASEREG, addrReg); break;
}
if (doCheck) {
if (load) {

View File

@ -263,7 +263,7 @@ namespace MIPSComp
SetCCAndR0ForSafeAddress(rs, imm, R1);
doCheck = true;
}
ADD(R0, R0, R11);
ADD(R0, R0, MEMBASEREG);
}
#ifdef __ARM_ARCH_7S__
FixupBranch skip;
@ -301,7 +301,7 @@ namespace MIPSComp
SetCCAndR0ForSafeAddress(rs, imm, R1);
doCheck = true;
}
ADD(R0, R0, R11);
ADD(R0, R0, MEMBASEREG);
}
#ifdef __ARM_ARCH_7S__
FixupBranch skip;
@ -357,7 +357,7 @@ namespace MIPSComp
SetCCAndR0ForSafeAddress(rs, imm, R1);
doCheck = true;
}
ADD(R0, R0, R11);
ADD(R0, R0, MEMBASEREG);
}
#ifdef __ARM_ARCH_7S__
@ -406,7 +406,7 @@ namespace MIPSComp
SetCCAndR0ForSafeAddress(rs, imm, R1);
doCheck = true;
}
ADD(R0, R0, R11);
ADD(R0, R0, MEMBASEREG);
}
#ifdef __ARM_ARCH_7S__

View File

@ -91,7 +91,7 @@ ARMReg ArmRegCache::MapRegAsPointer(MIPSGPReg mipsReg) { // read-only, non-dirt
// Convert to a pointer by adding the base and clearing off the top bits.
// If SP, we can probably avoid the top bit clear, let's play with that later.
emit_->BIC(armReg, armReg, Operand2(0xC0, 4)); // &= 0x3FFFFFFF
emit_->ADD(armReg, R11, armReg);
emit_->ADD(armReg, MEMBASEREG, armReg);
ar[armReg].isDirty = false;
ar[armReg].mipsReg = mipsReg;
mr[mipsReg].loc = ML_ARMREG_AS_PTR;
@ -356,7 +356,7 @@ void ArmRegCache::FlushArmReg(ARMReg r) {
if (ar[r].mipsReg != MIPS_REG_INVALID) {
auto &mreg = mr[ar[r].mipsReg];
if (mreg.loc == ML_ARMREG_IMM) {
// We know it's immedate value, no need to STR now.
// We know its immedate value, no need to STR now.
mreg.loc = ML_IMM;
mreg.reg = INVALID_REG;
} else {

View File

@ -24,6 +24,7 @@
using namespace ArmGen;
#define CTXREG (R10)
#define MEMBASEREG (R11)
// R2 to R8: mapped MIPS regs
// R9 = code pointers

View File

@ -134,7 +134,6 @@ void MIPSState::Reset()
hi = 0;
lo = 0;
fpcond = 0;
fcr0 = 0;
fcr31 = 0;
debugCount = 0;
currentMIPS = this;
@ -147,7 +146,7 @@ void MIPSState::Reset()
}
void MIPSState::DoState(PointerWrap &p) {
auto s = p.Section("MIPSState", 1);
auto s = p.Section("MIPSState", 1, 2);
if (!s)
return;
@ -169,7 +168,10 @@ void MIPSState::DoState(PointerWrap &p) {
p.Do(hi);
p.Do(lo);
p.Do(fpcond);
p.Do(fcr0);
if (s <= 1) {
u32 fcr0_unusued = 0;
p.Do(fcr0_unusued);
}
p.Do(fcr31);
p.Do(rng.m_w);
p.Do(rng.m_z);
@ -204,7 +206,7 @@ void MIPSState::WriteFCR(int reg, int value)
{
if (reg == 31)
{
fcr31 = value;
fcr31 = value & 0x0181FFFF;
fpcond = (value >> 23) & 1;
}
else
@ -225,7 +227,7 @@ u32 MIPSState::ReadFCR(int reg)
}
else if (reg == 0)
{
return fcr0;
return FCR0_VALUE;
}
else
{

View File

@ -146,7 +146,6 @@ public:
u32 hi;
u32 lo;
u32 fcr0;
u32 fcr31; //fpu control register
u32 fpcond; // cache the cond flag of fcr31 (& 1 << 23)
};
@ -165,6 +164,8 @@ public:
// Debug stuff
u32 debugCount; // can be used to count basic blocks before crashes, etc.
static const u32 FCR0_VALUE = 0x00003351;
void WriteFCR(int reg, int value);
u32 ReadFCR(int reg);

View File

@ -587,18 +587,21 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
}
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
bool andLink = (op & 0x3f) == 9;
MIPSOpcode delaySlotOp = Memory::Read_Instruction(js.compilerPC + 4);
bool delaySlotIsNice = IsDelaySlotNiceReg(op, delaySlotOp, rs);
if (andLink && rs == rd)
delaySlotIsNice = false;
CONDITIONAL_NICE_DELAYSLOT;
if (IsSyscall(delaySlotOp))
{
_dbg_assert_msg_(JIT, (op & 0x3f) == 8, "jalr followed by syscall not supported.");
// If this is a syscall, write the pc (for thread switching and other good reasons.)
gpr.MapReg(rs, true, false);
MOV(32, M(&currentMIPS->pc), gpr.R(rs));
if (andLink)
gpr.SetImm(rd, js.compilerPC + 8);
CompileDelaySlot(DELAYSLOT_FLUSH);
// Syscalls write the exit code for us.
@ -607,9 +610,11 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
}
else if (delaySlotIsNice)
{
if (andLink)
gpr.SetImm(rd, js.compilerPC + 8);
CompileDelaySlot(DELAYSLOT_NICE);
if (rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) {
if (!andLink && rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) {
// According to the MIPS ABI, there are some regs we don't need to preserve.
// Let's discard them so we don't need to write them back.
// NOTE: Not all games follow the MIPS ABI! Tekken 6, for example, will crash
@ -625,8 +630,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
{
// Account for the increment in the loop.
js.compilerPC = gpr.GetImm(rs) - 4;
if ((op & 0x3f) == 9)
gpr.SetImm(rd, js.compilerPC + 8);
// In case the delay slot was a break or something.
js.compiling = true;
return;
@ -640,6 +643,8 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
// Latch destination now - save it in memory.
gpr.MapReg(rs, true, false);
MOV(32, M(&savedPC), gpr.R(rs));
if (andLink)
gpr.SetImm(rd, js.compilerPC + 8);
CompileDelaySlot(DELAYSLOT_NICE);
MOV(32, R(EAX), M(&savedPC));
FlushAll();
@ -650,7 +655,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
case 8: //jr
break;
case 9: //jalr
MOV(32, M(&mips_->r[rd]), Imm32(js.compilerPC + 8));
break;
default:
_dbg_assert_msg_(CPU,0,"Trying to compile instruction that can't be compiled");

View File

@ -46,6 +46,10 @@ public:
fullInfo = "NULL";
}
virtual bool FramebufferReallyDirty() {
return !(gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME);
}
protected:
virtual void FastRunLoop(DisplayList &list);
};