reimplement forced interlocks

This commit is contained in:
Jaklyy 2024-12-07 09:55:55 -05:00
parent 9a4dc94910
commit 98f24d05c7
3 changed files with 25 additions and 12 deletions

View File

@ -1447,6 +1447,11 @@ void ARMv5::HandleInterlocksMemory_2()
ILPrevTime = 16; ILPrevTime = 16;
} }
void ARMv5::ForceInterlock_2()
{
NDS.ARM9Timestamp = TimestampMemory + ILForceDelay;
}
void ARMv4::CodeRead16(u32 addr) void ARMv4::CodeRead16(u32 addr)
{ {
if ((addr >> 24) == 0x02) if ((addr >> 24) == 0x02)

View File

@ -372,6 +372,12 @@ public:
QueueFunction(&ARMv5::HandleInterlocksExecute_2); QueueFunction(&ARMv5::HandleInterlocksExecute_2);
} }
inline void ForceInterlock(s8 delay = 0)
{
ILForceDelay = delay;
QueueFunction(&ARMv5::ForceInterlock_2);
}
inline void HandleInterlocksMemory(u8 reg) inline void HandleInterlocksMemory(u8 reg)
{ {
ILQueueMemReg = reg; ILQueueMemReg = reg;
@ -726,6 +732,7 @@ public:
void SetupInterlock_2(); void SetupInterlock_2();
void HandleInterlocksExecute_2(); void HandleInterlocksExecute_2();
void HandleInterlocksMemory_2(); void HandleInterlocksMemory_2();
void ForceInterlock_2();
void QueueUpdateMode() { UpdateMode(QueueMode[0], QueueMode[1], true); } void QueueUpdateMode() { UpdateMode(QueueMode[0], QueueMode[1], true); }
void SignExtend8() { R[ExtReg] = (s32)(s8)R[ExtReg]; } void SignExtend8() { R[ExtReg] = (s32)(s8)R[ExtReg]; }
void SignExtend16() { R[ExtReg] = (s32)(s16)R[ExtReg]; } void SignExtend16() { R[ExtReg] = (s32)(s16)R[ExtReg]; }
@ -812,6 +819,7 @@ public:
u64 ICacheStreamTimes[7]; u64 ICacheStreamTimes[7];
u64 DCacheStreamTimes[7]; u64 DCacheStreamTimes[7];
s8 ILForceDelay;
u8 WBWritePointer; // which entry to attempt to write next; should always be ANDed with 0xF after incrementing u8 WBWritePointer; // which entry to attempt to write next; should always be ANDed with 0xF after incrementing
u8 WBFillPointer; // where the next entry should be added; should always be ANDed with 0xF after incrementing u8 WBFillPointer; // where the next entry should be added; should always be ANDed with 0xF after incrementing
u8 WBWriting; // whether the buffer is actively trying to perform a write u8 WBWriting; // whether the buffer is actively trying to perform a write

View File

@ -170,7 +170,7 @@ void LoadSingle(ARM* cpu, const u8 rd, const u8 rn, const s32 offset, const u16
if (rd == 15) if (rd == 15)
{ {
//if (cpu->Num==0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampMemory + ((size<32) || (addr&0x3)); // force an interlock if (cpu->Num==0) ((ARMv5*)cpu)->ForceInterlock((size<32) || (addr&0x3));
cpu->JumpTo(cpu->R[15], false, 1); cpu->JumpTo(cpu->R[15], false, 1);
} }
@ -373,7 +373,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
((ARMv5*)cpu)->DataAbort(); \ ((ARMv5*)cpu)->DataAbort(); \
return; } \ return; } \
if (r+1 == 15) { \ if (r+1 == 15) { \
/*if (cpu->Num==0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampMemory;*/ \ if (cpu->Num==0) ((ARMv5*)cpu)->ForceInterlock(); \
cpu->JumpTo(cpu->R[15], cpu->CurInstr & (1<<22), 1); } /* restores cpsr presumably due to shared dna with ldm */ \ cpu->JumpTo(cpu->R[15], cpu->CurInstr & (1<<22), 1); } /* restores cpsr presumably due to shared dna with ldm */ \
else { \ else { \
if (cpu->Num == 0) ((ARMv5*)cpu)->SetupInterlock(r+1); } \ if (cpu->Num == 0) ((ARMv5*)cpu)->SetupInterlock(r+1); } \
@ -395,7 +395,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
((ARMv5*)cpu)->DataAbort(); \ ((ARMv5*)cpu)->DataAbort(); \
return; } \ return; } \
if (r+1 == 15) { \ if (r+1 == 15) { \
/*if (cpu->Num==0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampMemory;*/ \ if (cpu->Num==0) ((ARMv5*)cpu)->ForceInterlock(); ; \
cpu->JumpTo(cpu->R[15], cpu->CurInstr & (1<<22), 1); } /* restores cpsr presumably due to shared dna with ldm */ \ cpu->JumpTo(cpu->R[15], cpu->CurInstr & (1<<22), 1); } /* restores cpsr presumably due to shared dna with ldm */ \
else { \ else { \
if (cpu->Num == 0) ((ARMv5*)cpu)->SetupInterlock(r+1); } \ if (cpu->Num == 0) ((ARMv5*)cpu)->SetupInterlock(r+1); } \
@ -681,7 +681,7 @@ void A_LDM(ARM* cpu)
{ {
//if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1; //if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1;
cpu->AddCycles_CDI(); cpu->AddCycles_CDI();
if (cpu->Num == 0) ;//cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampMemory; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages if (cpu->Num == 0) ((ARMv5*)cpu)->ForceInterlock(); // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
else; // CHECKME: ARM7 timing behavior? else; // CHECKME: ARM7 timing behavior?
} }
else else
@ -739,7 +739,7 @@ void A_LDM(ARM* cpu)
// jump if pc got written // jump if pc got written
if (cpu->CurInstr & (1<<15)) if (cpu->CurInstr & (1<<15))
{ {
//if (cpu->Num==0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampMemory; // force an interlock if (cpu->Num==0) ((ARMv5*)cpu)->ForceInterlock();
cpu->JumpTo(cpu->R[15], cpu->CurInstr & (1<<22), 1); cpu->JumpTo(cpu->R[15], cpu->CurInstr & (1<<22), 1);
} }
else if (cpu->Num == 0) else if (cpu->Num == 0)
@ -831,7 +831,7 @@ void A_STM(ARM* cpu)
{ {
//if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1; //if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1;
cpu->AddCycles_CD(); cpu->AddCycles_CD();
if (cpu->Num == 0);// cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampMemory; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages if (cpu->Num == 0) ((ARMv5*)cpu)->ForceInterlock(); // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
else; // CHECKME: ARM7 timing behavior? else; // CHECKME: ARM7 timing behavior?
} }
else else
@ -1015,7 +1015,7 @@ void T_PUSH(ARM* cpu)
{ {
//if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1; //if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1;
cpu->AddCycles_CD(); cpu->AddCycles_CD();
if (cpu->Num == 0);// cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampMemory; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages if (cpu->Num == 0) ((ARMv5*)cpu)->ForceInterlock(); // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
else; // CHECKME: ARM7 timing behavior? else; // CHECKME: ARM7 timing behavior?
} }
else else
@ -1071,7 +1071,7 @@ void T_POP(ARM* cpu)
{ {
//if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1; //if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1;
cpu->AddCycles_CDI(); cpu->AddCycles_CDI();
if (cpu->Num == 0);// cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampMemory; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages if (cpu->Num == 0) ((ARMv5*)cpu)->ForceInterlock(); // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
else; // CHECKME: ARM7 timing behavior? else; // CHECKME: ARM7 timing behavior?
} }
else else
@ -1082,7 +1082,7 @@ void T_POP(ARM* cpu)
if (!dabort) [[likely]] if (!dabort) [[likely]]
{ {
//if (cpu->Num==0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampMemory; // force an interlock if (cpu->Num==0) ((ARMv5*)cpu)->ForceInterlock();
cpu->JumpTo(cpu->R[15], false, 2); cpu->JumpTo(cpu->R[15], false, 2);
base += 4; base += 4;
@ -1101,7 +1101,7 @@ void T_POP(ARM* cpu)
{ {
//if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1; //if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1;
cpu->AddCycles_CDI(); cpu->AddCycles_CDI();
if (cpu->Num == 0);// cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampMemory; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages if (cpu->Num == 0) ((ARMv5*)cpu)->ForceInterlock(); // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
else; // CHECKME: ARM7 timing behavior? else; // CHECKME: ARM7 timing behavior?
} }
else else
@ -1162,7 +1162,7 @@ void T_STMIA(ARM* cpu)
{ {
//if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1; //if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1;
cpu->AddCycles_CD(); cpu->AddCycles_CD();
if (cpu->Num == 0);// cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampMemory; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages if (cpu->Num == 0) ((ARMv5*)cpu)->ForceInterlock(); // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
else; // CHECKME: ARM7 timing behavior? else; // CHECKME: ARM7 timing behavior?
} }
else else
@ -1212,7 +1212,7 @@ void T_LDMIA(ARM* cpu)
{ {
//if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1; //if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1;
cpu->AddCycles_CDI(); cpu->AddCycles_CDI();
if (cpu->Num == 0);// cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampMemory; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages if (cpu->Num == 0) ((ARMv5*)cpu)->ForceInterlock(); // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
else; // CHECKME: ARM7 timing behavior? else; // CHECKME: ARM7 timing behavior?
} }
else else