diff --git a/src/ARM.cpp b/src/ARM.cpp index acf1b6e4..cf45a564 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -1152,20 +1152,22 @@ u32 ARMv5::ReadMem(u32 addr, int size) } #endif -void ARMv4::DataRead8(u32 addr, u32* val) +bool ARMv4::DataRead8(u32 addr, u32* val) { *val = BusRead8(addr); DataRegion = addr; DataCycles = NDS.ARM7MemTimings[addr >> 15][0]; + return true; } -void ARMv4::DataRead16(u32 addr, u32* val) +bool ARMv4::DataRead16(u32 addr, u32* val) { addr &= ~1; *val = BusRead16(addr); DataRegion = addr; DataCycles = NDS.ARM7MemTimings[addr >> 15][0]; + return true; } bool ARMv4::DataRead32(u32 addr, u32* val) @@ -1187,20 +1189,22 @@ bool ARMv4::DataRead32S(u32 addr, u32* val) return true; } -void ARMv4::DataWrite8(u32 addr, u8 val) +bool ARMv4::DataWrite8(u32 addr, u8 val) { BusWrite8(addr, val); DataRegion = addr; DataCycles = NDS.ARM7MemTimings[addr >> 15][0]; + return true; } -void ARMv4::DataWrite16(u32 addr, u16 val) +bool ARMv4::DataWrite16(u32 addr, u16 val) { addr &= ~1; BusWrite16(addr, val); DataRegion = addr; DataCycles = NDS.ARM7MemTimings[addr >> 15][0]; + return true; } bool ARMv4::DataWrite32(u32 addr, u32 val) diff --git a/src/ARM.h b/src/ARM.h index 67087433..f2277253 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -128,12 +128,12 @@ public: void SetupCodeMem(u32 addr); - virtual void DataRead8(u32 addr, u32* val) = 0; - virtual void DataRead16(u32 addr, u32* val) = 0; + virtual bool DataRead8(u32 addr, u32* val) = 0; + virtual bool DataRead16(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 bool DataWrite8(u32 addr, u8 val) = 0; + virtual bool DataWrite16(u32 addr, u16 val) = 0; virtual bool DataWrite32(u32 addr, u32 val) = 0; virtual bool DataWrite32S(u32 addr, u32 val) = 0; @@ -249,12 +249,12 @@ public: // all code accesses are forced nonseq 32bit u32 CodeRead32(u32 addr, bool branch); - void DataRead8(u32 addr, u32* val) override; - void DataRead16(u32 addr, u32* val) override; + bool DataRead8(u32 addr, u32* val) override; + bool DataRead16(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; + bool DataWrite8(u32 addr, u8 val) override; + bool DataWrite16(u32 addr, u16 val) override; bool DataWrite32(u32 addr, u32 val) override; bool DataWrite32S(u32 addr, u32 val) override; @@ -398,12 +398,12 @@ public: return BusRead32(addr); } - void DataRead8(u32 addr, u32* val) override; - void DataRead16(u32 addr, u32* val) override; + bool DataRead8(u32 addr, u32* val) override; + bool DataRead16(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; + bool DataWrite8(u32 addr, u8 val) override; + bool DataWrite16(u32 addr, u16 val) override; bool DataWrite32(u32 addr, u32 val) override; bool DataWrite32S(u32 addr, u32 val) override; void AddCycles_C() override; diff --git a/src/ARMInterpreter_LoadStore.cpp b/src/ARMInterpreter_LoadStore.cpp index fe9bfd0c..67e09a7b 100644 --- a/src/ARMInterpreter_LoadStore.cpp +++ b/src/ARMInterpreter_LoadStore.cpp @@ -83,16 +83,18 @@ namespace melonDS::ARMInterpreter #define A_STRB \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - cpu->DataWrite8(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \ - if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ - cpu->AddCycles_CD(); + bool dataabort = !cpu->DataWrite8(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \ + cpu->AddCycles_CD(); \ + if (dataabort) return; \ + if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; // TODO: user mode (bit21) #define A_STRB_POST \ u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - cpu->DataWrite8(addr, cpu->R[(cpu->CurInstr>>12) & 0xF]); \ - cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \ - cpu->AddCycles_CD(); + bool dataabort = !cpu->DataWrite8(addr, cpu->R[(cpu->CurInstr>>12) & 0xF]); \ + cpu->AddCycles_CD(); \ + if (dataabort) return; \ + cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; #define A_LDR \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ @@ -131,18 +133,20 @@ namespace melonDS::ARMInterpreter #define A_LDRB \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - u32 val; cpu->DataRead8(offset, &val); \ - if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ + u32 val; bool dataabort = !cpu->DataRead8(offset, &val); \ cpu->AddCycles_CDI(); \ + if (dataabort) return; \ + if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ 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; cpu->DataRead8(addr, &val); \ - cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \ + u32 val; bool dataabort = !cpu->DataRead8(addr, &val); \ cpu->AddCycles_CDI(); \ + if (dataabort) return; \ + cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \ cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \ if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRB PC %08X\n", cpu->R[15]); \ @@ -229,103 +233,113 @@ A_IMPLEMENT_WB_LDRSTR(LDRB) #define A_STRH \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - cpu->DataWrite16(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \ - if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ - cpu->AddCycles_CD(); + bool dataabort = !cpu->DataWrite16(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \ + cpu->AddCycles_CD(); \ + if (dataabort) return; \ + if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; #define A_STRH_POST \ u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - cpu->DataWrite16(addr, cpu->R[(cpu->CurInstr>>12) & 0xF]); \ - cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \ - cpu->AddCycles_CD(); + bool dataabort = !cpu->DataWrite16(addr, cpu->R[(cpu->CurInstr>>12) & 0xF]); \ + cpu->AddCycles_CD(); \ + if (dataabort) return; \ + cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; // TODO: CHECK LDRD/STRD TIMINGS!! #define A_LDRD \ if (cpu->Num != 0) return; \ 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) { r--; printf("!! MISALIGNED LDRD %d\n", r+1); } \ - cpu->DataRead32 (offset , &cpu->R[r ]); \ - cpu->DataRead32S(offset+4, &cpu->R[r+1]); \ - cpu->AddCycles_CDI(); + if (!cpu->DataRead32 (offset , &cpu->R[r ])) {cpu->AddCycles_CDI(); return;} \ + if (!cpu->DataRead32S(offset+4, &cpu->R[r+1])) {cpu->AddCycles_CDI(); return;} \ + cpu->AddCycles_CDI(); \ + if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; #define A_LDRD_POST \ if (cpu->Num != 0) return; \ u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \ u32 r = (cpu->CurInstr>>12) & 0xF; \ if (r&1) { r--; printf("!! MISALIGNED LDRD_POST %d\n", r+1); } \ - cpu->DataRead32 (addr , &cpu->R[r ]); \ - cpu->DataRead32S(addr+4, &cpu->R[r+1]); \ - cpu->AddCycles_CDI(); + if (!cpu->DataRead32 (addr , &cpu->R[r ])) {cpu->AddCycles_CDI(); return;} \ + if (!cpu->DataRead32S(addr+4, &cpu->R[r+1])) {cpu->AddCycles_CDI(); return;} \ + cpu->AddCycles_CDI(); \ + cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; #define A_STRD \ if (cpu->Num != 0) return; \ 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) { r--; printf("!! MISALIGNED STRD %d\n", r+1); } \ - cpu->DataWrite32 (offset , cpu->R[r ]); \ - cpu->DataWrite32S(offset+4, cpu->R[r+1]); \ - cpu->AddCycles_CD(); + bool dataabort = !cpu->DataWrite32(offset, cpu->R[r ]); /* yes, this data abort behavior is on purpose */ \ + dataabort |= !cpu->DataWrite32S (offset+4, cpu->R[r+1]); /* no, i dont understand it either */ \ + cpu->AddCycles_CD(); \ + if (dataabort) return; \ + if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; #define A_STRD_POST \ if (cpu->Num != 0) return; \ u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \ u32 r = (cpu->CurInstr>>12) & 0xF; \ if (r&1) { r--; printf("!! MISALIGNED STRD_POST %d\n", r+1); } \ - cpu->DataWrite32 (addr , cpu->R[r ]); \ - cpu->DataWrite32S(addr+4, cpu->R[r+1]); \ - cpu->AddCycles_CD(); + bool dataabort = !cpu->DataWrite32(addr, cpu->R[r ]); \ + dataabort |= !cpu->DataWrite32S (addr+4, cpu->R[r+1]); \ + cpu->AddCycles_CD(); \ + if (dataabort) return; \ + cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; #define A_LDRH \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ - cpu->DataRead16(offset, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \ + bool dataabort = !cpu->DataRead16(offset, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \ cpu->AddCycles_CDI(); \ + if (dataabort) return; \ if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRH PC %08X\n", cpu->R[15]); \ + if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; #define A_LDRH_POST \ u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \ - cpu->DataRead16(addr, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \ + bool dataabort = !cpu->DataRead16(addr, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \ cpu->AddCycles_CDI(); \ + if (dataabort) return; \ if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRH PC %08X\n", cpu->R[15]); \ + cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; #define A_LDRSB \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ - cpu->DataRead8(offset, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \ - cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->R[(cpu->CurInstr>>12) & 0xF]; \ + bool dataabort = !cpu->DataRead8(offset, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \ cpu->AddCycles_CDI(); \ + if (dataabort) return; \ + cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->R[(cpu->CurInstr>>12) & 0xF]; \ if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSB PC %08X\n", cpu->R[15]); \ + if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; #define A_LDRSB_POST \ u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \ - cpu->DataRead8(addr, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \ - cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->R[(cpu->CurInstr>>12) & 0xF]; \ + bool dataabort = !cpu->DataRead8(addr, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \ cpu->AddCycles_CDI(); \ + if (dataabort) return; \ + cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->R[(cpu->CurInstr>>12) & 0xF]; \ if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSB PC %08X\n", cpu->R[15]); \ + cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; #define A_LDRSH \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ - cpu->DataRead16(offset, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \ - cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->R[(cpu->CurInstr>>12) & 0xF]; \ + bool dataabort = !cpu->DataRead16(offset, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \ cpu->AddCycles_CDI(); \ + if (dataabort) return; \ + cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->R[(cpu->CurInstr>>12) & 0xF]; \ if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSH PC %08X\n", cpu->R[15]); \ + if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; #define A_LDRSH_POST \ u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \ - cpu->DataRead16(addr, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \ - cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->R[(cpu->CurInstr>>12) & 0xF]; \ + bool dataabort = !cpu->DataRead16(addr, &cpu->R[(cpu->CurInstr>>12) & 0xF]); \ cpu->AddCycles_CDI(); \ + if (dataabort) return; \ + cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->R[(cpu->CurInstr>>12) & 0xF]; \ if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSH PC %08X\n", cpu->R[15]); \ + cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; #define A_IMPLEMENT_HD_LDRSTR(x) \ diff --git a/src/CP15.cpp b/src/CP15.cpp index b2ab9f91..857c5c90 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -807,12 +807,12 @@ u32 ARMv5::CodeRead32(u32 addr, bool branch) } -void ARMv5::DataRead8(u32 addr, u32* val) +bool ARMv5::DataRead8(u32 addr, u32* val) { if (!(PU_Map[addr>>12] & 0x01)) { DataAbort(); - return; + return false; } DataRegion = addr; @@ -821,25 +821,26 @@ void ARMv5::DataRead8(u32 addr, u32* val) { DataCycles = 1; *val = *(u8*)&ITCM[addr & (ITCMPhysicalSize - 1)]; - return; + return true; } if ((addr & DTCMMask) == DTCMBase) { DataCycles = 1; *val = *(u8*)&DTCM[addr & (DTCMPhysicalSize - 1)]; - return; + return true; } *val = BusRead8(addr); DataCycles = MemTimings[addr >> 12][1]; + return true; } -void ARMv5::DataRead16(u32 addr, u32* val) +bool ARMv5::DataRead16(u32 addr, u32* val) { if (!(PU_Map[addr>>12] & 0x01)) { DataAbort(); - return; + return false; } DataRegion = addr; @@ -850,17 +851,18 @@ void ARMv5::DataRead16(u32 addr, u32* val) { DataCycles = 1; *val = *(u16*)&ITCM[addr & (ITCMPhysicalSize - 1)]; - return; + return true; } if ((addr & DTCMMask) == DTCMBase) { DataCycles = 1; *val = *(u16*)&DTCM[addr & (DTCMPhysicalSize - 1)]; - return; + return true; } *val = BusRead16(addr); DataCycles = MemTimings[addr >> 12][1]; + return true; } bool ARMv5::DataRead32(u32 addr, u32* val) @@ -921,12 +923,12 @@ bool ARMv5::DataRead32S(u32 addr, u32* val) return true; } -void ARMv5::DataWrite8(u32 addr, u8 val) +bool ARMv5::DataWrite8(u32 addr, u8 val) { if (!(PU_Map[addr>>12] & 0x02)) { DataAbort(); - return; + return false; } DataRegion = addr; @@ -936,25 +938,26 @@ void ARMv5::DataWrite8(u32 addr, u8 val) DataCycles = 1; *(u8*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val; NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr); - return; + return true; } if ((addr & DTCMMask) == DTCMBase) { DataCycles = 1; *(u8*)&DTCM[addr & (DTCMPhysicalSize - 1)] = val; - return; + return true; } BusWrite8(addr, val); DataCycles = MemTimings[addr >> 12][1]; + return true; } -void ARMv5::DataWrite16(u32 addr, u16 val) +bool ARMv5::DataWrite16(u32 addr, u16 val) { if (!(PU_Map[addr>>12] & 0x02)) { DataAbort(); - return; + return false; } DataRegion = addr; @@ -966,17 +969,18 @@ void ARMv5::DataWrite16(u32 addr, u16 val) DataCycles = 1; *(u16*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val; NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr); - return; + return true; } if ((addr & DTCMMask) == DTCMBase) { DataCycles = 1; *(u16*)&DTCM[addr & (DTCMPhysicalSize - 1)] = val; - return; + return true; } BusWrite16(addr, val); DataCycles = MemTimings[addr >> 12][1]; + return true; } bool ARMv5::DataWrite32(u32 addr, u32 val)