add support for 1 reg ldm/stm a9 timings and fix a bug
This commit is contained in:
parent
8ff0946b8a
commit
9ed4c66592
|
@ -617,6 +617,12 @@ void A_LDM(ARM* cpu)
|
||||||
|
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
|
|
||||||
|
if (__builtin_popcount(cpu->CurInstr & 0xFFFF) == 1) [[unlikely]] // single reg
|
||||||
|
{
|
||||||
|
if (cpu->Num == 0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
|
||||||
|
else; // CHECKME: ARM7 timing behavior?
|
||||||
|
}
|
||||||
|
|
||||||
// handle data aborts
|
// handle data aborts
|
||||||
if (dabort) [[unlikely]]
|
if (dabort) [[unlikely]]
|
||||||
{
|
{
|
||||||
|
@ -735,6 +741,12 @@ void A_STM(ARM* cpu)
|
||||||
|
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
|
|
||||||
|
if (__builtin_popcount(cpu->CurInstr & 0xFFFF) == 1) [[unlikely]] // single reg
|
||||||
|
{
|
||||||
|
if (cpu->Num == 0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
|
||||||
|
else; // CHECKME: ARM7 timing behavior?
|
||||||
|
}
|
||||||
|
|
||||||
// handle data aborts
|
// handle data aborts
|
||||||
if (dabort) [[unlikely]]
|
if (dabort) [[unlikely]]
|
||||||
{
|
{
|
||||||
|
@ -909,6 +921,12 @@ void T_PUSH(ARM* cpu)
|
||||||
|
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
|
|
||||||
|
if (__builtin_popcount(cpu->CurInstr & 0x1FF) == 1) [[unlikely]] // single reg
|
||||||
|
{
|
||||||
|
if (cpu->Num == 0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
|
||||||
|
else; // CHECKME: ARM7 timing behavior?
|
||||||
|
}
|
||||||
|
|
||||||
if (dabort) [[unlikely]]
|
if (dabort) [[unlikely]]
|
||||||
{
|
{
|
||||||
((ARMv5*)cpu)->DataAbort();
|
((ARMv5*)cpu)->DataAbort();
|
||||||
|
@ -952,31 +970,45 @@ void T_POP(ARM* cpu)
|
||||||
dabort |= !(first ? cpu->DataRead32 (base, &pc)
|
dabort |= !(first ? cpu->DataRead32 (base, &pc)
|
||||||
: cpu->DataRead32S(base, &pc));
|
: cpu->DataRead32S(base, &pc));
|
||||||
|
|
||||||
if (dabort) [[unlikely]] goto dataabort;
|
if (!dabort) [[likely]]
|
||||||
|
{
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
|
|
||||||
|
if (__builtin_popcount(cpu->CurInstr & 0x1FF) == 1) [[unlikely]] // single reg
|
||||||
|
{
|
||||||
|
if (cpu->Num == 0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
|
||||||
|
else; // CHECKME: ARM7 timing behavior?
|
||||||
|
}
|
||||||
|
|
||||||
if (cpu->Num==1 || (((ARMv5*)cpu)->CP15Control & (1<<15))) pc |= 0x1;
|
if (cpu->Num==1 || (((ARMv5*)cpu)->CP15Control & (1<<15))) pc |= 0x1;
|
||||||
cpu->JumpTo(pc);
|
cpu->JumpTo(pc);
|
||||||
base += 4;
|
base += 4;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
|
|
||||||
|
if (__builtin_popcount(cpu->CurInstr & 0x1FF) == 1) [[unlikely]] // single reg
|
||||||
|
{
|
||||||
|
if (cpu->Num == 0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
|
||||||
|
else; // CHECKME: ARM7 timing behavior?
|
||||||
|
}
|
||||||
|
|
||||||
if (cpu->Num == 0)
|
if (cpu->Num == 0)
|
||||||
|
{
|
||||||
|
if (dabort) [[unlikely]]
|
||||||
|
{
|
||||||
|
((ARMv5*)cpu)->DataAbort();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
u8 lastreg = 31 - __builtin_clz(cpu->CurInstr & 0xFF);
|
u8 lastreg = 31 - __builtin_clz(cpu->CurInstr & 0xFF);
|
||||||
((ARMv5*)cpu)->ILCurrReg = lastreg;
|
((ARMv5*)cpu)->ILCurrReg = lastreg;
|
||||||
((ARMv5*)cpu)->ILCurrTime = ((ARMv5*)cpu)->TimestampActual;
|
((ARMv5*)cpu)->ILCurrTime = ((ARMv5*)cpu)->TimestampActual;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dabort) [[unlikely]]
|
|
||||||
{
|
|
||||||
dataabort:
|
|
||||||
cpu->AddCycles_CDI();
|
|
||||||
((ARMv5*)cpu)->DataAbort();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->R[13] = base;
|
cpu->R[13] = base;
|
||||||
|
@ -1015,6 +1047,12 @@ void T_STMIA(ARM* cpu)
|
||||||
|
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
|
|
||||||
|
if (__builtin_popcount(cpu->CurInstr & 0xFF) == 1) [[unlikely]] // single reg
|
||||||
|
{
|
||||||
|
if (cpu->Num == 0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
|
||||||
|
else; // CHECKME: ARM7 timing behavior?
|
||||||
|
}
|
||||||
|
|
||||||
if (dabort) [[unlikely]]
|
if (dabort) [[unlikely]]
|
||||||
{
|
{
|
||||||
((ARMv5*)cpu)->DataAbort();
|
((ARMv5*)cpu)->DataAbort();
|
||||||
|
@ -1054,6 +1092,12 @@ void T_LDMIA(ARM* cpu)
|
||||||
|
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
|
|
||||||
|
if (__builtin_popcount(cpu->CurInstr & 0xFF) == 1) [[unlikely]] // single reg
|
||||||
|
{
|
||||||
|
if (cpu->Num == 0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
|
||||||
|
else; // CHECKME: ARM7 timing behavior?
|
||||||
|
}
|
||||||
|
|
||||||
if (dabort) [[unlikely]]
|
if (dabort) [[unlikely]]
|
||||||
{
|
{
|
||||||
((ARMv5*)cpu)->DataAbort();
|
((ARMv5*)cpu)->DataAbort();
|
||||||
|
|
|
@ -321,7 +321,7 @@ void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend)
|
||||||
{
|
{
|
||||||
MemTimings[i][1] = ((bustimings[0] - 1) << NDS.ARM9ClockShift) + 1;
|
MemTimings[i][1] = ((bustimings[0] - 1) << NDS.ARM9ClockShift) + 1;
|
||||||
MemTimings[i][2] = ((bustimings[2] - 1) << NDS.ARM9ClockShift) + 1;
|
MemTimings[i][2] = ((bustimings[2] - 1) << NDS.ARM9ClockShift) + 1;
|
||||||
MemTimings[i][3] = bustimings[3] << NDS.ARM9ClockShift; // inaccurate but ehgh
|
MemTimings[i][3] = ((bustimings[3] - 1) << NDS.ARM9ClockShift) + 1;; // inaccurate but ehgh
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1367,7 +1367,7 @@ bool ARMv5::DataWrite32S(u32 addr, u32 val)
|
||||||
|
|
||||||
if ((addr >> 24) == 0x02)
|
if ((addr >> 24) == 0x02)
|
||||||
{
|
{
|
||||||
if ((DataRegion != Mem9_MainRAM) && ((NDS.ARM9Timestamp + DataCycles) < MainRAMTimestamp)) NDS.ARM9Timestamp = MainRAMTimestamp - DataCycles;
|
if ((DataRegion != Mem9_MainRAM) && ((NDS.ARM9Timestamp + DataCycles) < MainRAMTimestamp)) DataCycles += MainRAMTimestamp - NDS.ARM9Timestamp;
|
||||||
MainRAMTimestamp = NDS.ARM9Timestamp + DataCycles;
|
MainRAMTimestamp = NDS.ARM9Timestamp + DataCycles;
|
||||||
DataRegion = Mem9_MainRAM;
|
DataRegion = Mem9_MainRAM;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue