From 6ebabde39217e948406f4aff123f8a4afdf7f30b Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Wed, 18 Sep 2024 19:23:23 -0400 Subject: [PATCH] implement changing thumb bit. and bkpt ig probably wrong --- src/ARM.cpp | 33 ++++++++++++++++++++++++++++++--- src/ARM.h | 6 +++++- src/ARMInterpreter.cpp | 20 ++++++++++++++------ src/ARMInterpreter.h | 1 + src/ARM_InstrInfo.cpp | 1 + src/ARM_InstrTable.h | 2 +- 6 files changed, 52 insertions(+), 11 deletions(-) diff --git a/src/ARM.cpp b/src/ARM.cpp index a7c6c11e..c7fea92d 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -201,6 +201,13 @@ void ARMv5::Reset() ARM::Reset(); } +void ARMv4::Reset() +{ + Thumb = false; + + ARM::Reset(); +} + void ARM::DoSavestate(Savestate* file) { @@ -395,6 +402,7 @@ void ARMv4::JumpTo(u32 addr, bool restorecpsr) Cycles += NDS.ARM7MemTimings[CodeCycles][0] + NDS.ARM7MemTimings[CodeCycles][1]; CPSR |= 0x20; + Thumb = true; } else { @@ -408,6 +416,7 @@ void ARMv4::JumpTo(u32 addr, bool restorecpsr) Cycles += NDS.ARM7MemTimings[CodeCycles][2] + NDS.ARM7MemTimings[CodeCycles][3]; CPSR &= ~0x20; + Thumb = false; } } @@ -724,7 +733,12 @@ void ARMv5::Execute() ARMInterpreter::A_BLX_IMM(this); } else - AddCycles_C(); + { + if ((((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0)) == 0x127) + ARMInterpreter::A_BKPT(this); // always passes regardless of condition code + else + AddCycles_C(); + } } // TODO optimize this shit!!! @@ -826,8 +840,11 @@ void ARMv4::Execute() else #endif { - if (CPSR & 0x20) // THUMB + if (Thumb) // THUMB { + Thumb = (CPSR & 0x20); + bool fix = !Thumb; + if constexpr (mode == CPUExecuteMode::InterpreterGDB) GdbCheckC(); @@ -841,12 +858,22 @@ void ARMv4::Execute() else { // actually execute - u32 icode = (CurInstr >> 6); + u32 icode = (CurInstr >> 6) & 0x3FF; ARMInterpreter::THUMBInstrTable[icode](this); } + + if (fix) [[unlikely]] + { + // probably wrong? + // fixup + R[15] &= ~0x3; + NextInstr[1] = CodeRead32(R[15]); + } } else { + Thumb = (CPSR & 0x20); + if constexpr (mode == CPUExecuteMode::InterpreterGDB) GdbCheckC(); diff --git a/src/ARM.h b/src/ARM.h index 26080b51..8d640a30 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -385,6 +385,8 @@ class ARMv4 : public ARM public: ARMv4(melonDS::NDS& nds, std::optional gdb, bool jit); + void Reset() override; + void FillPipeline() override; void JumpTo(u32 addr, bool restorecpsr = false) override; @@ -393,7 +395,7 @@ public: template void Execute(); - u16 CodeRead16(u32 addr) + u32 CodeRead16(u32 addr) { return BusRead16(addr); } @@ -403,6 +405,8 @@ public: return BusRead32(addr); } + bool Thumb; + bool DataRead8(u32 addr, u32* val) override; bool DataRead16(u32 addr, u32* val) override; bool DataRead32(u32 addr, u32* val) override; diff --git a/src/ARMInterpreter.cpp b/src/ARMInterpreter.cpp index 8ce15db1..979e3bb8 100644 --- a/src/ARMInterpreter.cpp +++ b/src/ARMInterpreter.cpp @@ -69,6 +69,14 @@ void T_UNK(ARM* cpu) cpu->JumpTo(cpu->ExceptionBase + 0x04); } +void A_BKPT(ARM* cpu) +{ + if (cpu->Num == 1) A_UNK(cpu); // checkme + + Log(LogLevel::Warn, "BKPT: "); // combine with the prefetch abort warning message + ((ARMv5*)cpu)->PrefetchAbort(); +} + void A_MSR_IMM(ARM* cpu) @@ -105,9 +113,6 @@ void A_MSR_IMM(ARM* cpu) //if (cpu->CurInstr & (1<<18)) mask |= 0x00FF0000; // unused by arm 7 & 9 if (cpu->CurInstr & (1<<19)) mask |= ((cpu->Num==1) ? 0xF0000000 : 0xF8000000); - if (!(cpu->CurInstr & (1<<22))) - mask &= 0xFFFFFFDF; - if ((cpu->CPSR & 0x1F) == 0x10) mask &= 0xFFFFFF00; u32 val = ROR((cpu->CurInstr & 0xFF), ((cpu->CurInstr >> 7) & 0x1E)); @@ -121,6 +126,9 @@ void A_MSR_IMM(ARM* cpu) if (!(cpu->CurInstr & (1<<22))) cpu->UpdateMode(oldpsr, cpu->CPSR); + if (cpu->Num == 0) + if (!(oldpsr & 0x20) && (cpu->CPSR & 0x20)) cpu->NextInstr[1] &= 0xFFFF; // checkme: probably not the right way to handle this + cpu->AddCycles_C(); } @@ -158,9 +166,6 @@ void A_MSR_REG(ARM* cpu) //if (cpu->CurInstr & (1<<18)) mask |= 0x00FF0000; // unused by arm 7 & 9 if (cpu->CurInstr & (1<<19)) mask |= ((cpu->Num==1) ? 0xF0000000 : 0xF8000000); - if (!(cpu->CurInstr & (1<<22))) - mask &= 0xFFFFFFDF; - if ((cpu->CPSR & 0x1F) == 0x10) mask &= 0xFFFFFF00; u32 val = cpu->R[cpu->CurInstr & 0xF]; @@ -173,6 +178,9 @@ void A_MSR_REG(ARM* cpu) if (!(cpu->CurInstr & (1<<22))) cpu->UpdateMode(oldpsr, cpu->CPSR); + + if (cpu->Num == 0) + if (!(oldpsr & 0x20) && (cpu->CPSR & 0x20)) cpu->NextInstr[1] &= 0xFFFF; // checkme: probably not the right way to handle this cpu->AddCycles_C(); } diff --git a/src/ARMInterpreter.h b/src/ARMInterpreter.h index 1066ac69..4c5ddafe 100644 --- a/src/ARMInterpreter.h +++ b/src/ARMInterpreter.h @@ -36,6 +36,7 @@ void A_MRS(ARM* cpu); void A_MCR(ARM* cpu); void A_MRC(ARM* cpu); void A_SVC(ARM* cpu); +void A_BKPT(ARM* cpu); void T_SVC(ARM* cpu); diff --git a/src/ARM_InstrInfo.cpp b/src/ARM_InstrInfo.cpp index 58838307..d1be9761 100644 --- a/src/ARM_InstrInfo.cpp +++ b/src/ARM_InstrInfo.cpp @@ -194,6 +194,7 @@ const u32 A_BX = A_BranchAlways | A_Read0 | ak(ak_BX); const u32 A_BLX_REG = A_BranchAlways | A_Link | A_Read0 | ak(ak_BLX_REG); const u32 A_UNK = A_BranchAlways | A_Link | ak(ak_UNK); +const u32 A_BKPT = A_BranchAlways | A_Link | ak(ak_UNK); const u32 A_MSR_IMM = ak(ak_MSR_IMM); const u32 A_MSR_REG = A_Read0 | ak(ak_MSR_REG); const u32 A_MRS = A_Write12 | ak(ak_MRS); diff --git a/src/ARM_InstrTable.h b/src/ARM_InstrTable.h index 8213c2e0..2c480f8d 100644 --- a/src/ARM_InstrTable.h +++ b/src/ARM_InstrTable.h @@ -130,7 +130,7 @@ INSTRFUNC_PROTO(ARMInstrTable[4096]) = // 0001 0010 0000 A_MSR_REG, A_BX, A_UNK, A_BLX_REG, - A_UNK, A_QSUB, A_UNK, A_UNK, + A_UNK, A_QSUB, A_UNK, A_BKPT, A_SMLAWy, A_UNK, A_SMULWy, A_STRH_REG, A_SMLAWy, A_LDRD_REG, A_SMULWy, A_STRD_REG,