mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-06-30 02:49:41 -06:00
take it somewhere.
still need to speed it up a tad.
This commit is contained in:
35
src/ARM.cpp
35
src/ARM.cpp
@ -136,17 +136,6 @@ void ARMv5::DoSavestate(Savestate* file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ARMv5::CalculateTimings()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
void ARMv4::CalculateTimings()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ARM::SetupCodeMem(u32 addr)
|
void ARM::SetupCodeMem(u32 addr)
|
||||||
{
|
{
|
||||||
if (!Num)
|
if (!Num)
|
||||||
@ -181,8 +170,11 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
|
|||||||
//printf("[%03d] IRQ handler thing. wait=%08X\n", GPU::VCount, dorp);
|
//printf("[%03d] IRQ handler thing. wait=%08X\n", GPU::VCount, dorp);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 oldregion = R[15] >> 23;
|
u32 oldregion = R[15] >> 24;
|
||||||
u32 newregion = addr >> 23;
|
u32 newregion = addr >> 24;
|
||||||
|
|
||||||
|
if (addr < ITCMSize) CodeCycles = 1;
|
||||||
|
else CodeCycles = MemTimings[addr >> 12][0];
|
||||||
|
|
||||||
s32 cycles;
|
s32 cycles;
|
||||||
|
|
||||||
@ -199,13 +191,13 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
|
|||||||
{
|
{
|
||||||
NextInstr[0] = CodeRead32(addr-2) >> 16;
|
NextInstr[0] = CodeRead32(addr-2) >> 16;
|
||||||
NextInstr[1] = CodeRead32(addr+2);
|
NextInstr[1] = CodeRead32(addr+2);
|
||||||
cycles = NDS::ARM9MemTimings[CodeRegion][2] * 2;
|
cycles = CodeCycles * 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NextInstr[0] = CodeRead32(addr);
|
NextInstr[0] = CodeRead32(addr);
|
||||||
NextInstr[1] = NextInstr[0] >> 16;
|
NextInstr[1] = NextInstr[0] >> 16;
|
||||||
cycles = NDS::ARM9MemTimings[CodeRegion][2];
|
cycles = CodeCycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPSR |= 0x20;
|
CPSR |= 0x20;
|
||||||
@ -219,7 +211,7 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
|
|||||||
|
|
||||||
NextInstr[0] = CodeRead32(addr);
|
NextInstr[0] = CodeRead32(addr);
|
||||||
NextInstr[1] = CodeRead32(addr+4);
|
NextInstr[1] = CodeRead32(addr+4);
|
||||||
cycles = NDS::ARM9MemTimings[CodeRegion][2] * 2;
|
cycles = CodeCycles * 2;
|
||||||
|
|
||||||
CPSR &= ~0x20;
|
CPSR &= ~0x20;
|
||||||
}
|
}
|
||||||
@ -250,6 +242,9 @@ void ARMv4::JumpTo(u32 addr, bool restorecpsr)
|
|||||||
u32 oldregion = R[15] >> 23;
|
u32 oldregion = R[15] >> 23;
|
||||||
u32 newregion = addr >> 23;
|
u32 newregion = addr >> 23;
|
||||||
|
|
||||||
|
CodeRegion = addr >> 24;
|
||||||
|
CodeCycles = addr >> 15; // cheato
|
||||||
|
|
||||||
if (addr & 0x1)
|
if (addr & 0x1)
|
||||||
{
|
{
|
||||||
addr &= ~0x1;
|
addr &= ~0x1;
|
||||||
@ -259,7 +254,7 @@ void ARMv4::JumpTo(u32 addr, bool restorecpsr)
|
|||||||
|
|
||||||
NextInstr[0] = CodeRead16(addr);
|
NextInstr[0] = CodeRead16(addr);
|
||||||
NextInstr[1] = CodeRead16(addr+2);
|
NextInstr[1] = CodeRead16(addr+2);
|
||||||
Cycles += NDS::ARM7MemTimings[CodeRegion][0] + NDS::ARM7MemTimings[CodeRegion][1];
|
Cycles += NDS::ARM7MemTimings[CodeCycles][0] + NDS::ARM7MemTimings[CodeCycles][1];
|
||||||
|
|
||||||
CPSR |= 0x20;
|
CPSR |= 0x20;
|
||||||
}
|
}
|
||||||
@ -272,7 +267,7 @@ void ARMv4::JumpTo(u32 addr, bool restorecpsr)
|
|||||||
|
|
||||||
NextInstr[0] = CodeRead32(addr);
|
NextInstr[0] = CodeRead32(addr);
|
||||||
NextInstr[1] = CodeRead32(addr+4);
|
NextInstr[1] = CodeRead32(addr+4);
|
||||||
Cycles += NDS::ARM7MemTimings[CodeRegion][2] + NDS::ARM7MemTimings[CodeRegion][3];
|
Cycles += NDS::ARM7MemTimings[CodeCycles][2] + NDS::ARM7MemTimings[CodeCycles][3];
|
||||||
|
|
||||||
CPSR &= ~0x20;
|
CPSR &= ~0x20;
|
||||||
}
|
}
|
||||||
@ -482,8 +477,8 @@ s32 ARMv5::Execute()
|
|||||||
R[15] += 2;
|
R[15] += 2;
|
||||||
CurInstr = NextInstr[0];
|
CurInstr = NextInstr[0];
|
||||||
NextInstr[0] = NextInstr[1];
|
NextInstr[0] = NextInstr[1];
|
||||||
if (R[15] & 0x2) { NextInstr[1] >>= 16; CodeRegion = NDS::Region9_MAX; }
|
if (R[15] & 0x2) NextInstr[1] >>= 16;
|
||||||
else NextInstr[1] = CodeRead32(R[15]);
|
else NextInstr[1] = CodeRead32(R[15]);
|
||||||
|
|
||||||
// actually execute
|
// actually execute
|
||||||
u32 icode = (CurInstr >> 6) & 0x3FF;
|
u32 icode = (CurInstr >> 6) & 0x3FF;
|
||||||
|
187
src/ARM.h
187
src/ARM.h
@ -48,8 +48,6 @@ public:
|
|||||||
ClockDiffMask = (1<<shift) - 1;
|
ClockDiffMask = (1<<shift) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void CalculateTimings() = 0;
|
|
||||||
|
|
||||||
virtual void JumpTo(u32 addr, bool restorecpsr = false) = 0;
|
virtual void JumpTo(u32 addr, bool restorecpsr = false) = 0;
|
||||||
void RestoreCPSR();
|
void RestoreCPSR();
|
||||||
|
|
||||||
@ -107,15 +105,17 @@ public:
|
|||||||
void SetupCodeMem(u32 addr);
|
void SetupCodeMem(u32 addr);
|
||||||
|
|
||||||
|
|
||||||
virtual bool DataRead8(u32 addr, u32* val, u32 flags) = 0;
|
virtual void DataRead8(u32 addr, u32* val) = 0;
|
||||||
virtual bool DataRead16(u32 addr, u32* val, u32 flags) = 0;
|
virtual void DataRead16(u32 addr, u32* val) = 0;
|
||||||
virtual bool DataRead32(u32 addr, u32* val, u32 flags) = 0;
|
virtual void DataRead32(u32 addr, u32* val) = 0;
|
||||||
virtual bool DataWrite8(u32 addr, u8 val, u32 flags) = 0;
|
virtual void DataRead32S(u32 addr, u32* val) = 0;
|
||||||
virtual bool DataWrite16(u32 addr, u16 val, u32 flags) = 0;
|
virtual void DataWrite8(u32 addr, u8 val) = 0;
|
||||||
virtual bool DataWrite32(u32 addr, u32 val, u32 flags) = 0;
|
virtual void DataWrite16(u32 addr, u16 val) = 0;
|
||||||
|
virtual void DataWrite32(u32 addr, u32 val) = 0;
|
||||||
|
virtual void DataWrite32S(u32 addr, u32 val) = 0;
|
||||||
|
|
||||||
virtual void AddCycles_C() = 0;
|
virtual void AddCycles_C() = 0;
|
||||||
virtual void AddCycles_CI(s32 num) = 0;
|
virtual void AddCycles_CI(s32 numI) = 0;
|
||||||
virtual void AddCycles_CDI() = 0;
|
virtual void AddCycles_CDI() = 0;
|
||||||
virtual void AddCycles_CD() = 0;
|
virtual void AddCycles_CD() = 0;
|
||||||
|
|
||||||
@ -131,9 +131,10 @@ public:
|
|||||||
s32 CyclesToRun;
|
s32 CyclesToRun;
|
||||||
u32 Halted;
|
u32 Halted;
|
||||||
|
|
||||||
int CodeRegion;
|
u32 CodeRegion;
|
||||||
|
s32 CodeCycles;
|
||||||
|
|
||||||
int DataRegion;
|
u32 DataRegion;
|
||||||
s32 DataCycles;
|
s32 DataCycles;
|
||||||
|
|
||||||
u32 R[16]; // heh
|
u32 R[16]; // heh
|
||||||
@ -162,7 +163,7 @@ public:
|
|||||||
|
|
||||||
void DoSavestate(Savestate* file);
|
void DoSavestate(Savestate* file);
|
||||||
|
|
||||||
void CalculateTimings();
|
void UpdateRegionTimings(u32 addrstart, u32 addrend);
|
||||||
|
|
||||||
void JumpTo(u32 addr, bool restorecpsr = false);
|
void JumpTo(u32 addr, bool restorecpsr = false);
|
||||||
|
|
||||||
@ -174,48 +175,52 @@ public:
|
|||||||
// all code accesses are forced nonseq 32bit
|
// all code accesses are forced nonseq 32bit
|
||||||
u32 CodeRead32(u32 addr);
|
u32 CodeRead32(u32 addr);
|
||||||
|
|
||||||
bool DataRead8(u32 addr, u32* val, u32 flags);
|
void DataRead8(u32 addr, u32* val);
|
||||||
bool DataRead16(u32 addr, u32* val, u32 flags);
|
void DataRead16(u32 addr, u32* val);
|
||||||
bool DataRead32(u32 addr, u32* val, u32 flags);
|
void DataRead32(u32 addr, u32* val);
|
||||||
bool DataWrite8(u32 addr, u8 val, u32 flags);
|
void DataRead32S(u32 addr, u32* val);
|
||||||
bool DataWrite16(u32 addr, u16 val, u32 flags);
|
void DataWrite8(u32 addr, u8 val);
|
||||||
bool DataWrite32(u32 addr, u32 val, u32 flags);
|
void DataWrite16(u32 addr, u16 val);
|
||||||
|
void DataWrite32(u32 addr, u32 val);
|
||||||
|
void DataWrite32S(u32 addr, u32 val);
|
||||||
|
|
||||||
void AddCycles_C()
|
void AddCycles_C()
|
||||||
{
|
{
|
||||||
// code only. always nonseq 32-bit for ARM9.
|
// code only. always nonseq 32-bit for ARM9.
|
||||||
Cycles += NDS::ARM9MemTimings[CodeRegion][2];
|
s32 numC = (R[15] & 0x2) ? 0 : CodeCycles;
|
||||||
|
Cycles += numC;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddCycles_CI(s32 num)
|
void AddCycles_CI(s32 numI)
|
||||||
{
|
{
|
||||||
// code+internal
|
// code+internal
|
||||||
Cycles += NDS::ARM9MemTimings[CodeRegion][2] + num;
|
s32 numC = (R[15] & 0x2) ? 0 : CodeCycles;
|
||||||
|
Cycles += numC + numI;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddCycles_CDI()
|
void AddCycles_CDI()
|
||||||
{
|
{
|
||||||
// LDR/LDM cycles. ARM9 seems to skip the internal cycle there.
|
// LDR/LDM cycles. ARM9 seems to skip the internal cycle there.
|
||||||
// TODO: ITCM data fetches shouldn't be parallelized, they say
|
// TODO: ITCM data fetches shouldn't be parallelized, they say
|
||||||
s32 numC = NDS::ARM9MemTimings[CodeRegion][2];
|
s32 numC = (R[15] & 0x2) ? 0 : CodeCycles;
|
||||||
s32 numD = DataCycles;
|
s32 numD = DataCycles;
|
||||||
|
|
||||||
if (DataRegion != CodeRegion)
|
//if (DataRegion != CodeRegion)
|
||||||
Cycles += std::max(numC + numD - 6, std::max(numC, numD));
|
Cycles += std::max(numC + numD - 6, std::max(numC, numD));
|
||||||
else
|
//else
|
||||||
Cycles += numC + numD;
|
// Cycles += numC + numD;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddCycles_CD()
|
void AddCycles_CD()
|
||||||
{
|
{
|
||||||
// TODO: ITCM data fetches shouldn't be parallelized, they say
|
// TODO: ITCM data fetches shouldn't be parallelized, they say
|
||||||
s32 numC = NDS::ARM9MemTimings[CodeRegion][2];
|
s32 numC = (R[15] & 0x2) ? 0 : CodeCycles;
|
||||||
s32 numD = DataCycles;
|
s32 numD = DataCycles;
|
||||||
|
|
||||||
if (DataRegion != CodeRegion)
|
//if (DataRegion != CodeRegion)
|
||||||
Cycles += std::max(numC + numD - 6, std::max(numC, numD));
|
Cycles += std::max(numC + numD - 6, std::max(numC, numD));
|
||||||
else
|
//else
|
||||||
Cycles += numC + numD;
|
// Cycles += numC + numD;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetCodeMemRegion(u32 addr, NDS::MemRegion* region);
|
void GetCodeMemRegion(u32 addr, NDS::MemRegion* region);
|
||||||
@ -250,14 +255,14 @@ public:
|
|||||||
u32 PU_Region[8];
|
u32 PU_Region[8];
|
||||||
|
|
||||||
// 0=dataR 1=dataW 2=codeR 4=datacache 5=datawrite 6=codecache
|
// 0=dataR 1=dataW 2=codeR 4=datacache 5=datawrite 6=codecache
|
||||||
// seems the DS operates entirely under privileged mode? it never sets user regions to be read/writable
|
|
||||||
// TODO: investigate
|
|
||||||
u8 PU_UserMap[0x100000];
|
|
||||||
u8 PU_PrivMap[0x100000];
|
u8 PU_PrivMap[0x100000];
|
||||||
//u8* PU_Map;
|
u8 PU_UserMap[0x100000];
|
||||||
|
|
||||||
|
// games operate under system mode, generally
|
||||||
#define PU_Map PU_PrivMap
|
#define PU_Map PU_PrivMap
|
||||||
|
|
||||||
bool CodeCached;
|
// code/16N/32N/32S
|
||||||
|
u8 MemTimings[0x100000][4];
|
||||||
};
|
};
|
||||||
|
|
||||||
class ARMv4 : public ARM
|
class ARMv4 : public ARM
|
||||||
@ -265,122 +270,108 @@ class ARMv4 : public ARM
|
|||||||
public:
|
public:
|
||||||
ARMv4();
|
ARMv4();
|
||||||
|
|
||||||
void CalculateTimings();
|
|
||||||
|
|
||||||
void JumpTo(u32 addr, bool restorecpsr = false);
|
void JumpTo(u32 addr, bool restorecpsr = false);
|
||||||
|
|
||||||
s32 Execute();
|
s32 Execute();
|
||||||
|
|
||||||
u16 CodeRead16(u32 addr)
|
u16 CodeRead16(u32 addr)
|
||||||
{
|
{
|
||||||
u32 ret;
|
return NDS::ARM7Read16(addr);
|
||||||
CodeRegion = NDS::ARM7Read16(addr, &ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 CodeRead32(u32 addr)
|
u32 CodeRead32(u32 addr)
|
||||||
{
|
{
|
||||||
u32 ret;
|
return NDS::ARM7Read32(addr);
|
||||||
CodeRegion = NDS::ARM7Read32(addr, &ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DataRead8(u32 addr, u32* val, u32 flags)
|
void DataRead8(u32 addr, u32* val)
|
||||||
{
|
{
|
||||||
DataRegion = NDS::ARM7Read8(addr, val);
|
*val = NDS::ARM7Read8(addr);
|
||||||
if (flags & RWFlags_Nonseq)
|
DataRegion = addr >> 24;
|
||||||
DataCycles = NDS::ARM7MemTimings[DataRegion][0];
|
DataCycles = NDS::ARM7MemTimings[DataRegion][0];
|
||||||
else
|
|
||||||
DataCycles += NDS::ARM7MemTimings[DataRegion][1];
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DataRead16(u32 addr, u32* val, u32 flags)
|
void DataRead16(u32 addr, u32* val)
|
||||||
{
|
{
|
||||||
addr &= ~1;
|
addr &= ~1;
|
||||||
|
|
||||||
DataRegion = NDS::ARM7Read16(addr, val);
|
*val = NDS::ARM7Read16(addr);
|
||||||
if (flags & RWFlags_Nonseq)
|
DataRegion = addr >> 24;
|
||||||
DataCycles = NDS::ARM7MemTimings[DataRegion][0];
|
DataCycles = NDS::ARM7MemTimings[DataRegion][0];
|
||||||
else
|
|
||||||
DataCycles += NDS::ARM7MemTimings[DataRegion][1];
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DataRead32(u32 addr, u32* val, u32 flags)
|
void DataRead32(u32 addr, u32* val)
|
||||||
{
|
{
|
||||||
addr &= ~3;
|
addr &= ~3;
|
||||||
|
|
||||||
DataRegion = NDS::ARM7Read32(addr, val);
|
*val = NDS::ARM7Read32(addr);
|
||||||
if (flags & RWFlags_Nonseq)
|
DataRegion = addr >> 24;
|
||||||
DataCycles = NDS::ARM7MemTimings[DataRegion][2];
|
DataCycles = NDS::ARM7MemTimings[DataRegion][2];
|
||||||
else
|
|
||||||
DataCycles += NDS::ARM7MemTimings[DataRegion][3];
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DataWrite8(u32 addr, u8 val, u32 flags)
|
void DataRead32S(u32 addr, u32* val)
|
||||||
{
|
{
|
||||||
DataRegion = NDS::ARM7Write8(addr, val);
|
addr &= ~3;
|
||||||
if (flags & RWFlags_Nonseq)
|
|
||||||
DataCycles = NDS::ARM7MemTimings[DataRegion][0];
|
|
||||||
else
|
|
||||||
DataCycles += NDS::ARM7MemTimings[DataRegion][1];
|
|
||||||
|
|
||||||
return true;
|
*val = NDS::ARM7Read32(addr);
|
||||||
|
DataCycles += NDS::ARM7MemTimings[DataRegion][3];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DataWrite16(u32 addr, u16 val, u32 flags)
|
void DataWrite8(u32 addr, u8 val)
|
||||||
|
{
|
||||||
|
NDS::ARM7Write8(addr, val);
|
||||||
|
DataRegion = addr >> 24;
|
||||||
|
DataCycles = NDS::ARM7MemTimings[DataRegion][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataWrite16(u32 addr, u16 val)
|
||||||
{
|
{
|
||||||
addr &= ~1;
|
addr &= ~1;
|
||||||
|
|
||||||
DataRegion = NDS::ARM7Write16(addr, val);
|
NDS::ARM7Write16(addr, val);
|
||||||
if (flags & RWFlags_Nonseq)
|
DataRegion = addr >> 24;
|
||||||
DataCycles = NDS::ARM7MemTimings[DataRegion][0];
|
DataCycles = NDS::ARM7MemTimings[DataRegion][0];
|
||||||
else
|
|
||||||
DataCycles += NDS::ARM7MemTimings[DataRegion][1];
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DataWrite32(u32 addr, u32 val, u32 flags)
|
void DataWrite32(u32 addr, u32 val)
|
||||||
{
|
{
|
||||||
addr &= ~3;
|
addr &= ~3;
|
||||||
|
|
||||||
DataRegion = NDS::ARM7Write32(addr, val);
|
NDS::ARM7Write32(addr, val);
|
||||||
if (flags & RWFlags_Nonseq)
|
DataRegion = addr >> 24;
|
||||||
DataCycles = NDS::ARM7MemTimings[DataRegion][2];
|
DataCycles = NDS::ARM7MemTimings[DataRegion][2];
|
||||||
else
|
}
|
||||||
DataCycles += NDS::ARM7MemTimings[DataRegion][3];
|
|
||||||
|
|
||||||
return true;
|
void DataWrite32S(u32 addr, u32 val)
|
||||||
|
{
|
||||||
|
addr &= ~3;
|
||||||
|
|
||||||
|
NDS::ARM7Write32(addr, val);
|
||||||
|
DataCycles += NDS::ARM7MemTimings[DataRegion][3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AddCycles_C()
|
void AddCycles_C()
|
||||||
{
|
{
|
||||||
// code only. this code fetch is sequential.
|
// code only. this code fetch is sequential.
|
||||||
Cycles += NDS::ARM7MemTimings[CodeRegion][(CPSR&0x20)?1:3];
|
Cycles += NDS::ARM7MemTimings[CodeCycles][(CPSR&0x20)?1:3];
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddCycles_CI(s32 num)
|
void AddCycles_CI(s32 num)
|
||||||
{
|
{
|
||||||
// code+internal. results in a nonseq code fetch.
|
// code+internal. results in a nonseq code fetch.
|
||||||
Cycles += NDS::ARM7MemTimings[CodeRegion][(CPSR&0x20)?0:2] + num;
|
Cycles += NDS::ARM7MemTimings[CodeCycles][(CPSR&0x20)?0:2] + num;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddCycles_CDI()
|
void AddCycles_CDI()
|
||||||
{
|
{
|
||||||
// LDR/LDM cycles.
|
// LDR/LDM cycles.
|
||||||
s32 numC = NDS::ARM7MemTimings[CodeRegion][(CPSR&0x20)?0:2];
|
s32 numC = NDS::ARM7MemTimings[CodeCycles][(CPSR&0x20)?0:2];
|
||||||
s32 numD = DataCycles;
|
s32 numD = DataCycles;
|
||||||
|
|
||||||
if (DataRegion == NDS::Region7_MainRAM)
|
if (DataRegion == 0x02) // mainRAM
|
||||||
{
|
{
|
||||||
if (CodeRegion == NDS::Region7_MainRAM)
|
if (CodeRegion == 0x02)
|
||||||
Cycles += numC + numD;
|
Cycles += numC + numD;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -388,7 +379,7 @@ public:
|
|||||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (CodeRegion == NDS::Region7_MainRAM)
|
else if (CodeRegion == 0x02)
|
||||||
{
|
{
|
||||||
numD++;
|
numD++;
|
||||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||||
@ -402,17 +393,17 @@ public:
|
|||||||
void AddCycles_CD()
|
void AddCycles_CD()
|
||||||
{
|
{
|
||||||
// TODO: max gain should be 5c when writing to mainRAM
|
// TODO: max gain should be 5c when writing to mainRAM
|
||||||
s32 numC = NDS::ARM7MemTimings[CodeRegion][(CPSR&0x20)?0:2];
|
s32 numC = NDS::ARM7MemTimings[CodeCycles][(CPSR&0x20)?0:2];
|
||||||
s32 numD = DataCycles;
|
s32 numD = DataCycles;
|
||||||
|
|
||||||
if (DataRegion == NDS::Region7_MainRAM)
|
if (DataRegion == 0x02)
|
||||||
{
|
{
|
||||||
if (CodeRegion == NDS::Region7_MainRAM)
|
if (CodeRegion == 0x02)
|
||||||
Cycles += numC + numD;
|
Cycles += numC + numD;
|
||||||
else
|
else
|
||||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||||
}
|
}
|
||||||
else if (CodeRegion == NDS::Region7_MainRAM)
|
else if (CodeRegion == 0x02)
|
||||||
{
|
{
|
||||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||||
}
|
}
|
||||||
|
@ -62,32 +62,33 @@ namespace ARMInterpreter
|
|||||||
|
|
||||||
#define A_STR \
|
#define A_STR \
|
||||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
if (!cpu->DataWrite32(offset, cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
cpu->DataWrite32(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
||||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
|
|
||||||
|
// TODO: user mode (bit21)
|
||||||
#define A_STR_POST \
|
#define A_STR_POST \
|
||||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
if (!cpu->DataWrite32(addr, cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq | (cpu->CurInstr & (1<<21)))) return; \
|
cpu->DataWrite32(addr, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
||||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
|
|
||||||
#define A_STRB \
|
#define A_STRB \
|
||||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
if (!cpu->DataWrite8(offset, cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
cpu->DataWrite8(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
||||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
|
|
||||||
|
// TODO: user mode (bit21)
|
||||||
#define A_STRB_POST \
|
#define A_STRB_POST \
|
||||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
if (!cpu->DataWrite8(addr, cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq | (cpu->CurInstr & (1<<21)))) return; \
|
cpu->DataWrite8(addr, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
||||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
|
|
||||||
#define A_LDR \
|
#define A_LDR \
|
||||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
u32 val; \
|
u32 val; cpu->DataRead32(offset, &val); \
|
||||||
if (!cpu->DataRead32(offset, &val, RWFlags_Nonseq)) return; \
|
|
||||||
val = ROR(val, ((offset&0x3)<<3)); \
|
val = ROR(val, ((offset&0x3)<<3)); \
|
||||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||||
cpu->AddCycles_CDI(); \
|
cpu->AddCycles_CDI(); \
|
||||||
@ -101,10 +102,10 @@ namespace ARMInterpreter
|
|||||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \
|
cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: user mode
|
||||||
#define A_LDR_POST \
|
#define A_LDR_POST \
|
||||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
u32 val; \
|
u32 val; cpu->DataRead32(addr, &val); \
|
||||||
if (!cpu->DataRead32(addr, &val, RWFlags_Nonseq | (cpu->CurInstr & (1<<21)))) return; \
|
|
||||||
val = ROR(val, ((addr&0x3)<<3)); \
|
val = ROR(val, ((addr&0x3)<<3)); \
|
||||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||||
cpu->AddCycles_CDI(); \
|
cpu->AddCycles_CDI(); \
|
||||||
@ -120,17 +121,16 @@ namespace ARMInterpreter
|
|||||||
|
|
||||||
#define A_LDRB \
|
#define A_LDRB \
|
||||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
u32 val; \
|
u32 val; cpu->DataRead8(offset, &val); \
|
||||||
if (!cpu->DataRead8(offset, &val, RWFlags_Nonseq)) return; \
|
|
||||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||||
cpu->AddCycles_CDI(); \
|
cpu->AddCycles_CDI(); \
|
||||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \
|
cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRB PC %08X\n", cpu->R[15]); \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRB PC %08X\n", cpu->R[15]); \
|
||||||
|
|
||||||
|
// TODO: user mode
|
||||||
#define A_LDRB_POST \
|
#define A_LDRB_POST \
|
||||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
u32 val; \
|
u32 val; cpu->DataRead8(addr, &val); \
|
||||||
if (!cpu->DataRead8(addr, &val, RWFlags_Nonseq | (cpu->CurInstr & (1<<21)))) return; \
|
|
||||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||||
cpu->AddCycles_CDI(); \
|
cpu->AddCycles_CDI(); \
|
||||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \
|
cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \
|
||||||
@ -219,13 +219,13 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||||||
|
|
||||||
#define A_STRH \
|
#define A_STRH \
|
||||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
if (!cpu->DataWrite16(offset, cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
cpu->DataWrite16(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
||||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
|
|
||||||
#define A_STRH_POST \
|
#define A_STRH_POST \
|
||||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
if (!cpu->DataWrite16(addr, cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
cpu->DataWrite16(addr, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
||||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
|
|
||||||
@ -236,9 +236,9 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||||
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
||||||
if (r&1) printf("!! MISALIGNED LDRD %d\n", r); \
|
if (r&1) { r--; printf("!! MISALIGNED LDRD_POST %d\n", r); } \
|
||||||
if (!cpu->DataRead32(offset , &cpu->R[r ], RWFlags_Nonseq)) return; \
|
cpu->DataRead32 (offset , &cpu->R[r ]); \
|
||||||
if (!cpu->DataRead32(offset+4, &cpu->R[r+1], 0)) return; \
|
cpu->DataRead32S(offset+4, &cpu->R[r+1]); \
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
|
|
||||||
#define A_LDRD_POST \
|
#define A_LDRD_POST \
|
||||||
@ -246,9 +246,9 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||||
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
||||||
if (r&1) printf("!! MISALIGNED LDRD_POST %d\n", r); \
|
if (r&1) { r--; printf("!! MISALIGNED LDRD_POST %d\n", r); } \
|
||||||
if (!cpu->DataRead32(addr , &cpu->R[r ], RWFlags_Nonseq)) return; \
|
cpu->DataRead32 (addr , &cpu->R[r ]); \
|
||||||
if (!cpu->DataRead32(addr+4, &cpu->R[r+1], 0)) return; \
|
cpu->DataRead32S(addr+4, &cpu->R[r+1]); \
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
|
|
||||||
#define A_STRD \
|
#define A_STRD \
|
||||||
@ -256,38 +256,38 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||||
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
||||||
if (r&1) printf("!! MISALIGNED STRD %d\n", r); \
|
if (r&1) { r--; printf("!! MISALIGNED LDRD_POST %d\n", r); } \
|
||||||
if (!cpu->DataWrite32(offset , cpu->R[r ], RWFlags_Nonseq)) return; \
|
cpu->DataWrite32 (offset , cpu->R[r ]); \
|
||||||
if (!cpu->DataWrite32(offset+4, cpu->R[r+1], 0)) return; \
|
cpu->DataWrite32S(offset+4, cpu->R[r+1]); \
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
|
|
||||||
#define A_STRD_POST \
|
#define A_STRD_POST \
|
||||||
if (cpu->Num != 0) return; \
|
if (cpu->Num != 0) return; \
|
||||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||||
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
||||||
if (r&1) printf("!! MISALIGNED STRD_POST %d\n", r); \
|
if (r&1) { r--; printf("!! MISALIGNED LDRD_POST %d\n", r); } \
|
||||||
if (!cpu->DataWrite32(offset , cpu->R[r ], RWFlags_Nonseq)) return; \
|
cpu->DataWrite32 (offset , cpu->R[r ]); \
|
||||||
if (!cpu->DataWrite32(offset+4, cpu->R[r+1], 0)) return; \
|
cpu->DataWrite32S(offset+4, cpu->R[r+1]); \
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
|
|
||||||
#define A_LDRH \
|
#define A_LDRH \
|
||||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||||
if (!cpu->DataRead16(offset, &cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
cpu->DataRead16(offset, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
||||||
cpu->AddCycles_CDI(); \
|
cpu->AddCycles_CDI(); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRH PC %08X\n", cpu->R[15]); \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRH PC %08X\n", cpu->R[15]); \
|
||||||
|
|
||||||
#define A_LDRH_POST \
|
#define A_LDRH_POST \
|
||||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||||
if (!cpu->DataRead16(addr, &cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
cpu->DataRead16(addr, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
||||||
cpu->AddCycles_CDI(); \
|
cpu->AddCycles_CDI(); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRH PC %08X\n", cpu->R[15]); \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRH PC %08X\n", cpu->R[15]); \
|
||||||
|
|
||||||
#define A_LDRSB \
|
#define A_LDRSB \
|
||||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||||
if (!cpu->DataRead8(offset, &cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
cpu->DataRead8(offset, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
||||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->R[(cpu->CurInstr>>12) & 0xF]; \
|
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->R[(cpu->CurInstr>>12) & 0xF]; \
|
||||||
cpu->AddCycles_CDI(); \
|
cpu->AddCycles_CDI(); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSB PC %08X\n", cpu->R[15]); \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSB PC %08X\n", cpu->R[15]); \
|
||||||
@ -295,7 +295,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||||||
#define A_LDRSB_POST \
|
#define A_LDRSB_POST \
|
||||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||||
if (!cpu->DataRead8(addr, &cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
cpu->DataRead8(addr, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
||||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->R[(cpu->CurInstr>>12) & 0xF]; \
|
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->R[(cpu->CurInstr>>12) & 0xF]; \
|
||||||
cpu->AddCycles_CDI(); \
|
cpu->AddCycles_CDI(); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSB PC %08X\n", cpu->R[15]); \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSB PC %08X\n", cpu->R[15]); \
|
||||||
@ -303,7 +303,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||||||
#define A_LDRSH \
|
#define A_LDRSH \
|
||||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||||
if (!cpu->DataRead16(offset, &cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
cpu->DataRead16(offset, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
||||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->R[(cpu->CurInstr>>12) & 0xF]; \
|
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->R[(cpu->CurInstr>>12) & 0xF]; \
|
||||||
cpu->AddCycles_CDI(); \
|
cpu->AddCycles_CDI(); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSH PC %08X\n", cpu->R[15]); \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSH PC %08X\n", cpu->R[15]); \
|
||||||
@ -311,7 +311,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||||||
#define A_LDRSH_POST \
|
#define A_LDRSH_POST \
|
||||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||||
if (!cpu->DataRead16(addr, &cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
cpu->DataRead16(addr, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
||||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->R[(cpu->CurInstr>>12) & 0xF]; \
|
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->R[(cpu->CurInstr>>12) & 0xF]; \
|
||||||
cpu->AddCycles_CDI(); \
|
cpu->AddCycles_CDI(); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSH PC %08X\n", cpu->R[15]); \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSH PC %08X\n", cpu->R[15]); \
|
||||||
@ -357,11 +357,11 @@ void A_SWP(ARM* cpu)
|
|||||||
u32 rm = cpu->R[cpu->CurInstr & 0xF];
|
u32 rm = cpu->R[cpu->CurInstr & 0xF];
|
||||||
|
|
||||||
u32 val;
|
u32 val;
|
||||||
if (!cpu->DataRead32(base, &val, RWFlags_Nonseq)) return;
|
cpu->DataRead32(base, &val);
|
||||||
cpu->R[(cpu->CurInstr >> 12) & 0xF] = ROR(val, 8*(base&0x3));
|
cpu->R[(cpu->CurInstr >> 12) & 0xF] = ROR(val, 8*(base&0x3));
|
||||||
|
|
||||||
u32 numD = cpu->DataCycles;
|
u32 numD = cpu->DataCycles;
|
||||||
if (!cpu->DataWrite32(base, rm, RWFlags_Nonseq)) return;
|
cpu->DataWrite32(base, rm);
|
||||||
cpu->DataCycles += numD;
|
cpu->DataCycles += numD;
|
||||||
|
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
@ -372,10 +372,10 @@ void A_SWPB(ARM* cpu)
|
|||||||
u32 base = cpu->R[(cpu->CurInstr >> 16) & 0xF];
|
u32 base = cpu->R[(cpu->CurInstr >> 16) & 0xF];
|
||||||
u32 rm = cpu->R[cpu->CurInstr & 0xF] & 0xFF;
|
u32 rm = cpu->R[cpu->CurInstr & 0xF] & 0xFF;
|
||||||
|
|
||||||
if (!cpu->DataRead8(base, &cpu->R[(cpu->CurInstr >> 12) & 0xF], RWFlags_Nonseq)) return;
|
cpu->DataRead8(base, &cpu->R[(cpu->CurInstr >> 12) & 0xF]);
|
||||||
|
|
||||||
u32 numD = cpu->DataCycles;
|
u32 numD = cpu->DataCycles;
|
||||||
if (!cpu->DataWrite8(base, rm, RWFlags_Nonseq)) return;
|
cpu->DataWrite8(base, rm);
|
||||||
cpu->DataCycles += numD;
|
cpu->DataCycles += numD;
|
||||||
|
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
@ -389,7 +389,7 @@ void A_LDM(ARM* cpu)
|
|||||||
u32 base = cpu->R[baseid];
|
u32 base = cpu->R[baseid];
|
||||||
u32 wbbase;
|
u32 wbbase;
|
||||||
u32 preinc = (cpu->CurInstr & (1<<24));
|
u32 preinc = (cpu->CurInstr & (1<<24));
|
||||||
u32 flags = RWFlags_Nonseq;
|
bool first = true;
|
||||||
|
|
||||||
if (!(cpu->CurInstr & (1<<23)))
|
if (!(cpu->CurInstr & (1<<23)))
|
||||||
{
|
{
|
||||||
@ -416,8 +416,9 @@ void A_LDM(ARM* cpu)
|
|||||||
if (cpu->CurInstr & (1<<i))
|
if (cpu->CurInstr & (1<<i))
|
||||||
{
|
{
|
||||||
if (preinc) base += 4;
|
if (preinc) base += 4;
|
||||||
if (!cpu->DataRead32(base, &cpu->R[i], flags)) return;
|
if (first) cpu->DataRead32 (base, &cpu->R[i]);
|
||||||
flags &= ~RWFlags_Nonseq;
|
else cpu->DataRead32S(base, &cpu->R[i]);
|
||||||
|
first = false;
|
||||||
if (!preinc) base += 4;
|
if (!preinc) base += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -426,7 +427,8 @@ void A_LDM(ARM* cpu)
|
|||||||
{
|
{
|
||||||
u32 pc;
|
u32 pc;
|
||||||
if (preinc) base += 4;
|
if (preinc) base += 4;
|
||||||
if (!cpu->DataRead32(base, &pc, flags)) return;
|
if (first) cpu->DataRead32 (base, &pc);
|
||||||
|
else cpu->DataRead32S(base, &pc);
|
||||||
if (!preinc) base += 4;
|
if (!preinc) base += 4;
|
||||||
|
|
||||||
if (cpu->Num == 1)
|
if (cpu->Num == 1)
|
||||||
@ -466,7 +468,7 @@ void A_STM(ARM* cpu)
|
|||||||
u32 base = cpu->R[baseid];
|
u32 base = cpu->R[baseid];
|
||||||
u32 oldbase = base;
|
u32 oldbase = base;
|
||||||
u32 preinc = (cpu->CurInstr & (1<<24));
|
u32 preinc = (cpu->CurInstr & (1<<24));
|
||||||
u32 flags = RWFlags_Nonseq;
|
bool first = true;
|
||||||
|
|
||||||
if (!(cpu->CurInstr & (1<<23)))
|
if (!(cpu->CurInstr & (1<<23)))
|
||||||
{
|
{
|
||||||
@ -500,19 +502,17 @@ void A_STM(ARM* cpu)
|
|||||||
{
|
{
|
||||||
if (preinc) base += 4;
|
if (preinc) base += 4;
|
||||||
|
|
||||||
bool res;
|
|
||||||
if (i == baseid && !isbanked)
|
if (i == baseid && !isbanked)
|
||||||
{
|
{
|
||||||
if ((cpu->Num == 0) || (!(cpu->CurInstr & ((1<<i)-1))))
|
if ((cpu->Num == 0) || (!(cpu->CurInstr & ((1<<i)-1))))
|
||||||
res = cpu->DataWrite32(base, oldbase, flags);
|
first ? cpu->DataWrite32(base, oldbase) : cpu->DataWrite32S(base, oldbase);
|
||||||
else
|
else
|
||||||
res = cpu->DataWrite32(base, base, flags); // checkme
|
first ? cpu->DataWrite32(base, base) : cpu->DataWrite32S(base, base); // checkme
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
res = cpu->DataWrite32(base, cpu->R[i], flags);
|
first ? cpu->DataWrite32(base, cpu->R[i]) : cpu->DataWrite32S(base, cpu->R[i]);
|
||||||
|
|
||||||
if (!res) return;
|
first = false;
|
||||||
flags &= ~RWFlags_Nonseq;
|
|
||||||
|
|
||||||
if (!preinc) base += 4;
|
if (!preinc) base += 4;
|
||||||
}
|
}
|
||||||
@ -537,7 +537,7 @@ void A_STM(ARM* cpu)
|
|||||||
void T_LDR_PCREL(ARM* cpu)
|
void T_LDR_PCREL(ARM* cpu)
|
||||||
{
|
{
|
||||||
u32 addr = (cpu->R[15] & ~0x2) + ((cpu->CurInstr & 0xFF) << 2);
|
u32 addr = (cpu->R[15] & ~0x2) + ((cpu->CurInstr & 0xFF) << 2);
|
||||||
if (!cpu->DataRead32(addr, &cpu->R[(cpu->CurInstr >> 8) & 0x7], RWFlags_Nonseq)) return;
|
cpu->DataRead32(addr, &cpu->R[(cpu->CurInstr >> 8) & 0x7]);
|
||||||
|
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
}
|
}
|
||||||
@ -546,7 +546,7 @@ void T_LDR_PCREL(ARM* cpu)
|
|||||||
void T_STR_REG(ARM* cpu)
|
void T_STR_REG(ARM* cpu)
|
||||||
{
|
{
|
||||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||||
if (!cpu->DataWrite32(addr, cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
cpu->DataWrite32(addr, cpu->R[cpu->CurInstr & 0x7]);
|
||||||
|
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
}
|
}
|
||||||
@ -554,7 +554,7 @@ void T_STR_REG(ARM* cpu)
|
|||||||
void T_STRB_REG(ARM* cpu)
|
void T_STRB_REG(ARM* cpu)
|
||||||
{
|
{
|
||||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||||
if (!cpu->DataWrite8(addr, cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
cpu->DataWrite8(addr, cpu->R[cpu->CurInstr & 0x7]);
|
||||||
|
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
}
|
}
|
||||||
@ -564,7 +564,7 @@ void T_LDR_REG(ARM* cpu)
|
|||||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||||
|
|
||||||
u32 val;
|
u32 val;
|
||||||
if (!cpu->DataRead32(addr, &val, RWFlags_Nonseq)) return;
|
cpu->DataRead32(addr, &val);
|
||||||
cpu->R[cpu->CurInstr & 0x7] = ROR(val, 8*(addr&0x3));
|
cpu->R[cpu->CurInstr & 0x7] = ROR(val, 8*(addr&0x3));
|
||||||
|
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
@ -573,7 +573,7 @@ void T_LDR_REG(ARM* cpu)
|
|||||||
void T_LDRB_REG(ARM* cpu)
|
void T_LDRB_REG(ARM* cpu)
|
||||||
{
|
{
|
||||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||||
if (!cpu->DataRead8(addr, &cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
cpu->DataRead8(addr, &cpu->R[cpu->CurInstr & 0x7]);
|
||||||
|
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
}
|
}
|
||||||
@ -582,7 +582,7 @@ void T_LDRB_REG(ARM* cpu)
|
|||||||
void T_STRH_REG(ARM* cpu)
|
void T_STRH_REG(ARM* cpu)
|
||||||
{
|
{
|
||||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||||
if (!cpu->DataWrite16(addr, cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
cpu->DataWrite16(addr, cpu->R[cpu->CurInstr & 0x7]);
|
||||||
|
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
}
|
}
|
||||||
@ -590,7 +590,7 @@ void T_STRH_REG(ARM* cpu)
|
|||||||
void T_LDRSB_REG(ARM* cpu)
|
void T_LDRSB_REG(ARM* cpu)
|
||||||
{
|
{
|
||||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||||
if (!cpu->DataRead8(addr, &cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
cpu->DataRead8(addr, &cpu->R[cpu->CurInstr & 0x7]);
|
||||||
cpu->R[cpu->CurInstr & 0x7] = (s32)(s8)cpu->R[cpu->CurInstr & 0x7];
|
cpu->R[cpu->CurInstr & 0x7] = (s32)(s8)cpu->R[cpu->CurInstr & 0x7];
|
||||||
|
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
@ -599,7 +599,7 @@ void T_LDRSB_REG(ARM* cpu)
|
|||||||
void T_LDRH_REG(ARM* cpu)
|
void T_LDRH_REG(ARM* cpu)
|
||||||
{
|
{
|
||||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||||
if (!cpu->DataRead16(addr, &cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
cpu->DataRead16(addr, &cpu->R[cpu->CurInstr & 0x7]);
|
||||||
|
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
}
|
}
|
||||||
@ -607,7 +607,7 @@ void T_LDRH_REG(ARM* cpu)
|
|||||||
void T_LDRSH_REG(ARM* cpu)
|
void T_LDRSH_REG(ARM* cpu)
|
||||||
{
|
{
|
||||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||||
if (!cpu->DataRead16(addr, &cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
cpu->DataRead16(addr, &cpu->R[cpu->CurInstr & 0x7]);
|
||||||
cpu->R[cpu->CurInstr & 0x7] = (s32)(s16)cpu->R[cpu->CurInstr & 0x7];
|
cpu->R[cpu->CurInstr & 0x7] = (s32)(s16)cpu->R[cpu->CurInstr & 0x7];
|
||||||
|
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
@ -619,7 +619,7 @@ void T_STR_IMM(ARM* cpu)
|
|||||||
u32 offset = (cpu->CurInstr >> 4) & 0x7C;
|
u32 offset = (cpu->CurInstr >> 4) & 0x7C;
|
||||||
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
||||||
|
|
||||||
if (!cpu->DataWrite32(offset, cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
cpu->DataWrite32(offset, cpu->R[cpu->CurInstr & 0x7]);
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -629,7 +629,7 @@ void T_LDR_IMM(ARM* cpu)
|
|||||||
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
||||||
|
|
||||||
u32 val;
|
u32 val;
|
||||||
if (!cpu->DataRead32(offset, &val, RWFlags_Nonseq)) return;
|
cpu->DataRead32(offset, &val);
|
||||||
cpu->R[cpu->CurInstr & 0x7] = ROR(val, 8*(offset&0x3));
|
cpu->R[cpu->CurInstr & 0x7] = ROR(val, 8*(offset&0x3));
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
}
|
}
|
||||||
@ -639,7 +639,7 @@ void T_STRB_IMM(ARM* cpu)
|
|||||||
u32 offset = (cpu->CurInstr >> 6) & 0x1F;
|
u32 offset = (cpu->CurInstr >> 6) & 0x1F;
|
||||||
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
||||||
|
|
||||||
if (!cpu->DataWrite8(offset, cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
cpu->DataWrite8(offset, cpu->R[cpu->CurInstr & 0x7]);
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,7 +648,7 @@ void T_LDRB_IMM(ARM* cpu)
|
|||||||
u32 offset = (cpu->CurInstr >> 6) & 0x1F;
|
u32 offset = (cpu->CurInstr >> 6) & 0x1F;
|
||||||
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
||||||
|
|
||||||
if (!cpu->DataRead8(offset, &cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
cpu->DataRead8(offset, &cpu->R[cpu->CurInstr & 0x7]);
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -658,7 +658,7 @@ void T_STRH_IMM(ARM* cpu)
|
|||||||
u32 offset = (cpu->CurInstr >> 5) & 0x3E;
|
u32 offset = (cpu->CurInstr >> 5) & 0x3E;
|
||||||
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
||||||
|
|
||||||
if (!cpu->DataWrite16(offset, cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
cpu->DataWrite16(offset, cpu->R[cpu->CurInstr & 0x7]);
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -667,7 +667,7 @@ void T_LDRH_IMM(ARM* cpu)
|
|||||||
u32 offset = (cpu->CurInstr >> 5) & 0x3E;
|
u32 offset = (cpu->CurInstr >> 5) & 0x3E;
|
||||||
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
||||||
|
|
||||||
if (!cpu->DataRead16(offset, &cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
cpu->DataRead16(offset, &cpu->R[cpu->CurInstr & 0x7]);
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -677,7 +677,7 @@ void T_STR_SPREL(ARM* cpu)
|
|||||||
u32 offset = (cpu->CurInstr << 2) & 0x3FC;
|
u32 offset = (cpu->CurInstr << 2) & 0x3FC;
|
||||||
offset += cpu->R[13];
|
offset += cpu->R[13];
|
||||||
|
|
||||||
if (!cpu->DataWrite32(offset, cpu->R[(cpu->CurInstr >> 8) & 0x7], RWFlags_Nonseq)) return;
|
cpu->DataWrite32(offset, cpu->R[(cpu->CurInstr >> 8) & 0x7]);
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -686,7 +686,7 @@ void T_LDR_SPREL(ARM* cpu)
|
|||||||
u32 offset = (cpu->CurInstr << 2) & 0x3FC;
|
u32 offset = (cpu->CurInstr << 2) & 0x3FC;
|
||||||
offset += cpu->R[13];
|
offset += cpu->R[13];
|
||||||
|
|
||||||
if (!cpu->DataRead32(offset, &cpu->R[(cpu->CurInstr >> 8) & 0x7], RWFlags_Nonseq)) return;
|
cpu->DataRead32(offset, &cpu->R[(cpu->CurInstr >> 8) & 0x7]);
|
||||||
cpu->AddCycles_CDI();
|
cpu->AddCycles_CDI();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -694,7 +694,7 @@ void T_LDR_SPREL(ARM* cpu)
|
|||||||
void T_PUSH(ARM* cpu)
|
void T_PUSH(ARM* cpu)
|
||||||
{
|
{
|
||||||
int nregs = 0;
|
int nregs = 0;
|
||||||
u32 flags = RWFlags_Nonseq;
|
bool first = true;
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
@ -713,15 +713,17 @@ void T_PUSH(ARM* cpu)
|
|||||||
{
|
{
|
||||||
if (cpu->CurInstr & (1<<i))
|
if (cpu->CurInstr & (1<<i))
|
||||||
{
|
{
|
||||||
if (!cpu->DataWrite32(base, cpu->R[i], flags)) return;
|
if (first) cpu->DataWrite32 (base, cpu->R[i]);
|
||||||
flags &= ~RWFlags_Nonseq;
|
else cpu->DataWrite32S(base, cpu->R[i]);
|
||||||
|
first = false;
|
||||||
base += 4;
|
base += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu->CurInstr & (1<<8))
|
if (cpu->CurInstr & (1<<8))
|
||||||
{
|
{
|
||||||
if (!cpu->DataWrite32(base, cpu->R[14], flags)) return;
|
if (first) cpu->DataWrite32 (base, cpu->R[14]);
|
||||||
|
else cpu->DataWrite32S(base, cpu->R[14]);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->AddCycles_CD();
|
cpu->AddCycles_CD();
|
||||||
@ -730,14 +732,15 @@ void T_PUSH(ARM* cpu)
|
|||||||
void T_POP(ARM* cpu)
|
void T_POP(ARM* cpu)
|
||||||
{
|
{
|
||||||
u32 base = cpu->R[13];
|
u32 base = cpu->R[13];
|
||||||
u32 flags = RWFlags_Nonseq;
|
bool first = true;
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if (cpu->CurInstr & (1<<i))
|
if (cpu->CurInstr & (1<<i))
|
||||||
{
|
{
|
||||||
if (!cpu->DataRead32(base, &cpu->R[i], flags)) return;
|
if (first) cpu->DataRead32 (base, &cpu->R[i]);
|
||||||
flags &= ~RWFlags_Nonseq;
|
else cpu->DataRead32S(base, &cpu->R[i]);
|
||||||
|
first = false;
|
||||||
base += 4;
|
base += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -745,7 +748,8 @@ void T_POP(ARM* cpu)
|
|||||||
if (cpu->CurInstr & (1<<8))
|
if (cpu->CurInstr & (1<<8))
|
||||||
{
|
{
|
||||||
u32 pc;
|
u32 pc;
|
||||||
if (!cpu->DataRead32(base, &pc, flags)) return;
|
if (first) cpu->DataRead32 (base, &pc);
|
||||||
|
else cpu->DataRead32S(base, &pc);
|
||||||
if (cpu->Num==1) pc |= 0x1;
|
if (cpu->Num==1) pc |= 0x1;
|
||||||
cpu->JumpTo(pc);
|
cpu->JumpTo(pc);
|
||||||
base += 4;
|
base += 4;
|
||||||
@ -758,14 +762,15 @@ void T_POP(ARM* cpu)
|
|||||||
void T_STMIA(ARM* cpu)
|
void T_STMIA(ARM* cpu)
|
||||||
{
|
{
|
||||||
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
|
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
|
||||||
u32 flags = RWFlags_Nonseq;
|
bool first = true;
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if (cpu->CurInstr & (1<<i))
|
if (cpu->CurInstr & (1<<i))
|
||||||
{
|
{
|
||||||
if (!cpu->DataWrite32(base, cpu->R[i], flags)) return;
|
if (first) cpu->DataWrite32 (base, cpu->R[i]);
|
||||||
flags &= ~RWFlags_Nonseq;
|
else cpu->DataWrite32S(base, cpu->R[i]);
|
||||||
|
first = false;
|
||||||
base += 4;
|
base += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -778,14 +783,15 @@ void T_STMIA(ARM* cpu)
|
|||||||
void T_LDMIA(ARM* cpu)
|
void T_LDMIA(ARM* cpu)
|
||||||
{
|
{
|
||||||
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
|
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
|
||||||
u32 flags = RWFlags_Nonseq;
|
bool first = true;
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if (cpu->CurInstr & (1<<i))
|
if (cpu->CurInstr & (1<<i))
|
||||||
{
|
{
|
||||||
if (!cpu->DataRead32(base, &cpu->R[i], flags)) return;
|
if (first) cpu->DataRead32 (base, &cpu->R[i]);
|
||||||
flags &= ~RWFlags_Nonseq;
|
else cpu->DataRead32S(base, &cpu->R[i]);
|
||||||
|
first = false;
|
||||||
base += 4;
|
base += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
307
src/CP15.cpp
307
src/CP15.cpp
@ -22,6 +22,11 @@
|
|||||||
#include "ARM.h"
|
#include "ARM.h"
|
||||||
|
|
||||||
|
|
||||||
|
// access timing for cached regions
|
||||||
|
// this would be an average between cache hits and cache misses
|
||||||
|
const int kDataCacheTiming = 2;
|
||||||
|
const int kCodeCacheTiming = 1;
|
||||||
|
|
||||||
|
|
||||||
void ARMv5::CP15Reset()
|
void ARMv5::CP15Reset()
|
||||||
{
|
{
|
||||||
@ -211,6 +216,47 @@ void ARMv5::UpdatePURegions()
|
|||||||
codecache >>= 1;
|
codecache >>= 1;
|
||||||
datacache >>= 1;
|
datacache >>= 1;
|
||||||
datawrite >>= 1;
|
datawrite >>= 1;
|
||||||
|
|
||||||
|
// TODO: this will not be enough if they change their PU regions after the intial setup
|
||||||
|
//UpdateRegionTimings(start<<12, end<<12);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateRegionTimings(0x00000000, 0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend)
|
||||||
|
{
|
||||||
|
addrstart >>= 12;
|
||||||
|
addrend >>= 12;
|
||||||
|
|
||||||
|
if (addrend == 0xFFFFF) addrend++;
|
||||||
|
|
||||||
|
for (u32 i = addrstart; i < addrend; i++)
|
||||||
|
{
|
||||||
|
u8 pu = PU_Map[i];
|
||||||
|
u8* bustimings = NDS::ARM9MemTimings[i >> 2];
|
||||||
|
|
||||||
|
if (pu & 0x40)
|
||||||
|
{
|
||||||
|
MemTimings[i][0] = kCodeCacheTiming;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MemTimings[i][0] = bustimings[2] << ClockShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pu & 0x10)
|
||||||
|
{
|
||||||
|
MemTimings[i][1] = kDataCacheTiming;
|
||||||
|
MemTimings[i][2] = kDataCacheTiming;
|
||||||
|
MemTimings[i][3] = kDataCacheTiming;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MemTimings[i][1] = bustimings[0] << ClockShift;
|
||||||
|
MemTimings[i][2] = bustimings[2] << ClockShift;
|
||||||
|
MemTimings[i][3] = bustimings[3] << ClockShift;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,280 +506,183 @@ u32 ARMv5::CP15Read(u32 id)
|
|||||||
|
|
||||||
u32 ARMv5::CodeRead32(u32 addr)
|
u32 ARMv5::CodeRead32(u32 addr)
|
||||||
{
|
{
|
||||||
u8 pu = PU_Map[addr>>12];
|
|
||||||
|
|
||||||
if (addr < ITCMSize)
|
if (addr < ITCMSize)
|
||||||
{
|
{
|
||||||
CodeRegion = NDS::Region9_ITCM;
|
|
||||||
return *(u32*)&ITCM[addr & 0x7FFF];
|
return *(u32*)&ITCM[addr & 0x7FFF];
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ret;
|
return NDS::ARM9Read32(addr);
|
||||||
CodeRegion = NDS::ARM9Read32(addr, &ret);
|
|
||||||
if (pu & 0x40) CodeRegion = NDS::Region9_ICache;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ARMv5::DataRead8(u32 addr, u32* val, u32 flags)
|
void ARMv5::DataRead8(u32 addr, u32* val)
|
||||||
{
|
{
|
||||||
u8 pu = PU_Map[addr>>12];
|
|
||||||
/*if (!(pu & 0x01))
|
|
||||||
{
|
|
||||||
DataAbort();
|
|
||||||
return false;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (addr < ITCMSize)
|
if (addr < ITCMSize)
|
||||||
{
|
{
|
||||||
DataRegion = NDS::Region9_ITCM;
|
DataCycles = 1;
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 1;
|
|
||||||
else DataCycles += 1;
|
|
||||||
*val = *(u8*)&ITCM[addr & 0x7FFF];
|
*val = *(u8*)&ITCM[addr & 0x7FFF];
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
||||||
{
|
{
|
||||||
DataRegion = NDS::Region9_DTCM;
|
DataCycles = 1;
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 1;
|
|
||||||
else DataCycles += 1;
|
|
||||||
*val = *(u8*)&DTCM[(addr - DTCMBase) & 0x3FFF];
|
*val = *(u8*)&DTCM[(addr - DTCMBase) & 0x3FFF];
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataRegion = NDS::ARM9Read8(addr, val);
|
*val = NDS::ARM9Read8(addr);
|
||||||
if (pu & 0x10)
|
DataCycles = MemTimings[addr >> 12][1];
|
||||||
{
|
|
||||||
DataRegion = NDS::Region9_DCache;
|
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 2;
|
|
||||||
else DataCycles += 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = NDS::ARM9MemTimings[DataRegion][0];
|
|
||||||
else DataCycles += NDS::ARM9MemTimings[DataRegion][1];
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMv5::DataRead16(u32 addr, u32* val, u32 flags)
|
void ARMv5::DataRead16(u32 addr, u32* val)
|
||||||
{
|
{
|
||||||
addr &= ~1;
|
addr &= ~1;
|
||||||
|
|
||||||
u8 pu = PU_Map[addr>>12];
|
|
||||||
/*if (!(pu & 0x01))
|
|
||||||
{
|
|
||||||
DataAbort();
|
|
||||||
return false;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (addr < ITCMSize)
|
if (addr < ITCMSize)
|
||||||
{
|
{
|
||||||
DataRegion = NDS::Region9_ITCM;
|
DataCycles = 1;
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 1;
|
|
||||||
else DataCycles += 1;
|
|
||||||
*val = *(u16*)&ITCM[addr & 0x7FFF];
|
*val = *(u16*)&ITCM[addr & 0x7FFF];
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
||||||
{
|
{
|
||||||
DataRegion = NDS::Region9_DTCM;
|
DataCycles = 1;
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 1;
|
|
||||||
else DataCycles += 1;
|
|
||||||
*val = *(u16*)&DTCM[(addr - DTCMBase) & 0x3FFF];
|
*val = *(u16*)&DTCM[(addr - DTCMBase) & 0x3FFF];
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataRegion = NDS::ARM9Read16(addr, val);
|
*val = NDS::ARM9Read16(addr);
|
||||||
if (pu & 0x10)
|
DataCycles = MemTimings[addr >> 12][1];
|
||||||
{
|
|
||||||
DataRegion = NDS::Region9_DCache;
|
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 2;
|
|
||||||
else DataCycles += 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = NDS::ARM9MemTimings[DataRegion][0];
|
|
||||||
else DataCycles += NDS::ARM9MemTimings[DataRegion][1];
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMv5::DataRead32(u32 addr, u32* val, u32 flags)
|
void ARMv5::DataRead32(u32 addr, u32* val)
|
||||||
{
|
{
|
||||||
addr &= ~3;
|
addr &= ~3;
|
||||||
|
|
||||||
u8 pu = PU_Map[addr>>12];
|
|
||||||
/*if (!(pu & 0x01))
|
|
||||||
{
|
|
||||||
DataAbort();
|
|
||||||
return false;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (addr < ITCMSize)
|
if (addr < ITCMSize)
|
||||||
{
|
{
|
||||||
DataRegion = NDS::Region9_ITCM;
|
DataCycles = 1;
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 1;
|
|
||||||
else DataCycles += 1;
|
|
||||||
*val = *(u32*)&ITCM[addr & 0x7FFF];
|
*val = *(u32*)&ITCM[addr & 0x7FFF];
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
||||||
{
|
{
|
||||||
DataRegion = NDS::Region9_DTCM;
|
DataCycles = 1;
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 1;
|
|
||||||
else DataCycles += 1;
|
|
||||||
*val = *(u32*)&DTCM[(addr - DTCMBase) & 0x3FFF];
|
*val = *(u32*)&DTCM[(addr - DTCMBase) & 0x3FFF];
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataRegion = NDS::ARM9Read32(addr, val);
|
*val = NDS::ARM9Read32(addr);
|
||||||
if (pu & 0x10)
|
DataCycles = MemTimings[addr >> 12][2];
|
||||||
{
|
|
||||||
DataRegion = NDS::Region9_DCache;
|
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 2;
|
|
||||||
else DataCycles += 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = NDS::ARM9MemTimings[DataRegion][0];
|
|
||||||
else DataCycles += NDS::ARM9MemTimings[DataRegion][1];
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMv5::DataWrite8(u32 addr, u8 val, u32 flags)
|
void ARMv5::DataRead32S(u32 addr, u32* val)
|
||||||
{
|
{
|
||||||
u8 pu = PU_Map[addr>>12];
|
addr &= ~3;
|
||||||
/*if (!(pu & 0x02))
|
|
||||||
{
|
|
||||||
DataAbort();
|
|
||||||
return false;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (addr < ITCMSize)
|
if (addr < ITCMSize)
|
||||||
{
|
{
|
||||||
DataRegion = NDS::Region9_ITCM;
|
DataCycles += 1;
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 1;
|
*val = *(u32*)&ITCM[addr & 0x7FFF];
|
||||||
else DataCycles += 1;
|
return;
|
||||||
*(u8*)&ITCM[addr & 0x7FFF] = val;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
||||||
{
|
{
|
||||||
DataRegion = NDS::Region9_DTCM;
|
DataCycles += 1;
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 1;
|
*val = *(u32*)&DTCM[(addr - DTCMBase) & 0x3FFF];
|
||||||
else DataCycles += 1;
|
return;
|
||||||
*(u8*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DataRegion = NDS::ARM9Write8(addr, val);
|
*val = NDS::ARM9Read32(addr);
|
||||||
if (pu & 0x20)
|
DataCycles += MemTimings[addr >> 12][3];
|
||||||
{
|
|
||||||
DataRegion = NDS::Region9_DCache;
|
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 2;
|
|
||||||
else DataCycles += 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = NDS::ARM9MemTimings[DataRegion][0];
|
|
||||||
else DataCycles += NDS::ARM9MemTimings[DataRegion][1];
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMv5::DataWrite16(u32 addr, u16 val, u32 flags)
|
void ARMv5::DataWrite8(u32 addr, u8 val)
|
||||||
|
{
|
||||||
|
if (addr < ITCMSize)
|
||||||
|
{
|
||||||
|
DataCycles = 1;
|
||||||
|
*(u8*)&ITCM[addr & 0x7FFF] = val;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
||||||
|
{
|
||||||
|
DataCycles = 1;
|
||||||
|
*(u8*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NDS::ARM9Write8(addr, val);
|
||||||
|
DataCycles = MemTimings[addr >> 12][1];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMv5::DataWrite16(u32 addr, u16 val)
|
||||||
{
|
{
|
||||||
addr &= ~1;
|
addr &= ~1;
|
||||||
|
|
||||||
u8 pu = PU_Map[addr>>12];
|
|
||||||
/*if (!(pu & 0x02))
|
|
||||||
{
|
|
||||||
DataAbort();
|
|
||||||
return false;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (addr < ITCMSize)
|
if (addr < ITCMSize)
|
||||||
{
|
{
|
||||||
DataRegion = NDS::Region9_ITCM;
|
DataCycles = 1;
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 1;
|
|
||||||
else DataCycles += 1;
|
|
||||||
*(u16*)&ITCM[addr & 0x7FFF] = val;
|
*(u16*)&ITCM[addr & 0x7FFF] = val;
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
||||||
{
|
{
|
||||||
DataRegion = NDS::Region9_DTCM;
|
DataCycles = 1;
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 1;
|
|
||||||
else DataCycles += 1;
|
|
||||||
*(u16*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val;
|
*(u16*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val;
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataRegion = NDS::ARM9Write16(addr, val);
|
NDS::ARM9Write16(addr, val);
|
||||||
if (pu & 0x20)
|
DataCycles = MemTimings[addr >> 12][1];
|
||||||
{
|
|
||||||
DataRegion = NDS::Region9_DCache;
|
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 2;
|
|
||||||
else DataCycles += 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = NDS::ARM9MemTimings[DataRegion][0];
|
|
||||||
else DataCycles += NDS::ARM9MemTimings[DataRegion][1];
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMv5::DataWrite32(u32 addr, u32 val, u32 flags)
|
void ARMv5::DataWrite32(u32 addr, u32 val)
|
||||||
{
|
{
|
||||||
addr &= ~3;
|
addr &= ~3;
|
||||||
|
|
||||||
u8 pu = PU_Map[addr>>12];
|
|
||||||
/*if (!(pu & 0x02))
|
|
||||||
{
|
|
||||||
DataAbort();
|
|
||||||
return false;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (addr < ITCMSize)
|
if (addr < ITCMSize)
|
||||||
{
|
{
|
||||||
DataRegion = NDS::Region9_ITCM;
|
DataCycles = 1;
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 1;
|
|
||||||
else DataCycles += 1;
|
|
||||||
*(u32*)&ITCM[addr & 0x7FFF] = val;
|
*(u32*)&ITCM[addr & 0x7FFF] = val;
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
||||||
{
|
{
|
||||||
DataRegion = NDS::Region9_DTCM;
|
DataCycles = 1;
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 1;
|
|
||||||
else DataCycles += 1;
|
|
||||||
*(u32*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val;
|
*(u32*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val;
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataRegion = NDS::ARM9Write32(addr, val);
|
NDS::ARM9Write32(addr, val);
|
||||||
if (pu & 0x20)
|
DataCycles = MemTimings[addr >> 12][2];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMv5::DataWrite32S(u32 addr, u32 val)
|
||||||
|
{
|
||||||
|
addr &= ~3;
|
||||||
|
|
||||||
|
if (addr < ITCMSize)
|
||||||
{
|
{
|
||||||
DataRegion = NDS::Region9_DCache;
|
DataCycles += 1;
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = 2;
|
*(u32*)&ITCM[addr & 0x7FFF] = val;
|
||||||
else DataCycles += 2;
|
return;
|
||||||
}
|
}
|
||||||
else
|
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
||||||
{
|
{
|
||||||
if (flags & RWFlags_Nonseq) DataCycles = NDS::ARM9MemTimings[DataRegion][0];
|
DataCycles += 1;
|
||||||
else DataCycles += NDS::ARM9MemTimings[DataRegion][1];
|
*(u32*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
NDS::ARM9Write32(addr, val);
|
||||||
|
DataCycles += MemTimings[addr >> 12][3];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMv5::GetCodeMemRegion(u32 addr, NDS::MemRegion* region)
|
void ARMv5::GetCodeMemRegion(u32 addr, NDS::MemRegion* region)
|
||||||
{
|
{
|
||||||
if (addr < ITCMSize)
|
if (addr < ITCMSize)
|
||||||
{
|
{
|
||||||
region->Region = NDS::Region9_ITCM;
|
|
||||||
region->Mem = ITCM;
|
region->Mem = ITCM;
|
||||||
region->Mask = 0x7FFF;
|
region->Mask = 0x7FFF;
|
||||||
return;
|
return;
|
||||||
|
52
src/DMA.cpp
52
src/DMA.cpp
@ -203,17 +203,17 @@ s32 DMA::Run(s32 cycles)
|
|||||||
{
|
{
|
||||||
if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02)
|
if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02)
|
||||||
{
|
{
|
||||||
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 12][0] + NDS::ARM9MemTimings[CurDstAddr >> 12][0];
|
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][0] + NDS::ARM9MemTimings[CurDstAddr >> 14][0];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 12][1] + NDS::ARM9MemTimings[CurDstAddr >> 12][1];
|
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][1] + NDS::ARM9MemTimings[CurDstAddr >> 14][1];
|
||||||
if ((CurSrcAddr >> 24) == (CurDstAddr >> 24))
|
if ((CurSrcAddr >> 24) == (CurDstAddr >> 24))
|
||||||
unitcycles++;
|
unitcycles++;
|
||||||
|
|
||||||
if (burststart)
|
if (burststart)
|
||||||
{
|
{
|
||||||
cycles -= (NDS::ARM9MemTimings[CurSrcAddr >> 12][0] + NDS::ARM9MemTimings[CurDstAddr >> 12][0]);
|
cycles -= (NDS::ARM9MemTimings[CurSrcAddr >> 14][0] + NDS::ARM9MemTimings[CurDstAddr >> 14][0]);
|
||||||
cycles += unitcycles;
|
cycles += unitcycles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -222,38 +222,38 @@ s32 DMA::Run(s32 cycles)
|
|||||||
{
|
{
|
||||||
if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02)
|
if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02)
|
||||||
{
|
{
|
||||||
unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 17][0] + NDS::ARM7MemTimings[CurDstAddr >> 17][0];
|
unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][0] + NDS::ARM7MemTimings[CurDstAddr >> 15][0];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 17][1] + NDS::ARM7MemTimings[CurDstAddr >> 17][1];
|
unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][1] + NDS::ARM7MemTimings[CurDstAddr >> 15][1];
|
||||||
if ((CurSrcAddr >> 23) == (CurDstAddr >> 23))
|
if ((CurSrcAddr >> 23) == (CurDstAddr >> 23))
|
||||||
unitcycles++;
|
unitcycles++;
|
||||||
|
|
||||||
if (burststart)
|
if (burststart)
|
||||||
{
|
{
|
||||||
cycles -= (NDS::ARM7MemTimings[CurSrcAddr >> 17][0] + NDS::ARM7MemTimings[CurDstAddr >> 17][0]);
|
cycles -= (NDS::ARM7MemTimings[CurSrcAddr >> 15][0] + NDS::ARM7MemTimings[CurDstAddr >> 15][0]);
|
||||||
cycles += unitcycles;
|
cycles += unitcycles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int (*readfn)(u32,u32*) = CPU ? NDS::ARM7Read16 : NDS::ARM9Read16;
|
u16 (*readfn)(u32) = CPU ? NDS::ARM7Read16 : NDS::ARM9Read16;
|
||||||
int (*writefn)(u32,u16) = CPU ? NDS::ARM7Write16 : NDS::ARM9Write16;
|
void (*writefn)(u32,u16) = CPU ? NDS::ARM7Write16 : NDS::ARM9Write16;
|
||||||
|
|
||||||
while (IterCount > 0 && cycles > 0 && !Stall)
|
while (IterCount > 0 && !Stall)
|
||||||
{
|
{
|
||||||
u32 val;
|
writefn(CurDstAddr, readfn(CurSrcAddr));
|
||||||
readfn(CurSrcAddr, &val);
|
|
||||||
writefn(CurDstAddr, val);
|
|
||||||
|
|
||||||
cycles -= unitcycles;
|
cycles -= unitcycles;
|
||||||
NDS::RunTimingCriticalDevices(CPU, c);
|
NDS::RunTimingCriticalDevices(CPU, unitcycles);
|
||||||
|
|
||||||
CurSrcAddr += SrcAddrInc<<1;
|
CurSrcAddr += SrcAddrInc<<1;
|
||||||
CurDstAddr += DstAddrInc<<1;
|
CurDstAddr += DstAddrInc<<1;
|
||||||
IterCount--;
|
IterCount--;
|
||||||
RemCount--;
|
RemCount--;
|
||||||
|
|
||||||
|
if (cycles < 0) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -263,11 +263,11 @@ s32 DMA::Run(s32 cycles)
|
|||||||
{
|
{
|
||||||
if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02)
|
if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02)
|
||||||
{
|
{
|
||||||
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 12][2] + NDS::ARM9MemTimings[CurDstAddr >> 12][2];
|
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][2] + NDS::ARM9MemTimings[CurDstAddr >> 14][2];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 12][3] + NDS::ARM9MemTimings[CurDstAddr >> 12][3];
|
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][3] + NDS::ARM9MemTimings[CurDstAddr >> 14][3];
|
||||||
if ((CurSrcAddr >> 24) == (CurDstAddr >> 24))
|
if ((CurSrcAddr >> 24) == (CurDstAddr >> 24))
|
||||||
unitcycles++;
|
unitcycles++;
|
||||||
else if ((CurSrcAddr >> 24) == 0x02)
|
else if ((CurSrcAddr >> 24) == 0x02)
|
||||||
@ -275,7 +275,7 @@ s32 DMA::Run(s32 cycles)
|
|||||||
|
|
||||||
if (burststart)
|
if (burststart)
|
||||||
{
|
{
|
||||||
cycles -= (NDS::ARM9MemTimings[CurSrcAddr >> 12][2] + NDS::ARM9MemTimings[CurDstAddr >> 12][2]);
|
cycles -= (NDS::ARM9MemTimings[CurSrcAddr >> 14][2] + NDS::ARM9MemTimings[CurDstAddr >> 14][2]);
|
||||||
cycles += unitcycles;
|
cycles += unitcycles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -284,11 +284,11 @@ s32 DMA::Run(s32 cycles)
|
|||||||
{
|
{
|
||||||
if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02)
|
if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02)
|
||||||
{
|
{
|
||||||
unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 17][2] + NDS::ARM7MemTimings[CurDstAddr >> 17][2];
|
unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][2] + NDS::ARM7MemTimings[CurDstAddr >> 15][2];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 17][3] + NDS::ARM7MemTimings[CurDstAddr >> 17][3];
|
unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][3] + NDS::ARM7MemTimings[CurDstAddr >> 15][3];
|
||||||
if ((CurSrcAddr >> 23) == (CurDstAddr >> 23))
|
if ((CurSrcAddr >> 23) == (CurDstAddr >> 23))
|
||||||
unitcycles++;
|
unitcycles++;
|
||||||
else if ((CurSrcAddr >> 24) == 0x02)
|
else if ((CurSrcAddr >> 24) == 0x02)
|
||||||
@ -296,28 +296,28 @@ s32 DMA::Run(s32 cycles)
|
|||||||
|
|
||||||
if (burststart)
|
if (burststart)
|
||||||
{
|
{
|
||||||
cycles -= (NDS::ARM7MemTimings[CurSrcAddr >> 17][2] + NDS::ARM7MemTimings[CurDstAddr >> 17][2]);
|
cycles -= (NDS::ARM7MemTimings[CurSrcAddr >> 15][2] + NDS::ARM7MemTimings[CurDstAddr >> 15][2]);
|
||||||
cycles += unitcycles;
|
cycles += unitcycles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int (*readfn)(u32,u32*) = CPU ? NDS::ARM7Read32 : NDS::ARM9Read32;
|
u32 (*readfn)(u32) = CPU ? NDS::ARM7Read32 : NDS::ARM9Read32;
|
||||||
int (*writefn)(u32,u32) = CPU ? NDS::ARM7Write32 : NDS::ARM9Write32;
|
void (*writefn)(u32,u32) = CPU ? NDS::ARM7Write32 : NDS::ARM9Write32;
|
||||||
|
|
||||||
while (IterCount > 0 && cycles > 0 && !Stall)
|
while (IterCount > 0 && !Stall)
|
||||||
{
|
{
|
||||||
u32 val;
|
writefn(CurDstAddr, readfn(CurSrcAddr));
|
||||||
readfn(CurSrcAddr, &val);
|
|
||||||
writefn(CurDstAddr, val);
|
|
||||||
|
|
||||||
cycles -= unitcycles;
|
cycles -= unitcycles;
|
||||||
NDS::RunTimingCriticalDevices(CPU, c);
|
NDS::RunTimingCriticalDevices(CPU, unitcycles);
|
||||||
|
|
||||||
CurSrcAddr += SrcAddrInc<<2;
|
CurSrcAddr += SrcAddrInc<<2;
|
||||||
CurDstAddr += DstAddrInc<<2;
|
CurDstAddr += DstAddrInc<<2;
|
||||||
IterCount--;
|
IterCount--;
|
||||||
RemCount--;
|
RemCount--;
|
||||||
|
|
||||||
|
if (cycles < 0) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -813,7 +813,7 @@ void StartScanline(u32 line)
|
|||||||
GPU2D_A->VBlank();
|
GPU2D_A->VBlank();
|
||||||
GPU2D_B->VBlank();
|
GPU2D_B->VBlank();
|
||||||
GPU3D::VBlank();
|
GPU3D::VBlank();
|
||||||
printf("VBlank. PC=%08X\n", NDS::GetPC(0));
|
//printf("VBlank. PC=%08X\n", NDS::GetPC(0));
|
||||||
}
|
}
|
||||||
else if (VCount == 144)
|
else if (VCount == 144)
|
||||||
{
|
{
|
||||||
|
26
src/NDS.cpp
26
src/NDS.cpp
@ -56,7 +56,7 @@ namespace NDS
|
|||||||
//
|
//
|
||||||
// timings for GBA slot and wifi are set up at runtime
|
// timings for GBA slot and wifi are set up at runtime
|
||||||
|
|
||||||
u8 ARM9MemTimings[0x100000][4];
|
u8 ARM9MemTimings[0x40000][4];
|
||||||
u8 ARM7MemTimings[0x20000][4];
|
u8 ARM7MemTimings[0x20000][4];
|
||||||
|
|
||||||
ARMv5* ARM9;
|
ARMv5* ARM9;
|
||||||
@ -134,6 +134,8 @@ bool Running;
|
|||||||
void DivDone(u32 param);
|
void DivDone(u32 param);
|
||||||
void SqrtDone(u32 param);
|
void SqrtDone(u32 param);
|
||||||
void RunTimer(u32 tid, s32 cycles);
|
void RunTimer(u32 tid, s32 cycles);
|
||||||
|
void SetWifiWaitCnt(u16 val);
|
||||||
|
void SetGBASlotTimings();
|
||||||
|
|
||||||
|
|
||||||
bool Init()
|
bool Init()
|
||||||
@ -185,10 +187,10 @@ void DeInit()
|
|||||||
|
|
||||||
void SetARM9RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, int seq)
|
void SetARM9RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, int seq)
|
||||||
{
|
{
|
||||||
addrstart >>= 12;
|
addrstart >>= 14;
|
||||||
addrend >>= 12;
|
addrend >>= 14;
|
||||||
|
|
||||||
if (addrend == 0xFFFFF) addrend++;
|
if (addrend == 0x3FFFF) addrend++;
|
||||||
|
|
||||||
int N16, S16, N32, S32;
|
int N16, S16, N32, S32;
|
||||||
N16 = nonseq;
|
N16 = nonseq;
|
||||||
@ -211,12 +213,14 @@ void SetARM9RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq,
|
|||||||
ARM9MemTimings[i][2] = N32;
|
ARM9MemTimings[i][2] = N32;
|
||||||
ARM9MemTimings[i][3] = S32;
|
ARM9MemTimings[i][3] = S32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ARM9->UpdateRegionTimings(addrstart<<14, addrend<<14);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetARM7RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, int seq)
|
void SetARM7RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, int seq)
|
||||||
{
|
{
|
||||||
addrstart >>= 17;
|
addrstart >>= 15;
|
||||||
addrend >>= 17;
|
addrend >>= 15;
|
||||||
|
|
||||||
if (addrend == 0x1FFFF) addrend++;
|
if (addrend == 0x1FFFF) addrend++;
|
||||||
|
|
||||||
@ -400,6 +404,9 @@ void Reset()
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ARM9->SetClockShift(1);
|
||||||
|
ARM7->SetClockShift(0);
|
||||||
|
|
||||||
InitTimings();
|
InitTimings();
|
||||||
|
|
||||||
memset(MainRAM, 0, MAIN_RAM_SIZE);
|
memset(MainRAM, 0, MAIN_RAM_SIZE);
|
||||||
@ -469,9 +476,6 @@ void Reset()
|
|||||||
SPI::Reset();
|
SPI::Reset();
|
||||||
RTC::Reset();
|
RTC::Reset();
|
||||||
Wifi::Reset();
|
Wifi::Reset();
|
||||||
|
|
||||||
ARM9->SetClockShift(1);
|
|
||||||
ARM7->SetClockShift(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stop()
|
void Stop()
|
||||||
@ -1449,7 +1453,7 @@ u16 ARM9Read16(u32 addr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ARM9Read32(u32 addr, u32* val)
|
u32 ARM9Read32(u32 addr)
|
||||||
{
|
{
|
||||||
if ((addr & 0xFFFFF000) == 0xFFFF0000)
|
if ((addr & 0xFFFFF000) == 0xFFFF0000)
|
||||||
{
|
{
|
||||||
@ -1739,7 +1743,7 @@ u16 ARM7Read16(u32 addr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ARM7Read32(u32 addr, u32* val)
|
u32 ARM7Read32(u32 addr)
|
||||||
{
|
{
|
||||||
if (addr < 0x00004000)
|
if (addr < 0x00004000)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user