diff options
-rw-r--r-- | src/ARM.cpp | 35 | ||||
-rw-r--r-- | src/ARM.h | 187 | ||||
-rw-r--r-- | src/ARMInterpreter_LoadStore.cpp | 162 | ||||
-rw-r--r-- | src/CP15.cpp | 297 | ||||
-rw-r--r-- | src/DMA.cpp | 52 | ||||
-rw-r--r-- | src/GPU.cpp | 2 | ||||
-rw-r--r-- | src/NDS.cpp | 26 | ||||
-rw-r--r-- | src/NDS.h | 2 |
8 files changed, 354 insertions, 409 deletions
diff --git a/src/ARM.cpp b/src/ARM.cpp index 10e2e04..6f58343 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -136,17 +136,6 @@ void ARMv5::DoSavestate(Savestate* file) } -void ARMv5::CalculateTimings() -{ - // -} - -void ARMv4::CalculateTimings() -{ - // -} - - void ARM::SetupCodeMem(u32 addr) { if (!Num) @@ -181,8 +170,11 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr) //printf("[%03d] IRQ handler thing. wait=%08X\n", GPU::VCount, dorp); } - u32 oldregion = R[15] >> 23; - u32 newregion = addr >> 23; + u32 oldregion = R[15] >> 24; + u32 newregion = addr >> 24; + + if (addr < ITCMSize) CodeCycles = 1; + else CodeCycles = MemTimings[addr >> 12][0]; s32 cycles; @@ -199,13 +191,13 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr) { NextInstr[0] = CodeRead32(addr-2) >> 16; NextInstr[1] = CodeRead32(addr+2); - cycles = NDS::ARM9MemTimings[CodeRegion][2] * 2; + cycles = CodeCycles * 2; } else { NextInstr[0] = CodeRead32(addr); NextInstr[1] = NextInstr[0] >> 16; - cycles = NDS::ARM9MemTimings[CodeRegion][2]; + cycles = CodeCycles; } CPSR |= 0x20; @@ -219,7 +211,7 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr) NextInstr[0] = CodeRead32(addr); NextInstr[1] = CodeRead32(addr+4); - cycles = NDS::ARM9MemTimings[CodeRegion][2] * 2; + cycles = CodeCycles * 2; CPSR &= ~0x20; } @@ -250,6 +242,9 @@ void ARMv4::JumpTo(u32 addr, bool restorecpsr) u32 oldregion = R[15] >> 23; u32 newregion = addr >> 23; + CodeRegion = addr >> 24; + CodeCycles = addr >> 15; // cheato + if (addr & 0x1) { addr &= ~0x1; @@ -259,7 +254,7 @@ void ARMv4::JumpTo(u32 addr, bool restorecpsr) NextInstr[0] = CodeRead16(addr); 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; } @@ -272,7 +267,7 @@ void ARMv4::JumpTo(u32 addr, bool restorecpsr) NextInstr[0] = CodeRead32(addr); 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; } @@ -482,8 +477,8 @@ s32 ARMv5::Execute() R[15] += 2; CurInstr = NextInstr[0]; NextInstr[0] = NextInstr[1]; - if (R[15] & 0x2) { NextInstr[1] >>= 16; CodeRegion = NDS::Region9_MAX; } - else NextInstr[1] = CodeRead32(R[15]); + if (R[15] & 0x2) NextInstr[1] >>= 16; + else NextInstr[1] = CodeRead32(R[15]); // actually execute u32 icode = (CurInstr >> 6) & 0x3FF; @@ -48,8 +48,6 @@ public: ClockDiffMask = (1<<shift) - 1; } - virtual void CalculateTimings() = 0; - virtual void JumpTo(u32 addr, bool restorecpsr = false) = 0; void RestoreCPSR(); @@ -107,15 +105,17 @@ public: void SetupCodeMem(u32 addr); - virtual bool DataRead8(u32 addr, u32* val, u32 flags) = 0; - virtual bool DataRead16(u32 addr, u32* val, u32 flags) = 0; - virtual bool DataRead32(u32 addr, u32* val, u32 flags) = 0; - virtual bool DataWrite8(u32 addr, u8 val, u32 flags) = 0; - virtual bool DataWrite16(u32 addr, u16 val, u32 flags) = 0; - virtual bool DataWrite32(u32 addr, u32 val, u32 flags) = 0; + virtual void DataRead8(u32 addr, u32* val) = 0; + virtual void DataRead16(u32 addr, u32* val) = 0; + virtual void DataRead32(u32 addr, u32* val) = 0; + virtual void DataRead32S(u32 addr, u32* val) = 0; + virtual void DataWrite8(u32 addr, u8 val) = 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_CI(s32 num) = 0; + virtual void AddCycles_CI(s32 numI) = 0; virtual void AddCycles_CDI() = 0; virtual void AddCycles_CD() = 0; @@ -131,9 +131,10 @@ public: s32 CyclesToRun; u32 Halted; - int CodeRegion; + u32 CodeRegion; + s32 CodeCycles; - int DataRegion; + u32 DataRegion; s32 DataCycles; u32 R[16]; // heh @@ -162,7 +163,7 @@ public: void DoSavestate(Savestate* file); - void CalculateTimings(); + void UpdateRegionTimings(u32 addrstart, u32 addrend); void JumpTo(u32 addr, bool restorecpsr = false); @@ -174,48 +175,52 @@ public: // all code accesses are forced nonseq 32bit u32 CodeRead32(u32 addr); - bool DataRead8(u32 addr, u32* val, u32 flags); - bool DataRead16(u32 addr, u32* val, u32 flags); - bool DataRead32(u32 addr, u32* val, u32 flags); - bool DataWrite8(u32 addr, u8 val, u32 flags); - bool DataWrite16(u32 addr, u16 val, u32 flags); - bool DataWrite32(u32 addr, u32 val, u32 flags); + void DataRead8(u32 addr, u32* val); + void DataRead16(u32 addr, u32* val); + void DataRead32(u32 addr, u32* val); + void DataRead32S(u32 addr, u32* val); + void DataWrite8(u32 addr, u8 val); + void DataWrite16(u32 addr, u16 val); + void DataWrite32(u32 addr, u32 val); + void DataWrite32S(u32 addr, u32 val); void AddCycles_C() { // 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 - Cycles += NDS::ARM9MemTimings[CodeRegion][2] + num; + s32 numC = (R[15] & 0x2) ? 0 : CodeCycles; + Cycles += numC + numI; } void AddCycles_CDI() { // LDR/LDM cycles. ARM9 seems to skip the internal cycle there. // 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; - if (DataRegion != CodeRegion) + //if (DataRegion != CodeRegion) Cycles += std::max(numC + numD - 6, std::max(numC, numD)); - else - Cycles += numC + numD; + //else + // Cycles += numC + numD; } void AddCycles_CD() { // 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; - if (DataRegion != CodeRegion) + //if (DataRegion != CodeRegion) Cycles += std::max(numC + numD - 6, std::max(numC, numD)); - else - Cycles += numC + numD; + //else + // Cycles += numC + numD; } void GetCodeMemRegion(u32 addr, NDS::MemRegion* region); @@ -250,14 +255,14 @@ public: u32 PU_Region[8]; // 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_Map; + u8 PU_UserMap[0x100000]; + + // games operate under system mode, generally #define PU_Map PU_PrivMap - bool CodeCached; + // code/16N/32N/32S + u8 MemTimings[0x100000][4]; }; class ARMv4 : public ARM @@ -265,122 +270,108 @@ class ARMv4 : public ARM public: ARMv4(); - void CalculateTimings(); - void JumpTo(u32 addr, bool restorecpsr = false); s32 Execute(); u16 CodeRead16(u32 addr) { - u32 ret; - CodeRegion = NDS::ARM7Read16(addr, &ret); - return ret; + return NDS::ARM7Read16(addr); } u32 CodeRead32(u32 addr) { - u32 ret; - CodeRegion = NDS::ARM7Read32(addr, &ret); - return ret; + return NDS::ARM7Read32(addr); } - bool DataRead8(u32 addr, u32* val, u32 flags) + void DataRead8(u32 addr, u32* val) { - DataRegion = NDS::ARM7Read8(addr, val); - if (flags & RWFlags_Nonseq) - DataCycles = NDS::ARM7MemTimings[DataRegion][0]; - else - DataCycles += NDS::ARM7MemTimings[DataRegion][1]; - - return true; + *val = NDS::ARM7Read8(addr); + DataRegion = addr >> 24; + DataCycles = NDS::ARM7MemTimings[DataRegion][0]; } - bool DataRead16(u32 addr, u32* val, u32 flags) + void DataRead16(u32 addr, u32* val) { addr &= ~1; - DataRegion = NDS::ARM7Read16(addr, val); - if (flags & RWFlags_Nonseq) - DataCycles = NDS::ARM7MemTimings[DataRegion][0]; - else - DataCycles += NDS::ARM7MemTimings[DataRegion][1]; - - return true; + *val = NDS::ARM7Read16(addr); + DataRegion = addr >> 24; + DataCycles = NDS::ARM7MemTimings[DataRegion][0]; } - bool DataRead32(u32 addr, u32* val, u32 flags) + void DataRead32(u32 addr, u32* val) { addr &= ~3; - DataRegion = NDS::ARM7Read32(addr, val); - if (flags & RWFlags_Nonseq) - DataCycles = NDS::ARM7MemTimings[DataRegion][2]; - else - DataCycles += NDS::ARM7MemTimings[DataRegion][3]; - - return true; + *val = NDS::ARM7Read32(addr); + DataRegion = addr >> 24; + DataCycles = NDS::ARM7MemTimings[DataRegion][2]; } - bool DataWrite8(u32 addr, u8 val, u32 flags) + void DataRead32S(u32 addr, u32* val) { - DataRegion = NDS::ARM7Write8(addr, val); - if (flags & RWFlags_Nonseq) - DataCycles = NDS::ARM7MemTimings[DataRegion][0]; - else - DataCycles += NDS::ARM7MemTimings[DataRegion][1]; + addr &= ~3; - 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) { - addr &= ~1; + NDS::ARM7Write8(addr, val); + DataRegion = addr >> 24; + DataCycles = NDS::ARM7MemTimings[DataRegion][0]; + } - DataRegion = NDS::ARM7Write16(addr, val); - if (flags & RWFlags_Nonseq) - DataCycles = NDS::ARM7MemTimings[DataRegion][0]; - else - DataCycles += NDS::ARM7MemTimings[DataRegion][1]; + void DataWrite16(u32 addr, u16 val) + { + addr &= ~1; - return true; + NDS::ARM7Write16(addr, val); + DataRegion = addr >> 24; + DataCycles = NDS::ARM7MemTimings[DataRegion][0]; } - bool DataWrite32(u32 addr, u32 val, u32 flags) + void DataWrite32(u32 addr, u32 val) { addr &= ~3; - DataRegion = NDS::ARM7Write32(addr, val); - if (flags & RWFlags_Nonseq) - DataCycles = NDS::ARM7MemTimings[DataRegion][2]; - else - DataCycles += NDS::ARM7MemTimings[DataRegion][3]; + NDS::ARM7Write32(addr, val); + DataRegion = addr >> 24; + DataCycles = NDS::ARM7MemTimings[DataRegion][2]; + } + + void DataWrite32S(u32 addr, u32 val) + { + addr &= ~3; - return true; + NDS::ARM7Write32(addr, val); + DataCycles += NDS::ARM7MemTimings[DataRegion][3]; } void AddCycles_C() { // 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) { // 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() { // LDR/LDM cycles. - s32 numC = NDS::ARM7MemTimings[CodeRegion][(CPSR&0x20)?0:2]; + s32 numC = NDS::ARM7MemTimings[CodeCycles][(CPSR&0x20)?0:2]; s32 numD = DataCycles; - if (DataRegion == NDS::Region7_MainRAM) + if (DataRegion == 0x02) // mainRAM { - if (CodeRegion == NDS::Region7_MainRAM) + if (CodeRegion == 0x02) Cycles += numC + numD; else { @@ -388,7 +379,7 @@ public: Cycles += std::max(numC + numD - 3, std::max(numC, numD)); } } - else if (CodeRegion == NDS::Region7_MainRAM) + else if (CodeRegion == 0x02) { numD++; Cycles += std::max(numC + numD - 3, std::max(numC, numD)); @@ -402,17 +393,17 @@ public: void AddCycles_CD() { // 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; - if (DataRegion == NDS::Region7_MainRAM) + if (DataRegion == 0x02) { - if (CodeRegion == NDS::Region7_MainRAM) + if (CodeRegion == 0x02) Cycles += numC + numD; else 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)); } diff --git a/src/ARMInterpreter_LoadStore.cpp b/src/ARMInterpreter_LoadStore.cpp index b34a341..5a1b88d 100644 --- a/src/ARMInterpreter_LoadStore.cpp +++ b/src/ARMInterpreter_LoadStore.cpp @@ -62,32 +62,33 @@ namespace ARMInterpreter #define A_STR \ 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; \ cpu->AddCycles_CD(); +// TODO: user mode (bit21) #define A_STR_POST \ 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->AddCycles_CD(); #define A_STRB \ 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; \ cpu->AddCycles_CD(); +// TODO: user mode (bit21) #define A_STRB_POST \ 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->AddCycles_CD(); #define A_LDR \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - u32 val; \ - if (!cpu->DataRead32(offset, &val, RWFlags_Nonseq)) return; \ + u32 val; cpu->DataRead32(offset, &val); \ val = ROR(val, ((offset&0x3)<<3)); \ if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ cpu->AddCycles_CDI(); \ @@ -101,10 +102,10 @@ namespace ARMInterpreter cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \ } +// TODO: user mode #define A_LDR_POST \ u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - u32 val; \ - if (!cpu->DataRead32(addr, &val, RWFlags_Nonseq | (cpu->CurInstr & (1<<21)))) return; \ + u32 val; cpu->DataRead32(addr, &val); \ val = ROR(val, ((addr&0x3)<<3)); \ cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \ cpu->AddCycles_CDI(); \ @@ -120,17 +121,16 @@ namespace ARMInterpreter #define A_LDRB \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - u32 val; \ - if (!cpu->DataRead8(offset, &val, RWFlags_Nonseq)) return; \ + u32 val; cpu->DataRead8(offset, &val); \ if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ cpu->AddCycles_CDI(); \ cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \ if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRB PC %08X\n", cpu->R[15]); \ +// TODO: user mode #define A_LDRB_POST \ u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - u32 val; \ - if (!cpu->DataRead8(addr, &val, RWFlags_Nonseq | (cpu->CurInstr & (1<<21)))) return; \ + u32 val; cpu->DataRead8(addr, &val); \ cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \ cpu->AddCycles_CDI(); \ cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \ @@ -219,13 +219,13 @@ A_IMPLEMENT_WB_LDRSTR(LDRB) #define A_STRH \ 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; \ cpu->AddCycles_CD(); #define A_STRH_POST \ 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->AddCycles_CD(); @@ -236,9 +236,9 @@ A_IMPLEMENT_WB_LDRSTR(LDRB) offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ u32 r = (cpu->CurInstr>>12) & 0xF; \ - if (r&1) printf("!! MISALIGNED LDRD %d\n", r); \ - if (!cpu->DataRead32(offset , &cpu->R[r ], RWFlags_Nonseq)) return; \ - if (!cpu->DataRead32(offset+4, &cpu->R[r+1], 0)) return; \ + if (r&1) { r--; printf("!! MISALIGNED LDRD_POST %d\n", r); } \ + cpu->DataRead32 (offset , &cpu->R[r ]); \ + cpu->DataRead32S(offset+4, &cpu->R[r+1]); \ cpu->AddCycles_CDI(); #define A_LDRD_POST \ @@ -246,9 +246,9 @@ A_IMPLEMENT_WB_LDRSTR(LDRB) u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \ u32 r = (cpu->CurInstr>>12) & 0xF; \ - if (r&1) printf("!! MISALIGNED LDRD_POST %d\n", r); \ - if (!cpu->DataRead32(addr , &cpu->R[r ], RWFlags_Nonseq)) return; \ - if (!cpu->DataRead32(addr+4, &cpu->R[r+1], 0)) return; \ + if (r&1) { r--; printf("!! MISALIGNED LDRD_POST %d\n", r); } \ + cpu->DataRead32 (addr , &cpu->R[r ]); \ + cpu->DataRead32S(addr+4, &cpu->R[r+1]); \ cpu->AddCycles_CDI(); #define A_STRD \ @@ -256,38 +256,38 @@ A_IMPLEMENT_WB_LDRSTR(LDRB) offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ u32 r = (cpu->CurInstr>>12) & 0xF; \ - if (r&1) printf("!! MISALIGNED STRD %d\n", r); \ - if (!cpu->DataWrite32(offset , cpu->R[r ], RWFlags_Nonseq)) return; \ - if (!cpu->DataWrite32(offset+4, cpu->R[r+1], 0)) return; \ + if (r&1) { r--; printf("!! MISALIGNED LDRD_POST %d\n", r); } \ + cpu->DataWrite32 (offset , cpu->R[r ]); \ + cpu->DataWrite32S(offset+4, cpu->R[r+1]); \ cpu->AddCycles_CD(); #define A_STRD_POST \ if (cpu->Num != 0) return; \ cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \ u32 r = (cpu->CurInstr>>12) & 0xF; \ - if (r&1) printf("!! MISALIGNED STRD_POST %d\n", r); \ - if (!cpu->DataWrite32(offset , cpu->R[r ], RWFlags_Nonseq)) return; \ - if (!cpu->DataWrite32(offset+4, cpu->R[r+1], 0)) return; \ + if (r&1) { r--; printf("!! MISALIGNED LDRD_POST %d\n", r); } \ + cpu->DataWrite32 (offset , cpu->R[r ]); \ + cpu->DataWrite32S(offset+4, cpu->R[r+1]); \ cpu->AddCycles_CD(); #define A_LDRH \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ 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(); \ if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRH PC %08X\n", cpu->R[15]); \ #define A_LDRH_POST \ u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ 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(); \ if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRH PC %08X\n", cpu->R[15]); \ #define A_LDRSB \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ 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->AddCycles_CDI(); \ 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 \ u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ 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->AddCycles_CDI(); \ 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 \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ 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->AddCycles_CDI(); \ 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 \ u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ 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->AddCycles_CDI(); \ 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 val; - if (!cpu->DataRead32(base, &val, RWFlags_Nonseq)) return; + cpu->DataRead32(base, &val); cpu->R[(cpu->CurInstr >> 12) & 0xF] = ROR(val, 8*(base&0x3)); u32 numD = cpu->DataCycles; - if (!cpu->DataWrite32(base, rm, RWFlags_Nonseq)) return; + cpu->DataWrite32(base, rm); cpu->DataCycles += numD; cpu->AddCycles_CDI(); @@ -372,10 +372,10 @@ void A_SWPB(ARM* cpu) u32 base = cpu->R[(cpu->CurInstr >> 16) & 0xF]; 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; - if (!cpu->DataWrite8(base, rm, RWFlags_Nonseq)) return; + cpu->DataWrite8(base, rm); cpu->DataCycles += numD; cpu->AddCycles_CDI(); @@ -389,7 +389,7 @@ void A_LDM(ARM* cpu) u32 base = cpu->R[baseid]; u32 wbbase; u32 preinc = (cpu->CurInstr & (1<<24)); - u32 flags = RWFlags_Nonseq; + bool first = true; if (!(cpu->CurInstr & (1<<23))) { @@ -416,8 +416,9 @@ void A_LDM(ARM* cpu) if (cpu->CurInstr & (1<<i)) { if (preinc) base += 4; - if (!cpu->DataRead32(base, &cpu->R[i], flags)) return; - flags &= ~RWFlags_Nonseq; + if (first) cpu->DataRead32 (base, &cpu->R[i]); + else cpu->DataRead32S(base, &cpu->R[i]); + first = false; if (!preinc) base += 4; } } @@ -426,7 +427,8 @@ void A_LDM(ARM* cpu) { u32 pc; 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 (cpu->Num == 1) @@ -466,7 +468,7 @@ void A_STM(ARM* cpu) u32 base = cpu->R[baseid]; u32 oldbase = base; u32 preinc = (cpu->CurInstr & (1<<24)); - u32 flags = RWFlags_Nonseq; + bool first = true; if (!(cpu->CurInstr & (1<<23))) { @@ -500,19 +502,17 @@ void A_STM(ARM* cpu) { if (preinc) base += 4; - bool res; if (i == baseid && !isbanked) { 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 - res = cpu->DataWrite32(base, base, flags); // checkme + first ? cpu->DataWrite32(base, base) : cpu->DataWrite32S(base, base); // checkme } 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; - flags &= ~RWFlags_Nonseq; + first = false; if (!preinc) base += 4; } @@ -537,7 +537,7 @@ void A_STM(ARM* cpu) void T_LDR_PCREL(ARM* cpu) { 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(); } @@ -546,7 +546,7 @@ void T_LDR_PCREL(ARM* cpu) void T_STR_REG(ARM* cpu) { 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(); } @@ -554,7 +554,7 @@ void T_STR_REG(ARM* cpu) void T_STRB_REG(ARM* cpu) { 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(); } @@ -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 val; - if (!cpu->DataRead32(addr, &val, RWFlags_Nonseq)) return; + cpu->DataRead32(addr, &val); cpu->R[cpu->CurInstr & 0x7] = ROR(val, 8*(addr&0x3)); cpu->AddCycles_CDI(); @@ -573,7 +573,7 @@ void T_LDR_REG(ARM* cpu) void T_LDRB_REG(ARM* cpu) { 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(); } @@ -582,7 +582,7 @@ void T_LDRB_REG(ARM* cpu) void T_STRH_REG(ARM* cpu) { 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(); } @@ -590,7 +590,7 @@ void T_STRH_REG(ARM* cpu) void T_LDRSB_REG(ARM* cpu) { 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->AddCycles_CDI(); @@ -599,7 +599,7 @@ void T_LDRSB_REG(ARM* cpu) void T_LDRH_REG(ARM* cpu) { 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(); } @@ -607,7 +607,7 @@ void T_LDRH_REG(ARM* cpu) void T_LDRSH_REG(ARM* cpu) { 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->AddCycles_CDI(); @@ -619,7 +619,7 @@ void T_STR_IMM(ARM* cpu) u32 offset = (cpu->CurInstr >> 4) & 0x7C; 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(); } @@ -629,7 +629,7 @@ void T_LDR_IMM(ARM* cpu) offset += cpu->R[(cpu->CurInstr >> 3) & 0x7]; 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->AddCycles_CDI(); } @@ -639,7 +639,7 @@ void T_STRB_IMM(ARM* cpu) u32 offset = (cpu->CurInstr >> 6) & 0x1F; 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(); } @@ -648,7 +648,7 @@ void T_LDRB_IMM(ARM* cpu) u32 offset = (cpu->CurInstr >> 6) & 0x1F; 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(); } @@ -658,7 +658,7 @@ void T_STRH_IMM(ARM* cpu) u32 offset = (cpu->CurInstr >> 5) & 0x3E; 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(); } @@ -667,7 +667,7 @@ void T_LDRH_IMM(ARM* cpu) u32 offset = (cpu->CurInstr >> 5) & 0x3E; 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(); } @@ -677,7 +677,7 @@ void T_STR_SPREL(ARM* cpu) u32 offset = (cpu->CurInstr << 2) & 0x3FC; 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(); } @@ -686,7 +686,7 @@ void T_LDR_SPREL(ARM* cpu) u32 offset = (cpu->CurInstr << 2) & 0x3FC; 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(); } @@ -694,7 +694,7 @@ void T_LDR_SPREL(ARM* cpu) void T_PUSH(ARM* cpu) { int nregs = 0; - u32 flags = RWFlags_Nonseq; + bool first = true; for (int i = 0; i < 8; i++) { @@ -713,15 +713,17 @@ void T_PUSH(ARM* cpu) { if (cpu->CurInstr & (1<<i)) { - if (!cpu->DataWrite32(base, cpu->R[i], flags)) return; - flags &= ~RWFlags_Nonseq; + if (first) cpu->DataWrite32 (base, cpu->R[i]); + else cpu->DataWrite32S(base, cpu->R[i]); + first = false; base += 4; } } 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(); @@ -730,14 +732,15 @@ void T_PUSH(ARM* cpu) void T_POP(ARM* cpu) { u32 base = cpu->R[13]; - u32 flags = RWFlags_Nonseq; + bool first = true; for (int i = 0; i < 8; i++) { if (cpu->CurInstr & (1<<i)) { - if (!cpu->DataRead32(base, &cpu->R[i], flags)) return; - flags &= ~RWFlags_Nonseq; + if (first) cpu->DataRead32 (base, &cpu->R[i]); + else cpu->DataRead32S(base, &cpu->R[i]); + first = false; base += 4; } } @@ -745,7 +748,8 @@ void T_POP(ARM* cpu) if (cpu->CurInstr & (1<<8)) { 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; cpu->JumpTo(pc); base += 4; @@ -758,14 +762,15 @@ void T_POP(ARM* cpu) void T_STMIA(ARM* cpu) { u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7]; - u32 flags = RWFlags_Nonseq; + bool first = true; for (int i = 0; i < 8; i++) { if (cpu->CurInstr & (1<<i)) { - if (!cpu->DataWrite32(base, cpu->R[i], flags)) return; - flags &= ~RWFlags_Nonseq; + if (first) cpu->DataWrite32 (base, cpu->R[i]); + else cpu->DataWrite32S(base, cpu->R[i]); + first = false; base += 4; } } @@ -778,14 +783,15 @@ void T_STMIA(ARM* cpu) void T_LDMIA(ARM* cpu) { u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7]; - u32 flags = RWFlags_Nonseq; + bool first = true; for (int i = 0; i < 8; i++) { if (cpu->CurInstr & (1<<i)) { - if (!cpu->DataRead32(base, &cpu->R[i], flags)) return; - flags &= ~RWFlags_Nonseq; + if (first) cpu->DataRead32 (base, &cpu->R[i]); + else cpu->DataRead32S(base, &cpu->R[i]); + first = false; base += 4; } } diff --git a/src/CP15.cpp b/src/CP15.cpp index 0665137..0d1be76 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -22,6 +22,11 @@ #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() { @@ -211,6 +216,47 @@ void ARMv5::UpdatePURegions() codecache >>= 1; datacache >>= 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) { - u8 pu = PU_Map[addr>>12]; - if (addr < ITCMSize) { - CodeRegion = NDS::Region9_ITCM; return *(u32*)&ITCM[addr & 0x7FFF]; } - u32 ret; - CodeRegion = NDS::ARM9Read32(addr, &ret); - if (pu & 0x40) CodeRegion = NDS::Region9_ICache; - return ret; + return NDS::ARM9Read32(addr); } -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) { - DataRegion = NDS::Region9_ITCM; - if (flags & RWFlags_Nonseq) DataCycles = 1; - else DataCycles += 1; + DataCycles = 1; *val = *(u8*)&ITCM[addr & 0x7FFF]; - return true; + return; } if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize)) { - DataRegion = NDS::Region9_DTCM; - if (flags & RWFlags_Nonseq) DataCycles = 1; - else DataCycles += 1; + DataCycles = 1; *val = *(u8*)&DTCM[(addr - DTCMBase) & 0x3FFF]; - return true; + return; } - DataRegion = NDS::ARM9Read8(addr, val); - if (pu & 0x10) - { - 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; + *val = NDS::ARM9Read8(addr); + DataCycles = MemTimings[addr >> 12][1]; } -bool ARMv5::DataRead16(u32 addr, u32* val, u32 flags) +void ARMv5::DataRead16(u32 addr, u32* val) { addr &= ~1; - u8 pu = PU_Map[addr>>12]; - /*if (!(pu & 0x01)) - { - DataAbort(); - return false; - }*/ - if (addr < ITCMSize) { - DataRegion = NDS::Region9_ITCM; - if (flags & RWFlags_Nonseq) DataCycles = 1; - else DataCycles += 1; + DataCycles = 1; *val = *(u16*)&ITCM[addr & 0x7FFF]; - return true; + return; } if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize)) { - DataRegion = NDS::Region9_DTCM; - if (flags & RWFlags_Nonseq) DataCycles = 1; - else DataCycles += 1; + DataCycles = 1; *val = *(u16*)&DTCM[(addr - DTCMBase) & 0x3FFF]; - return true; + return; } - DataRegion = NDS::ARM9Read16(addr, val); - if (pu & 0x10) - { - 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; + *val = NDS::ARM9Read16(addr); + DataCycles = MemTimings[addr >> 12][1]; } -bool ARMv5::DataRead32(u32 addr, u32* val, u32 flags) +void ARMv5::DataRead32(u32 addr, u32* val) { addr &= ~3; - u8 pu = PU_Map[addr>>12]; - /*if (!(pu & 0x01)) - { - DataAbort(); - return false; - }*/ - if (addr < ITCMSize) { - DataRegion = NDS::Region9_ITCM; - if (flags & RWFlags_Nonseq) DataCycles = 1; - else DataCycles += 1; + DataCycles = 1; *val = *(u32*)&ITCM[addr & 0x7FFF]; - return true; + return; } if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize)) { - DataRegion = NDS::Region9_DTCM; - if (flags & RWFlags_Nonseq) DataCycles = 1; - else DataCycles += 1; + DataCycles = 1; *val = *(u32*)&DTCM[(addr - DTCMBase) & 0x3FFF]; - return true; + return; } - DataRegion = NDS::ARM9Read32(addr, val); - if (pu & 0x10) + *val = NDS::ARM9Read32(addr); + DataCycles = MemTimings[addr >> 12][2]; +} + +void ARMv5::DataRead32S(u32 addr, u32* val) +{ + addr &= ~3; + + if (addr < ITCMSize) { - DataRegion = NDS::Region9_DCache; - if (flags & RWFlags_Nonseq) DataCycles = 2; - else DataCycles += 2; + DataCycles += 1; + *val = *(u32*)&ITCM[addr & 0x7FFF]; + return; } - else + if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize)) { - if (flags & RWFlags_Nonseq) DataCycles = NDS::ARM9MemTimings[DataRegion][0]; - else DataCycles += NDS::ARM9MemTimings[DataRegion][1]; + DataCycles += 1; + *val = *(u32*)&DTCM[(addr - DTCMBase) & 0x3FFF]; + return; } - return true; + + *val = NDS::ARM9Read32(addr); + DataCycles += MemTimings[addr >> 12][3]; } -bool ARMv5::DataWrite8(u32 addr, u8 val, u32 flags) +void ARMv5::DataWrite8(u32 addr, u8 val) { - u8 pu = PU_Map[addr>>12]; - /*if (!(pu & 0x02)) - { - DataAbort(); - return false; - }*/ - if (addr < ITCMSize) { - DataRegion = NDS::Region9_ITCM; - if (flags & RWFlags_Nonseq) DataCycles = 1; - else DataCycles += 1; + DataCycles = 1; *(u8*)&ITCM[addr & 0x7FFF] = val; - return true; + return; } if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize)) { - DataRegion = NDS::Region9_DTCM; - if (flags & RWFlags_Nonseq) DataCycles = 1; - else DataCycles += 1; + DataCycles = 1; *(u8*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val; - return true; + return; } - DataRegion = NDS::ARM9Write8(addr, val); - if (pu & 0x20) - { - 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; + NDS::ARM9Write8(addr, val); + DataCycles = MemTimings[addr >> 12][1]; } -bool ARMv5::DataWrite16(u32 addr, u16 val, u32 flags) +void ARMv5::DataWrite16(u32 addr, u16 val) { addr &= ~1; - u8 pu = PU_Map[addr>>12]; - /*if (!(pu & 0x02)) - { - DataAbort(); - return false; - }*/ - if (addr < ITCMSize) { - DataRegion = NDS::Region9_ITCM; - if (flags & RWFlags_Nonseq) DataCycles = 1; - else DataCycles += 1; + DataCycles = 1; *(u16*)&ITCM[addr & 0x7FFF] = val; - return true; + return; } if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize)) { - DataRegion = NDS::Region9_DTCM; - if (flags & RWFlags_Nonseq) DataCycles = 1; - else DataCycles += 1; + DataCycles = 1; *(u16*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val; - return true; + return; } - DataRegion = NDS::ARM9Write16(addr, val); - if (pu & 0x20) - { - 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; + NDS::ARM9Write16(addr, val); + DataCycles = MemTimings[addr >> 12][1]; } -bool ARMv5::DataWrite32(u32 addr, u32 val, u32 flags) +void ARMv5::DataWrite32(u32 addr, u32 val) { addr &= ~3; - u8 pu = PU_Map[addr>>12]; - /*if (!(pu & 0x02)) - { - DataAbort(); - return false; - }*/ - if (addr < ITCMSize) { - DataRegion = NDS::Region9_ITCM; - if (flags & RWFlags_Nonseq) DataCycles = 1; - else DataCycles += 1; + DataCycles = 1; *(u32*)&ITCM[addr & 0x7FFF] = val; - return true; + return; } if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize)) { - DataRegion = NDS::Region9_DTCM; - if (flags & RWFlags_Nonseq) DataCycles = 1; - else DataCycles += 1; + DataCycles = 1; *(u32*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val; - return true; + return; } - DataRegion = NDS::ARM9Write32(addr, val); - if (pu & 0x20) + NDS::ARM9Write32(addr, val); + DataCycles = MemTimings[addr >> 12][2]; +} + +void ARMv5::DataWrite32S(u32 addr, u32 val) +{ + addr &= ~3; + + if (addr < ITCMSize) { - DataRegion = NDS::Region9_DCache; - if (flags & RWFlags_Nonseq) DataCycles = 2; - else DataCycles += 2; + DataCycles += 1; + *(u32*)&ITCM[addr & 0x7FFF] = val; + return; } - else + if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize)) { - if (flags & RWFlags_Nonseq) DataCycles = NDS::ARM9MemTimings[DataRegion][0]; - else DataCycles += NDS::ARM9MemTimings[DataRegion][1]; + DataCycles += 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) { if (addr < ITCMSize) { - region->Region = NDS::Region9_ITCM; region->Mem = ITCM; region->Mask = 0x7FFF; return; diff --git a/src/DMA.cpp b/src/DMA.cpp index 6bdc71d..90eb910 100644 --- a/src/DMA.cpp +++ b/src/DMA.cpp @@ -203,17 +203,17 @@ s32 DMA::Run(s32 cycles) { 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 { - 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)) unitcycles++; 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; } } @@ -222,38 +222,38 @@ s32 DMA::Run(s32 cycles) { 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 { - 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)) unitcycles++; 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; } } } - int (*readfn)(u32,u32*) = CPU ? NDS::ARM7Read16 : NDS::ARM9Read16; - int (*writefn)(u32,u16) = CPU ? NDS::ARM7Write16 : NDS::ARM9Write16; + u16 (*readfn)(u32) = CPU ? NDS::ARM7Read16 : NDS::ARM9Read16; + void (*writefn)(u32,u16) = CPU ? NDS::ARM7Write16 : NDS::ARM9Write16; - while (IterCount > 0 && cycles > 0 && !Stall) + while (IterCount > 0 && !Stall) { - u32 val; - readfn(CurSrcAddr, &val); - writefn(CurDstAddr, val); + writefn(CurDstAddr, readfn(CurSrcAddr)); cycles -= unitcycles; - NDS::RunTimingCriticalDevices(CPU, c); + NDS::RunTimingCriticalDevices(CPU, unitcycles); CurSrcAddr += SrcAddrInc<<1; CurDstAddr += DstAddrInc<<1; IterCount--; RemCount--; + + if (cycles < 0) break; } } else @@ -263,11 +263,11 @@ s32 DMA::Run(s32 cycles) { 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 { - 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)) unitcycles++; else if ((CurSrcAddr >> 24) == 0x02) @@ -275,7 +275,7 @@ s32 DMA::Run(s32 cycles) 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; } } @@ -284,11 +284,11 @@ s32 DMA::Run(s32 cycles) { 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 { - 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)) unitcycles++; else if ((CurSrcAddr >> 24) == 0x02) @@ -296,28 +296,28 @@ s32 DMA::Run(s32 cycles) 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; } } } - int (*readfn)(u32,u32*) = CPU ? NDS::ARM7Read32 : NDS::ARM9Read32; - int (*writefn)(u32,u32) = CPU ? NDS::ARM7Write32 : NDS::ARM9Write32; + u32 (*readfn)(u32) = CPU ? NDS::ARM7Read32 : NDS::ARM9Read32; + void (*writefn)(u32,u32) = CPU ? NDS::ARM7Write32 : NDS::ARM9Write32; - while (IterCount > 0 && cycles > 0 && !Stall) + while (IterCount > 0 && !Stall) { - u32 val; - readfn(CurSrcAddr, &val); - writefn(CurDstAddr, val); + writefn(CurDstAddr, readfn(CurSrcAddr)); cycles -= unitcycles; - NDS::RunTimingCriticalDevices(CPU, c); + NDS::RunTimingCriticalDevices(CPU, unitcycles); CurSrcAddr += SrcAddrInc<<2; CurDstAddr += DstAddrInc<<2; IterCount--; RemCount--; + + if (cycles < 0) break; } } diff --git a/src/GPU.cpp b/src/GPU.cpp index 9d79848..7da78a9 100644 --- a/src/GPU.cpp +++ b/src/GPU.cpp @@ -813,7 +813,7 @@ void StartScanline(u32 line) GPU2D_A->VBlank(); GPU2D_B->VBlank(); GPU3D::VBlank(); - printf("VBlank. PC=%08X\n", NDS::GetPC(0)); + //printf("VBlank. PC=%08X\n", NDS::GetPC(0)); } else if (VCount == 144) { diff --git a/src/NDS.cpp b/src/NDS.cpp index daed205..12cd8a5 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -56,7 +56,7 @@ namespace NDS // // timings for GBA slot and wifi are set up at runtime -u8 ARM9MemTimings[0x100000][4]; +u8 ARM9MemTimings[0x40000][4]; u8 ARM7MemTimings[0x20000][4]; ARMv5* ARM9; @@ -134,6 +134,8 @@ bool Running; void DivDone(u32 param); void SqrtDone(u32 param); void RunTimer(u32 tid, s32 cycles); +void SetWifiWaitCnt(u16 val); +void SetGBASlotTimings(); bool Init() @@ -185,10 +187,10 @@ void DeInit() void SetARM9RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, int seq) { - addrstart >>= 12; - addrend >>= 12; + addrstart >>= 14; + addrend >>= 14; - if (addrend == 0xFFFFF) addrend++; + if (addrend == 0x3FFFF) addrend++; int N16, S16, N32, S32; N16 = nonseq; @@ -211,12 +213,14 @@ void SetARM9RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, ARM9MemTimings[i][2] = N32; ARM9MemTimings[i][3] = S32; } + + ARM9->UpdateRegionTimings(addrstart<<14, addrend<<14); } void SetARM7RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, int seq) { - addrstart >>= 17; - addrend >>= 17; + addrstart >>= 15; + addrend >>= 15; if (addrend == 0x1FFFF) addrend++; @@ -400,6 +404,9 @@ void Reset() fclose(f); } + ARM9->SetClockShift(1); + ARM7->SetClockShift(0); + InitTimings(); memset(MainRAM, 0, MAIN_RAM_SIZE); @@ -469,9 +476,6 @@ void Reset() SPI::Reset(); RTC::Reset(); Wifi::Reset(); - - ARM9->SetClockShift(1); - ARM7->SetClockShift(0); } void Stop() @@ -1449,7 +1453,7 @@ u16 ARM9Read16(u32 addr) return 0; } -int ARM9Read32(u32 addr, u32* val) +u32 ARM9Read32(u32 addr) { if ((addr & 0xFFFFF000) == 0xFFFF0000) { @@ -1739,7 +1743,7 @@ u16 ARM7Read16(u32 addr) return 0; } -int ARM7Read32(u32 addr, u32* val) +u32 ARM7Read32(u32 addr) { if (addr < 0x00004000) { @@ -94,7 +94,7 @@ typedef struct } MemRegion; -extern u8 ARM9MemTimings[0x100000][4]; +extern u8 ARM9MemTimings[0x40000][4]; extern u8 ARM7MemTimings[0x20000][4]; // hax |