implement arm7 code fetches
This commit is contained in:
parent
6f0a76d130
commit
08435d2272
465
src/ARM.cpp
465
src/ARM.cpp
|
@ -241,6 +241,7 @@ void ARMv5::Reset()
|
||||||
|
|
||||||
void ARMv4::Reset()
|
void ARMv4::Reset()
|
||||||
{
|
{
|
||||||
|
FuncQueue[0] = &ARMv4::StartExec;
|
||||||
Nonseq = true;
|
Nonseq = true;
|
||||||
|
|
||||||
ARM::Reset();
|
ARM::Reset();
|
||||||
|
@ -337,24 +338,26 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr, u8 R15)
|
||||||
BranchRestore = restorecpsr;
|
BranchRestore = restorecpsr;
|
||||||
BranchUpdate = R15;
|
BranchUpdate = R15;
|
||||||
BranchAddr = addr;
|
BranchAddr = addr;
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::JumpTo_2;
|
QueueFunction(&ARMv5::JumpTo_2);
|
||||||
else JumpTo_2();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMv5::JumpTo_2()
|
void ARMv5::JumpTo_2()
|
||||||
{
|
{
|
||||||
if (CP15Control & (1<<15))
|
if (BranchUpdate)
|
||||||
{
|
{
|
||||||
if (BranchUpdate == 1) BranchAddr = R[15] & ~1;
|
if (CP15Control & (1<<15))
|
||||||
else if (BranchUpdate == 2) BranchAddr = R[15] | 1;
|
{
|
||||||
|
if (BranchUpdate == 1) BranchAddr = R[15] & ~1;
|
||||||
|
else BranchAddr = R[15] | 1;
|
||||||
|
}
|
||||||
|
else BranchAddr = R[15];
|
||||||
}
|
}
|
||||||
else if (BranchUpdate) BranchAddr = R[15];
|
|
||||||
|
|
||||||
if (BranchRestore)
|
if (BranchRestore)
|
||||||
{
|
{
|
||||||
RestoreCPSR();
|
RestoreCPSR();
|
||||||
|
|
||||||
if (CPSR & 0x20) BranchAddr |= 0x1;
|
if (CPSR & 0x20) BranchAddr |= 0x1;
|
||||||
else BranchAddr &= ~0x1;
|
else BranchAddr &= ~0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,15 +387,13 @@ void ARMv5::JumpTo_2()
|
||||||
{
|
{
|
||||||
CodeRead32(BranchAddr-2);
|
CodeRead32(BranchAddr-2);
|
||||||
|
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::JumpTo_3A;
|
QueueFunction(&ARMv5::JumpTo_3A);
|
||||||
else JumpTo_3A();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CodeRead32(BranchAddr);
|
CodeRead32(BranchAddr);
|
||||||
|
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::JumpTo_3B;
|
QueueFunction(&ARMv5::JumpTo_3B);
|
||||||
else JumpTo_3B();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -404,8 +405,7 @@ void ARMv5::JumpTo_2()
|
||||||
|
|
||||||
CodeRead32(BranchAddr);
|
CodeRead32(BranchAddr);
|
||||||
|
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::JumpTo_3C;
|
QueueFunction(&ARMv5::JumpTo_3C);
|
||||||
else JumpTo_3C();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,8 +414,7 @@ void ARMv5::JumpTo_3A()
|
||||||
NextInstr[0] = RetVal >> 16;
|
NextInstr[0] = RetVal >> 16;
|
||||||
CodeRead32(BranchAddr+2);
|
CodeRead32(BranchAddr+2);
|
||||||
|
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::JumpTo_4;
|
QueueFunction(&ARMv5::JumpTo_4);
|
||||||
else JumpTo_4();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMv5::JumpTo_3B()
|
void ARMv5::JumpTo_3B()
|
||||||
|
@ -429,8 +428,7 @@ void ARMv5::JumpTo_3C()
|
||||||
NextInstr[0] = RetVal;
|
NextInstr[0] = RetVal;
|
||||||
CodeRead32(BranchAddr+4);
|
CodeRead32(BranchAddr+4);
|
||||||
|
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::JumpTo_4;
|
QueueFunction(&ARMv5::JumpTo_4);
|
||||||
else JumpTo_4();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMv5::JumpTo_4()
|
void ARMv5::JumpTo_4()
|
||||||
|
@ -440,40 +438,71 @@ void ARMv5::JumpTo_4()
|
||||||
|
|
||||||
void ARMv4::JumpTo(u32 addr, bool restorecpsr, u8 R15)
|
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();
|
RestoreCPSR();
|
||||||
|
|
||||||
if (CPSR & 0x20) addr |= 0x1;
|
if (CPSR & 0x20) BranchAddr |= 0x1;
|
||||||
else addr &= ~0x1;
|
else BranchAddr &= ~0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//printf("JUMP2! %08X\n", BranchAddr);
|
||||||
|
|
||||||
if (addr & 0x1)
|
if (BranchAddr & 0x1)
|
||||||
{
|
{
|
||||||
addr &= ~0x1;
|
BranchAddr &= ~0x1;
|
||||||
R[15] = addr+2;
|
R[15] = BranchAddr+2;
|
||||||
|
|
||||||
Nonseq = true;
|
|
||||||
NextInstr[0] = CodeRead16(addr);
|
|
||||||
Nonseq = false;
|
|
||||||
NextInstr[1] = CodeRead16(addr+2);
|
|
||||||
|
|
||||||
CPSR |= 0x20;
|
CPSR |= 0x20;
|
||||||
|
|
||||||
|
Nonseq = true;
|
||||||
|
CodeRead16(BranchAddr);
|
||||||
|
QueueFunction(&ARMv4::JumpTo_3A);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
addr &= ~0x3;
|
BranchAddr &= ~0x3;
|
||||||
R[15] = addr+4;
|
R[15] = BranchAddr+4;
|
||||||
|
|
||||||
Nonseq = true;
|
|
||||||
NextInstr[0] = CodeRead32(addr);
|
|
||||||
Nonseq = false;
|
|
||||||
NextInstr[1] = CodeRead32(addr+4);
|
|
||||||
|
|
||||||
CPSR &= ~0x20;
|
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()
|
void ARM::RestoreCPSR()
|
||||||
{
|
{
|
||||||
u32 oldcpsr = CPSR;
|
u32 oldcpsr = CPSR;
|
||||||
|
@ -632,7 +661,6 @@ template void ARM::TriggerIRQ<CPUExecuteMode::JIT>();
|
||||||
|
|
||||||
void ARMv5::PrefetchAbort()
|
void ARMv5::PrefetchAbort()
|
||||||
{
|
{
|
||||||
abt = true;
|
|
||||||
AddCycles_C();
|
AddCycles_C();
|
||||||
Log(LogLevel::Warn, "ARM9: prefetch abort (%08X)\n", R[15]);
|
Log(LogLevel::Warn, "ARM9: prefetch abort (%08X)\n", R[15]);
|
||||||
|
|
||||||
|
@ -648,7 +676,6 @@ void ARMv5::PrefetchAbort()
|
||||||
|
|
||||||
void ARMv5::DataAbort()
|
void ARMv5::DataAbort()
|
||||||
{
|
{
|
||||||
abt = true;
|
|
||||||
Log(LogLevel::Warn, "ARM9: data abort (%08X) %08llX\n", R[15], CurInstr);
|
Log(LogLevel::Warn, "ARM9: data abort (%08X) %08llX\n", R[15], CurInstr);
|
||||||
|
|
||||||
u32 oldcpsr = CPSR;
|
u32 oldcpsr = CPSR;
|
||||||
|
@ -815,29 +842,11 @@ void ARMv5::Execute()
|
||||||
// check if we're done with the queue, if so, reset everything
|
// check if we're done with the queue, if so, reset everything
|
||||||
if (FuncQueueProg >= FuncQueueEnd)
|
if (FuncQueueProg >= FuncQueueEnd)
|
||||||
{
|
{
|
||||||
|
|
||||||
FuncQueueFill = 0;
|
FuncQueueFill = 0;
|
||||||
FuncQueueProg = 0;
|
FuncQueueProg = 0;
|
||||||
FuncQueueEnd = 0;
|
FuncQueueEnd = 0;
|
||||||
FuncQueueActive = false;
|
FuncQueueActive = false;
|
||||||
FuncQueue[0] = &ARMv5::StartExec;
|
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
|
else
|
||||||
|
@ -852,30 +861,10 @@ void ARMv5::Execute()
|
||||||
FuncQueueFill = 0;
|
FuncQueueFill = 0;
|
||||||
FuncQueueActive = true;
|
FuncQueueActive = true;
|
||||||
}
|
}
|
||||||
else
|
if (MRTrack.Type != MainRAMType::Null) return; // check if we need to resolve main ram
|
||||||
{
|
|
||||||
/*
|
|
||||||
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
|
|
||||||
|
|
||||||
// TODO optimize this shit!!!
|
// TODO optimize this shit!!!
|
||||||
if (Halted)
|
if (!FuncQueueActive && Halted)
|
||||||
{
|
{
|
||||||
if (Halted == 1 && NDS.ARM9Timestamp < NDS.ARM9Target)
|
if (Halted == 1 && NDS.ARM9Timestamp < NDS.ARM9Target)
|
||||||
{
|
{
|
||||||
|
@ -904,6 +893,45 @@ template void ARMv5::Execute<CPUExecuteMode::InterpreterGDB>();
|
||||||
template void ARMv5::Execute<CPUExecuteMode::JIT>();
|
template void ARMv5::Execute<CPUExecuteMode::JIT>();
|
||||||
#endif
|
#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<CPUExecuteMode::Interpreter>();
|
||||||
|
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<CPUExecuteMode::Interpreter>();
|
||||||
|
else if (CheckCondition(CurInstr >> 28)) // actually execute
|
||||||
|
{
|
||||||
|
u32 icode = ((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0);
|
||||||
|
ARMInterpreter::ARMInstrTable[icode](this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
AddCycles_C();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <CPUExecuteMode mode>
|
template <CPUExecuteMode mode>
|
||||||
void ARMv4::Execute()
|
void ARMv4::Execute()
|
||||||
{
|
{
|
||||||
|
@ -921,8 +949,11 @@ void ARMv4::Execute()
|
||||||
Halted = 0;
|
Halted = 0;
|
||||||
if (NDS.IME[1] & 0x1)
|
if (NDS.IME[1] & 0x1)
|
||||||
{
|
{
|
||||||
|
#ifdef JIT_ENABLED
|
||||||
if constexpr (mode == CPUExecuteMode::JIT) TriggerIRQ<mode>();
|
if constexpr (mode == CPUExecuteMode::JIT) TriggerIRQ<mode>();
|
||||||
else IRQ = 1;
|
else
|
||||||
|
#endif
|
||||||
|
IRQ = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -974,48 +1005,84 @@ void ARMv4::Execute()
|
||||||
else
|
else
|
||||||
#endif
|
#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)
|
if (FuncQueueFill == FuncQueueProg)
|
||||||
GdbCheckC();
|
{
|
||||||
|
// we did not get a new addition to the queue; increment and reset ptrs
|
||||||
|
FuncQueueFill = ++FuncQueueProg;
|
||||||
|
|
||||||
// prefetch
|
// check if we're done with the queue, if so, reset everything
|
||||||
R[15] += 2;
|
if (FuncQueueProg >= FuncQueueEnd)
|
||||||
CurInstr = NextInstr[0];
|
{
|
||||||
NextInstr[0] = NextInstr[1];
|
FuncQueueFill = 0;
|
||||||
NextInstr[1] = CodeRead16(R[15]);
|
FuncQueueProg = 0;
|
||||||
|
FuncQueueEnd = 0;
|
||||||
|
FuncQueueActive = false;
|
||||||
|
FuncQueue[0] = &ARMv4::StartExec;
|
||||||
|
|
||||||
if (IRQ && !(CPSR & 0x80)) TriggerIRQ<mode>();
|
/*
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
// actually execute
|
// we got a new addition to the list; redo the current entry
|
||||||
u32 icode = (CurInstr >> 6);
|
FuncQueueFill = FuncQueueProg;
|
||||||
ARMInterpreter::THUMBInstrTable[icode](this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (FuncQueueFill > 0) // check if we started the queue up
|
||||||
|
{
|
||||||
|
FuncQueueEnd = FuncQueueFill;
|
||||||
|
FuncQueueFill = 0;
|
||||||
|
FuncQueueActive = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if constexpr (mode == CPUExecuteMode::InterpreterGDB)
|
/*
|
||||||
GdbCheckC();
|
if (filey == NULL) Platform::OpenFile("REGLOG.bin", Platform::FileMode::Read);
|
||||||
|
|
||||||
// prefetch
|
|
||||||
R[15] += 4;
|
|
||||||
CurInstr = NextInstr[0];
|
|
||||||
NextInstr[0] = NextInstr[1];
|
|
||||||
NextInstr[1] = CodeRead32(R[15]);
|
|
||||||
|
|
||||||
if (IRQ && !(CPSR & 0x80)) TriggerIRQ<mode>();
|
|
||||||
else if (CheckCondition(CurInstr >> 28)) // actually execute
|
|
||||||
{
|
|
||||||
u32 icode = ((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0);
|
|
||||||
ARMInterpreter::ARMInstrTable[icode](this);
|
|
||||||
}
|
|
||||||
else
|
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!!!
|
// TODO optimize this shit!!!
|
||||||
if (Halted)
|
if (!FuncQueueActive && Halted)
|
||||||
{
|
{
|
||||||
if (Halted == 1 && NDS.ARM7Timestamp < NDS.ARM7Target)
|
if (Halted == 1 && NDS.ARM7Timestamp < NDS.ARM7Target)
|
||||||
{
|
{
|
||||||
|
@ -1075,7 +1142,7 @@ void ARMv5::FillPipeline()
|
||||||
|
|
||||||
void ARMv4::FillPipeline()
|
void ARMv4::FillPipeline()
|
||||||
{
|
{
|
||||||
SetupCodeMem(R[15]);
|
/*SetupCodeMem(R[15]);
|
||||||
|
|
||||||
if (CPSR & 0x20)
|
if (CPSR & 0x20)
|
||||||
{
|
{
|
||||||
|
@ -1086,7 +1153,7 @@ void ARMv4::FillPipeline()
|
||||||
{
|
{
|
||||||
NextInstr[0] = CodeRead32(R[15] - 4);
|
NextInstr[0] = CodeRead32(R[15] - 4);
|
||||||
NextInstr[1] = CodeRead32(R[15]);
|
NextInstr[1] = CodeRead32(R[15]);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GDBSTUB_ENABLED
|
#ifdef GDBSTUB_ENABLED
|
||||||
|
@ -1314,8 +1381,7 @@ void ARMv5::CodeFetch()
|
||||||
{
|
{
|
||||||
CodeRead32(PC);
|
CodeRead32(PC);
|
||||||
}
|
}
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::AddExecute;
|
QueueFunction(&ARMv5::AddExecute);
|
||||||
else AddExecute();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMv5::AddExecute()
|
void ARMv5::AddExecute()
|
||||||
|
@ -1328,8 +1394,7 @@ void ARMv5::AddExecute()
|
||||||
void ARMv5::AddCycles_MW(s32 numM)
|
void ARMv5::AddCycles_MW(s32 numM)
|
||||||
{
|
{
|
||||||
DataCycles = numM;
|
DataCycles = numM;
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::AddCycles_MW_2;
|
QueueFunction(&ARMv5::AddCycles_MW_2);
|
||||||
else AddCycles_MW_2();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMv5::AddCycles_MW_2()
|
void ARMv5::AddCycles_MW_2()
|
||||||
|
@ -1389,45 +1454,53 @@ void ARMv5::HandleInterlocksMemory(u8 reg)
|
||||||
ILPrevTime = 16;*/
|
ILPrevTime = 16;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 ARMv4::CodeRead16(u32 addr)
|
void ARMv4::CodeRead16(u32 addr)
|
||||||
{
|
{
|
||||||
if ((addr >> 24) == 0x02)
|
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;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
NDS.ARM7Timestamp += NDS.ARM7MemTimings[addr>>15][Nonseq?0:1];
|
|
||||||
|
|
||||||
if ((addr >> 24) == 0x02)
|
|
||||||
{
|
{
|
||||||
MainRAMTimestamp = NDS.ARM7Timestamp;
|
NDS.ARM7Timestamp += NDS.ARM7MemTimings[addr>>15][Nonseq?0:1];
|
||||||
NDS.ARM7Timestamp -= 3;
|
RetVal = BusRead16(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return BusRead16(addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ARMv4::CodeRead32(u32 addr)
|
void ARMv4::CodeRead32(u32 addr)
|
||||||
{
|
{
|
||||||
if ((addr >> 24) == 0x02)
|
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;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
NDS.ARM7Timestamp += NDS.ARM7MemTimings[addr>>15][Nonseq?2:3];
|
|
||||||
|
|
||||||
if ((addr >> 24) == 0x02)
|
|
||||||
{
|
{
|
||||||
MainRAMTimestamp = NDS.ARM7Timestamp;
|
NDS.ARM7Timestamp += NDS.ARM7MemTimings[addr>>15][Nonseq?2:3];
|
||||||
NDS.ARM7Timestamp -= 3;
|
RetVal = BusRead32(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return BusRead32(addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMv4::DataRead8(u32 addr, u8 reg)
|
bool ARMv4::DataRead8(u32 addr, u8 reg)
|
||||||
{
|
{
|
||||||
u32* val = &R[reg];
|
FetchAddr[reg] = addr;
|
||||||
|
LDRRegs = 1<<reg;
|
||||||
|
|
||||||
|
QueueFunction(&ARMv4::DRead8_2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMv4::DRead8_2()
|
||||||
|
{
|
||||||
|
u8 reg = __builtin_ctz(LDRRegs);
|
||||||
|
u32 addr = FetchAddr[reg];
|
||||||
|
u32 dummy;
|
||||||
|
u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
|
||||||
|
|
||||||
if ((addr >> 24) == 0x02)
|
if ((addr >> 24) == 0x02)
|
||||||
{
|
{
|
||||||
|
@ -1443,12 +1516,24 @@ bool ARMv4::DataRead8(u32 addr, u8 reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
*val = BusRead8(addr);
|
*val = BusRead8(addr);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMv4::DataRead16(u32 addr, u8 reg)
|
bool ARMv4::DataRead16(u32 addr, u8 reg)
|
||||||
{
|
{
|
||||||
u32* val = &R[reg];
|
FetchAddr[reg] = addr;
|
||||||
|
LDRRegs = 1<<reg;
|
||||||
|
|
||||||
|
QueueFunction(&ARMv4::DRead16_2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMv4::DRead16_2()
|
||||||
|
{
|
||||||
|
u8 reg = __builtin_ctz(LDRRegs);
|
||||||
|
u32 addr = FetchAddr[reg];
|
||||||
|
u32 dummy;
|
||||||
|
u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
|
||||||
|
|
||||||
addr &= ~1;
|
addr &= ~1;
|
||||||
|
|
||||||
if ((addr >> 24) == 0x02)
|
if ((addr >> 24) == 0x02)
|
||||||
|
@ -1465,12 +1550,24 @@ bool ARMv4::DataRead16(u32 addr, u8 reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
*val = BusRead16(addr);
|
*val = BusRead16(addr);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMv4::DataRead32(u32 addr, u8 reg)
|
bool ARMv4::DataRead32(u32 addr, u8 reg)
|
||||||
{
|
{
|
||||||
u32* val = &R[reg];
|
FetchAddr[reg] = addr;
|
||||||
|
LDRRegs = 1<<reg;
|
||||||
|
|
||||||
|
QueueFunction(&ARMv4::DRead32_2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMv4::DRead32_2()
|
||||||
|
{
|
||||||
|
u8 reg = __builtin_ctz(LDRRegs);
|
||||||
|
u32 addr = FetchAddr[reg];
|
||||||
|
u32 dummy;
|
||||||
|
u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
|
||||||
|
|
||||||
addr &= ~3;
|
addr &= ~3;
|
||||||
|
|
||||||
if ((addr >> 24) == 0x02)
|
if ((addr >> 24) == 0x02)
|
||||||
|
@ -1487,12 +1584,25 @@ bool ARMv4::DataRead32(u32 addr, u8 reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
*val = BusRead32(addr);
|
*val = BusRead32(addr);
|
||||||
return true;
|
LDRRegs &= ~1<<reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMv4::DataRead32S(u32 addr, u8 reg)
|
bool ARMv4::DataRead32S(u32 addr, u8 reg)
|
||||||
{
|
{
|
||||||
u32* val = &R[reg];
|
FetchAddr[reg] = addr;
|
||||||
|
LDRRegs |= 1<<reg;
|
||||||
|
|
||||||
|
QueueFunction(&ARMv4::DRead32S_2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMv4::DRead32S_2()
|
||||||
|
{
|
||||||
|
u8 reg = __builtin_ctz(LDRRegs);
|
||||||
|
u32 addr = FetchAddr[reg];
|
||||||
|
u32 dummy;
|
||||||
|
u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
|
||||||
|
|
||||||
addr &= ~3;
|
addr &= ~3;
|
||||||
|
|
||||||
if ((addr >> 24) == 0x02)
|
if ((addr >> 24) == 0x02)
|
||||||
|
@ -1509,11 +1619,24 @@ bool ARMv4::DataRead32S(u32 addr, u8 reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
*val = BusRead32(addr);
|
*val = BusRead32(addr);
|
||||||
return true;
|
LDRRegs &= ~1<<reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMv4::DataWrite8(u32 addr, u8 val, u8 reg)
|
bool ARMv4::DataWrite8(u32 addr, u8 val, u8 reg)
|
||||||
{
|
{
|
||||||
|
FetchAddr[reg] = addr;
|
||||||
|
STRRegs = 1<<reg;
|
||||||
|
STRVal[reg] = val;
|
||||||
|
QueueFunction(&ARMv4::DWrite8_2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMv4::DWrite8_2()
|
||||||
|
{
|
||||||
|
u8 reg = __builtin_ctz(STRRegs);
|
||||||
|
u32 addr = FetchAddr[reg];
|
||||||
|
u8 val = STRVal[reg];
|
||||||
|
|
||||||
if ((addr >> 24) == 0x02)
|
if ((addr >> 24) == 0x02)
|
||||||
{
|
{
|
||||||
if (NDS.ARM7Timestamp < MainRAMTimestamp) NDS.ARM7Timestamp = MainRAMTimestamp;
|
if (NDS.ARM7Timestamp < MainRAMTimestamp) NDS.ARM7Timestamp = MainRAMTimestamp;
|
||||||
|
@ -1528,11 +1651,23 @@ bool ARMv4::DataWrite8(u32 addr, u8 val, u8 reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
BusWrite8(addr, val);
|
BusWrite8(addr, val);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMv4::DataWrite16(u32 addr, u16 val, u8 reg)
|
bool ARMv4::DataWrite16(u32 addr, u16 val, u8 reg)
|
||||||
{
|
{
|
||||||
|
FetchAddr[reg] = addr;
|
||||||
|
STRRegs = 1<<reg;
|
||||||
|
STRVal[reg] = val;
|
||||||
|
QueueFunction(&ARMv4::DWrite16_2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMv4::DWrite16_2()
|
||||||
|
{
|
||||||
|
u8 reg = __builtin_ctz(STRRegs);
|
||||||
|
u32 addr = FetchAddr[reg];
|
||||||
|
u16 val = STRVal[reg];
|
||||||
|
|
||||||
addr &= ~1;
|
addr &= ~1;
|
||||||
|
|
||||||
if ((addr >> 24) == 0x02)
|
if ((addr >> 24) == 0x02)
|
||||||
|
@ -1549,11 +1684,23 @@ bool ARMv4::DataWrite16(u32 addr, u16 val, u8 reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
BusWrite16(addr, val);
|
BusWrite16(addr, val);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMv4::DataWrite32(u32 addr, u32 val, u8 reg)
|
bool ARMv4::DataWrite32(u32 addr, u32 val, u8 reg)
|
||||||
{
|
{
|
||||||
|
FetchAddr[reg] = addr;
|
||||||
|
STRRegs = 1<<reg;
|
||||||
|
STRVal[reg] = val;
|
||||||
|
QueueFunction(&ARMv4::DWrite32_2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMv4::DWrite32_2()
|
||||||
|
{
|
||||||
|
u8 reg = __builtin_ctz(STRRegs);
|
||||||
|
u32 addr = FetchAddr[reg];
|
||||||
|
u32 val = STRVal[reg];
|
||||||
|
|
||||||
addr &= ~3;
|
addr &= ~3;
|
||||||
|
|
||||||
if ((addr >> 24) == 0x02)
|
if ((addr >> 24) == 0x02)
|
||||||
|
@ -1570,11 +1717,24 @@ bool ARMv4::DataWrite32(u32 addr, u32 val, u8 reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
BusWrite32(addr, val);
|
BusWrite32(addr, val);
|
||||||
return true;
|
STRRegs &= ~1<<reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMv4::DataWrite32S(u32 addr, u32 val, u8 reg)
|
bool ARMv4::DataWrite32S(u32 addr, u32 val, u8 reg)
|
||||||
{
|
{
|
||||||
|
FetchAddr[reg] = addr;
|
||||||
|
STRRegs |= 1<<reg;
|
||||||
|
STRVal[reg] = val;
|
||||||
|
QueueFunction(&ARMv4::DWrite32S_2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMv4::DWrite32S_2()
|
||||||
|
{
|
||||||
|
u8 reg = __builtin_ctz(STRRegs);
|
||||||
|
u32 addr = FetchAddr[reg];
|
||||||
|
u32 val = STRVal[reg];
|
||||||
|
|
||||||
addr &= ~3;
|
addr &= ~3;
|
||||||
|
|
||||||
if ((addr >> 24) == 0x02)
|
if ((addr >> 24) == 0x02)
|
||||||
|
@ -1591,7 +1751,7 @@ bool ARMv4::DataWrite32S(u32 addr, u32 val, u8 reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
BusWrite32(addr, val);
|
BusWrite32(addr, val);
|
||||||
return true;
|
STRRegs &= ~1<<reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1604,17 +1764,28 @@ void ARMv4::AddCycles_C()
|
||||||
void ARMv4::AddCycles_CI(s32 num)
|
void ARMv4::AddCycles_CI(s32 num)
|
||||||
{
|
{
|
||||||
// code+internal. results in a nonseq code fetch.
|
// code+internal. results in a nonseq code fetch.
|
||||||
NDS.ARM7Timestamp += num;
|
ExecuteCycles = num;
|
||||||
|
|
||||||
Nonseq = true;
|
Nonseq = true;
|
||||||
|
QueueFunction(&ARMv4::AddExecute);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMv4::AddExecute()
|
||||||
|
{
|
||||||
|
NDS.ARM7Timestamp += ExecuteCycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMv4::AddCycles_CDI()
|
void ARMv4::AddCycles_CDI()
|
||||||
{
|
{
|
||||||
// LDR/LDM cycles.
|
// LDR/LDM cycles.
|
||||||
NDS.ARM7Timestamp += 1;
|
|
||||||
|
|
||||||
Nonseq = true;
|
Nonseq = true;
|
||||||
|
QueueFunction(&ARMv4::AddExtraCycle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMv4::AddExtraCycle()
|
||||||
|
{
|
||||||
|
NDS.ARM7Timestamp += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMv4::AddCycles_CD()
|
void ARMv4::AddCycles_CD()
|
||||||
|
|
67
src/ARM.h
67
src/ARM.h
|
@ -26,6 +26,7 @@
|
||||||
#include "MemRegion.h"
|
#include "MemRegion.h"
|
||||||
#include "MemConstants.h"
|
#include "MemConstants.h"
|
||||||
#include "CP15_Constants.h"
|
#include "CP15_Constants.h"
|
||||||
|
#include "Platform.h"
|
||||||
|
|
||||||
#ifdef GDBSTUB_ENABLED
|
#ifdef GDBSTUB_ENABLED
|
||||||
#include "debug/GdbStub.h"
|
#include "debug/GdbStub.h"
|
||||||
|
@ -57,6 +58,17 @@ enum class MainRAMType : u8
|
||||||
{
|
{
|
||||||
Null = 0,
|
Null = 0,
|
||||||
ICacheStream,
|
ICacheStream,
|
||||||
|
Fetch
|
||||||
|
};
|
||||||
|
|
||||||
|
// each one represents a bit in the field
|
||||||
|
enum FetchFlags
|
||||||
|
{
|
||||||
|
MR16 = 0x01,
|
||||||
|
MR32 = 0x02,
|
||||||
|
MRWrite = 0x20,
|
||||||
|
MRSequential = 0x40,
|
||||||
|
MRCodeFetch = 0x80,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MainRAMTrackers
|
struct MainRAMTrackers
|
||||||
|
@ -218,7 +230,9 @@ public:
|
||||||
u16 STRRegs;
|
u16 STRRegs;
|
||||||
u32 FetchAddr[17];
|
u32 FetchAddr[17];
|
||||||
u32 STRVal[16];
|
u32 STRVal[16];
|
||||||
|
|
||||||
|
// debugging crud: REMOVE ME
|
||||||
|
u8 abt;
|
||||||
u64 iter;
|
u64 iter;
|
||||||
|
|
||||||
u8 FuncQueueFill;
|
u8 FuncQueueFill;
|
||||||
|
@ -651,6 +665,14 @@ public:
|
||||||
*/
|
*/
|
||||||
u32 CP15Read(const u32 id) const;
|
u32 CP15Read(const u32 id) const;
|
||||||
|
|
||||||
|
inline void QueueFunction(void (ARMv5::*QueueEntry)(void))
|
||||||
|
{
|
||||||
|
if (MRTrack.Type != MainRAMType::Null)
|
||||||
|
FuncQueue[FuncQueueFill++] = QueueEntry;
|
||||||
|
else
|
||||||
|
(this->*QueueEntry)();
|
||||||
|
}
|
||||||
|
|
||||||
void StartExec();
|
void StartExec();
|
||||||
void AddExecute();
|
void AddExecute();
|
||||||
void AddCycles_MW_2();
|
void AddCycles_MW_2();
|
||||||
|
@ -669,15 +691,12 @@ public:
|
||||||
void DWrite16_2();
|
void DWrite16_2();
|
||||||
void DWrite32_2();
|
void DWrite32_2();
|
||||||
void DWrite32S_2();
|
void DWrite32S_2();
|
||||||
|
|
||||||
void QueueUpdateMode() { UpdateMode(QueueMode[0], QueueMode[1], true); }
|
void QueueUpdateMode() { UpdateMode(QueueMode[0], QueueMode[1], true); }
|
||||||
|
|
||||||
void SignExtend8() { R[ExtReg] = (s32)(s8)R[ExtReg]; }
|
void SignExtend8() { R[ExtReg] = (s32)(s8)R[ExtReg]; }
|
||||||
|
|
||||||
void SignExtend16() { R[ExtReg] = (s32)(s16)R[ExtReg]; }
|
void SignExtend16() { R[ExtReg] = (s32)(s16)R[ExtReg]; }
|
||||||
|
|
||||||
void ROR32() { R[ExtReg] = ROR(R[ExtReg], ExtROROffs); }
|
void ROR32() { R[ExtReg] = ROR(R[ExtReg], ExtROROffs); }
|
||||||
|
|
||||||
|
|
||||||
u32 CP15Control; //! CP15 Register 1: Control Register
|
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
|
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 ICacheStreamTimes[7];
|
||||||
u64 DCacheStreamTimes[7];
|
u64 DCacheStreamTimes[7];
|
||||||
|
|
||||||
bool abt;
|
|
||||||
|
|
||||||
u8 WBWritePointer; // which entry to attempt to write next; should always be ANDed with 0xF after incrementing
|
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 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
|
u8 WBWriting; // whether the buffer is actively trying to perform a write
|
||||||
|
@ -796,11 +813,13 @@ public:
|
||||||
|
|
||||||
template <CPUExecuteMode mode>
|
template <CPUExecuteMode mode>
|
||||||
void Execute();
|
void Execute();
|
||||||
|
|
||||||
|
Platform::FileHandle* filey;
|
||||||
|
void (ARMv4::*FuncQueue[31])(void);
|
||||||
bool Nonseq;
|
bool Nonseq;
|
||||||
|
|
||||||
u16 CodeRead16(u32 addr);
|
void CodeRead16(u32 addr);
|
||||||
u32 CodeRead32(u32 addr);
|
void CodeRead32(u32 addr);
|
||||||
|
|
||||||
bool DataRead8(u32 addr, u8 reg) override;
|
bool DataRead8(u32 addr, u8 reg) override;
|
||||||
bool DataRead16(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_CI(s32 num) override;
|
||||||
void AddCycles_CDI() override;
|
void AddCycles_CDI() override;
|
||||||
void AddCycles_CD() 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:
|
protected:
|
||||||
u8 BusRead8(u32 addr) override;
|
u8 BusRead8(u32 addr) override;
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace melonDS::ARMInterpreter
|
||||||
void A_UNK(ARM* cpu)
|
void A_UNK(ARM* cpu)
|
||||||
{
|
{
|
||||||
cpu->AddCycles_C();
|
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);
|
Log(LogLevel::Warn, "undefined ARM%d instruction %08X @ %08X\n", cpu->Num?7:9, cpu->CurInstr, cpu->R[15]-8);
|
||||||
#ifdef GDBSTUB_ENABLED
|
#ifdef GDBSTUB_ENABLED
|
||||||
cpu->GdbStub.Enter(cpu->GdbStub.IsConnected(), Gdb::TgtStatus::FaultInsn, cpu->R[15]-8);
|
cpu->GdbStub.Enter(cpu->GdbStub.IsConnected(), Gdb::TgtStatus::FaultInsn, cpu->R[15]-8);
|
||||||
|
|
|
@ -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 constexpr (size == 8 && signextend)
|
||||||
{
|
{
|
||||||
if (cpu->Num == 0)
|
cpu->ExtReg = rd;
|
||||||
{
|
if (cpu->Num == 0) ((ARMv5*)cpu)->QueueFunction(&ARMv5::SignExtend8);
|
||||||
cpu->ExtReg = rd;
|
else ((ARMv4*)cpu)->QueueFunction(&ARMv4::SignExtend8);
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (size == 16)
|
if constexpr (size == 16)
|
||||||
{
|
{
|
||||||
if (cpu->Num == 1)
|
if (cpu->Num == 1)
|
||||||
{
|
{
|
||||||
cpu->R[rd] = ROR(cpu->R[rd], ((addr&0x1)<<3)); // unaligned 16 bit loads are ROR'd on arm7
|
cpu->ExtReg = rd;
|
||||||
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->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)
|
else if constexpr (signextend)
|
||||||
{
|
{
|
||||||
cpu->ExtReg = rd;
|
cpu->ExtReg = rd;
|
||||||
if (cpu->MRTrack.Type != MainRAMType::Null) ((ARMv5*)cpu)->FuncQueue[cpu->FuncQueueFill++] = &ARMv5::SignExtend16;
|
((ARMv5*)cpu)->QueueFunction(&ARMv5::SignExtend16);
|
||||||
else ((ARMv5*)cpu)->SignExtend16();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (size == 32)
|
if constexpr (size == 32)
|
||||||
{
|
{
|
||||||
if (cpu->Num == 0)
|
cpu->ExtReg = rd;
|
||||||
{
|
cpu->ExtROROffs = (addr & 0x3) * 8;
|
||||||
cpu->ExtReg = rd;
|
if (cpu->Num == 0) ((ARMv5*)cpu)->QueueFunction(&ARMv5::ROR32);
|
||||||
cpu->ExtROROffs = (addr & 0x3) * 8;
|
else ((ARMv4*)cpu)->QueueFunction(&ARMv4::ROR32);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (writeback >= Writeback::Post) addr += offset;
|
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 (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
|
//if (cpu->Num==0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual + ((size<32) || (addr&0x3)); // force an interlock
|
||||||
|
|
||||||
cpu->JumpTo(cpu->R[15], false, 1);
|
cpu->JumpTo(cpu->R[15], false, 1);
|
||||||
|
@ -533,14 +529,10 @@ inline void SWP(ARM* cpu)
|
||||||
|
|
||||||
if constexpr (!byte)
|
if constexpr (!byte)
|
||||||
{
|
{
|
||||||
if (cpu->Num == 0)
|
cpu->ExtReg = rd;
|
||||||
{
|
cpu->ExtROROffs = (base & 0x3) * 8;
|
||||||
cpu->ExtReg = rd;
|
if (cpu->Num == 0) ((ARMv5*)cpu)->QueueFunction(&ARMv5::ROR32);
|
||||||
cpu->ExtROROffs = (base & 0x3) * 8;
|
else ((ARMv4*)cpu)->QueueFunction(&ARMv4::ROR32);
|
||||||
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->AddCycles_CDI();
|
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?
|
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);
|
cpu->JumpTo(cpu->R[rd], false, 1);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -608,7 +599,7 @@ void EmptyRListLDMSTM(ARM* cpu, const u8 baseid, const u8 flags)
|
||||||
|
|
||||||
cpu->AddCycles_CDI();
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -699,8 +690,6 @@ void A_LDM(ARM* cpu)
|
||||||
dabort |= !(first ? cpu->DataRead32 (base, 15)
|
dabort |= !(first ? cpu->DataRead32 (base, 15)
|
||||||
: cpu->DataRead32S(base, 15));
|
: cpu->DataRead32S(base, 15));
|
||||||
if (dabort) [[unlikely]] { cpu->R[15] = oldval; cpu->LDRFailedRegs |= (1<<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;
|
if (!preinc) base += 4;
|
||||||
}
|
}
|
||||||
|
@ -723,15 +712,11 @@ void A_LDM(ARM* cpu)
|
||||||
{
|
{
|
||||||
if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15)))
|
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;
|
if (cpu->Num == 0) ((ARMv5*)cpu)->QueueFunction(&ARMv5::QueueUpdateMode);
|
||||||
else ((ARMv5*)cpu)->QueueUpdateMode();
|
else ((ARMv4*)cpu)->QueueFunction(&ARMv4::QueueUpdateMode);
|
||||||
}
|
|
||||||
else cpu->UpdateMode((cpu->CPSR&~0x1F)|0x10, cpu->CPSR, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
((ARMv5*)cpu)->DataAbort();
|
((ARMv5*)cpu)->DataAbort();
|
||||||
|
@ -761,15 +746,11 @@ void A_LDM(ARM* cpu)
|
||||||
// switch back to previous regs
|
// switch back to previous regs
|
||||||
if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15)))
|
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;
|
if (cpu->Num == 0) ((ARMv5*)cpu)->QueueFunction(&ARMv5::QueueUpdateMode);
|
||||||
else ((ARMv5*)cpu)->QueueUpdateMode();
|
else ((ARMv4*)cpu)->QueueFunction(&ARMv4::QueueUpdateMode);
|
||||||
}
|
|
||||||
else cpu->UpdateMode((cpu->CPSR&~0x1F)|0x10, cpu->CPSR, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// jump if pc got written
|
// jump if pc got written
|
||||||
|
@ -1120,7 +1101,6 @@ void T_POP(ARM* cpu)
|
||||||
|
|
||||||
if (!dabort) [[likely]]
|
if (!dabort) [[likely]]
|
||||||
{
|
{
|
||||||
if (cpu->Num==1) cpu->R[15] |= 0x1;
|
|
||||||
//if (cpu->Num==0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // force an interlock
|
//if (cpu->Num==0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // force an interlock
|
||||||
|
|
||||||
cpu->JumpTo(cpu->R[15], false, 2);
|
cpu->JumpTo(cpu->R[15], false, 2);
|
||||||
|
|
48
src/CP15.cpp
48
src/CP15.cpp
|
@ -2163,16 +2163,14 @@ bool ARMv5::DataRead8(u32 addr, u8 reg)
|
||||||
// Exception is handled in the actual instruction implementation
|
// Exception is handled in the actual instruction implementation
|
||||||
if (!(PU_Map[addr>>12] & CP15_MAP_READABLE)) [[unlikely]]
|
if (!(PU_Map[addr>>12] & CP15_MAP_READABLE)) [[unlikely]]
|
||||||
{
|
{
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DAbortHandle;
|
QueueFunction(&ARMv5::DAbortHandle);
|
||||||
else DAbortHandle();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FetchAddr[reg] = addr;
|
FetchAddr[reg] = addr;
|
||||||
LDRRegs = 1<<reg;
|
LDRRegs = 1<<reg;
|
||||||
|
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DRead8_2;
|
QueueFunction(&ARMv5::DRead8_2);
|
||||||
else DRead8_2();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2261,16 +2259,14 @@ bool ARMv5::DataRead16(u32 addr, u8 reg)
|
||||||
// Exception is handled in the actual instruction implementation
|
// Exception is handled in the actual instruction implementation
|
||||||
if (!(PU_Map[addr>>12] & CP15_MAP_READABLE)) [[unlikely]]
|
if (!(PU_Map[addr>>12] & CP15_MAP_READABLE)) [[unlikely]]
|
||||||
{
|
{
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DAbortHandle;
|
QueueFunction(&ARMv5::DAbortHandle);
|
||||||
else DAbortHandle();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FetchAddr[reg] = addr;
|
FetchAddr[reg] = addr;
|
||||||
LDRRegs = 1<<reg;
|
LDRRegs = 1<<reg;
|
||||||
|
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DRead16_2;
|
QueueFunction(&ARMv5::DRead16_2);
|
||||||
else DRead16_2();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2361,16 +2357,14 @@ bool ARMv5::DataRead32(u32 addr, u8 reg)
|
||||||
// Exception is handled in the actual instruction implementation
|
// Exception is handled in the actual instruction implementation
|
||||||
if (!(PU_Map[addr>>12] & CP15_MAP_READABLE)) [[unlikely]]
|
if (!(PU_Map[addr>>12] & CP15_MAP_READABLE)) [[unlikely]]
|
||||||
{
|
{
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DAbortHandle;
|
QueueFunction(&ARMv5::DAbortHandle);
|
||||||
else DAbortHandle();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FetchAddr[reg] = addr;
|
FetchAddr[reg] = addr;
|
||||||
LDRRegs = 1<<reg;
|
LDRRegs = 1<<reg;
|
||||||
|
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DRead32_2;
|
QueueFunction(&ARMv5::DRead32_2);
|
||||||
else DRead32_2();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2465,16 +2459,14 @@ bool ARMv5::DataRead32S(u32 addr, u8 reg)
|
||||||
// Exception is handled in the actual instruction implementation
|
// Exception is handled in the actual instruction implementation
|
||||||
if (!(PU_Map[addr>>12] & CP15_MAP_READABLE)) [[unlikely]]
|
if (!(PU_Map[addr>>12] & CP15_MAP_READABLE)) [[unlikely]]
|
||||||
{
|
{
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill] = &ARMv5::DAbortHandleS;
|
QueueFunction(&ARMv5::DAbortHandleS);
|
||||||
else DAbortHandleS();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FetchAddr[reg] = addr;
|
FetchAddr[reg] = addr;
|
||||||
LDRRegs |= 1<<reg;
|
LDRRegs |= 1<<reg;
|
||||||
|
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DRead32S_2;
|
QueueFunction(&ARMv5::DRead32S_2);
|
||||||
else DRead32S_2();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2585,8 +2577,7 @@ bool ARMv5::DataWrite8(u32 addr, u8 val, u8 reg)
|
||||||
// Exception is handled in the actual instruction implementation
|
// Exception is handled in the actual instruction implementation
|
||||||
if (!(PU_Map[addr>>12] & CP15_MAP_WRITEABLE)) [[unlikely]]
|
if (!(PU_Map[addr>>12] & CP15_MAP_WRITEABLE)) [[unlikely]]
|
||||||
{
|
{
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DAbortHandle;
|
QueueFunction(&ARMv5::DAbortHandle);
|
||||||
else DAbortHandle();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2594,8 +2585,7 @@ bool ARMv5::DataWrite8(u32 addr, u8 val, u8 reg)
|
||||||
STRRegs = 1<<reg;
|
STRRegs = 1<<reg;
|
||||||
STRVal[reg] = val;
|
STRVal[reg] = val;
|
||||||
|
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DWrite8_2;
|
QueueFunction(&ARMv5::DWrite8_2);
|
||||||
else DWrite8_2();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2691,8 +2681,7 @@ bool ARMv5::DataWrite16(u32 addr, u16 val, u8 reg)
|
||||||
// Exception is handled in the actual instruction implementation
|
// Exception is handled in the actual instruction implementation
|
||||||
if (!(PU_Map[addr>>12] & CP15_MAP_WRITEABLE)) [[unlikely]]
|
if (!(PU_Map[addr>>12] & CP15_MAP_WRITEABLE)) [[unlikely]]
|
||||||
{
|
{
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DAbortHandle;
|
QueueFunction(&ARMv5::DAbortHandle);
|
||||||
else DAbortHandle();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2700,8 +2689,7 @@ bool ARMv5::DataWrite16(u32 addr, u16 val, u8 reg)
|
||||||
STRRegs = 1<<reg;
|
STRRegs = 1<<reg;
|
||||||
STRVal[reg] = val;
|
STRVal[reg] = val;
|
||||||
|
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DWrite16_2;
|
QueueFunction(&ARMv5::DWrite16_2);
|
||||||
else DWrite16_2();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2799,8 +2787,7 @@ bool ARMv5::DataWrite32(u32 addr, u32 val, u8 reg)
|
||||||
// Exception is handled in the actual instruction implementation
|
// Exception is handled in the actual instruction implementation
|
||||||
if (!(PU_Map[addr>>12] & CP15_MAP_WRITEABLE)) [[unlikely]]
|
if (!(PU_Map[addr>>12] & CP15_MAP_WRITEABLE)) [[unlikely]]
|
||||||
{
|
{
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DAbortHandle;
|
QueueFunction(&ARMv5::DAbortHandle);
|
||||||
else DAbortHandle();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2808,8 +2795,7 @@ bool ARMv5::DataWrite32(u32 addr, u32 val, u8 reg)
|
||||||
STRRegs = 1<<reg;
|
STRRegs = 1<<reg;
|
||||||
STRVal[reg] = val;
|
STRVal[reg] = val;
|
||||||
|
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DWrite32_2;
|
QueueFunction(&ARMv5::DWrite32_2);
|
||||||
else DWrite32_2();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2913,8 +2899,7 @@ bool ARMv5::DataWrite32S(u32 addr, u32 val, u8 reg)
|
||||||
// Exception is handled in the actual instruction implementation
|
// Exception is handled in the actual instruction implementation
|
||||||
if (!(PU_Map[addr>>12] & CP15_MAP_WRITEABLE)) [[unlikely]]
|
if (!(PU_Map[addr>>12] & CP15_MAP_WRITEABLE)) [[unlikely]]
|
||||||
{
|
{
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DAbortHandleS;
|
QueueFunction(&ARMv5::DAbortHandleS);
|
||||||
else DAbortHandleS();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2922,8 +2907,7 @@ bool ARMv5::DataWrite32S(u32 addr, u32 val, u8 reg)
|
||||||
STRRegs |= 1<<reg;
|
STRRegs |= 1<<reg;
|
||||||
STRVal[reg] = val;
|
STRVal[reg] = val;
|
||||||
|
|
||||||
if (MRTrack.Type != MainRAMType::Null) FuncQueue[FuncQueueFill++] = &ARMv5::DWrite32S_2;
|
QueueFunction(&ARMv5::DWrite32S_2);
|
||||||
else DWrite32S_2();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
79
src/NDS.cpp
79
src/NDS.cpp
|
@ -412,6 +412,18 @@ void NDS::SetupDirectBoot(const std::string& romname)
|
||||||
|
|
||||||
ARM9.JumpTo(header.ARM9EntryAddress);
|
ARM9.JumpTo(header.ARM9EntryAddress);
|
||||||
ARM7.JumpTo(header.ARM7EntryAddress);
|
ARM7.JumpTo(header.ARM7EntryAddress);
|
||||||
|
if (ARM9.FuncQueueFill > 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;
|
PostFlag9 = 0x01;
|
||||||
PostFlag7 = 0x01;
|
PostFlag7 = 0x01;
|
||||||
|
@ -902,19 +914,17 @@ void NDS::MainRAMHandleARM9()
|
||||||
{
|
{
|
||||||
switch (ARM9.MRTrack.Type)
|
switch (ARM9.MRTrack.Type)
|
||||||
{
|
{
|
||||||
case MainRAMType::Null:
|
default:
|
||||||
Platform::Log(Platform::LogLevel::Error, "NULL MAIN RAM TYPE ARM9");
|
{
|
||||||
|
Platform::Log(Platform::LogLevel::Error, "INVALID MAIN RAM TYPE ARM9");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case MainRAMType::ICacheStream:
|
case MainRAMType::ICacheStream:
|
||||||
{
|
{
|
||||||
if (A9ContentionTS < MainRAMTimestamp) { A9ContentionTS = MainRAMTimestamp; return; }
|
|
||||||
|
|
||||||
//printf("ICACHEHANDLER\n");
|
|
||||||
|
|
||||||
u8* prog = &ARM9.MRTrack.Progress;
|
u8* prog = &ARM9.MRTrack.Progress;
|
||||||
u32 addr = (ARM9.FetchAddr[16] & ~0x1F) | (*prog * 4);
|
u32 addr = (ARM9.FetchAddr[16] & ~0x1F) | (*prog * 4);
|
||||||
u32* icache = (u32*)&ARM9.ICache[ARM9.MRTrack.Var << 5];
|
u32* icache = (u32*)&ARM9.ICache[ARM9.MRTrack.Var << 5];
|
||||||
icache[*prog] = ARM9Read32(addr);
|
|
||||||
|
|
||||||
if ((*prog > 0) && A9WENTLAST)
|
if ((*prog > 0) && A9WENTLAST)
|
||||||
{
|
{
|
||||||
|
@ -923,11 +933,15 @@ void NDS::MainRAMHandleARM9()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (A9ContentionTS < MainRAMTimestamp) { A9ContentionTS = MainRAMTimestamp; return; }
|
||||||
|
|
||||||
MainRAMTimestamp = A9ContentionTS + 9;
|
MainRAMTimestamp = A9ContentionTS + 9;
|
||||||
A9ContentionTS += (ARM9ClockShift == 1) ? 9 : 8;
|
A9ContentionTS += (ARM9ClockShift == 1) ? 9 : 8;
|
||||||
MainRAMLastAccess = A9LAST;
|
MainRAMLastAccess = A9LAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
icache[*prog] = ARM9Read32(addr);
|
||||||
|
|
||||||
if (*prog == ARM9.ICacheStreamPtr) ARM9Timestamp = (A9ContentionTS << ARM9ClockShift) - 1;
|
if (*prog == ARM9.ICacheStreamPtr) ARM9Timestamp = (A9ContentionTS << ARM9ClockShift) - 1;
|
||||||
else if (*prog > ARM9.ICacheStreamPtr) ARM9.ICacheStreamTimes[*prog-1] = (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()
|
void NDS::MainRAMHandle()
|
||||||
{
|
{
|
||||||
if (!A9ContentionTS)
|
if (!A9ContentionTS)
|
||||||
|
@ -963,7 +1013,8 @@ void NDS::MainRAMHandle()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (true) return;
|
if (ARM7.MRTrack.Type == MainRAMType::Null) return;
|
||||||
|
MainRAMHandleARM7();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -978,7 +1029,8 @@ void NDS::MainRAMHandle()
|
||||||
}
|
}
|
||||||
else
|
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)
|
else if (ARM9.MRTrack.Type == MainRAMType::Null)
|
||||||
{
|
{
|
||||||
if (ARM9.abt) ARM9Timestamp = ARM9Target;
|
//if (ARM9.abt) ARM9Timestamp = ARM9Target;
|
||||||
ARM9.Execute<cpuMode>();
|
ARM9.Execute<cpuMode>();
|
||||||
}
|
}
|
||||||
|
|
||||||
//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();
|
MainRAMHandle();
|
||||||
|
|
||||||
|
@ -1094,7 +1146,7 @@ u32 NDS::RunFrame()
|
||||||
target = ARM9Timestamp >> ARM9ClockShift;
|
target = ARM9Timestamp >> ARM9ClockShift;
|
||||||
CurCPU = 1;
|
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
|
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);
|
dsi.RunNDMAs(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (ARM7.MRTrack.Type == MainRAMType::Null)
|
||||||
{
|
{
|
||||||
|
//if (ARM7.abt > 16) ARM7Timestamp = ARM7Target;
|
||||||
ARM7.Execute<cpuMode>();
|
ARM7.Execute<cpuMode>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -402,6 +402,7 @@ public: // TODO: Encapsulate the rest of these members
|
||||||
std::unique_ptr<GBACart::CartCommon> EjectGBACart() { return GBACartSlot.EjectCart(); }
|
std::unique_ptr<GBACart::CartCommon> EjectGBACart() { return GBACartSlot.EjectCart(); }
|
||||||
|
|
||||||
void MainRAMHandleARM9();
|
void MainRAMHandleARM9();
|
||||||
|
void MainRAMHandleARM7();
|
||||||
void MainRAMHandle();
|
void MainRAMHandle();
|
||||||
|
|
||||||
u32 RunFrame();
|
u32 RunFrame();
|
||||||
|
|
Loading…
Reference in New Issue