data abort handling for (almost) all (arm) instructions

full list: strb, ldrb, strh, ldrd, strd, ldrh, ldrsb, ldrsh
This commit is contained in:
Jaklyy
2024-06-04 21:22:39 -04:00
parent 1e8194e367
commit 317a8c61e5
4 changed files with 102 additions and 80 deletions

View File

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