diff --git a/src/ARM.h b/src/ARM.h index e56534ad..abb0e686 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -343,6 +343,7 @@ public: u32 DCacheLockDown, ICacheLockDown; u32 CacheDebugRegisterIndex; u32 CP15TraceProcessId; + u32 CP15BISTTestStateRegister; // for aarch64 JIT they need to go up here // to be addressable by a 12-bit immediate diff --git a/src/ARMInterpreter.cpp b/src/ARMInterpreter.cpp index ff73e230..316db0a2 100644 --- a/src/ARMInterpreter.cpp +++ b/src/ARMInterpreter.cpp @@ -212,14 +212,14 @@ void A_MCR(ARM* cpu) return A_UNK(cpu); u32 cp = (cpu->CurInstr >> 8) & 0xF; - //u32 op = (cpu->CurInstr >> 21) & 0x7; + u32 op = (cpu->CurInstr >> 21) & 0x7; u32 cn = (cpu->CurInstr >> 16) & 0xF; u32 cm = cpu->CurInstr & 0xF; u32 cpinfo = (cpu->CurInstr >> 5) & 0x7; if (cpu->Num==0 && cp==15) { - ((ARMv5*)cpu)->CP15Write((cn<<8)|(cm<<4)|cpinfo, cpu->R[(cpu->CurInstr>>12)&0xF]); + ((ARMv5*)cpu)->CP15Write((cn<<8)|(cm<<4)|cpinfo|(op<<12), cpu->R[(cpu->CurInstr>>12)&0xF]); } else if (cpu->Num==1 && cp==14) { @@ -227,7 +227,7 @@ void A_MCR(ARM* cpu) } else { - Log(LogLevel::Warn, "bad MCR opcode p%d,%d,%d,%d on ARM%d\n", cp, cn, cm, cpinfo, cpu->Num?7:9); + Log(LogLevel::Warn, "bad MCR opcode p%d, %d, reg, c%d, c%d, %d on ARM%d\n", cp, op, cn, cm, cpinfo, cpu->Num?7:9); return A_UNK(cpu); // TODO: check what kind of exception it really is } @@ -240,14 +240,14 @@ void A_MRC(ARM* cpu) return A_UNK(cpu); u32 cp = (cpu->CurInstr >> 8) & 0xF; - //u32 op = (cpu->CurInstr >> 21) & 0x7; + u32 op = (cpu->CurInstr >> 21) & 0x7; u32 cn = (cpu->CurInstr >> 16) & 0xF; u32 cm = cpu->CurInstr & 0xF; u32 cpinfo = (cpu->CurInstr >> 5) & 0x7; if (cpu->Num==0 && cp==15) { - cpu->R[(cpu->CurInstr>>12)&0xF] = ((ARMv5*)cpu)->CP15Read((cn<<8)|(cm<<4)|cpinfo); + cpu->R[(cpu->CurInstr>>12)&0xF] = ((ARMv5*)cpu)->CP15Read((cn<<8)|(cm<<4)|cpinfo|(op<<12)); } else if (cpu->Num==1 && cp==14) { @@ -255,7 +255,7 @@ void A_MRC(ARM* cpu) } else { - Log(LogLevel::Warn, "bad MRC opcode p%d,%d,%d,%d on ARM%d\n", cp, cn, cm, cpinfo, cpu->Num?7:9); + Log(LogLevel::Warn, "bad MRC opcode p%d, %d, reg, c%d, c%d, %d on ARM%d\n", cp, op, cn, cm, cpinfo, cpu->Num?7:9); return A_UNK(cpu); // TODO: check what kind of exception it really is } diff --git a/src/CP15.cpp b/src/CP15.cpp index caa8de34..f6f11a7a 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -69,6 +69,7 @@ void ARMv5::CP15Reset() ICacheLockDown = 0; DCacheLockDown = 0; CacheDebugRegisterIndex = 0; + CP15BISTTestStateRegister = 0; memset(ICache, 0, ICACHE_SIZE); ICacheInvalidateAll(); @@ -116,6 +117,7 @@ void ARMv5::CP15DoSavestate(Savestate* file) file->Var32(&ICacheLockDown); file->Var32(&CacheDebugRegisterIndex); file->Var32(&CP15TraceProcessId); + file->Var32(&CP15BISTTestStateRegister); file->Var32(&PU_CodeCacheable); file->Var32(&PU_DataCacheable); @@ -384,6 +386,21 @@ u32 ARMv5::ICacheLookup(const u32 addr) } // cache miss + + // We do not fill the cacheline if it is disabled in the + // BIST test State register (See arm946e-s Rev 1 technical manual, 2.3.15 "Register 15, test State Register") + if (CP15BISTTestStateRegister & CP15_BIST_TR_DISABLE_ICACHE_LINEFILL) + { + CodeCycles = NDS.ARM9MemTimings[tag >> 14][2]; + if (CodeMem.Mem) + { + return *(u32*)&CodeMem.Mem[(addr & CodeMem.Mask) & ~3]; + } else + { + return NDS.ARM9Read32(addr & ~3); + } + } + u32 line; #if 0 // caclulate in which cacheline the data is to be filled @@ -507,6 +524,25 @@ u32 ARMv5::DCacheLookup(const u32 addr) } // cache miss + + // We do not fill the cacheline if it is disabled in the + // BIST test State register (See arm946e-s Rev 1 technical manual, 2.3.15 "Register 15, test State Register") + if (CP15BISTTestStateRegister & CP15_BIST_TR_DISABLE_DCACHE_LINEFILL) + { + DataCycles = NDS.ARM9MemTimings[tag >> 14][2]; + if (addr < ITCMSize) + { + return *(u32*)&ITCM[addr & (ITCMPhysicalSize - 3)]; + } else + if ((addr & DTCMMask) == DTCMBase) + { + return *(u32*)&DTCM[addr & (DTCMPhysicalSize - 3)]; + } else + { + return BusRead32(addr & ~3); + } + } + u32 line; #if 0 // caclulate in which cacheline the data is to be filled @@ -694,7 +730,7 @@ void ARMv5::CP15Write(u32 id, u32 val) { //if(id!=0x704)printf("CP15 write op %03X %08X %08X\n", id, val, R[15]); - switch (id) + switch (id & 0xFFF) { case 0x100: { @@ -1112,7 +1148,20 @@ void ARMv5::CP15Write(u32 id, u32 val) else return ARMInterpreter::A_UNK(this); } else - CacheDebugRegisterIndex = val; + { + if (((id >> 12) & 0x0f) == 0x03) + CacheDebugRegisterIndex = val; + else if (((id >> 12) & 0x0f) == 0x00) + CP15BISTTestStateRegister = val; + else + { + if (CPSR & 0x20) // THUMB + return ARMInterpreter::T_UNK(this); + else + return ARMInterpreter::A_UNK(this); + } + + } return; case 0xF10: @@ -1184,14 +1233,14 @@ void ARMv5::CP15Write(u32 id, u32 val) } - Log(LogLevel::Debug, "unknown CP15 write op %03X %08X\n", id, val); + Log(LogLevel::Debug, "unknown CP15 write op %04X %08X\n", id, val); } u32 ARMv5::CP15Read(u32 id) const { //printf("CP15 read op %03X %08X\n", id, NDS::ARM9->R[15]); - switch (id) + switch (id & 0xFFF) { case 0x000: // CPU ID case 0x003: @@ -1304,7 +1353,12 @@ u32 ARMv5::CP15Read(u32 id) const { return 0; } else - return CacheDebugRegisterIndex; + { + if (((id >> 12) & 0x0f) == 0x03) + return CacheDebugRegisterIndex; + if (((id >> 12) & 0x0f) == 0x00) + return CP15BISTTestStateRegister; + } case 0xF10: // instruction cache Tag register if (PU_Map != PU_PrivMap) @@ -1351,7 +1405,7 @@ u32 ARMv5::CP15Read(u32 id) const } } - Log(LogLevel::Debug, "unknown CP15 read op %03X\n", id); + Log(LogLevel::Debug, "unknown CP15 read op %04X\n", id); return 0; } diff --git a/src/CP15_Constants.h b/src/CP15_Constants.h index 80fadf31..0d786afa 100644 --- a/src/CP15_Constants.h +++ b/src/CP15_Constants.h @@ -91,6 +91,10 @@ constexpr u32 CP15_CACHE_CR_ICACHEENABLE = (1 << 12); constexpr u32 CP15_CACHE_CR_DCACHEENABLE = (1 << 2); constexpr u32 CP15_CACHE_CR_WRITEBUFFERENABLE = (1 << 3); +/* CP15 BIST Test State register */ +constexpr u32 CP15_BIST_TR_DISABLE_ICACHE_LINEFILL = (1 << 9); +constexpr u32 CP15_BIST_TR_DISABLE_DCACHE_LINEFILL = (1 << 10); + /* CP15 TCM Control Register */ constexpr u32 CP15_TCM_CR_DTCM_ENABLE = (1 << 16); constexpr u32 CP15_TCM_CR_ITCM_ENABLE = (1 << 18);