Added check of op1 in MCR/MRC

Fixed Cache Debug registers were accessible, when op1 != 3 in MCR/MRC instructions
Added BIST Test Status register and its cache linefill disable bits
This commit is contained in:
DesperateProgrammer 2024-02-01 13:15:03 +01:00
parent 81c9434116
commit 9fa814b68e
4 changed files with 71 additions and 12 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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;
}

View File

@ -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);