diff --git a/src/ARM.cpp b/src/ARM.cpp index 487724dd..c4655969 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -241,6 +241,7 @@ void ARMv5::Reset() void ARMv4::Reset() { + FuncQueue[0] = &ARMv4::StartExec; Nonseq = true; ARM::Reset(); @@ -337,24 +338,26 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr, u8 R15) BranchRestore = restorecpsr; BranchUpdate = R15; BranchAddr = addr; - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::JumpTo_2; - else JumpTo_2(); + QueueFunction(&ARMv5::JumpTo_2); } void ARMv5::JumpTo_2() { - if (CP15Control & (1<<15)) + if (BranchUpdate) { - if (BranchUpdate == 1) BranchAddr = R[15] & ~1; - else if (BranchUpdate == 2) BranchAddr = R[15] | 1; + if (CP15Control & (1<<15)) + { + if (BranchUpdate == 1) BranchAddr = R[15] & ~1; + else BranchAddr = R[15] | 1; + } + else BranchAddr = R[15]; } - else if (BranchUpdate) BranchAddr = R[15]; if (BranchRestore) { RestoreCPSR(); - if (CPSR & 0x20) BranchAddr |= 0x1; + if (CPSR & 0x20) BranchAddr |= 0x1; else BranchAddr &= ~0x1; } @@ -384,15 +387,13 @@ void ARMv5::JumpTo_2() { CodeRead32(BranchAddr-2); - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::JumpTo_3A; - else JumpTo_3A(); + QueueFunction(&ARMv5::JumpTo_3A); } else { CodeRead32(BranchAddr); - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::JumpTo_3B; - else JumpTo_3B(); + QueueFunction(&ARMv5::JumpTo_3B); } } else @@ -404,8 +405,7 @@ void ARMv5::JumpTo_2() CodeRead32(BranchAddr); - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::JumpTo_3C; - else JumpTo_3C(); + QueueFunction(&ARMv5::JumpTo_3C); } } @@ -414,8 +414,7 @@ void ARMv5::JumpTo_3A() NextInstr[0] = RetVal >> 16; CodeRead32(BranchAddr+2); - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::JumpTo_4; - else JumpTo_4(); + QueueFunction(&ARMv5::JumpTo_4); } void ARMv5::JumpTo_3B() @@ -429,8 +428,7 @@ void ARMv5::JumpTo_3C() NextInstr[0] = RetVal; CodeRead32(BranchAddr+4); - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::JumpTo_4; - else JumpTo_4(); + QueueFunction(&ARMv5::JumpTo_4); } void ARMv5::JumpTo_4() @@ -440,40 +438,71 @@ void ARMv5::JumpTo_4() void ARMv4::JumpTo(u32 addr, bool restorecpsr, u8 R15) { - if (restorecpsr) + //printf("JUMP! %08X %08X %i %i\n", addr, R[15], restorecpsr, R15); + BranchRestore = restorecpsr; + BranchUpdate = R15; + BranchAddr = addr; + QueueFunction(&ARMv4::JumpTo_2); +} + +void ARMv4::JumpTo_2() +{ + if (BranchUpdate) + { + if (BranchUpdate == 1) BranchAddr = R[15] & ~1; + else BranchAddr = R[15] | 1; + } + + if (BranchRestore) { RestoreCPSR(); - if (CPSR & 0x20) addr |= 0x1; - else addr &= ~0x1; + if (CPSR & 0x20) BranchAddr |= 0x1; + else BranchAddr &= ~0x1; } + + //printf("JUMP2! %08X\n", BranchAddr); - if (addr & 0x1) + if (BranchAddr & 0x1) { - addr &= ~0x1; - R[15] = addr+2; - - Nonseq = true; - NextInstr[0] = CodeRead16(addr); - Nonseq = false; - NextInstr[1] = CodeRead16(addr+2); + BranchAddr &= ~0x1; + R[15] = BranchAddr+2; CPSR |= 0x20; + + Nonseq = true; + CodeRead16(BranchAddr); + QueueFunction(&ARMv4::JumpTo_3A); } else { - addr &= ~0x3; - R[15] = addr+4; - - Nonseq = true; - NextInstr[0] = CodeRead32(addr); - Nonseq = false; - NextInstr[1] = CodeRead32(addr+4); + BranchAddr &= ~0x3; + R[15] = BranchAddr+4; CPSR &= ~0x20; + + Nonseq = true; + CodeRead32(BranchAddr); + QueueFunction(&ARMv4::JumpTo_3B); } } +void ARMv4::JumpTo_3A() +{ + NextInstr[0] = RetVal; + Nonseq = false; + CodeRead16(BranchAddr+2); + QueueFunction(&ARMv4::UpdateNextInstr1); +} + +void ARMv4::JumpTo_3B() +{ + NextInstr[0] = RetVal; + Nonseq = false; + CodeRead32(BranchAddr+4); + QueueFunction(&ARMv4::UpdateNextInstr1); +} + void ARM::RestoreCPSR() { u32 oldcpsr = CPSR; @@ -632,7 +661,6 @@ template void ARM::TriggerIRQ(); void ARMv5::PrefetchAbort() { - abt = true; AddCycles_C(); Log(LogLevel::Warn, "ARM9: prefetch abort (%08X)\n", R[15]); @@ -648,7 +676,6 @@ void ARMv5::PrefetchAbort() void ARMv5::DataAbort() { - abt = true; Log(LogLevel::Warn, "ARM9: data abort (%08X) %08llX\n", R[15], CurInstr); u32 oldcpsr = CPSR; @@ -815,29 +842,11 @@ void ARMv5::Execute() // check if we're done with the queue, if so, reset everything if (FuncQueueProg >= FuncQueueEnd) { - FuncQueueFill = 0; FuncQueueProg = 0; FuncQueueEnd = 0; FuncQueueActive = false; FuncQueue[0] = &ARMv5::StartExec; - /* - Platform::FileHandle* file = Platform::OpenFile("REGLOG.bin", Platform::FileMode::Read); - Platform::FileSeek(file, iter*16*4, Platform::FileSeekOrigin::Start); - u32 Regs[16]; - Platform::FileRead(Regs, 4, 16, file); - if (memcmp(Regs, R, 16*4)) - { - printf("MISMATCH ON ITERATION %lli! %08llX", iter, CurInstr); - for (int i = 0; i < 16; i++) - { - printf(" %i: %08X vs %08X", i, R[i], Regs[i]); - } - printf("\n"); - abt=1; - } - Platform::CloseFile(file); - iter++;*/ } } else @@ -852,30 +861,10 @@ void ARMv5::Execute() FuncQueueFill = 0; FuncQueueActive = true; } - else - { - /* - Platform::FileHandle* file = Platform::OpenFile("REGLOG.bin", Platform::FileMode::Read); - Platform::FileSeek(file, iter*16*4, Platform::FileSeekOrigin::Start); - u32 Regs[16]; - Platform::FileRead(Regs, 4, 16, file); - if (memcmp(Regs, R, 16*4)) - { - printf("MISMATCH ON ITERATION %lli! %08llX", iter, CurInstr); - for (int i = 0; i < 16; i++) - { - printf(" %i: %08X vs %08X", i, R[i], Regs[i]); - } - printf("\n"); - abt=1; - } - Platform::CloseFile(file); - iter++;*/ - } - if (MRTrack.Type != MainRAMType::Null) break; // check if we need to resolve main ram + if (MRTrack.Type != MainRAMType::Null) return; // check if we need to resolve main ram // TODO optimize this shit!!! - if (Halted) + if (!FuncQueueActive && Halted) { if (Halted == 1 && NDS.ARM9Timestamp < NDS.ARM9Target) { @@ -904,6 +893,45 @@ template void ARMv5::Execute(); template void ARMv5::Execute(); #endif +void ARMv4::StartExec() +{ + if (CPSR & 0x20) // THUMB + { + // prefetch + R[15] += 2; + CurInstr = NextInstr[0]; + NextInstr[0] = NextInstr[1]; + CodeRead16(R[15]); + QueueFunction(&ARMv4::UpdateNextInstr1); + + if (IRQ && !(CPSR & 0x80)) TriggerIRQ(); + else + { + // actually execute + u32 icode = (CurInstr >> 6); + ARMInterpreter::THUMBInstrTable[icode](this); + } + } + else + { + // prefetch + R[15] += 4; + CurInstr = NextInstr[0]; + NextInstr[0] = NextInstr[1]; + CodeRead32(R[15]); + QueueFunction(&ARMv4::UpdateNextInstr1); + + if (IRQ && !(CPSR & 0x80)) TriggerIRQ(); + else if (CheckCondition(CurInstr >> 28)) // actually execute + { + u32 icode = ((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0); + ARMInterpreter::ARMInstrTable[icode](this); + } + else + AddCycles_C(); + } +} + template void ARMv4::Execute() { @@ -921,8 +949,11 @@ void ARMv4::Execute() Halted = 0; if (NDS.IME[1] & 0x1) { +#ifdef JIT_ENABLED if constexpr (mode == CPUExecuteMode::JIT) TriggerIRQ(); - else IRQ = 1; + else +#endif + IRQ = 1; } } else @@ -974,48 +1005,84 @@ void ARMv4::Execute() else #endif { - if (CPSR & 0x20) // THUMB + if constexpr (mode == CPUExecuteMode::InterpreterGDB) + GdbCheckC(); + + //printf("A:%i, F:%i, P:%i, E:%i, I:%08llX, 15:%08X\n", FuncQueueActive, FuncQueueFill, FuncQueueProg, FuncQueueEnd, CurInstr, R[15]); + + (this->*FuncQueue[FuncQueueProg])(); + + if (FuncQueueActive) { - if constexpr (mode == CPUExecuteMode::InterpreterGDB) - GdbCheckC(); + if (FuncQueueFill == FuncQueueProg) + { + // we did not get a new addition to the queue; increment and reset ptrs + FuncQueueFill = ++FuncQueueProg; - // prefetch - R[15] += 2; - CurInstr = NextInstr[0]; - NextInstr[0] = NextInstr[1]; - NextInstr[1] = CodeRead16(R[15]); + // check if we're done with the queue, if so, reset everything + if (FuncQueueProg >= FuncQueueEnd) + { + FuncQueueFill = 0; + FuncQueueProg = 0; + FuncQueueEnd = 0; + FuncQueueActive = false; + FuncQueue[0] = &ARMv4::StartExec; - if (IRQ && !(CPSR & 0x80)) TriggerIRQ(); + /* + if (filey == NULL) filey = Platform::OpenFile("REGLOG.bin", Platform::FileMode::Read); + else + { + u32 regscmp[16]; + Platform::FileRead(regscmp, 4, 16, filey); + if (iter > 471000 && memcmp(regscmp, R, 4*16)) + { + printf("MISMATCH on iter: %lli!!!! %08llX\n", iter, CurInstr); + for (int i = 0; i < 16; i++) + { + printf("R%i :%08X vs CMP:%08X\n", i, R[i], regscmp[i]); + } + //abt++; + } + iter++; + }*/ + } + } else { - // actually execute - u32 icode = (CurInstr >> 6); - ARMInterpreter::THUMBInstrTable[icode](this); + // we got a new addition to the list; redo the current entry + FuncQueueFill = FuncQueueProg; } } + else if (FuncQueueFill > 0) // check if we started the queue up + { + FuncQueueEnd = FuncQueueFill; + FuncQueueFill = 0; + FuncQueueActive = true; + } else { - if constexpr (mode == CPUExecuteMode::InterpreterGDB) - GdbCheckC(); - - // prefetch - R[15] += 4; - CurInstr = NextInstr[0]; - NextInstr[0] = NextInstr[1]; - NextInstr[1] = CodeRead32(R[15]); - - if (IRQ && !(CPSR & 0x80)) TriggerIRQ(); - else if (CheckCondition(CurInstr >> 28)) // actually execute - { - u32 icode = ((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0); - ARMInterpreter::ARMInstrTable[icode](this); - } + /* + if (filey == NULL) Platform::OpenFile("REGLOG.bin", Platform::FileMode::Read); else - AddCycles_C(); + { + u32 regscmp[16]; + Platform::FileRead(regscmp, 4, 16, filey); + if (iter > 471000 && memcmp(regscmp, R, 4*16)) + { + printf("MISMATCH on iter: %lli!!!! %08llX\n", iter, CurInstr); + for (int i = 0; i < 16; i++) + { + printf("R%i :%08X vs CMP:%08X\n", i, R[i], regscmp[i]); + } + //abt++; + iter++; + } + }*/ } + if (MRTrack.Type != MainRAMType::Null) return; // check if we need to resolve main ram // TODO optimize this shit!!! - if (Halted) + if (!FuncQueueActive && Halted) { if (Halted == 1 && NDS.ARM7Timestamp < NDS.ARM7Target) { @@ -1075,7 +1142,7 @@ void ARMv5::FillPipeline() void ARMv4::FillPipeline() { - SetupCodeMem(R[15]); + /*SetupCodeMem(R[15]); if (CPSR & 0x20) { @@ -1086,7 +1153,7 @@ void ARMv4::FillPipeline() { NextInstr[0] = CodeRead32(R[15] - 4); NextInstr[1] = CodeRead32(R[15]); - } + }*/ } #ifdef GDBSTUB_ENABLED @@ -1314,8 +1381,7 @@ void ARMv5::CodeFetch() { CodeRead32(PC); } - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::AddExecute; - else AddExecute(); + QueueFunction(&ARMv5::AddExecute); } void ARMv5::AddExecute() @@ -1328,8 +1394,7 @@ void ARMv5::AddExecute() void ARMv5::AddCycles_MW(s32 numM) { DataCycles = numM; - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::AddCycles_MW_2; - else AddCycles_MW_2(); + QueueFunction(&ARMv5::AddCycles_MW_2); } void ARMv5::AddCycles_MW_2() @@ -1389,45 +1454,53 @@ void ARMv5::HandleInterlocksMemory(u8 reg) ILPrevTime = 16;*/ } -u16 ARMv4::CodeRead16(u32 addr) +void ARMv4::CodeRead16(u32 addr) { if ((addr >> 24) == 0x02) { - if (NDS.ARM7Timestamp < MainRAMTimestamp) NDS.ARM7Timestamp = MainRAMTimestamp; + FetchAddr[16] = addr; + MRTrack.Type = MainRAMType::Fetch; + MRTrack.Var = MRCodeFetch | MR16; + if (!Nonseq) MRTrack.Var |= MRSequential; } - - NDS.ARM7Timestamp += NDS.ARM7MemTimings[addr>>15][Nonseq?0:1]; - - if ((addr >> 24) == 0x02) + else { - MainRAMTimestamp = NDS.ARM7Timestamp; - NDS.ARM7Timestamp -= 3; + NDS.ARM7Timestamp += NDS.ARM7MemTimings[addr>>15][Nonseq?0:1]; + RetVal = BusRead16(addr); } - - return BusRead16(addr); } -u32 ARMv4::CodeRead32(u32 addr) +void ARMv4::CodeRead32(u32 addr) { if ((addr >> 24) == 0x02) { - if (NDS.ARM7Timestamp < MainRAMTimestamp) NDS.ARM7Timestamp = MainRAMTimestamp; + FetchAddr[16] = addr; + MRTrack.Type = MainRAMType::Fetch; + MRTrack.Var = MRCodeFetch | MR32; + if (!Nonseq) MRTrack.Var |= MRSequential; } - - NDS.ARM7Timestamp += NDS.ARM7MemTimings[addr>>15][Nonseq?2:3]; - - if ((addr >> 24) == 0x02) + else { - MainRAMTimestamp = NDS.ARM7Timestamp; - NDS.ARM7Timestamp -= 3; + NDS.ARM7Timestamp += NDS.ARM7MemTimings[addr>>15][Nonseq?2:3]; + RetVal = BusRead32(addr); } - - return BusRead32(addr); } bool ARMv4::DataRead8(u32 addr, u8 reg) { - u32* val = &R[reg]; + FetchAddr[reg] = addr; + LDRRegs = 1<> 24) == 0x02) { @@ -1443,12 +1516,24 @@ bool ARMv4::DataRead8(u32 addr, u8 reg) } *val = BusRead8(addr); - return true; } bool ARMv4::DataRead16(u32 addr, u8 reg) { - u32* val = &R[reg]; + FetchAddr[reg] = addr; + LDRRegs = 1<> 24) == 0x02) @@ -1465,12 +1550,24 @@ bool ARMv4::DataRead16(u32 addr, u8 reg) } *val = BusRead16(addr); - return true; } bool ARMv4::DataRead32(u32 addr, u8 reg) { - u32* val = &R[reg]; + FetchAddr[reg] = addr; + LDRRegs = 1<> 24) == 0x02) @@ -1487,12 +1584,25 @@ bool ARMv4::DataRead32(u32 addr, u8 reg) } *val = BusRead32(addr); - return true; + LDRRegs &= ~1<> 24) == 0x02) @@ -1509,11 +1619,24 @@ bool ARMv4::DataRead32S(u32 addr, u8 reg) } *val = BusRead32(addr); - return true; + LDRRegs &= ~1<> 24) == 0x02) { if (NDS.ARM7Timestamp < MainRAMTimestamp) NDS.ARM7Timestamp = MainRAMTimestamp; @@ -1528,11 +1651,23 @@ bool ARMv4::DataWrite8(u32 addr, u8 val, u8 reg) } BusWrite8(addr, val); - return true; } bool ARMv4::DataWrite16(u32 addr, u16 val, u8 reg) { + FetchAddr[reg] = addr; + STRRegs = 1<> 24) == 0x02) @@ -1549,11 +1684,23 @@ bool ARMv4::DataWrite16(u32 addr, u16 val, u8 reg) } BusWrite16(addr, val); - return true; } bool ARMv4::DataWrite32(u32 addr, u32 val, u8 reg) { + FetchAddr[reg] = addr; + STRRegs = 1<> 24) == 0x02) @@ -1570,11 +1717,24 @@ bool ARMv4::DataWrite32(u32 addr, u32 val, u8 reg) } BusWrite32(addr, val); - return true; + STRRegs &= ~1<> 24) == 0x02) @@ -1591,7 +1751,7 @@ bool ARMv4::DataWrite32S(u32 addr, u32 val, u8 reg) } BusWrite32(addr, val); - return true; + STRRegs &= ~1<*QueueEntry)(); + } + void StartExec(); void AddExecute(); void AddCycles_MW_2(); @@ -669,15 +691,12 @@ public: void DWrite16_2(); void DWrite32_2(); void DWrite32S_2(); - void QueueUpdateMode() { UpdateMode(QueueMode[0], QueueMode[1], true); } - void SignExtend8() { R[ExtReg] = (s32)(s8)R[ExtReg]; } - void SignExtend16() { R[ExtReg] = (s32)(s16)R[ExtReg]; } - void ROR32() { R[ExtReg] = ROR(R[ExtReg], ExtROROffs); } + u32 CP15Control; //! CP15 Register 1: Control Register u32 RNGSeed; //! Global cache line fill seed. Used for pseudo random replacement strategy with the instruction and data cache @@ -753,8 +772,6 @@ public: u64 ICacheStreamTimes[7]; u64 DCacheStreamTimes[7]; - bool abt; - u8 WBWritePointer; // which entry to attempt to write next; should always be ANDed with 0xF after incrementing u8 WBFillPointer; // where the next entry should be added; should always be ANDed with 0xF after incrementing u8 WBWriting; // whether the buffer is actively trying to perform a write @@ -796,11 +813,13 @@ public: template void Execute(); - + + Platform::FileHandle* filey; + void (ARMv4::*FuncQueue[31])(void); bool Nonseq; - u16 CodeRead16(u32 addr); - u32 CodeRead32(u32 addr); + void CodeRead16(u32 addr); + void CodeRead32(u32 addr); bool DataRead8(u32 addr, u8 reg) override; bool DataRead16(u32 addr, u8 reg) override; @@ -814,6 +833,34 @@ public: void AddCycles_CI(s32 num) override; void AddCycles_CDI() override; void AddCycles_CD() override; + + inline void QueueFunction(void (ARMv4::*QueueEntry)(void)) + { + if (MRTrack.Type != MainRAMType::Null) + FuncQueue[FuncQueueFill++] = QueueEntry; + else + (this->*QueueEntry)(); + } + + void StartExec(); + void UpdateNextInstr1() { NextInstr[1] = RetVal; } + void JumpTo_2(); + void JumpTo_3A(); + void JumpTo_3B(); + void DRead8_2(); + void DRead16_2(); + void DRead32_2(); + void DRead32S_2(); + void DWrite8_2(); + void DWrite16_2(); + void DWrite32_2(); + void DWrite32S_2(); + void AddExecute(); + void AddExtraCycle(); + void QueueUpdateMode() { UpdateMode(QueueMode[0], QueueMode[1], true); } + void SignExtend8() { R[ExtReg] = (s32)(s8)R[ExtReg]; } + void SignExtend16() { R[ExtReg] = (s32)(s16)R[ExtReg]; } + void ROR32() { R[ExtReg] = ROR(R[ExtReg], ExtROROffs); } protected: u8 BusRead8(u32 addr) override; diff --git a/src/ARMInterpreter.cpp b/src/ARMInterpreter.cpp index 64249fac..671b3d8b 100644 --- a/src/ARMInterpreter.cpp +++ b/src/ARMInterpreter.cpp @@ -37,6 +37,7 @@ namespace melonDS::ARMInterpreter void A_UNK(ARM* cpu) { cpu->AddCycles_C(); + cpu->abt=1; Log(LogLevel::Warn, "undefined ARM%d instruction %08X @ %08X\n", cpu->Num?7:9, cpu->CurInstr, cpu->R[15]-8); #ifdef GDBSTUB_ENABLED cpu->GdbStub.Enter(cpu->GdbStub.IsConnected(), Gdb::TgtStatus::FaultInsn, cpu->R[15]-8); diff --git a/src/ARMInterpreter_LoadStore.cpp b/src/ARMInterpreter_LoadStore.cpp index 6fb39f74..4bf4984e 100644 --- a/src/ARMInterpreter_LoadStore.cpp +++ b/src/ARMInterpreter_LoadStore.cpp @@ -118,40 +118,38 @@ void LoadSingle(ARM* cpu, const u8 rd, const u8 rn, const s32 offset, const u16 if constexpr (size == 8 && signextend) { - if (cpu->Num == 0) - { - cpu->ExtReg = rd; - if (cpu->MRTrack.Type != MainRAMType::Null) ((ARMv5*)cpu)->FuncQueue[cpu->FuncQueueFill++] = &ARMv5::SignExtend8; - else ((ARMv5*)cpu)->SignExtend8(); - } - else cpu->R[rd] = (s32)(s8)cpu->R[rd]; + cpu->ExtReg = rd; + if (cpu->Num == 0) ((ARMv5*)cpu)->QueueFunction(&ARMv5::SignExtend8); + else ((ARMv4*)cpu)->QueueFunction(&ARMv4::SignExtend8); } if constexpr (size == 16) { if (cpu->Num == 1) { - cpu->R[rd] = ROR(cpu->R[rd], ((addr&0x1)<<3)); // unaligned 16 bit loads are ROR'd on arm7 - if constexpr (signextend) cpu->R[rd] = (s32)((addr&0x1) ? (s8)cpu->R[rd] : (s16)cpu->R[rd]); // sign extend like a ldrsb if we ror'd the value. + cpu->ExtReg = rd; + cpu->ExtROROffs = (addr & 0x1) * 8; + ((ARMv4*)cpu)->QueueFunction(&ARMv4::ROR32); // unaligned 16 bit loads are ROR'd on arm7 + + if constexpr (signextend) + { + if (addr&0x1) ((ARMv4*)cpu)->QueueFunction(&ARMv4::SignExtend8); // sign extend like an ldrsb if we ror'd the value. + else ((ARMv4*)cpu)->QueueFunction(&ARMv4::SignExtend16); + } } else if constexpr (signextend) { cpu->ExtReg = rd; - if (cpu->MRTrack.Type != MainRAMType::Null) ((ARMv5*)cpu)->FuncQueue[cpu->FuncQueueFill++] = &ARMv5::SignExtend16; - else ((ARMv5*)cpu)->SignExtend16(); + ((ARMv5*)cpu)->QueueFunction(&ARMv5::SignExtend16); } } if constexpr (size == 32) { - if (cpu->Num == 0) - { - cpu->ExtReg = rd; - cpu->ExtROROffs = (addr & 0x3) * 8; - if (cpu->MRTrack.Type != MainRAMType::Null) ((ARMv5*)cpu)->FuncQueue[cpu->FuncQueueFill++] = &ARMv5::ROR32; - else ((ARMv5*)cpu)->ROR32(); - } - else cpu->R[rd] = ROR(cpu->R[rd], ((addr&0x3)*8)); + cpu->ExtReg = rd; + cpu->ExtROROffs = (addr & 0x3) * 8; + if (cpu->Num == 0) ((ARMv5*)cpu)->QueueFunction(&ARMv5::ROR32); + else ((ARMv4*)cpu)->QueueFunction(&ARMv4::ROR32); } if constexpr (writeback >= Writeback::Post) addr += offset; @@ -172,8 +170,6 @@ void LoadSingle(ARM* cpu, const u8 rd, const u8 rn, const s32 offset, const u16 if (rd == 15) { - if (cpu->Num==1) cpu->R[15] &= ~0x1; - //if (cpu->Num==0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual + ((size<32) || (addr&0x3)); // force an interlock cpu->JumpTo(cpu->R[15], false, 1); @@ -533,14 +529,10 @@ inline void SWP(ARM* cpu) if constexpr (!byte) { - if (cpu->Num == 0) - { - cpu->ExtReg = rd; - cpu->ExtROROffs = (base & 0x3) * 8; - if (cpu->MRTrack.Type != MainRAMType::Null) ((ARMv5*)cpu)->FuncQueue[cpu->FuncQueueFill++] = &ARMv5::ROR32; - else ((ARMv5*)cpu)->ROR32(); - } - else cpu->R[rd] = ROR(cpu->R[rd], ((base&0x3)*8)); + cpu->ExtReg = rd; + cpu->ExtROROffs = (base & 0x3) * 8; + if (cpu->Num == 0) ((ARMv5*)cpu)->QueueFunction(&ARMv5::ROR32); + else ((ARMv4*)cpu)->QueueFunction(&ARMv4::ROR32); } cpu->AddCycles_CDI(); @@ -555,7 +547,6 @@ inline void SWP(ARM* cpu) } else if (cpu->Num==1) // for some reason these jumps don't seem to work on the arm 9? { - cpu->R[rd] = cpu->R[rd] & ~1; cpu->JumpTo(cpu->R[rd], false, 1); } return; @@ -608,7 +599,7 @@ void EmptyRListLDMSTM(ARM* cpu, const u8 baseid, const u8 flags) cpu->AddCycles_CDI(); - cpu->JumpTo(cpu->R[15] & ~1, flags & restoreorthumb, 1); // TODO: fix this not maintaining current mode properly + cpu->JumpTo(cpu->R[15], flags & restoreorthumb, 1); // TODO: fix this not maintaining current mode properly } else { @@ -699,8 +690,6 @@ void A_LDM(ARM* cpu) dabort |= !(first ? cpu->DataRead32 (base, 15) : cpu->DataRead32S(base, 15)); if (dabort) [[unlikely]] { cpu->R[15] = oldval; cpu->LDRFailedRegs |= (1<<15); } - else if (cpu->Num == 1) - cpu->R[15] &= ~0x1; if (!preinc) base += 4; } @@ -723,15 +712,11 @@ void A_LDM(ARM* cpu) { if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15))) { - if (cpu->Num == 0) - { - cpu->QueueMode[0] = (cpu->CPSR&~0x1F)|0x10; - cpu->QueueMode[1] = cpu->CPSR; + cpu->QueueMode[0] = (cpu->CPSR&~0x1F)|0x10; + cpu->QueueMode[1] = cpu->CPSR; - if (cpu->MRTrack.Type != MainRAMType::Null) ((ARMv5*)cpu)->FuncQueue[cpu->FuncQueueFill++] = &ARMv5::QueueUpdateMode; - else ((ARMv5*)cpu)->QueueUpdateMode(); - } - else cpu->UpdateMode((cpu->CPSR&~0x1F)|0x10, cpu->CPSR, true); + if (cpu->Num == 0) ((ARMv5*)cpu)->QueueFunction(&ARMv5::QueueUpdateMode); + else ((ARMv4*)cpu)->QueueFunction(&ARMv4::QueueUpdateMode); } ((ARMv5*)cpu)->DataAbort(); @@ -761,15 +746,11 @@ void A_LDM(ARM* cpu) // switch back to previous regs if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15))) { - if (cpu->Num == 0) - { - cpu->QueueMode[0] = (cpu->CPSR&~0x1F)|0x10; - cpu->QueueMode[1] = cpu->CPSR; + cpu->QueueMode[0] = (cpu->CPSR&~0x1F)|0x10; + cpu->QueueMode[1] = cpu->CPSR; - if (cpu->MRTrack.Type != MainRAMType::Null) ((ARMv5*)cpu)->FuncQueue[cpu->FuncQueueFill++] = &ARMv5::QueueUpdateMode; - else ((ARMv5*)cpu)->QueueUpdateMode(); - } - else cpu->UpdateMode((cpu->CPSR&~0x1F)|0x10, cpu->CPSR, true); + if (cpu->Num == 0) ((ARMv5*)cpu)->QueueFunction(&ARMv5::QueueUpdateMode); + else ((ARMv4*)cpu)->QueueFunction(&ARMv4::QueueUpdateMode); } // jump if pc got written @@ -1120,7 +1101,6 @@ void T_POP(ARM* cpu) if (!dabort) [[likely]] { - if (cpu->Num==1) cpu->R[15] |= 0x1; //if (cpu->Num==0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // force an interlock cpu->JumpTo(cpu->R[15], false, 2); diff --git a/src/CP15.cpp b/src/CP15.cpp index cf5617c3..538c66a4 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -2163,16 +2163,14 @@ bool ARMv5::DataRead8(u32 addr, u8 reg) // Exception is handled in the actual instruction implementation if (!(PU_Map[addr>>12] & CP15_MAP_READABLE)) [[unlikely]] { - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DAbortHandle; - else DAbortHandle(); + QueueFunction(&ARMv5::DAbortHandle); return false; } FetchAddr[reg] = addr; LDRRegs = 1<>12] & CP15_MAP_READABLE)) [[unlikely]] { - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DAbortHandle; - else DAbortHandle(); + QueueFunction(&ARMv5::DAbortHandle); return false; } FetchAddr[reg] = addr; LDRRegs = 1<>12] & CP15_MAP_READABLE)) [[unlikely]] { - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DAbortHandle; - else DAbortHandle(); + QueueFunction(&ARMv5::DAbortHandle); return false; } FetchAddr[reg] = addr; LDRRegs = 1<>12] & CP15_MAP_READABLE)) [[unlikely]] { - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill] = &ARMv5::DAbortHandleS; - else DAbortHandleS(); + QueueFunction(&ARMv5::DAbortHandleS); return false; } FetchAddr[reg] = addr; LDRRegs |= 1<>12] & CP15_MAP_WRITEABLE)) [[unlikely]] { - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DAbortHandle; - else DAbortHandle(); + QueueFunction(&ARMv5::DAbortHandle); return false; } @@ -2594,8 +2585,7 @@ bool ARMv5::DataWrite8(u32 addr, u8 val, u8 reg) STRRegs = 1<>12] & CP15_MAP_WRITEABLE)) [[unlikely]] { - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DAbortHandle; - else DAbortHandle(); + QueueFunction(&ARMv5::DAbortHandle); return false; } @@ -2700,8 +2689,7 @@ bool ARMv5::DataWrite16(u32 addr, u16 val, u8 reg) STRRegs = 1<>12] & CP15_MAP_WRITEABLE)) [[unlikely]] { - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DAbortHandle; - else DAbortHandle(); + QueueFunction(&ARMv5::DAbortHandle); return false; } @@ -2808,8 +2795,7 @@ bool ARMv5::DataWrite32(u32 addr, u32 val, u8 reg) STRRegs = 1<>12] & CP15_MAP_WRITEABLE)) [[unlikely]] { - if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DAbortHandleS; - else DAbortHandleS(); + QueueFunction(&ARMv5::DAbortHandleS); return false; } @@ -2922,8 +2907,7 @@ bool ARMv5::DataWrite32S(u32 addr, u32 val, u8 reg) STRRegs |= 1< 0) // check if we started the queue up + { + ARM9.FuncQueueEnd = ARM9.FuncQueueFill; + ARM9.FuncQueueFill = 0; + ARM9.FuncQueueActive = true; + } + if (ARM7.FuncQueueFill > 0) // check if we started the queue up + { + ARM7.FuncQueueEnd = ARM7.FuncQueueFill; + ARM7.FuncQueueFill = 0; + ARM7.FuncQueueActive = true; + } PostFlag9 = 0x01; PostFlag7 = 0x01; @@ -902,19 +914,17 @@ void NDS::MainRAMHandleARM9() { switch (ARM9.MRTrack.Type) { - case MainRAMType::Null: - Platform::Log(Platform::LogLevel::Error, "NULL MAIN RAM TYPE ARM9"); + default: + { + Platform::Log(Platform::LogLevel::Error, "INVALID MAIN RAM TYPE ARM9"); break; + } + case MainRAMType::ICacheStream: { - if (A9ContentionTS < MainRAMTimestamp) { A9ContentionTS = MainRAMTimestamp; return; } - - //printf("ICACHEHANDLER\n"); - u8* prog = &ARM9.MRTrack.Progress; u32 addr = (ARM9.FetchAddr[16] & ~0x1F) | (*prog * 4); u32* icache = (u32*)&ARM9.ICache[ARM9.MRTrack.Var << 5]; - icache[*prog] = ARM9Read32(addr); if ((*prog > 0) && A9WENTLAST) { @@ -923,11 +933,15 @@ void NDS::MainRAMHandleARM9() } else { + if (A9ContentionTS < MainRAMTimestamp) { A9ContentionTS = MainRAMTimestamp; return; } + MainRAMTimestamp = A9ContentionTS + 9; A9ContentionTS += (ARM9ClockShift == 1) ? 9 : 8; MainRAMLastAccess = A9LAST; } + icache[*prog] = ARM9Read32(addr); + if (*prog == ARM9.ICacheStreamPtr) ARM9Timestamp = (A9ContentionTS << ARM9ClockShift) - 1; else if (*prog > ARM9.ICacheStreamPtr) ARM9.ICacheStreamTimes[*prog-1] = (A9ContentionTS << ARM9ClockShift) - 1; @@ -943,6 +957,42 @@ void NDS::MainRAMHandleARM9() } } +void NDS::MainRAMHandleARM7() +{ + switch (ARM7.MRTrack.Type) + { + default: + { + Platform::Log(Platform::LogLevel::Error, "INVALID MAIN RAM TYPE ARM7"); + break; + } + + case MainRAMType::Fetch: + { + u32 addr = ARM7.FetchAddr[16]; + u8 var = ARM7.MRTrack.Var; + + if ((var & MRSequential) && A7WENTLAST) + { + int cycles = (var & MR32) ? 2 : 1; + MainRAMTimestamp = ARM7Timestamp += cycles; + } + else + { + if (ARM7Timestamp < MainRAMTimestamp) { ARM7Timestamp = MainRAMTimestamp; return; } + + MainRAMTimestamp = ARM7Timestamp + (var & MR16) ? 8 : 9; + ARM7Timestamp += (var & MR16) ? 5 : 6; + } + + if (var & MRCodeFetch) ARM7.RetVal = (var & MR32) ? ARM7Read32(addr) : ARM7Read16(addr); + + memset(&ARM7.MRTrack, 0, sizeof(ARM7.MRTrack)); + break; + } + } +} + void NDS::MainRAMHandle() { if (!A9ContentionTS) @@ -963,7 +1013,8 @@ void NDS::MainRAMHandle() } else { - if (true) return; + if (ARM7.MRTrack.Type == MainRAMType::Null) return; + MainRAMHandleARM7(); } } } @@ -978,7 +1029,8 @@ void NDS::MainRAMHandle() } else { - if (true) return; + if (ARM7.MRTrack.Type == MainRAMType::Null) return; + MainRAMHandleARM7(); } } } @@ -1080,11 +1132,11 @@ u32 NDS::RunFrame() } else if (ARM9.MRTrack.Type == MainRAMType::Null) { - if (ARM9.abt) ARM9Timestamp = ARM9Target; + //if (ARM9.abt) ARM9Timestamp = ARM9Target; ARM9.Execute(); } - //printf("MAIN LOOP: %lli %lli\n", ARM9Timestamp>>ARM9ClockShift, ARM7Timestamp); + //printf("MAIN LOOP: 9 %lli %08X %08llX 7 %lli %08X %08llX %i %08X\n", ARM9Timestamp>>ARM9ClockShift, ARM9.PC, ARM9.CurInstr, ARM7Timestamp, ARM7.R[15], ARM7.CurInstr, IME[1], IE[1]); MainRAMHandle(); @@ -1094,7 +1146,7 @@ u32 NDS::RunFrame() target = ARM9Timestamp >> ARM9ClockShift; CurCPU = 1; - while ((ARM7Timestamp < target) || (ARM9.MRTrack.Type != MainRAMType::Null)) + while (((ARM7Timestamp < target) && (ARM7.MRTrack.Type == MainRAMType::Null)) || (ARM9.MRTrack.Type != MainRAMType::Null)) { ARM7Target = (ARM9.MRTrack.Type != MainRAMType::Null) ? (ARM7Timestamp+1) : target; // might be changed by a reschedule @@ -1112,8 +1164,9 @@ u32 NDS::RunFrame() dsi.RunNDMAs(1); } } - else + else if (ARM7.MRTrack.Type == MainRAMType::Null) { + //if (ARM7.abt > 16) ARM7Timestamp = ARM7Target; ARM7.Execute(); } diff --git a/src/NDS.h b/src/NDS.h index 38d14e88..6263247e 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -402,6 +402,7 @@ public: // TODO: Encapsulate the rest of these members std::unique_ptr EjectGBACart() { return GBACartSlot.EjectCart(); } void MainRAMHandleARM9(); + void MainRAMHandleARM7(); void MainRAMHandle(); u32 RunFrame();