From 63d4b787334f2d2f41e220c88044e933a24b0266 Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Sun, 2 Jun 2024 10:13:50 -0400 Subject: [PATCH] improve implementation --- src/ARM.cpp | 6 ++-- src/ARM.h | 12 +++---- src/ARMInterpreter_LoadStore.cpp | 56 +++++++++++--------------------- src/CP15.cpp | 22 +++++++++---- 4 files changed, 44 insertions(+), 52 deletions(-) diff --git a/src/ARM.cpp b/src/ARM.cpp index c2f6a6c2..c96cb65d 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -1168,21 +1168,23 @@ void ARMv4::DataRead16(u32 addr, u32* val) DataCycles = NDS.ARM7MemTimings[addr >> 15][0]; } -void ARMv4::DataRead32(u32 addr, u32* val) +bool ARMv4::DataRead32(u32 addr, u32* val) { addr &= ~3; *val = BusRead32(addr); DataRegion = addr; DataCycles = NDS.ARM7MemTimings[addr >> 15][2]; + return true; } -void ARMv4::DataRead32S(u32 addr, u32* val) +bool ARMv4::DataRead32S(u32 addr, u32* val) { addr &= ~3; *val = BusRead32(addr); DataCycles += NDS.ARM7MemTimings[addr >> 15][3]; + return true; } void ARMv4::DataWrite8(u32 addr, u8 val) diff --git a/src/ARM.h b/src/ARM.h index 1e0b71b8..56a6306e 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -130,8 +130,8 @@ public: 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 bool DataRead32(u32 addr, u32* val) = 0; + virtual bool 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; @@ -251,8 +251,8 @@ public: void DataRead8(u32 addr, u32* val) override; void DataRead16(u32 addr, u32* val) override; - void DataRead32(u32 addr, u32* val) override; - void DataRead32S(u32 addr, u32* val) override; + bool DataRead32(u32 addr, u32* val) override; + bool DataRead32S(u32 addr, u32* val) override; void DataWrite8(u32 addr, u8 val) override; void DataWrite16(u32 addr, u16 val) override; void DataWrite32(u32 addr, u32 val) override; @@ -400,8 +400,8 @@ public: void DataRead8(u32 addr, u32* val) override; void DataRead16(u32 addr, u32* val) override; - void DataRead32(u32 addr, u32* val) override; - void DataRead32S(u32 addr, u32* val) override; + bool DataRead32(u32 addr, u32* val) override; + bool DataRead32S(u32 addr, u32* val) override; void DataWrite8(u32 addr, u8 val) override; void DataWrite16(u32 addr, u16 val) override; void DataWrite32(u32 addr, u32 val) override; diff --git a/src/ARMInterpreter_LoadStore.cpp b/src/ARMInterpreter_LoadStore.cpp index dfdb98c2..806b4c3e 100644 --- a/src/ARMInterpreter_LoadStore.cpp +++ b/src/ARMInterpreter_LoadStore.cpp @@ -395,12 +395,14 @@ void A_LDM(ARM* cpu) u32 baseid = (cpu->CurInstr >> 16) & 0xF; u32 base = cpu->R[baseid]; u32 wbbase; + u32 oldbase = base; u32 preinc = (cpu->CurInstr & (1<<24)); 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++) { if (cpu->CurInstr & (1<Num == 0) - { - u32 tmpbase = base; - for (int i = 0; i < 16; i++) - { - if (cpu->CurInstr & (1<PU_Map[tmpbase>>12] & 0x01) - { - if (!preinc) tmpbase += 4; - } - else - { - abortreg = i; - break; - } - } - } - } - + // switch to user mode regs if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15))) 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<DataRead32 (base, &cpu->R[i]); - else cpu->DataRead32S(base, &cpu->R[i]); + if (first) {if (!cpu->DataRead32 (base, &cpu->R[i])) {dataabort = true; goto abortjump;}} + else if (!cpu->DataRead32S(base, &cpu->R[i])) {dataabort = true; goto abortjump;} first = false; if (!preinc) base += 4; } } u32 pc; - if ((cpu->CurInstr & (1<<15)) && (abortreg == 16)) + if ((cpu->CurInstr & (1<<15))) { if (preinc) base += 4; - if (first) cpu->DataRead32 (base, &pc); - else cpu->DataRead32S(base, &pc); + if (first) {if (!cpu->DataRead32 (base, &pc)) dataabort = true;} + else if (!cpu->DataRead32S(base, &pc)) dataabort = true; if (!preinc) base += 4; if (cpu->Num == 1) pc &= ~0x1; } + abortjump: + + // switch back to previous regs if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15))) cpu->UpdateMode((cpu->CPSR&~0x1F)|0x10, cpu->CPSR, true); - // if it's 16 then there was no data abort - if (abortreg == 16) + if (!dataabort) { + // writeback to base if (cpu->CurInstr & (1<<21)) { // post writeback @@ -489,14 +473,12 @@ void A_LDM(ARM* cpu) else cpu->R[baseid] = wbbase; } - + + // jump if pc got written if (cpu->CurInstr & (1<<15)) cpu->JumpTo(pc, cpu->CurInstr & (1<<22)); } - else - { - ((ARMv5*)cpu)->DataAbort(); - } + else cpu->R[baseid] = oldbase; // restore original value of base in case the reg got written to cpu->AddCycles_CDI(); } diff --git a/src/CP15.cpp b/src/CP15.cpp index 5e5b35ea..fa55853d 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -863,12 +863,12 @@ void ARMv5::DataRead16(u32 addr, u32* val) 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)) { DataAbort(); - return; + return false; } DataRegion = addr; @@ -879,38 +879,46 @@ void ARMv5::DataRead32(u32 addr, u32* val) { DataCycles = 1; *val = *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)]; - return; + return true; } if ((addr & DTCMMask) == DTCMBase) { DataCycles = 1; *val = *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)]; - return; + return true; } *val = BusRead32(addr); 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; if (addr < ITCMSize) { DataCycles += 1; *val = *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)]; - return; + return true; } if ((addr & DTCMMask) == DTCMBase) { DataCycles += 1; *val = *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)]; - return; + return true; } *val = BusRead32(addr); DataCycles += MemTimings[addr >> 12][3]; + return true; } void ARMv5::DataWrite8(u32 addr, u8 val)