Merge branch 'interpreter-fixes' into less-ambitious-timing-rework
This commit is contained in:
commit
5c120f45ee
|
@ -98,7 +98,8 @@ void A_MSR_IMM(ARM* cpu)
|
||||||
case 0x1A:
|
case 0x1A:
|
||||||
case 0x1B: psr = &cpu->R_UND[2]; break;
|
case 0x1B: psr = &cpu->R_UND[2]; break;
|
||||||
default:
|
default:
|
||||||
cpu->AddCycles_C();
|
if (cpu->Num != 1) cpu->AddCycles_C(); // arm 7
|
||||||
|
else cpu->AddCycles_CI(2); // arm 9
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +137,16 @@ void A_MSR_IMM(ARM* cpu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->AddCycles_C();
|
if (cpu->Num != 1)
|
||||||
|
{
|
||||||
|
if (cpu->CurInstr & (1<<22))
|
||||||
|
{
|
||||||
|
cpu->AddCycles_CI(2); // spsr
|
||||||
|
}
|
||||||
|
else if (cpu->CurInstr & (0x7<<16)) cpu->AddCycles_CI(2); // cpsr_sxc
|
||||||
|
else cpu->AddCycles_C();
|
||||||
|
}
|
||||||
|
else cpu->AddCycles_C();
|
||||||
}
|
}
|
||||||
|
|
||||||
void A_MSR_REG(ARM* cpu)
|
void A_MSR_REG(ARM* cpu)
|
||||||
|
@ -158,7 +168,8 @@ void A_MSR_REG(ARM* cpu)
|
||||||
case 0x1A:
|
case 0x1A:
|
||||||
case 0x1B: psr = &cpu->R_UND[2]; break;
|
case 0x1B: psr = &cpu->R_UND[2]; break;
|
||||||
default:
|
default:
|
||||||
cpu->AddCycles_C();
|
if (cpu->Num != 1) cpu->AddCycles_C(); // arm 7
|
||||||
|
else cpu->AddCycles_CI(2); // arm 9
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,7 +207,16 @@ void A_MSR_REG(ARM* cpu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->AddCycles_C();
|
if (cpu->Num != 1)
|
||||||
|
{
|
||||||
|
if (cpu->CurInstr & (1<<22))
|
||||||
|
{
|
||||||
|
cpu->AddCycles_CI(2); // spsr
|
||||||
|
}
|
||||||
|
else if (cpu->CurInstr & (0x7<<16)) cpu->AddCycles_CI(2); // cpsr_sxc
|
||||||
|
else cpu->AddCycles_C();
|
||||||
|
}
|
||||||
|
else cpu->AddCycles_C();
|
||||||
}
|
}
|
||||||
|
|
||||||
void A_MRS(ARM* cpu)
|
void A_MRS(ARM* cpu)
|
||||||
|
@ -282,11 +302,17 @@ void A_MRC(ARM* cpu)
|
||||||
u32 cpinfo = (cpu->CurInstr >> 5) & 0x7;
|
u32 cpinfo = (cpu->CurInstr >> 5) & 0x7;
|
||||||
u32 rd = (cpu->CurInstr>>12) & 0xF;
|
u32 rd = (cpu->CurInstr>>12) & 0xF;
|
||||||
|
|
||||||
if (cpu->Num==0 && cp==15 && rd!=15)
|
if (cpu->Num==0 && cp==15)
|
||||||
{
|
{
|
||||||
cpu->R[rd] = ((ARMv5*)cpu)->CP15Read((cn<<8)|(cm<<4)|cpinfo);
|
if (rd != 15) cpu->R[rd] = ((ARMv5*)cpu)->CP15Read((cn<<8)|(cm<<4)|cpinfo);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// r15 updates the top 4 bits of the cpsr, done to "allow for conditional branching based on coprocessor status"
|
||||||
|
u32 flags = ((ARMv5*)cpu)->CP15Read((cn<<8)|(cm<<4)|cpinfo) & 0xF0000000;
|
||||||
|
cpu->CPSR = (cpu->CPSR & ~0xF0000000) | flags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (cpu->Num==1 && cp==14 && rd!=15)
|
else if (cpu->Num==1 && cp==14)
|
||||||
{
|
{
|
||||||
Log(LogLevel::Debug, "MRC p14,%d,%d,%d on ARM7\n", cn, cm, cpinfo);
|
Log(LogLevel::Debug, "MRC p14,%d,%d,%d on ARM7\n", cn, cm, cpinfo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -581,12 +581,12 @@ A_IMPLEMENT_ALU_OP(RSC,)
|
||||||
#define A_TST(c) \
|
#define A_TST(c) \
|
||||||
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
u32 res = a & b; \
|
u32 res = a & b; \
|
||||||
cpu->SetNZ(res & 0x80000000, \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* this seems to trigger alu rd==15 behavior for arm7 and legacy instruction behavior for arm9 */ \
|
||||||
!res); \
|
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* yes this instruction has a secret rd for some reason */ \
|
|
||||||
{ \
|
{ \
|
||||||
if (cpu->Num == 1) \
|
if (cpu->Num == 1) \
|
||||||
{ \
|
{ \
|
||||||
|
cpu->SetNZ(res & 0x80000000, \
|
||||||
|
!res); \
|
||||||
u32 oldpsr = cpu->CPSR; \
|
u32 oldpsr = cpu->CPSR; \
|
||||||
cpu->RestoreCPSR(); /* ARM7TDMI restores cpsr and does ___not___ flush the pipeline. */ \
|
cpu->RestoreCPSR(); /* ARM7TDMI restores cpsr and does ___not___ flush the pipeline. */ \
|
||||||
if (cpu->CPSR & 0x20) \
|
if (cpu->CPSR & 0x20) \
|
||||||
|
@ -595,7 +595,12 @@ A_IMPLEMENT_ALU_OP(RSC,)
|
||||||
cpu->CPSR &= ~0x20; /* keep it from crashing the emulator at least */ \
|
cpu->CPSR &= ~0x20; /* keep it from crashing the emulator at least */ \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
else Platform::Log(Platform::LogLevel::Warn, "UNIMPLEMENTED: TST w/ rd == 15 on ARM9\n"); \
|
else cpu->JumpTo(res & ~1, true); /* TSTP dna, doesn't update flags */ \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
cpu->SetNZ(res & 0x80000000, \
|
||||||
|
!res); \
|
||||||
} \
|
} \
|
||||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C();
|
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C();
|
||||||
|
|
||||||
|
@ -605,12 +610,12 @@ A_IMPLEMENT_ALU_TEST(TST,_S)
|
||||||
#define A_TEQ(c) \
|
#define A_TEQ(c) \
|
||||||
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
u32 res = a ^ b; \
|
u32 res = a ^ b; \
|
||||||
cpu->SetNZ(res & 0x80000000, \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* this seems to trigger alu rd==15 behavior for arm7 and legacy instruction behavior for arm9 */ \
|
||||||
!res); \
|
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* yes this instruction has a secret rd for some reason */ \
|
|
||||||
{ \
|
{ \
|
||||||
if (cpu->Num == 1) \
|
if (cpu->Num == 1) \
|
||||||
{ \
|
{ \
|
||||||
|
cpu->SetNZ(res & 0x80000000, \
|
||||||
|
!res); \
|
||||||
u32 oldpsr = cpu->CPSR; \
|
u32 oldpsr = cpu->CPSR; \
|
||||||
cpu->RestoreCPSR(); /* ARM7TDMI restores cpsr and does ___not___ flush the pipeline. */ \
|
cpu->RestoreCPSR(); /* ARM7TDMI restores cpsr and does ___not___ flush the pipeline. */ \
|
||||||
if (cpu->CPSR & 0x20) \
|
if (cpu->CPSR & 0x20) \
|
||||||
|
@ -619,7 +624,12 @@ A_IMPLEMENT_ALU_TEST(TST,_S)
|
||||||
cpu->CPSR &= ~0x20; /* keep it from crashing the emulator at least */ \
|
cpu->CPSR &= ~0x20; /* keep it from crashing the emulator at least */ \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
else Platform::Log(Platform::LogLevel::Warn, "UNIMPLEMENTED: TEQ w/ rd == 15 on ARM9\n"); \
|
else cpu->JumpTo(res & ~1, true); /* TEQP dna, doesn't update flags */ \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
cpu->SetNZ(res & 0x80000000, \
|
||||||
|
!res); \
|
||||||
} \
|
} \
|
||||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C();
|
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C();
|
||||||
|
|
||||||
|
@ -629,14 +639,14 @@ A_IMPLEMENT_ALU_TEST(TEQ,_S)
|
||||||
#define A_CMP(c) \
|
#define A_CMP(c) \
|
||||||
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
u32 res = a - b; \
|
u32 res = a - b; \
|
||||||
cpu->SetNZCV(res & 0x80000000, \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* this seems to trigger alu rd==15 behavior for arm7 and legacy instruction behavior for arm9 */ \
|
||||||
!res, \
|
|
||||||
CarrySub(a, b), \
|
|
||||||
OverflowSub(a, b)); \
|
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* yes this instruction has a secret rd for some reason */ \
|
|
||||||
{ \
|
{ \
|
||||||
if (cpu->Num == 1) \
|
if (cpu->Num == 1) \
|
||||||
{ \
|
{ \
|
||||||
|
cpu->SetNZCV(res & 0x80000000, \
|
||||||
|
!res, \
|
||||||
|
CarrySub(a, b), \
|
||||||
|
OverflowSub(a, b)); \
|
||||||
u32 oldpsr = cpu->CPSR; \
|
u32 oldpsr = cpu->CPSR; \
|
||||||
cpu->RestoreCPSR(); /* ARM7TDMI restores cpsr and does ___not___ flush the pipeline. */ \
|
cpu->RestoreCPSR(); /* ARM7TDMI restores cpsr and does ___not___ flush the pipeline. */ \
|
||||||
if (cpu->CPSR & 0x20) \
|
if (cpu->CPSR & 0x20) \
|
||||||
|
@ -645,7 +655,14 @@ A_IMPLEMENT_ALU_TEST(TEQ,_S)
|
||||||
cpu->CPSR &= ~0x20; /* keep it from crashing the emulator at least */ \
|
cpu->CPSR &= ~0x20; /* keep it from crashing the emulator at least */ \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
else Platform::Log(Platform::LogLevel::Warn, "UNIMPLEMENTED: CMP w/ rd == 15 on ARM9\n"); \
|
else cpu->JumpTo(res & ~1, true); /* CMPP dna, doesn't update flags */ \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
cpu->SetNZCV(res & 0x80000000, \
|
||||||
|
!res, \
|
||||||
|
CarrySub(a, b), \
|
||||||
|
OverflowSub(a, b)); \
|
||||||
} \
|
} \
|
||||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C();
|
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C();
|
||||||
|
|
||||||
|
@ -655,14 +672,14 @@ A_IMPLEMENT_ALU_TEST(CMP,)
|
||||||
#define A_CMN(c) \
|
#define A_CMN(c) \
|
||||||
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
u32 res = a + b; \
|
u32 res = a + b; \
|
||||||
cpu->SetNZCV(res & 0x80000000, \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* this seems to trigger alu rd==15 behavior for arm7 and legacy instruction behavior for arm9 */ \
|
||||||
!res, \
|
|
||||||
CarryAdd(a, b), \
|
|
||||||
OverflowAdd(a, b)); \
|
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* yes this instruction has a secret rd for some reason */ \
|
|
||||||
{ \
|
{ \
|
||||||
if (cpu->Num == 1) \
|
if (cpu->Num == 1) \
|
||||||
{ \
|
{ \
|
||||||
|
cpu->SetNZCV(res & 0x80000000, \
|
||||||
|
!res, \
|
||||||
|
CarryAdd(a, b), \
|
||||||
|
OverflowAdd(a, b)); \
|
||||||
u32 oldpsr = cpu->CPSR; \
|
u32 oldpsr = cpu->CPSR; \
|
||||||
cpu->RestoreCPSR(); /* ARM7TDMI restores cpsr and does ___not___ flush the pipeline. */ \
|
cpu->RestoreCPSR(); /* ARM7TDMI restores cpsr and does ___not___ flush the pipeline. */ \
|
||||||
if (cpu->CPSR & 0x20) \
|
if (cpu->CPSR & 0x20) \
|
||||||
|
@ -671,7 +688,14 @@ A_IMPLEMENT_ALU_TEST(CMP,)
|
||||||
cpu->CPSR &= ~0x20; /* keep it from crashing the emulator at least */ \
|
cpu->CPSR &= ~0x20; /* keep it from crashing the emulator at least */ \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
else Platform::Log(Platform::LogLevel::Warn, "UNIMPLEMENTED: CMN w/ rd == 15 on ARM9\n"); \
|
else cpu->JumpTo(res & ~1, true); /* CMNP dna, doesn't update flags */ \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
cpu->SetNZCV(res & 0x80000000, \
|
||||||
|
!res, \
|
||||||
|
CarryAdd(a, b), \
|
||||||
|
OverflowAdd(a, b)); \
|
||||||
} \
|
} \
|
||||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C();
|
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C();
|
||||||
|
|
||||||
|
@ -1643,20 +1667,18 @@ void T_CMP_HIREG(ARM* cpu)
|
||||||
!res,
|
!res,
|
||||||
CarrySub(a, b),
|
CarrySub(a, b),
|
||||||
OverflowSub(a, b));
|
OverflowSub(a, b));
|
||||||
if (rd == 15) [[unlikely]]
|
|
||||||
|
if ((cpu->Num == 1) && (rd == 15))
|
||||||
{
|
{
|
||||||
if (cpu->Num == 1)
|
u32 oldpsr = cpu->CPSR;
|
||||||
|
cpu->RestoreCPSR(); // ARM7TDMI restores cpsr and does ___not___ flush the pipeline.
|
||||||
|
if (!(cpu->CPSR & 0x20))
|
||||||
{
|
{
|
||||||
u32 oldpsr = cpu->CPSR;
|
Platform::Log(Platform::LogLevel::Warn, "UNIMPLEMENTED: MSR REG T bit change on ARM7\n");
|
||||||
cpu->RestoreCPSR(); // ARM7TDMI restores cpsr and does ___not___ flush the pipeline.
|
cpu->CPSR |= 0x20; // keep it from crashing the emulator at least
|
||||||
if (!(cpu->CPSR & 0x20))
|
|
||||||
{
|
|
||||||
Platform::Log(Platform::LogLevel::Warn, "UNIMPLEMENTED: MSR REG T bit change on ARM7\n");
|
|
||||||
cpu->CPSR |= 0x20; // keep it from crashing the emulator at least
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else Platform::Log(Platform::LogLevel::Warn, "UNIMPLEMENTED: CMP HIREG w/ rd == 15 on ARM9\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->AddCycles_C();
|
cpu->AddCycles_C();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue