basic arm9 set up

This commit is contained in:
Jaklyy 2024-09-05 09:13:46 -04:00
parent 7cfc4b5849
commit 299713e412
3 changed files with 177 additions and 43 deletions

View File

@ -151,6 +151,7 @@ void ARM::Reset()
{
Cycles = 0;
Halted = 0;
DataCycles = 0;
IRQ = 0;
@ -199,6 +200,13 @@ void ARM::Reset()
void ARMv5::Reset()
{
PU_Map = PU_PrivMap;
TimestampActual = 0;
InterlockMem = 16;
InterlockWBCur = 16;
InterlockWBPrev = 16;
Store = false;
InterlockMask = 0;
ARM::Reset();
}
@ -310,14 +318,12 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
u32 oldregion = R[15] >> 24;
u32 newregion = addr >> 24;
RegionCodeCycles = MemTimings[addr >> 12][0];
if (addr & 0x1)
{
addr &= ~0x1;
R[15] = addr+2;
if (newregion != oldregion) SetupCodeMem(addr);
//if (newregion != oldregion) SetupCodeMem(addr);
// two-opcodes-at-once fetch
// doesn't matter if we put garbage in the MSbs there
@ -342,7 +348,7 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
addr &= ~0x3;
R[15] = addr+4;
if (newregion != oldregion) SetupCodeMem(addr);
//if (newregion != oldregion) SetupCodeMem(addr);
NextInstr[0] = CodeRead32(addr, true);
Cycles += CodeCycles;
@ -744,8 +750,8 @@ void ARMv5::Execute()
}*/
}
NDS.ARM9Timestamp += Cycles;
Cycles = 0;
//NDS.ARM9Timestamp += Cycles;
//Cycles = 0;
}
if (Halted == 2)
@ -816,7 +822,7 @@ void ARMv4::Execute()
{
if ((Halted == 1 || IdleLoop) && NDS.ARM7Timestamp < NDS.ARM7Target)
{
//Cycles = 0;
Cycles = 0;
NDS.ARM7Timestamp = NDS.ARM7Target;
}
IdleLoop = 0;
@ -882,9 +888,6 @@ void ARMv4::Execute()
TriggerIRQ<mode>();
}*/
}
//NDS.ARM7Timestamp += Cycles;
//Cycles = 0;
}
if (Halted == 2)
@ -1153,6 +1156,20 @@ u32 ARMv5::ReadMem(u32 addr, int size)
}
#endif
void ARMv5::AddCycles_CI(s32 numI)
{
NDS.ARM9Timestamp += numI;
}
void ARMv5::AddCycles_MW()
{
u64 TimestampActual = DataCycles + NDS.ARM9Timestamp;
s32 cycles = DataCycles - (3<<NDS.ARM9ClockShift);
if (cycles > 0) NDS.ARM9Timestamp += cycles;
}
u16 ARMv4::CodeRead16(u32 addr)
{
if ((addr >> 24) == 0x02)

View File

@ -265,44 +265,41 @@ public:
bool DataWrite16(u32 addr, u16 val) override;
bool DataWrite32(u32 addr, u32 val) override;
bool DataWrite32S(u32 addr, u32 val, bool dataabort = false) override;
template<u8 nregs>
void ExecuteStage(u8 rn, u8 rm)
{
static_assert((nregs < 2), "too many regs");
if constexpr (nregs == 1)
{
InterlockMask = 1 << rn;
}
if constexpr (nregs == 2)
{
InterlockMask = 1 << rn | 1 << rm;
}
AddCycles_C();
}
void AddCycles_C() override
{
// code only. always nonseq 32-bit for ARM9.
s32 numC = (R[15] & 0x2) ? 0 : CodeCycles;
Cycles += numC;
}
void AddCycles_CI(s32 numI) override
{
// code+internal
s32 numC = (R[15] & 0x2) ? 0 : CodeCycles;
Cycles += numC + numI;
}
void AddCycles_CI(s32 numI) override;
void AddCycles_MW();
void AddCycles_CDI() override
{
// LDR/LDM cycles. ARM9 seems to skip the internal cycle there.
// TODO: ITCM data fetches shouldn't be parallelized, they say
s32 numC = (R[15] & 0x2) ? 0 : CodeCycles;
s32 numD = DataCycles;
//if (DataRegion != CodeRegion)
Cycles += std::max(numC + numD - 6, std::max(numC, numD));
//else
// Cycles += numC + numD;
AddCycles_MW();
}
void AddCycles_CD() override
{
// TODO: ITCM data fetches shouldn't be parallelized, they say
s32 numC = (R[15] & 0x2) ? 0 : CodeCycles;
s32 numD = DataCycles;
//if (DataRegion != CodeRegion)
Cycles += std::max(numC + numD - 6, std::max(numC, numD));
//else
// Cycles += numC + numD;
AddCycles_MW();
}
void GetCodeMemRegion(u32 addr, MemRegion* region);
@ -367,6 +364,13 @@ public:
u8* CurICacheLine;
bool (*GetMemRegion)(u32 addr, bool write, MemRegion* region);
u64 TimestampActual;
u8 InterlockMem;
u8 InterlockWBCur;
u8 InterlockWBPrev;
bool Store;
u16 InterlockMask;
#ifdef GDBSTUB_ENABLED
u32 ReadMem(u32 addr, int size) override;

View File

@ -299,13 +299,16 @@ void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend)
u8 pu = PU_Map[i];
u8* bustimings = NDS.ARM9MemTimings[i >> 2];
// checkme: should these be (bus timings shifted) - 1 or ((bustimings - 1) shifted) + 1
// should the last cycle be halved...?
if (pu & 0x40)
{
MemTimings[i][0] = 0xFF;//kCodeCacheTiming;
}
else
{
MemTimings[i][0] = bustimings[2] << NDS.ARM9ClockShift;
MemTimings[i][0] = ((bustimings[2] - 1) << NDS.ARM9ClockShift) + 1;
}
if (pu & 0x10)
@ -316,9 +319,9 @@ void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend)
}
else
{
MemTimings[i][1] = bustimings[0] << NDS.ARM9ClockShift;
MemTimings[i][2] = bustimings[2] << NDS.ARM9ClockShift;
MemTimings[i][3] = bustimings[3] << NDS.ARM9ClockShift;
MemTimings[i][1] = ((bustimings[0] - 1) << NDS.ARM9ClockShift) + 1;
MemTimings[i][2] = ((bustimings[2] - 1) << NDS.ARM9ClockShift) + 1;
MemTimings[i][3] = ((bustimings[3] - 1) << NDS.ARM9ClockShift) + 1;
}
}
}
@ -784,10 +787,11 @@ u32 ARMv5::CodeRead32(u32 addr, bool branch)
if (addr < ITCMSize)
{
CodeCycles = 1;
if ((DataRegion == Mem9_ITCM) && (TimestampActual >= NDS.ARM9Timestamp)) NDS.ARM9Timestamp = TimestampActual + 1;
return *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)];
}
CodeCycles = RegionCodeCycles;
CodeCycles = MemTimings[addr >> 12][0];
if (CodeCycles == 0xFF) // cached memory. hax
{
if (branch || !(addr & 0x1F))
@ -798,7 +802,21 @@ u32 ARMv5::CodeRead32(u32 addr, bool branch)
//return *(u32*)&CurICacheLine[addr & 0x1C];
}
if (CodeMem.Mem) return *(u32*)&CodeMem.Mem[addr & CodeMem.Mask];
NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1);
if ((addr >> 24) == 0x02)
{
if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp;
if (DataRegion == Mem9_MainRAM) NDS.ARM9Timestamp += CodeCycles;
}
if (CodeRegion == DataRegion && Store) NDS.ARM9Timestamp += (1<<NDS.ARM9ClockShift);
NDS.ARM9Timestamp += CodeCycles;
if (NDS.ARM9Timestamp < TimestampActual) NDS.ARM9Timestamp = TimestampActual;
//if (CodeMem.Mem) return *(u32*)&CodeMem.Mem[addr & CodeMem.Mask];
return BusRead32(addr);
}
@ -806,6 +824,7 @@ u32 ARMv5::CodeRead32(u32 addr, bool branch)
bool ARMv5::DataRead8(u32 addr, u32* val)
{
Store = false;
if (!(PU_Map[addr>>12] & 0x01)) [[unlikely]]
{
DataAbort();
@ -815,15 +834,26 @@ bool ARMv5::DataRead8(u32 addr, u32* val)
if (addr < ITCMSize)
{
DataCycles = 1;
DataRegion = Mem9_ITCM;
*val = *(u8*)&ITCM[addr & (ITCMPhysicalSize - 1)];
return true;
}
if ((addr & DTCMMask) == DTCMBase)
{
DataCycles = 1;
DataRegion = Mem9_DTCM;
*val = *(u8*)&DTCM[addr & (DTCMPhysicalSize - 1)];
return true;
}
NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1);
if ((addr >> 24) == 0x02)
{
if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp;
DataRegion = Mem9_MainRAM;
}
else DataRegion = NDS.ARM9Regions[addr>>14];
*val = BusRead8(addr);
DataCycles = MemTimings[addr >> 12][1];
@ -832,6 +862,7 @@ bool ARMv5::DataRead8(u32 addr, u32* val)
bool ARMv5::DataRead16(u32 addr, u32* val)
{
Store = false;
if (!(PU_Map[addr>>12] & 0x01)) [[unlikely]]
{
DataAbort();
@ -843,15 +874,26 @@ bool ARMv5::DataRead16(u32 addr, u32* val)
if (addr < ITCMSize)
{
DataCycles = 1;
DataRegion = Mem9_ITCM;
*val = *(u16*)&ITCM[addr & (ITCMPhysicalSize - 1)];
return true;
}
if ((addr & DTCMMask) == DTCMBase)
{
DataCycles = 1;
DataRegion = Mem9_DTCM;
*val = *(u16*)&DTCM[addr & (DTCMPhysicalSize - 1)];
return true;
}
NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1);
if ((addr >> 24) == 0x02)
{
if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp;
DataRegion = Mem9_MainRAM;
}
else DataRegion = NDS.ARM9Regions[addr>>14];
*val = BusRead16(addr);
DataCycles = MemTimings[addr >> 12][1];
@ -860,6 +902,7 @@ bool ARMv5::DataRead16(u32 addr, u32* val)
bool ARMv5::DataRead32(u32 addr, u32* val)
{
Store = false;
if (!(PU_Map[addr>>12] & 0x01)) [[unlikely]]
{
DataAbort();
@ -871,16 +914,27 @@ bool ARMv5::DataRead32(u32 addr, u32* val)
if (addr < ITCMSize)
{
DataCycles = 1;
DataRegion = Mem9_ITCM;
*val = *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)];
return true;
}
if ((addr & DTCMMask) == DTCMBase)
{
DataCycles = 1;
DataRegion = Mem9_DTCM;
*val = *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)];
return true;
}
NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1);
if ((addr >> 24) == 0x02)
{
if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp;
DataRegion = Mem9_MainRAM;
}
else DataRegion = NDS.ARM9Regions[addr>>14];
*val = BusRead32(addr);
DataCycles = MemTimings[addr >> 12][2];
return true;
@ -899,23 +953,36 @@ bool ARMv5::DataRead32S(u32 addr, u32* val)
if (addr < ITCMSize)
{
DataCycles += 1;
DataRegion = Mem9_ITCM;
*val = *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)];
return true;
}
if ((addr & DTCMMask) == DTCMBase)
{
DataCycles += 1;
DataRegion = Mem9_DTCM;
*val = *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)];
return true;
}
NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1);
if ((addr >> 24) == 0x02)
{
if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp;
DataRegion = Mem9_MainRAM;
}
else DataRegion = NDS.ARM9Regions[addr>>14];
*val = BusRead32(addr);
DataCycles += MemTimings[addr >> 12][3];
NDS.ARM9Timestamp += DataCycles;
DataCycles = MemTimings[addr >> 12][3];
return true;
}
bool ARMv5::DataWrite8(u32 addr, u8 val)
{
Store = true;
if (!(PU_Map[addr>>12] & 0x02)) [[unlikely]]
{
DataAbort();
@ -925,6 +992,7 @@ bool ARMv5::DataWrite8(u32 addr, u8 val)
if (addr < ITCMSize)
{
DataCycles = 1;
DataRegion = Mem9_ITCM;
*(u8*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
return true;
@ -932,10 +1000,20 @@ bool ARMv5::DataWrite8(u32 addr, u8 val)
if ((addr & DTCMMask) == DTCMBase)
{
DataCycles = 1;
DataRegion = Mem9_DTCM;
*(u8*)&DTCM[addr & (DTCMPhysicalSize - 1)] = val;
return true;
}
NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1);
if ((addr >> 24) == 0x02)
{
if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp;
DataRegion = Mem9_MainRAM;
}
else DataRegion = NDS.ARM9Regions[addr>>14];
BusWrite8(addr, val);
DataCycles = MemTimings[addr >> 12][1];
return true;
@ -943,6 +1021,7 @@ bool ARMv5::DataWrite8(u32 addr, u8 val)
bool ARMv5::DataWrite16(u32 addr, u16 val)
{
Store = true;
if (!(PU_Map[addr>>12] & 0x02)) [[unlikely]]
{
DataAbort();
@ -954,6 +1033,7 @@ bool ARMv5::DataWrite16(u32 addr, u16 val)
if (addr < ITCMSize)
{
DataCycles = 1;
DataRegion = Mem9_ITCM;
*(u16*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
return true;
@ -961,10 +1041,20 @@ bool ARMv5::DataWrite16(u32 addr, u16 val)
if ((addr & DTCMMask) == DTCMBase)
{
DataCycles = 1;
DataRegion = Mem9_DTCM;
*(u16*)&DTCM[addr & (DTCMPhysicalSize - 1)] = val;
return true;
}
NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1);
if ((addr >> 24) == 0x02)
{
if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp;
DataRegion = Mem9_MainRAM;
}
else DataRegion = NDS.ARM9Regions[addr>>14];
BusWrite16(addr, val);
DataCycles = MemTimings[addr >> 12][1];
return true;
@ -972,6 +1062,7 @@ bool ARMv5::DataWrite16(u32 addr, u16 val)
bool ARMv5::DataWrite32(u32 addr, u32 val)
{
Store = true;
if (!(PU_Map[addr>>12] & 0x02)) [[unlikely]]
{
DataAbort();
@ -983,6 +1074,7 @@ bool ARMv5::DataWrite32(u32 addr, u32 val)
if (addr < ITCMSize)
{
DataCycles = 1;
DataRegion = Mem9_ITCM;
*(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
return true;
@ -990,10 +1082,20 @@ bool ARMv5::DataWrite32(u32 addr, u32 val)
if ((addr & DTCMMask) == DTCMBase)
{
DataCycles = 1;
DataRegion = Mem9_DTCM;
*(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)] = val;
return true;
}
NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1);
if ((addr >> 24) == 0x02)
{
if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp;
DataRegion = Mem9_MainRAM;
}
else DataRegion = NDS.ARM9Regions[addr>>14];
BusWrite32(addr, val);
DataCycles = MemTimings[addr >> 12][2];
return true;
@ -1012,6 +1114,7 @@ bool ARMv5::DataWrite32S(u32 addr, u32 val, bool dataabort)
if (addr < ITCMSize)
{
DataCycles += 1;
DataRegion = Mem9_ITCM;
*(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
#ifdef JIT_ENABLED
NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
@ -1021,10 +1124,20 @@ bool ARMv5::DataWrite32S(u32 addr, u32 val, bool dataabort)
if ((addr & DTCMMask) == DTCMBase)
{
DataCycles += 1;
DataRegion = Mem9_DTCM;
*(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)] = val;
return true;
}
NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1);
if ((addr >> 24) == 0x02)
{
if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp;
DataRegion = Mem9_MainRAM;
}
else DataRegion = NDS.ARM9Regions[addr>>14];
BusWrite32(addr, val);
DataCycles += MemTimings[addr >> 12][3];
return true;