improve implementation

This commit is contained in:
Jaklyy 2024-06-02 10:13:50 -04:00
parent 960f063eaa
commit 63d4b78733
4 changed files with 44 additions and 52 deletions

View File

@ -1168,21 +1168,23 @@ void ARMv4::DataRead16(u32 addr, u32* val)
DataCycles = NDS.ARM7MemTimings[addr >> 15][0]; DataCycles = NDS.ARM7MemTimings[addr >> 15][0];
} }
void ARMv4::DataRead32(u32 addr, u32* val) bool ARMv4::DataRead32(u32 addr, u32* val)
{ {
addr &= ~3; addr &= ~3;
*val = BusRead32(addr); *val = BusRead32(addr);
DataRegion = addr; DataRegion = addr;
DataCycles = NDS.ARM7MemTimings[addr >> 15][2]; DataCycles = NDS.ARM7MemTimings[addr >> 15][2];
return true;
} }
void ARMv4::DataRead32S(u32 addr, u32* val) bool ARMv4::DataRead32S(u32 addr, u32* val)
{ {
addr &= ~3; addr &= ~3;
*val = BusRead32(addr); *val = BusRead32(addr);
DataCycles += NDS.ARM7MemTimings[addr >> 15][3]; DataCycles += NDS.ARM7MemTimings[addr >> 15][3];
return true;
} }
void ARMv4::DataWrite8(u32 addr, u8 val) void ARMv4::DataWrite8(u32 addr, u8 val)

View File

@ -130,8 +130,8 @@ public:
virtual void DataRead8(u32 addr, u32* val) = 0; virtual void DataRead8(u32 addr, u32* val) = 0;
virtual void DataRead16(u32 addr, u32* val) = 0; virtual void DataRead16(u32 addr, u32* val) = 0;
virtual void DataRead32(u32 addr, u32* val) = 0; virtual bool DataRead32(u32 addr, u32* val) = 0;
virtual void DataRead32S(u32 addr, u32* val) = 0; virtual bool DataRead32S(u32 addr, u32* val) = 0;
virtual void DataWrite8(u32 addr, u8 val) = 0; virtual void DataWrite8(u32 addr, u8 val) = 0;
virtual void DataWrite16(u32 addr, u16 val) = 0; virtual void DataWrite16(u32 addr, u16 val) = 0;
virtual void DataWrite32(u32 addr, u32 val) = 0; virtual void DataWrite32(u32 addr, u32 val) = 0;
@ -251,8 +251,8 @@ public:
void DataRead8(u32 addr, u32* val) override; void DataRead8(u32 addr, u32* val) override;
void DataRead16(u32 addr, u32* val) override; void DataRead16(u32 addr, u32* val) override;
void DataRead32(u32 addr, u32* val) override; bool DataRead32(u32 addr, u32* val) override;
void DataRead32S(u32 addr, u32* val) override; bool DataRead32S(u32 addr, u32* val) override;
void DataWrite8(u32 addr, u8 val) override; void DataWrite8(u32 addr, u8 val) override;
void DataWrite16(u32 addr, u16 val) override; void DataWrite16(u32 addr, u16 val) override;
void DataWrite32(u32 addr, u32 val) override; void DataWrite32(u32 addr, u32 val) override;
@ -400,8 +400,8 @@ public:
void DataRead8(u32 addr, u32* val) override; void DataRead8(u32 addr, u32* val) override;
void DataRead16(u32 addr, u32* val) override; void DataRead16(u32 addr, u32* val) override;
void DataRead32(u32 addr, u32* val) override; bool DataRead32(u32 addr, u32* val) override;
void DataRead32S(u32 addr, u32* val) override; bool DataRead32S(u32 addr, u32* val) override;
void DataWrite8(u32 addr, u8 val) override; void DataWrite8(u32 addr, u8 val) override;
void DataWrite16(u32 addr, u16 val) override; void DataWrite16(u32 addr, u16 val) override;
void DataWrite32(u32 addr, u32 val) override; void DataWrite32(u32 addr, u32 val) override;

View File

@ -395,12 +395,14 @@ void A_LDM(ARM* cpu)
u32 baseid = (cpu->CurInstr >> 16) & 0xF; u32 baseid = (cpu->CurInstr >> 16) & 0xF;
u32 base = cpu->R[baseid]; u32 base = cpu->R[baseid];
u32 wbbase; u32 wbbase;
u32 oldbase = base;
u32 preinc = (cpu->CurInstr & (1<<24)); u32 preinc = (cpu->CurInstr & (1<<24));
bool first = true; bool first = true;
int abortreg = 16; bool dataabort = false;
if (!(cpu->CurInstr & (1<<23))) if (!(cpu->CurInstr & (1<<23))) // decrement
{ {
// decrement is actually an increment starting from the end address
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
if (cpu->CurInstr & (1<<i)) if (cpu->CurInstr & (1<<i))
@ -416,61 +418,43 @@ void A_LDM(ARM* cpu)
preinc = !preinc; preinc = !preinc;
} }
// check for data aborts // switch to user mode regs
if (cpu->Num == 0)
{
u32 tmpbase = base;
for (int i = 0; i < 16; i++)
{
if (cpu->CurInstr & (1<<i))
{
if (preinc) tmpbase += 4;
if(((ARMv5*)cpu)->PU_Map[tmpbase>>12] & 0x01)
{
if (!preinc) tmpbase += 4;
}
else
{
abortreg = i;
break;
}
}
}
}
if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15))) if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15)))
cpu->UpdateMode(cpu->CPSR, (cpu->CPSR&~0x1F)|0x10, true); cpu->UpdateMode(cpu->CPSR, (cpu->CPSR&~0x1F)|0x10, true);
for (int i = 0; i < std::min(15, abortreg); i++) for (int i = 0; i < 15; i++)
{ {
if (cpu->CurInstr & (1<<i)) if (cpu->CurInstr & (1<<i))
{ {
if (preinc) base += 4; if (preinc) base += 4;
if (first) cpu->DataRead32 (base, &cpu->R[i]); if (first) {if (!cpu->DataRead32 (base, &cpu->R[i])) {dataabort = true; goto abortjump;}}
else cpu->DataRead32S(base, &cpu->R[i]); else if (!cpu->DataRead32S(base, &cpu->R[i])) {dataabort = true; goto abortjump;}
first = false; first = false;
if (!preinc) base += 4; if (!preinc) base += 4;
} }
} }
u32 pc; u32 pc;
if ((cpu->CurInstr & (1<<15)) && (abortreg == 16)) if ((cpu->CurInstr & (1<<15)))
{ {
if (preinc) base += 4; if (preinc) base += 4;
if (first) cpu->DataRead32 (base, &pc); if (first) {if (!cpu->DataRead32 (base, &pc)) dataabort = true;}
else cpu->DataRead32S(base, &pc); else if (!cpu->DataRead32S(base, &pc)) dataabort = true;
if (!preinc) base += 4; if (!preinc) base += 4;
if (cpu->Num == 1) if (cpu->Num == 1)
pc &= ~0x1; pc &= ~0x1;
} }
abortjump:
// switch back to previous regs
if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15))) if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15)))
cpu->UpdateMode((cpu->CPSR&~0x1F)|0x10, cpu->CPSR, true); cpu->UpdateMode((cpu->CPSR&~0x1F)|0x10, cpu->CPSR, true);
// if it's 16 then there was no data abort if (!dataabort)
if (abortreg == 16)
{ {
// writeback to base
if (cpu->CurInstr & (1<<21)) if (cpu->CurInstr & (1<<21))
{ {
// post writeback // post writeback
@ -490,13 +474,11 @@ void A_LDM(ARM* cpu)
cpu->R[baseid] = wbbase; cpu->R[baseid] = wbbase;
} }
// jump if pc got written
if (cpu->CurInstr & (1<<15)) if (cpu->CurInstr & (1<<15))
cpu->JumpTo(pc, cpu->CurInstr & (1<<22)); cpu->JumpTo(pc, cpu->CurInstr & (1<<22));
} }
else else cpu->R[baseid] = oldbase; // restore original value of base in case the reg got written to
{
((ARMv5*)cpu)->DataAbort();
}
cpu->AddCycles_CDI(); cpu->AddCycles_CDI();
} }

View File

@ -863,12 +863,12 @@ void ARMv5::DataRead16(u32 addr, u32* val)
DataCycles = MemTimings[addr >> 12][1]; DataCycles = MemTimings[addr >> 12][1];
} }
void ARMv5::DataRead32(u32 addr, u32* val) bool ARMv5::DataRead32(u32 addr, u32* val)
{ {
if (!(PU_Map[addr>>12] & 0x01)) if (!(PU_Map[addr>>12] & 0x01))
{ {
DataAbort(); DataAbort();
return; return false;
} }
DataRegion = addr; DataRegion = addr;
@ -879,38 +879,46 @@ void ARMv5::DataRead32(u32 addr, u32* val)
{ {
DataCycles = 1; DataCycles = 1;
*val = *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)]; *val = *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)];
return; return true;
} }
if ((addr & DTCMMask) == DTCMBase) if ((addr & DTCMMask) == DTCMBase)
{ {
DataCycles = 1; DataCycles = 1;
*val = *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)]; *val = *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)];
return; return true;
} }
*val = BusRead32(addr); *val = BusRead32(addr);
DataCycles = MemTimings[addr >> 12][2]; DataCycles = MemTimings[addr >> 12][2];
return true;
} }
void ARMv5::DataRead32S(u32 addr, u32* val) bool ARMv5::DataRead32S(u32 addr, u32* val)
{ {
if (!(PU_Map[addr>>12] & 0x01))
{
DataAbort();
return false;
}
addr &= ~3; addr &= ~3;
if (addr < ITCMSize) if (addr < ITCMSize)
{ {
DataCycles += 1; DataCycles += 1;
*val = *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)]; *val = *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)];
return; return true;
} }
if ((addr & DTCMMask) == DTCMBase) if ((addr & DTCMMask) == DTCMBase)
{ {
DataCycles += 1; DataCycles += 1;
*val = *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)]; *val = *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)];
return; return true;
} }
*val = BusRead32(addr); *val = BusRead32(addr);
DataCycles += MemTimings[addr >> 12][3]; DataCycles += MemTimings[addr >> 12][3];
return true;
} }
void ARMv5::DataWrite8(u32 addr, u8 val) void ARMv5::DataWrite8(u32 addr, u8 val)