diff --git a/src/ARM.cpp b/src/ARM.cpp index 942fff91..040d8bfb 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -1447,6 +1447,11 @@ void ARMv5::HandleInterlocksMemory_2() ILPrevTime = 16; } +void ARMv5::ForceInterlock_2() +{ + NDS.ARM9Timestamp = TimestampMemory + ILForceDelay; +} + void ARMv4::CodeRead16(u32 addr) { if ((addr >> 24) == 0x02) diff --git a/src/ARM.h b/src/ARM.h index c5a530cf..b78c4130 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -372,6 +372,12 @@ public: QueueFunction(&ARMv5::HandleInterlocksExecute_2); } + inline void ForceInterlock(s8 delay = 0) + { + ILForceDelay = delay; + QueueFunction(&ARMv5::ForceInterlock_2); + } + inline void HandleInterlocksMemory(u8 reg) { ILQueueMemReg = reg; @@ -726,6 +732,7 @@ public: void SetupInterlock_2(); void HandleInterlocksExecute_2(); void HandleInterlocksMemory_2(); + void ForceInterlock_2(); void QueueUpdateMode() { UpdateMode(QueueMode[0], QueueMode[1], true); } void SignExtend8() { R[ExtReg] = (s32)(s8)R[ExtReg]; } void SignExtend16() { R[ExtReg] = (s32)(s16)R[ExtReg]; } @@ -812,6 +819,7 @@ public: u64 ICacheStreamTimes[7]; u64 DCacheStreamTimes[7]; + s8 ILForceDelay; 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 WBWriting; // whether the buffer is actively trying to perform a write diff --git a/src/ARMInterpreter_LoadStore.cpp b/src/ARMInterpreter_LoadStore.cpp index 697d9a6e..ff9d6e5c 100644 --- a/src/ARMInterpreter_LoadStore.cpp +++ b/src/ARMInterpreter_LoadStore.cpp @@ -170,7 +170,7 @@ void LoadSingle(ARM* cpu, const u8 rd, const u8 rn, const s32 offset, const u16 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); } @@ -373,7 +373,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB) ((ARMv5*)cpu)->DataAbort(); \ return; } \ 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 */ \ else { \ if (cpu->Num == 0) ((ARMv5*)cpu)->SetupInterlock(r+1); } \ @@ -395,7 +395,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB) ((ARMv5*)cpu)->DataAbort(); \ return; } \ 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 */ \ else { \ 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; 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 @@ -739,7 +739,7 @@ void A_LDM(ARM* cpu) // jump if pc got written 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); } 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; 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 @@ -1015,7 +1015,7 @@ void T_PUSH(ARM* cpu) { //if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1; 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 @@ -1071,7 +1071,7 @@ void T_POP(ARM* cpu) { //if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1; 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 @@ -1082,7 +1082,7 @@ void T_POP(ARM* cpu) 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); base += 4; @@ -1101,7 +1101,7 @@ void T_POP(ARM* cpu) { //if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1; 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 @@ -1162,7 +1162,7 @@ void T_STMIA(ARM* cpu) { //if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1; 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 @@ -1212,7 +1212,7 @@ void T_LDMIA(ARM* cpu) { //if (cpu->Num == 0 && cpu->DataRegion == Mem9_ITCM) cpu->NDS.ARM9Timestamp += 1; 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