begin work on general timing renovation. way shitty because it behaves as if caches were off, so everything will be slow as shit.
This commit is contained in:
parent
808bda9171
commit
172fb4876a
318
src/ARM.cpp
318
src/ARM.cpp
|
@ -22,6 +22,20 @@
|
|||
#include "ARMInterpreter.h"
|
||||
|
||||
|
||||
// instruction timing notes
|
||||
//
|
||||
// * simple instruction: 1S (code)
|
||||
// * LDR: 1N+1N+1I (code/data/internal)
|
||||
// * STR: 1N+1N (code/data)
|
||||
// * LDM: 1N+1N+(n-1)S+1I
|
||||
// * STM: 1N+1N+(n-1)S
|
||||
// * MUL/etc: 1N+xI (code/internal)
|
||||
// * branch: 1N+1S (code/code) (pipeline refill)
|
||||
//
|
||||
// MUL/MLA seems to take 1I on ARM9
|
||||
|
||||
|
||||
|
||||
u32 ARM::ConditionTable[16] =
|
||||
{
|
||||
0xF0F0, // EQ
|
||||
|
@ -49,97 +63,6 @@ ARM::ARM(u32 num)
|
|||
Num = num;
|
||||
|
||||
SetClockShift(0); // safe default
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
Waitstates[0][i] = 1;
|
||||
Waitstates[1][i] = 1;
|
||||
Waitstates[2][i] = 1;
|
||||
Waitstates[3][i] = 1;
|
||||
}
|
||||
|
||||
if (!num)
|
||||
{
|
||||
// ARM9
|
||||
Waitstates[0][0x2] = 1; // main RAM timing, assuming cache hit
|
||||
Waitstates[0][0x3] = 4;
|
||||
Waitstates[0][0x4] = 4;
|
||||
Waitstates[0][0x5] = 5;
|
||||
Waitstates[0][0x6] = 5;
|
||||
Waitstates[0][0x7] = 4;
|
||||
Waitstates[0][0x8] = 19;
|
||||
Waitstates[0][0x9] = 19;
|
||||
Waitstates[0][0xF] = 4;
|
||||
|
||||
Waitstates[1][0x2] = 1;
|
||||
Waitstates[1][0x3] = 8;
|
||||
Waitstates[1][0x4] = 8;
|
||||
Waitstates[1][0x5] = 10;
|
||||
Waitstates[1][0x6] = 10;
|
||||
Waitstates[1][0x7] = 8;
|
||||
Waitstates[1][0x8] = 38;
|
||||
Waitstates[1][0x9] = 38;
|
||||
Waitstates[1][0xF] = 8;
|
||||
|
||||
Waitstates[2][0x2] = 1;
|
||||
Waitstates[2][0x3] = 2;
|
||||
Waitstates[2][0x4] = 2;
|
||||
Waitstates[2][0x5] = 2;
|
||||
Waitstates[2][0x6] = 2;
|
||||
Waitstates[2][0x7] = 2;
|
||||
Waitstates[2][0x8] = 12;
|
||||
Waitstates[2][0x9] = 12;
|
||||
Waitstates[2][0xA] = 20;
|
||||
Waitstates[2][0xF] = 2;
|
||||
|
||||
Waitstates[3][0x2] = 1;
|
||||
Waitstates[3][0x3] = 2;
|
||||
Waitstates[3][0x4] = 2;
|
||||
Waitstates[3][0x5] = 4;
|
||||
Waitstates[3][0x6] = 4;
|
||||
Waitstates[3][0x7] = 2;
|
||||
Waitstates[3][0x8] = 24;
|
||||
Waitstates[3][0x9] = 24;
|
||||
Waitstates[3][0xA] = 20;
|
||||
Waitstates[3][0xF] = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ARM7
|
||||
Waitstates[0][0x0] = 1;
|
||||
Waitstates[0][0x2] = 1;
|
||||
Waitstates[0][0x3] = 1;
|
||||
Waitstates[0][0x4] = 1;
|
||||
Waitstates[0][0x6] = 1;
|
||||
Waitstates[0][0x8] = 6;
|
||||
Waitstates[0][0x9] = 6;
|
||||
|
||||
Waitstates[1][0x0] = 1;
|
||||
Waitstates[1][0x2] = 2;
|
||||
Waitstates[1][0x3] = 1;
|
||||
Waitstates[1][0x4] = 1;
|
||||
Waitstates[1][0x6] = 2;
|
||||
Waitstates[1][0x8] = 12;
|
||||
Waitstates[1][0x9] = 12;
|
||||
|
||||
Waitstates[2][0x0] = 1;
|
||||
Waitstates[2][0x2] = 1;
|
||||
Waitstates[2][0x3] = 1;
|
||||
Waitstates[2][0x4] = 1;
|
||||
Waitstates[2][0x6] = 1;
|
||||
Waitstates[2][0x8] = 6;
|
||||
Waitstates[2][0x9] = 6;
|
||||
Waitstates[2][0xA] = 10;
|
||||
|
||||
Waitstates[3][0x0] = 1;
|
||||
Waitstates[3][0x2] = 2;
|
||||
Waitstates[3][0x3] = 1;
|
||||
Waitstates[3][0x4] = 1;
|
||||
Waitstates[3][0x6] = 2;
|
||||
Waitstates[3][0x8] = 12;
|
||||
Waitstates[3][0x9] = 12;
|
||||
Waitstates[3][0xA] = 10;
|
||||
}
|
||||
}
|
||||
|
||||
ARM::~ARM()
|
||||
|
@ -147,6 +70,16 @@ ARM::~ARM()
|
|||
// dorp
|
||||
}
|
||||
|
||||
ARMv5::ARMv5() : ARM(0)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
ARMv4::ARMv4() : ARM(1)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
void ARM::Reset()
|
||||
{
|
||||
Cycles = 0;
|
||||
|
@ -165,6 +98,13 @@ void ARM::Reset()
|
|||
JumpTo(ExceptionBase);
|
||||
}
|
||||
|
||||
void ARMv5::Reset()
|
||||
{
|
||||
ARM::Reset();
|
||||
CP15Reset();
|
||||
}
|
||||
|
||||
|
||||
void ARM::DoSavestate(Savestate* file)
|
||||
{
|
||||
file->Section((char*)(Num ? "ARM7" : "ARM9"));
|
||||
|
@ -189,14 +129,29 @@ void ARM::DoSavestate(Savestate* file)
|
|||
SetupCodeMem(R[15]); // should fix it
|
||||
}
|
||||
|
||||
void ARMv5::DoSavestate(Savestate* file)
|
||||
{
|
||||
ARM::DoSavestate(file);
|
||||
CP15DoSavestate(file);
|
||||
}
|
||||
|
||||
|
||||
void ARMv5::CalculateTimings()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
void ARMv4::CalculateTimings()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
void ARM::SetupCodeMem(u32 addr)
|
||||
{
|
||||
if (!Num)
|
||||
{
|
||||
if (CP15::GetCodeMemRegion(addr, &CodeMem))
|
||||
return;
|
||||
|
||||
NDS::ARM9GetMemRegion(addr, false, &CodeMem);
|
||||
((ARMv5*)this)->GetCodeMemRegion(addr, &CodeMem);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -204,7 +159,7 @@ void ARM::SetupCodeMem(u32 addr)
|
|||
}
|
||||
}
|
||||
|
||||
void ARM::JumpTo(u32 addr, bool restorecpsr)
|
||||
void ARMv5::JumpTo(u32 addr, bool restorecpsr)
|
||||
{
|
||||
if (restorecpsr)
|
||||
{
|
||||
|
@ -221,16 +176,28 @@ void ARM::JumpTo(u32 addr, bool restorecpsr)
|
|||
|
||||
u32 oldregion = R[15] >> 23;
|
||||
u32 newregion = addr >> 23;
|
||||
//if(!Num)printf("ARM%c branch from %08X to %08X. %03X->%03X\n", Num?'7':'9', R[15], addr, oldregion, newregion);
|
||||
|
||||
if (addr & 0x1)
|
||||
{
|
||||
addr &= ~0x1;
|
||||
R[15] = addr+2;
|
||||
|
||||
if (newregion != oldregion) SetupCodeMem(addr);
|
||||
//if (newregion != oldregion) SetupCodeMem(addr);
|
||||
|
||||
NextInstr[0] = CodeRead16(addr);
|
||||
NextInstr[1] = CodeRead16(addr+2);
|
||||
// two-opcodes-at-once fetch
|
||||
// doesn't matter if we put garbage in the MSbs there
|
||||
if (addr & 0x2)
|
||||
{
|
||||
NextInstr[0] = CodeRead32(addr-2) >> 16;
|
||||
NextInstr[1] = CodeRead32(addr+2);
|
||||
Cycles += NDS::ARM9MemTimings[CodeRegion][2] * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
NextInstr[0] = CodeRead32(addr);
|
||||
NextInstr[1] = NextInstr[0] >> 16;
|
||||
Cycles += NDS::ARM9MemTimings[CodeRegion][2];
|
||||
}
|
||||
|
||||
CPSR |= 0x20;
|
||||
}
|
||||
|
@ -239,10 +206,52 @@ void ARM::JumpTo(u32 addr, bool restorecpsr)
|
|||
addr &= ~0x3;
|
||||
R[15] = addr+4;
|
||||
|
||||
if (newregion != oldregion) SetupCodeMem(addr);
|
||||
//if (newregion != oldregion) SetupCodeMem(addr);
|
||||
|
||||
NextInstr[0] = CodeRead32(addr);
|
||||
NextInstr[1] = CodeRead32(addr+4);
|
||||
Cycles += NDS::ARM9MemTimings[CodeRegion][2] * 2;
|
||||
|
||||
CPSR &= ~0x20;
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv4::JumpTo(u32 addr, bool restorecpsr)
|
||||
{
|
||||
if (restorecpsr)
|
||||
{
|
||||
RestoreCPSR();
|
||||
|
||||
if (CPSR & 0x20) addr |= 0x1;
|
||||
else addr &= ~0x1;
|
||||
}
|
||||
|
||||
u32 oldregion = R[15] >> 23;
|
||||
u32 newregion = addr >> 23;
|
||||
|
||||
if (addr & 0x1)
|
||||
{
|
||||
addr &= ~0x1;
|
||||
R[15] = addr+2;
|
||||
|
||||
//if (newregion != oldregion) SetupCodeMem(addr);
|
||||
|
||||
NextInstr[0] = CodeRead16(addr);
|
||||
NextInstr[1] = CodeRead16(addr+2);
|
||||
Cycles += NDS::ARM7MemTimings[CodeRegion][0] + NDS::ARM7MemTimings[CodeRegion][1];
|
||||
|
||||
CPSR |= 0x20;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr &= ~0x3;
|
||||
R[15] = addr+4;
|
||||
|
||||
//if (newregion != oldregion) SetupCodeMem(addr);
|
||||
|
||||
NextInstr[0] = CodeRead32(addr);
|
||||
NextInstr[1] = CodeRead32(addr+4);
|
||||
Cycles += NDS::ARM7MemTimings[CodeRegion][2] + NDS::ARM7MemTimings[CodeRegion][3];
|
||||
|
||||
CPSR &= ~0x20;
|
||||
}
|
||||
|
@ -373,7 +382,7 @@ void ARM::TriggerIRQ()
|
|||
JumpTo(ExceptionBase + 0x18);
|
||||
}
|
||||
|
||||
s32 ARM::Execute()
|
||||
s32 ARMv5::Execute()
|
||||
{
|
||||
if (Halted)
|
||||
{
|
||||
|
@ -381,19 +390,102 @@ s32 ARM::Execute()
|
|||
{
|
||||
Halted = 0;
|
||||
}
|
||||
else if (NDS::HaltInterrupted(Num))
|
||||
else if (NDS::HaltInterrupted(0))
|
||||
{
|
||||
Halted = 0;
|
||||
if (NDS::IME[Num] & 0x1)
|
||||
if (NDS::IME[0] & 0x1)
|
||||
TriggerIRQ();
|
||||
}
|
||||
else
|
||||
{
|
||||
Cycles = CyclesToRun;
|
||||
NDS::RunTimingCriticalDevices(0, CyclesToRun >> ClockShift);
|
||||
return Cycles;
|
||||
}
|
||||
}
|
||||
|
||||
if (Num == 0) NDS::RunTimingCriticalDevices(0, CyclesToRun >> 1);
|
||||
else NDS::RunTimingCriticalDevices(1, CyclesToRun);
|
||||
Cycles = 0;
|
||||
s32 lastcycles = 0;
|
||||
|
||||
while (Cycles < CyclesToRun)
|
||||
{
|
||||
if (CPSR & 0x20) // THUMB
|
||||
{
|
||||
// prefetch
|
||||
R[15] += 2;
|
||||
CurInstr = NextInstr[0];
|
||||
NextInstr[0] = NextInstr[1];
|
||||
if (R[15] & 0x2) { NextInstr[1] >>= 16; CodeRegion = NDS::Region9_MAX; }
|
||||
else NextInstr[1] = CodeRead32(R[15]);
|
||||
|
||||
// actually execute
|
||||
u32 icode = (CurInstr >> 6) & 0x3FF;
|
||||
ARMInterpreter::THUMBInstrTable[icode](this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// prefetch
|
||||
R[15] += 4;
|
||||
CurInstr = NextInstr[0];
|
||||
NextInstr[0] = NextInstr[1];
|
||||
NextInstr[1] = CodeRead32(R[15]);
|
||||
|
||||
// actually execute
|
||||
if (CheckCondition(CurInstr >> 28))
|
||||
{
|
||||
u32 icode = ((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0);
|
||||
ARMInterpreter::ARMInstrTable[icode](this);
|
||||
}
|
||||
else if ((CurInstr & 0xFE000000) == 0xFA000000)
|
||||
{
|
||||
ARMInterpreter::A_BLX_IMM(this);
|
||||
}
|
||||
else
|
||||
AddCycles_C();
|
||||
}
|
||||
|
||||
s32 diff = Cycles - lastcycles;
|
||||
NDS::RunTimingCriticalDevices(0, diff >> ClockShift);
|
||||
lastcycles = Cycles - (diff & ClockDiffMask);
|
||||
|
||||
// TODO optimize this shit!!!
|
||||
if (Halted)
|
||||
{
|
||||
if (Halted == 1)
|
||||
Cycles = CyclesToRun;
|
||||
break;
|
||||
}
|
||||
if (NDS::IF[0] & NDS::IE[0])
|
||||
{
|
||||
if (NDS::IME[0] & 0x1)
|
||||
TriggerIRQ();
|
||||
}
|
||||
}
|
||||
|
||||
if (Halted == 2)
|
||||
Halted = 0;
|
||||
|
||||
return Cycles;
|
||||
}
|
||||
|
||||
s32 ARMv4::Execute()
|
||||
{
|
||||
if (Halted)
|
||||
{
|
||||
if (Halted == 2)
|
||||
{
|
||||
Halted = 0;
|
||||
}
|
||||
else if (NDS::HaltInterrupted(1))
|
||||
{
|
||||
Halted = 0;
|
||||
if (NDS::IME[1] & 0x1)
|
||||
TriggerIRQ();
|
||||
}
|
||||
else
|
||||
{
|
||||
Cycles = CyclesToRun;
|
||||
NDS::RunTimingCriticalDevices(1, CyclesToRun);
|
||||
return Cycles;
|
||||
}
|
||||
}
|
||||
|
@ -429,15 +521,13 @@ s32 ARM::Execute()
|
|||
u32 icode = ((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0);
|
||||
ARMInterpreter::ARMInstrTable[icode](this);
|
||||
}
|
||||
else if ((CurInstr & 0xFE000000) == 0xFA000000)
|
||||
{
|
||||
ARMInterpreter::A_BLX_IMM(this);
|
||||
}
|
||||
else
|
||||
AddCycles_C();
|
||||
}
|
||||
|
||||
s32 diff = Cycles - lastcycles;
|
||||
NDS::RunTimingCriticalDevices(Num, diff >> ClockShift);
|
||||
lastcycles = Cycles - (diff & ClockDiffMask);
|
||||
NDS::RunTimingCriticalDevices(1, diff);
|
||||
lastcycles = Cycles;
|
||||
|
||||
// TODO optimize this shit!!!
|
||||
if (Halted)
|
||||
|
@ -446,9 +536,9 @@ s32 ARM::Execute()
|
|||
Cycles = CyclesToRun;
|
||||
break;
|
||||
}
|
||||
if (NDS::IF[Num] & NDS::IE[Num])
|
||||
if (NDS::IF[1] & NDS::IE[1])
|
||||
{
|
||||
if (NDS::IME[Num] & 0x1)
|
||||
if (NDS::IME[1] & 0x1)
|
||||
TriggerIRQ();
|
||||
}
|
||||
}
|
||||
|
|
417
src/ARM.h
417
src/ARM.h
|
@ -19,24 +19,29 @@
|
|||
#ifndef ARM_H
|
||||
#define ARM_H
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "types.h"
|
||||
#include "NDS.h"
|
||||
#include "CP15.h"
|
||||
|
||||
// lame
|
||||
#define C_S(x) x
|
||||
#define C_N(x) x
|
||||
#define C_I(x) x
|
||||
|
||||
#define ROR(x, n) (((x) >> (n)) | ((x) << (32-(n))))
|
||||
|
||||
enum
|
||||
{
|
||||
RWFlags_Nonseq = (1<<5),
|
||||
RWFlags_ForceUser = (1<<21),
|
||||
};
|
||||
|
||||
class ARM
|
||||
{
|
||||
public:
|
||||
ARM(u32 num);
|
||||
~ARM(); // destroy shit
|
||||
|
||||
void Reset();
|
||||
virtual void Reset();
|
||||
|
||||
virtual void DoSavestate(Savestate* file);
|
||||
|
||||
void SetClockShift(u32 shift)
|
||||
{
|
||||
|
@ -44,9 +49,9 @@ public:
|
|||
ClockDiffMask = (1<<shift) - 1;
|
||||
}
|
||||
|
||||
void DoSavestate(Savestate* file);
|
||||
virtual void CalculateTimings() = 0;
|
||||
|
||||
void JumpTo(u32 addr, bool restorecpsr = false);
|
||||
virtual void JumpTo(u32 addr, bool restorecpsr = false) = 0;
|
||||
void RestoreCPSR();
|
||||
|
||||
void Halt(u32 halt)
|
||||
|
@ -55,6 +60,7 @@ public:
|
|||
Halted = halt;
|
||||
}
|
||||
|
||||
// TODO: is this actually used??
|
||||
void CheckIRQ()
|
||||
{
|
||||
if (!(NDS::IME[Num] & 0x1)) return;
|
||||
|
@ -64,7 +70,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
s32 Execute();
|
||||
virtual s32 Execute() = 0;
|
||||
|
||||
bool CheckCondition(u32 code)
|
||||
{
|
||||
|
@ -102,133 +108,17 @@ public:
|
|||
void SetupCodeMem(u32 addr);
|
||||
|
||||
|
||||
u16 CodeRead16(u32 addr)
|
||||
{
|
||||
Cycles += Waitstates[0][(addr>>24)&0xF];
|
||||
virtual bool DataRead8(u32 addr, u32* val, u32 flags) = 0;
|
||||
virtual bool DataRead16(u32 addr, u32* val, u32 flags) = 0;
|
||||
virtual bool DataRead32(u32 addr, u32* val, u32 flags) = 0;
|
||||
virtual bool DataWrite8(u32 addr, u8 val, u32 flags) = 0;
|
||||
virtual bool DataWrite16(u32 addr, u16 val, u32 flags) = 0;
|
||||
virtual bool DataWrite32(u32 addr, u32 val, u32 flags) = 0;
|
||||
|
||||
if (CodeMem.Mem) return *(u16*)&CodeMem.Mem[addr & CodeMem.Mask];
|
||||
|
||||
u16 val;
|
||||
// TODO eventually: on ARM9, THUMB opcodes are prefetched with 32bit reads
|
||||
// probably not worth going through the trouble. we can probably just simulate
|
||||
// the timing quirks resulting from this. or not.
|
||||
if (!Num)
|
||||
{
|
||||
if (!CP15::HandleCodeRead16(addr, &val))
|
||||
val = NDS::ARM9Read16(addr);
|
||||
}
|
||||
else
|
||||
val = NDS::ARM7Read16(addr);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
u32 CodeRead32(u32 addr)
|
||||
{
|
||||
Cycles += Waitstates[1][(addr>>24)&0xF];
|
||||
|
||||
if (CodeMem.Mem) return *(u32*)&CodeMem.Mem[addr & CodeMem.Mask];
|
||||
|
||||
u32 val;
|
||||
if (!Num)
|
||||
{
|
||||
if (!CP15::HandleCodeRead32(addr, &val))
|
||||
val = NDS::ARM9Read32(addr);
|
||||
}
|
||||
else
|
||||
val = NDS::ARM7Read32(addr);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
u8 DataRead8(u32 addr, u32 forceuser=0)
|
||||
{
|
||||
u8 val;
|
||||
if (!Num)
|
||||
{
|
||||
if (!CP15::HandleDataRead8(addr, &val, forceuser))
|
||||
val = NDS::ARM9Read8(addr);
|
||||
}
|
||||
else
|
||||
val = NDS::ARM7Read8(addr);
|
||||
|
||||
Cycles += Waitstates[2][(addr>>24)&0xF];
|
||||
return val;
|
||||
}
|
||||
|
||||
u16 DataRead16(u32 addr, u32 forceuser=0)
|
||||
{
|
||||
u16 val;
|
||||
addr &= ~1;
|
||||
if (!Num)
|
||||
{
|
||||
if (!CP15::HandleDataRead16(addr, &val, forceuser))
|
||||
val = NDS::ARM9Read16(addr);
|
||||
}
|
||||
else
|
||||
val = NDS::ARM7Read16(addr);
|
||||
|
||||
Cycles += Waitstates[2][(addr>>24)&0xF];
|
||||
return val;
|
||||
}
|
||||
|
||||
u32 DataRead32(u32 addr, u32 forceuser=0)
|
||||
{
|
||||
u32 val;
|
||||
addr &= ~3;
|
||||
if (!Num)
|
||||
{
|
||||
if (!CP15::HandleDataRead32(addr, &val, forceuser))
|
||||
val = NDS::ARM9Read32(addr);
|
||||
}
|
||||
else
|
||||
val = NDS::ARM7Read32(addr);
|
||||
|
||||
Cycles += Waitstates[3][(addr>>24)&0xF];
|
||||
return val;
|
||||
}
|
||||
|
||||
void DataWrite8(u32 addr, u8 val, u32 forceuser=0)
|
||||
{
|
||||
if (!Num)
|
||||
{
|
||||
if (!CP15::HandleDataWrite8(addr, val, forceuser))
|
||||
NDS::ARM9Write8(addr, val);
|
||||
}
|
||||
else
|
||||
NDS::ARM7Write8(addr, val);
|
||||
|
||||
Cycles += Waitstates[2][(addr>>24)&0xF];
|
||||
}
|
||||
|
||||
void DataWrite16(u32 addr, u16 val, u32 forceuser=0)
|
||||
{
|
||||
addr &= ~1;
|
||||
if (!Num)
|
||||
{
|
||||
if (!CP15::HandleDataWrite16(addr, val, forceuser))
|
||||
NDS::ARM9Write16(addr, val);
|
||||
}
|
||||
else
|
||||
NDS::ARM7Write16(addr, val);
|
||||
|
||||
Cycles += Waitstates[2][(addr>>24)&0xF];
|
||||
}
|
||||
|
||||
void DataWrite32(u32 addr, u32 val, u32 forceuser=0)
|
||||
{
|
||||
addr &= ~3;
|
||||
if (!Num)
|
||||
{
|
||||
if (!CP15::HandleDataWrite32(addr, val, forceuser))
|
||||
NDS::ARM9Write32(addr, val);
|
||||
}
|
||||
else
|
||||
NDS::ARM7Write32(addr, val);
|
||||
|
||||
Cycles += Waitstates[3][(addr>>24)&0xF];
|
||||
}
|
||||
virtual void AddCycles_C() = 0;
|
||||
virtual void AddCycles_CI(s32 num) = 0;
|
||||
virtual void AddCycles_CDI() = 0;
|
||||
virtual void AddCycles_CD() = 0;
|
||||
|
||||
|
||||
u32 Num;
|
||||
|
@ -238,16 +128,15 @@ public:
|
|||
u32 ClockShift;
|
||||
u32 ClockDiffMask;
|
||||
|
||||
// waitstates:
|
||||
// 0=code16 1=code32 2=data16 3=data32
|
||||
// TODO eventually: nonsequential waitstates
|
||||
// TODO NOT MAKE THIS A FUCKING GROSS HACK!!!!!!
|
||||
s32 Waitstates[4][16];
|
||||
|
||||
s32 Cycles;
|
||||
s32 CyclesToRun;
|
||||
u32 Halted;
|
||||
|
||||
int CodeRegion;
|
||||
|
||||
int DataRegion;
|
||||
s32 DataCycles;
|
||||
|
||||
u32 R[16]; // heh
|
||||
u32 CPSR;
|
||||
u32 R_FIQ[8]; // holding SPSR too
|
||||
|
@ -265,6 +154,252 @@ public:
|
|||
static u32 ConditionTable[16];
|
||||
};
|
||||
|
||||
class ARMv5 : public ARM
|
||||
{
|
||||
public:
|
||||
ARMv5();
|
||||
|
||||
void Reset();
|
||||
|
||||
void DoSavestate(Savestate* file);
|
||||
|
||||
void CalculateTimings();
|
||||
|
||||
void JumpTo(u32 addr, bool restorecpsr = false);
|
||||
|
||||
s32 Execute();
|
||||
|
||||
// all code accesses are forced nonseq 32bit
|
||||
u32 CodeRead32(u32 addr);
|
||||
|
||||
bool DataRead8(u32 addr, u32* val, u32 flags);
|
||||
bool DataRead16(u32 addr, u32* val, u32 flags);
|
||||
bool DataRead32(u32 addr, u32* val, u32 flags);
|
||||
bool DataWrite8(u32 addr, u8 val, u32 flags);
|
||||
bool DataWrite16(u32 addr, u16 val, u32 flags);
|
||||
bool DataWrite32(u32 addr, u32 val, u32 flags);
|
||||
|
||||
void AddCycles_C()
|
||||
{
|
||||
// code only. always nonseq 32-bit for ARM9.
|
||||
Cycles += NDS::ARM9MemTimings[CodeRegion][2];
|
||||
}
|
||||
|
||||
void AddCycles_CI(s32 num)
|
||||
{
|
||||
// code+internal
|
||||
Cycles += NDS::ARM9MemTimings[CodeRegion][2] + num;
|
||||
}
|
||||
|
||||
void AddCycles_CDI()
|
||||
{
|
||||
// LDR/LDM cycles. ARM9 seems to skip the internal cycle there.
|
||||
// TODO: ITCM data fetches shouldn't be parallelized, they say
|
||||
s32 numC = NDS::ARM9MemTimings[CodeRegion][2];
|
||||
s32 numD = DataCycles;
|
||||
|
||||
if (DataRegion != CodeRegion)
|
||||
Cycles += std::max(numC + numD - 6, std::max(numC, numD));
|
||||
else
|
||||
Cycles += numC + numD;
|
||||
}
|
||||
|
||||
void AddCycles_CD()
|
||||
{
|
||||
// TODO: ITCM data fetches shouldn't be parallelized, they say
|
||||
s32 numC = NDS::ARM9MemTimings[CodeRegion][2];
|
||||
s32 numD = DataCycles;
|
||||
|
||||
if (DataRegion != CodeRegion)
|
||||
Cycles += std::max(numC + numD - 6, std::max(numC, numD));
|
||||
else
|
||||
Cycles += numC + numD;
|
||||
}
|
||||
|
||||
void GetCodeMemRegion(u32 addr, NDS::MemRegion* region);
|
||||
|
||||
void CP15Reset();
|
||||
void CP15DoSavestate(Savestate* file);
|
||||
|
||||
void UpdateDTCMSetting();
|
||||
void UpdateITCMSetting();
|
||||
|
||||
void CP15Write(u32 id, u32 val);
|
||||
u32 CP15Read(u32 id);
|
||||
|
||||
u32 CP15Control;
|
||||
|
||||
u32 DTCMSetting, ITCMSetting;
|
||||
|
||||
u8 ITCM[0x8000];
|
||||
u32 ITCMSize;
|
||||
u8 DTCM[0x4000];
|
||||
u32 DTCMBase, DTCMSize;
|
||||
};
|
||||
|
||||
class ARMv4 : public ARM
|
||||
{
|
||||
public:
|
||||
ARMv4();
|
||||
|
||||
void CalculateTimings();
|
||||
|
||||
void JumpTo(u32 addr, bool restorecpsr = false);
|
||||
|
||||
s32 Execute();
|
||||
|
||||
u16 CodeRead16(u32 addr)
|
||||
{
|
||||
u32 ret;
|
||||
CodeRegion = NDS::ARM7Read16(addr, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 CodeRead32(u32 addr)
|
||||
{
|
||||
u32 ret;
|
||||
CodeRegion = NDS::ARM7Read32(addr, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DataRead8(u32 addr, u32* val, u32 flags)
|
||||
{
|
||||
DataRegion = NDS::ARM7Read8(addr, val);
|
||||
if (flags & RWFlags_Nonseq)
|
||||
DataCycles = NDS::ARM7MemTimings[DataRegion][0];
|
||||
else
|
||||
DataCycles += NDS::ARM7MemTimings[DataRegion][1];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DataRead16(u32 addr, u32* val, u32 flags)
|
||||
{
|
||||
addr &= ~1;
|
||||
|
||||
DataRegion = NDS::ARM7Read16(addr, val);
|
||||
if (flags & RWFlags_Nonseq)
|
||||
DataCycles = NDS::ARM7MemTimings[DataRegion][0];
|
||||
else
|
||||
DataCycles += NDS::ARM7MemTimings[DataRegion][1];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DataRead32(u32 addr, u32* val, u32 flags)
|
||||
{
|
||||
addr &= ~3;
|
||||
|
||||
DataRegion = NDS::ARM7Read32(addr, val);
|
||||
if (flags & RWFlags_Nonseq)
|
||||
DataCycles = NDS::ARM7MemTimings[DataRegion][2];
|
||||
else
|
||||
DataCycles += NDS::ARM7MemTimings[DataRegion][3];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DataWrite8(u32 addr, u8 val, u32 flags)
|
||||
{
|
||||
DataRegion = NDS::ARM7Write8(addr, val);
|
||||
if (flags & RWFlags_Nonseq)
|
||||
DataCycles = NDS::ARM7MemTimings[DataRegion][0];
|
||||
else
|
||||
DataCycles += NDS::ARM7MemTimings[DataRegion][1];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DataWrite16(u32 addr, u16 val, u32 flags)
|
||||
{
|
||||
addr &= ~1;
|
||||
|
||||
DataRegion = NDS::ARM7Write16(addr, val);
|
||||
if (flags & RWFlags_Nonseq)
|
||||
DataCycles = NDS::ARM7MemTimings[DataRegion][0];
|
||||
else
|
||||
DataCycles += NDS::ARM7MemTimings[DataRegion][1];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DataWrite32(u32 addr, u32 val, u32 flags)
|
||||
{
|
||||
addr &= ~3;
|
||||
|
||||
DataRegion = NDS::ARM7Write32(addr, val);
|
||||
if (flags & RWFlags_Nonseq)
|
||||
DataCycles = NDS::ARM7MemTimings[DataRegion][2];
|
||||
else
|
||||
DataCycles += NDS::ARM7MemTimings[DataRegion][3];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void AddCycles_C()
|
||||
{
|
||||
// code only. this code fetch is sequential.
|
||||
Cycles += NDS::ARM7MemTimings[CodeRegion][(CPSR&0x20)?1:3];
|
||||
}
|
||||
|
||||
void AddCycles_CI(s32 num)
|
||||
{
|
||||
// code+internal. results in a nonseq code fetch.
|
||||
Cycles += NDS::ARM7MemTimings[CodeRegion][(CPSR&0x20)?0:2] + num;
|
||||
}
|
||||
|
||||
void AddCycles_CDI()
|
||||
{
|
||||
// LDR/LDM cycles.
|
||||
s32 numC = NDS::ARM7MemTimings[CodeRegion][(CPSR&0x20)?0:2];
|
||||
s32 numD = DataCycles;
|
||||
|
||||
if (DataRegion == NDS::Region7_MainRAM)
|
||||
{
|
||||
if (CodeRegion == NDS::Region7_MainRAM)
|
||||
Cycles += numC + numD;
|
||||
else
|
||||
{
|
||||
numC++;
|
||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||
}
|
||||
}
|
||||
else if (CodeRegion == NDS::Region7_MainRAM)
|
||||
{
|
||||
numD++;
|
||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||
}
|
||||
else
|
||||
{
|
||||
Cycles += numC + numD + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void AddCycles_CD()
|
||||
{
|
||||
// TODO: max gain should be 5c when writing to mainRAM
|
||||
s32 numC = NDS::ARM7MemTimings[CodeRegion][(CPSR&0x20)?0:2];
|
||||
s32 numD = DataCycles;
|
||||
|
||||
if (DataRegion == NDS::Region7_MainRAM)
|
||||
{
|
||||
if (CodeRegion == NDS::Region7_MainRAM)
|
||||
Cycles += numC + numD;
|
||||
else
|
||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||
}
|
||||
else if (CodeRegion == NDS::Region7_MainRAM)
|
||||
{
|
||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||
}
|
||||
else
|
||||
{
|
||||
Cycles += numC + numD;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace ARMInterpreter
|
||||
{
|
||||
|
||||
|
|
|
@ -98,6 +98,8 @@ void A_MSR_IMM(ARM* cpu)
|
|||
|
||||
if (!(cpu->CurInstr & (1<<22)))
|
||||
cpu->UpdateMode(oldpsr, cpu->CPSR);
|
||||
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void A_MSR_REG(ARM* cpu)
|
||||
|
@ -138,6 +140,8 @@ void A_MSR_REG(ARM* cpu)
|
|||
|
||||
if (!(cpu->CurInstr & (1<<22)))
|
||||
cpu->UpdateMode(oldpsr, cpu->CPSR);
|
||||
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void A_MRS(ARM* cpu)
|
||||
|
@ -159,6 +163,7 @@ void A_MRS(ARM* cpu)
|
|||
psr = cpu->CPSR;
|
||||
|
||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = psr;
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
|
||||
|
@ -172,7 +177,7 @@ void A_MCR(ARM* cpu)
|
|||
|
||||
if (cpu->Num==0 && cp==15)
|
||||
{
|
||||
CP15::Write((cn<<8)|(cm<<4)|cpinfo, cpu->R[(cpu->CurInstr>>12)&0xF]);
|
||||
((ARMv5*)cpu)->CP15Write((cn<<8)|(cm<<4)|cpinfo, cpu->R[(cpu->CurInstr>>12)&0xF]);
|
||||
}
|
||||
else if (cpu->Num==1 && cp==14)
|
||||
{
|
||||
|
@ -184,7 +189,7 @@ void A_MCR(ARM* cpu)
|
|||
return A_UNK(cpu); // TODO: check what kind of exception it really is
|
||||
}
|
||||
|
||||
cpu->Cycles += 2; // TODO: checkme
|
||||
cpu->AddCycles_CI(1 + 1); // TODO: checkme
|
||||
}
|
||||
|
||||
void A_MRC(ARM* cpu)
|
||||
|
@ -197,7 +202,7 @@ void A_MRC(ARM* cpu)
|
|||
|
||||
if (cpu->Num==0 && cp==15)
|
||||
{
|
||||
cpu->R[(cpu->CurInstr>>12)&0xF] = CP15::Read((cn<<8)|(cm<<4)|cpinfo);
|
||||
cpu->R[(cpu->CurInstr>>12)&0xF] = ((ARMv5*)cpu)->CP15Read((cn<<8)|(cm<<4)|cpinfo);
|
||||
}
|
||||
else if (cpu->Num==1 && cp==14)
|
||||
{
|
||||
|
@ -209,7 +214,7 @@ void A_MRC(ARM* cpu)
|
|||
return A_UNK(cpu); // TODO: check what kind of exception it really is
|
||||
}
|
||||
|
||||
cpu->Cycles += 3; // TODO: checkme
|
||||
cpu->AddCycles_CI(2 + 1); // TODO: checkme
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -282,7 +282,7 @@ void A_##x##_REG_ROR_REG(ARM* cpu) \
|
|||
#define A_AND(c) \
|
||||
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 res = a & b; \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res); \
|
||||
|
@ -297,7 +297,7 @@ void A_##x##_REG_ROR_REG(ARM* cpu) \
|
|||
u32 res = a & b; \
|
||||
cpu->SetNZ(res & 0x80000000, \
|
||||
!res); \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res, true); \
|
||||
|
@ -313,7 +313,7 @@ A_IMPLEMENT_ALU_OP(AND,_S)
|
|||
#define A_EOR(c) \
|
||||
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 res = a ^ b; \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res); \
|
||||
|
@ -328,7 +328,7 @@ A_IMPLEMENT_ALU_OP(AND,_S)
|
|||
u32 res = a ^ b; \
|
||||
cpu->SetNZ(res & 0x80000000, \
|
||||
!res); \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res, true); \
|
||||
|
@ -344,7 +344,7 @@ A_IMPLEMENT_ALU_OP(EOR,_S)
|
|||
#define A_SUB(c) \
|
||||
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 res = a - b; \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res); \
|
||||
|
@ -361,7 +361,7 @@ A_IMPLEMENT_ALU_OP(EOR,_S)
|
|||
!res, \
|
||||
CARRY_SUB(a, b), \
|
||||
OVERFLOW_SUB(a, b, res)); \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res, true); \
|
||||
|
@ -377,7 +377,7 @@ A_IMPLEMENT_ALU_OP(SUB,)
|
|||
#define A_RSB(c) \
|
||||
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 res = b - a; \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res); \
|
||||
|
@ -394,7 +394,7 @@ A_IMPLEMENT_ALU_OP(SUB,)
|
|||
!res, \
|
||||
CARRY_SUB(b, a), \
|
||||
OVERFLOW_SUB(b, a, res)); \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res, true); \
|
||||
|
@ -410,7 +410,7 @@ A_IMPLEMENT_ALU_OP(RSB,)
|
|||
#define A_ADD(c) \
|
||||
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 res = a + b; \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res); \
|
||||
|
@ -427,7 +427,7 @@ A_IMPLEMENT_ALU_OP(RSB,)
|
|||
!res, \
|
||||
CARRY_ADD(a, b), \
|
||||
OVERFLOW_ADD(a, b, res)); \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res, true); \
|
||||
|
@ -443,7 +443,7 @@ A_IMPLEMENT_ALU_OP(ADD,)
|
|||
#define A_ADC(c) \
|
||||
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 res = a + b + (cpu->CPSR&0x20000000 ? 1:0); \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res); \
|
||||
|
@ -462,7 +462,7 @@ A_IMPLEMENT_ALU_OP(ADD,)
|
|||
!res, \
|
||||
CARRY_ADD(a, b) | CARRY_ADD(res_tmp, carry), \
|
||||
OVERFLOW_ADD(a, b, res_tmp) | OVERFLOW_ADD(res_tmp, carry, res)); \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res, true); \
|
||||
|
@ -478,7 +478,7 @@ A_IMPLEMENT_ALU_OP(ADC,)
|
|||
#define A_SBC(c) \
|
||||
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 res = a - b - (cpu->CPSR&0x20000000 ? 0:1); \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res); \
|
||||
|
@ -497,7 +497,7 @@ A_IMPLEMENT_ALU_OP(ADC,)
|
|||
!res, \
|
||||
CARRY_SUB(a, b) & CARRY_SUB(res_tmp, carry), \
|
||||
OVERFLOW_SUB(a, b, res_tmp) | OVERFLOW_SUB(res_tmp, carry, res)); \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res, true); \
|
||||
|
@ -513,7 +513,7 @@ A_IMPLEMENT_ALU_OP(SBC,)
|
|||
#define A_RSC(c) \
|
||||
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 res = b - a - (cpu->CPSR&0x20000000 ? 0:1); \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res); \
|
||||
|
@ -532,7 +532,7 @@ A_IMPLEMENT_ALU_OP(SBC,)
|
|||
!res, \
|
||||
CARRY_SUB(b, a) & CARRY_SUB(res_tmp, carry), \
|
||||
OVERFLOW_SUB(b, a, res_tmp) | OVERFLOW_SUB(res_tmp, carry, res)); \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res, true); \
|
||||
|
@ -550,7 +550,7 @@ A_IMPLEMENT_ALU_OP(RSC,)
|
|||
u32 res = a & b; \
|
||||
cpu->SetNZ(res & 0x80000000, \
|
||||
!res); \
|
||||
cpu->Cycles += c;
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C();
|
||||
|
||||
A_IMPLEMENT_ALU_TEST(TST,_S)
|
||||
|
||||
|
@ -560,7 +560,7 @@ A_IMPLEMENT_ALU_TEST(TST,_S)
|
|||
u32 res = a ^ b; \
|
||||
cpu->SetNZ(res & 0x80000000, \
|
||||
!res); \
|
||||
cpu->Cycles += c;
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C();
|
||||
|
||||
A_IMPLEMENT_ALU_TEST(TEQ,_S)
|
||||
|
||||
|
@ -572,7 +572,7 @@ A_IMPLEMENT_ALU_TEST(TEQ,_S)
|
|||
!res, \
|
||||
CARRY_SUB(a, b), \
|
||||
OVERFLOW_SUB(a, b, res)); \
|
||||
cpu->Cycles += c;
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C();
|
||||
|
||||
A_IMPLEMENT_ALU_TEST(CMP,)
|
||||
|
||||
|
@ -584,7 +584,7 @@ A_IMPLEMENT_ALU_TEST(CMP,)
|
|||
!res, \
|
||||
CARRY_ADD(a, b), \
|
||||
OVERFLOW_ADD(a, b, res)); \
|
||||
cpu->Cycles += c;
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C();
|
||||
|
||||
A_IMPLEMENT_ALU_TEST(CMN,)
|
||||
|
||||
|
@ -592,7 +592,7 @@ A_IMPLEMENT_ALU_TEST(CMN,)
|
|||
#define A_ORR(c) \
|
||||
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 res = a | b; \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res); \
|
||||
|
@ -607,7 +607,7 @@ A_IMPLEMENT_ALU_TEST(CMN,)
|
|||
u32 res = a | b; \
|
||||
cpu->SetNZ(res & 0x80000000, \
|
||||
!res); \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res, true); \
|
||||
|
@ -621,7 +621,7 @@ A_IMPLEMENT_ALU_OP(ORR,_S)
|
|||
|
||||
|
||||
#define A_MOV(c) \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(b); \
|
||||
|
@ -634,7 +634,7 @@ A_IMPLEMENT_ALU_OP(ORR,_S)
|
|||
#define A_MOV_S(c) \
|
||||
cpu->SetNZ(b & 0x80000000, \
|
||||
!b); \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(b, true); \
|
||||
|
@ -650,7 +650,7 @@ A_IMPLEMENT_ALU_OP(MOV,_S)
|
|||
#define A_BIC(c) \
|
||||
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 res = a & ~b; \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res); \
|
||||
|
@ -665,7 +665,7 @@ A_IMPLEMENT_ALU_OP(MOV,_S)
|
|||
u32 res = a & ~b; \
|
||||
cpu->SetNZ(res & 0x80000000, \
|
||||
!res); \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(res, true); \
|
||||
|
@ -680,7 +680,7 @@ A_IMPLEMENT_ALU_OP(BIC,_S)
|
|||
|
||||
#define A_MVN(c) \
|
||||
b = ~b; \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(b); \
|
||||
|
@ -694,7 +694,7 @@ A_IMPLEMENT_ALU_OP(BIC,_S)
|
|||
b = ~b; \
|
||||
cpu->SetNZ(b & 0x80000000, \
|
||||
!b); \
|
||||
cpu->Cycles += c; \
|
||||
if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
cpu->JumpTo(b, true); \
|
||||
|
@ -724,12 +724,17 @@ void A_MUL(ARM* cpu)
|
|||
}
|
||||
|
||||
u32 cycles;
|
||||
if ((rs & 0xFFFFFF00) == 0x00000000 || (rs & 0xFFFFFF00) == 0xFFFFFF00) cycles = 1;
|
||||
else if ((rs & 0xFFFF0000) == 0x00000000 || (rs & 0xFFFF0000) == 0xFFFF0000) cycles = 2;
|
||||
else if ((rs & 0xFF000000) == 0x00000000 || (rs & 0xFF000000) == 0xFF000000) cycles = 3;
|
||||
else cycles = 4;
|
||||
if (cpu->Num == 0)
|
||||
cycles = (cpu->CurInstr & (1<<20)) ? 3 : 1;
|
||||
else
|
||||
{
|
||||
if ((rs & 0xFFFFFF00) == 0x00000000 || (rs & 0xFFFFFF00) == 0xFFFFFF00) cycles = 1;
|
||||
else if ((rs & 0xFFFF0000) == 0x00000000 || (rs & 0xFFFF0000) == 0xFFFF0000) cycles = 2;
|
||||
else if ((rs & 0xFF000000) == 0x00000000 || (rs & 0xFF000000) == 0xFF000000) cycles = 3;
|
||||
else cycles = 4;
|
||||
}
|
||||
|
||||
cpu->Cycles += cycles;
|
||||
cpu->AddCycles_CI(cycles);
|
||||
}
|
||||
|
||||
void A_MLA(ARM* cpu)
|
||||
|
@ -749,12 +754,17 @@ void A_MLA(ARM* cpu)
|
|||
}
|
||||
|
||||
u32 cycles;
|
||||
if ((rs & 0xFFFFFF00) == 0x00000000 || (rs & 0xFFFFFF00) == 0xFFFFFF00) cycles = 2;
|
||||
else if ((rs & 0xFFFF0000) == 0x00000000 || (rs & 0xFFFF0000) == 0xFFFF0000) cycles = 3;
|
||||
else if ((rs & 0xFF000000) == 0x00000000 || (rs & 0xFF000000) == 0xFF000000) cycles = 4;
|
||||
else cycles = 5;
|
||||
if (cpu->Num == 0)
|
||||
cycles = (cpu->CurInstr & (1<<20)) ? 3 : 1;
|
||||
else
|
||||
{
|
||||
if ((rs & 0xFFFFFF00) == 0x00000000 || (rs & 0xFFFFFF00) == 0xFFFFFF00) cycles = 2;
|
||||
else if ((rs & 0xFFFF0000) == 0x00000000 || (rs & 0xFFFF0000) == 0xFFFF0000) cycles = 3;
|
||||
else if ((rs & 0xFF000000) == 0x00000000 || (rs & 0xFF000000) == 0xFF000000) cycles = 4;
|
||||
else cycles = 5;
|
||||
}
|
||||
|
||||
cpu->Cycles += cycles;
|
||||
cpu->AddCycles_CI(cycles);
|
||||
}
|
||||
|
||||
void A_UMULL(ARM* cpu)
|
||||
|
@ -774,12 +784,17 @@ void A_UMULL(ARM* cpu)
|
|||
}
|
||||
|
||||
u32 cycles;
|
||||
if ((rs & 0xFFFFFF00) == 0x00000000) cycles = 2;
|
||||
else if ((rs & 0xFFFF0000) == 0x00000000) cycles = 3;
|
||||
else if ((rs & 0xFF000000) == 0x00000000) cycles = 4;
|
||||
else cycles = 5;
|
||||
if (cpu->Num == 0)
|
||||
cycles = (cpu->CurInstr & (1<<20)) ? 3 : 1;
|
||||
else
|
||||
{
|
||||
if ((rs & 0xFFFFFF00) == 0x00000000) cycles = 2;
|
||||
else if ((rs & 0xFFFF0000) == 0x00000000) cycles = 3;
|
||||
else if ((rs & 0xFF000000) == 0x00000000) cycles = 4;
|
||||
else cycles = 5;
|
||||
}
|
||||
|
||||
cpu->Cycles += cycles;
|
||||
cpu->AddCycles_CI(cycles);
|
||||
}
|
||||
|
||||
void A_UMLAL(ARM* cpu)
|
||||
|
@ -802,12 +817,17 @@ void A_UMLAL(ARM* cpu)
|
|||
}
|
||||
|
||||
u32 cycles;
|
||||
if ((rs & 0xFFFFFF00) == 0x00000000) cycles = 2;
|
||||
else if ((rs & 0xFFFF0000) == 0x00000000) cycles = 3;
|
||||
else if ((rs & 0xFF000000) == 0x00000000) cycles = 4;
|
||||
else cycles = 5;
|
||||
if (cpu->Num == 0)
|
||||
cycles = (cpu->CurInstr & (1<<20)) ? 3 : 1;
|
||||
else
|
||||
{
|
||||
if ((rs & 0xFFFFFF00) == 0x00000000) cycles = 2;
|
||||
else if ((rs & 0xFFFF0000) == 0x00000000) cycles = 3;
|
||||
else if ((rs & 0xFF000000) == 0x00000000) cycles = 4;
|
||||
else cycles = 5;
|
||||
}
|
||||
|
||||
cpu->Cycles += cycles;
|
||||
cpu->AddCycles_CI(cycles);
|
||||
}
|
||||
|
||||
void A_SMULL(ARM* cpu)
|
||||
|
@ -827,12 +847,17 @@ void A_SMULL(ARM* cpu)
|
|||
}
|
||||
|
||||
u32 cycles;
|
||||
if ((rs & 0xFFFFFF00) == 0x00000000 || (rs & 0xFFFFFF00) == 0xFFFFFF00) cycles = 2;
|
||||
else if ((rs & 0xFFFF0000) == 0x00000000 || (rs & 0xFFFF0000) == 0xFFFF0000) cycles = 3;
|
||||
else if ((rs & 0xFF000000) == 0x00000000 || (rs & 0xFF000000) == 0xFF000000) cycles = 4;
|
||||
else cycles = 5;
|
||||
if (cpu->Num == 0)
|
||||
cycles = (cpu->CurInstr & (1<<20)) ? 3 : 1;
|
||||
else
|
||||
{
|
||||
if ((rs & 0xFFFFFF00) == 0x00000000 || (rs & 0xFFFFFF00) == 0xFFFFFF00) cycles = 2;
|
||||
else if ((rs & 0xFFFF0000) == 0x00000000 || (rs & 0xFFFF0000) == 0xFFFF0000) cycles = 3;
|
||||
else if ((rs & 0xFF000000) == 0x00000000 || (rs & 0xFF000000) == 0xFF000000) cycles = 4;
|
||||
else cycles = 5;
|
||||
}
|
||||
|
||||
cpu->Cycles += cycles;
|
||||
cpu->AddCycles_CI(cycles);
|
||||
}
|
||||
|
||||
void A_SMLAL(ARM* cpu)
|
||||
|
@ -855,12 +880,17 @@ void A_SMLAL(ARM* cpu)
|
|||
}
|
||||
|
||||
u32 cycles;
|
||||
if ((rs & 0xFFFFFF00) == 0x00000000 || (rs & 0xFFFFFF00) == 0xFFFFFF00) cycles = 2;
|
||||
else if ((rs & 0xFFFF0000) == 0x00000000 || (rs & 0xFFFF0000) == 0xFFFF0000) cycles = 3;
|
||||
else if ((rs & 0xFF000000) == 0x00000000 || (rs & 0xFF000000) == 0xFF000000) cycles = 4;
|
||||
else cycles = 5;
|
||||
if (cpu->Num == 0)
|
||||
cycles = (cpu->CurInstr & (1<<20)) ? 3 : 1;
|
||||
else
|
||||
{
|
||||
if ((rs & 0xFFFFFF00) == 0x00000000 || (rs & 0xFFFFFF00) == 0xFFFFFF00) cycles = 2;
|
||||
else if ((rs & 0xFFFF0000) == 0x00000000 || (rs & 0xFFFF0000) == 0xFFFF0000) cycles = 3;
|
||||
else if ((rs & 0xFF000000) == 0x00000000 || (rs & 0xFF000000) == 0xFF000000) cycles = 4;
|
||||
else cycles = 5;
|
||||
}
|
||||
|
||||
cpu->Cycles += cycles;
|
||||
cpu->AddCycles_CI(cycles);
|
||||
}
|
||||
|
||||
void A_SMLAxy(ARM* cpu)
|
||||
|
@ -882,6 +912,8 @@ void A_SMLAxy(ARM* cpu)
|
|||
cpu->R[(cpu->CurInstr >> 16) & 0xF] = res;
|
||||
if (OVERFLOW_ADD(res_mul, rn, res))
|
||||
cpu->CPSR |= 0x08000000;
|
||||
|
||||
cpu->AddCycles_C(); // TODO: interlock??
|
||||
}
|
||||
|
||||
void A_SMLAWy(ARM* cpu)
|
||||
|
@ -901,6 +933,8 @@ void A_SMLAWy(ARM* cpu)
|
|||
cpu->R[(cpu->CurInstr >> 16) & 0xF] = res;
|
||||
if (OVERFLOW_ADD(res_mul, rn, res))
|
||||
cpu->CPSR |= 0x08000000;
|
||||
|
||||
cpu->AddCycles_C(); // TODO: interlock??
|
||||
}
|
||||
|
||||
void A_SMULxy(ARM* cpu)
|
||||
|
@ -918,6 +952,7 @@ void A_SMULxy(ARM* cpu)
|
|||
u32 res = ((s16)rm * (s16)rs);
|
||||
|
||||
cpu->R[(cpu->CurInstr >> 16) & 0xF] = res;
|
||||
cpu->AddCycles_C(); // TODO: interlock??
|
||||
}
|
||||
|
||||
void A_SMULWy(ARM* cpu)
|
||||
|
@ -933,6 +968,7 @@ void A_SMULWy(ARM* cpu)
|
|||
u32 res = ((s64)(s32)rm * (s16)rs) >> 16;
|
||||
|
||||
cpu->R[(cpu->CurInstr >> 16) & 0xF] = res;
|
||||
cpu->AddCycles_C(); // TODO: interlock??
|
||||
}
|
||||
|
||||
void A_SMLALxy(ARM* cpu)
|
||||
|
@ -955,7 +991,7 @@ void A_SMLALxy(ARM* cpu)
|
|||
cpu->R[(cpu->CurInstr >> 12) & 0xF] = (u32)res;
|
||||
cpu->R[(cpu->CurInstr >> 16) & 0xF] = (u32)(res >> 32ULL);
|
||||
|
||||
cpu->Cycles += 1;
|
||||
cpu->AddCycles_CI(1); // TODO: interlock??
|
||||
}
|
||||
|
||||
|
||||
|
@ -981,6 +1017,7 @@ void A_CLZ(ARM* cpu)
|
|||
}
|
||||
|
||||
cpu->R[(cpu->CurInstr >> 12) & 0xF] = res;
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void A_QADD(ARM* cpu)
|
||||
|
@ -998,6 +1035,7 @@ void A_QADD(ARM* cpu)
|
|||
}
|
||||
|
||||
cpu->R[(cpu->CurInstr >> 12) & 0xF] = res;
|
||||
cpu->AddCycles_C(); // TODO: interlock??
|
||||
}
|
||||
|
||||
void A_QSUB(ARM* cpu)
|
||||
|
@ -1015,6 +1053,7 @@ void A_QSUB(ARM* cpu)
|
|||
}
|
||||
|
||||
cpu->R[(cpu->CurInstr >> 12) & 0xF] = res;
|
||||
cpu->AddCycles_C(); // TODO: interlock??
|
||||
}
|
||||
|
||||
void A_QDADD(ARM* cpu)
|
||||
|
@ -1040,6 +1079,7 @@ void A_QDADD(ARM* cpu)
|
|||
}
|
||||
|
||||
cpu->R[(cpu->CurInstr >> 12) & 0xF] = res;
|
||||
cpu->AddCycles_C(); // TODO: interlock??
|
||||
}
|
||||
|
||||
void A_QDSUB(ARM* cpu)
|
||||
|
@ -1065,6 +1105,7 @@ void A_QDSUB(ARM* cpu)
|
|||
}
|
||||
|
||||
cpu->R[(cpu->CurInstr >> 12) & 0xF] = res;
|
||||
cpu->AddCycles_C(); // TODO: interlock??
|
||||
}
|
||||
|
||||
|
||||
|
@ -1081,6 +1122,7 @@ void T_LSL_IMM(ARM* cpu)
|
|||
cpu->R[cpu->CurInstr & 0x7] = op;
|
||||
cpu->SetNZ(op & 0x80000000,
|
||||
!op);
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_LSR_IMM(ARM* cpu)
|
||||
|
@ -1091,6 +1133,7 @@ void T_LSR_IMM(ARM* cpu)
|
|||
cpu->R[cpu->CurInstr & 0x7] = op;
|
||||
cpu->SetNZ(op & 0x80000000,
|
||||
!op);
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_ASR_IMM(ARM* cpu)
|
||||
|
@ -1101,6 +1144,7 @@ void T_ASR_IMM(ARM* cpu)
|
|||
cpu->R[cpu->CurInstr & 0x7] = op;
|
||||
cpu->SetNZ(op & 0x80000000,
|
||||
!op);
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_ADD_REG_(ARM* cpu)
|
||||
|
@ -1113,6 +1157,7 @@ void T_ADD_REG_(ARM* cpu)
|
|||
!res,
|
||||
CARRY_ADD(a, b),
|
||||
OVERFLOW_ADD(a, b, res));
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_SUB_REG_(ARM* cpu)
|
||||
|
@ -1125,6 +1170,7 @@ void T_SUB_REG_(ARM* cpu)
|
|||
!res,
|
||||
CARRY_SUB(a, b),
|
||||
OVERFLOW_SUB(a, b, res));
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_ADD_IMM_(ARM* cpu)
|
||||
|
@ -1137,6 +1183,7 @@ void T_ADD_IMM_(ARM* cpu)
|
|||
!res,
|
||||
CARRY_ADD(a, b),
|
||||
OVERFLOW_ADD(a, b, res));
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_SUB_IMM_(ARM* cpu)
|
||||
|
@ -1149,6 +1196,7 @@ void T_SUB_IMM_(ARM* cpu)
|
|||
!res,
|
||||
CARRY_SUB(a, b),
|
||||
OVERFLOW_SUB(a, b, res));
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_MOV_IMM(ARM* cpu)
|
||||
|
@ -1157,6 +1205,7 @@ void T_MOV_IMM(ARM* cpu)
|
|||
cpu->R[(cpu->CurInstr >> 8) & 0x7] = b;
|
||||
cpu->SetNZ(0,
|
||||
!b);
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_CMP_IMM(ARM* cpu)
|
||||
|
@ -1168,6 +1217,7 @@ void T_CMP_IMM(ARM* cpu)
|
|||
!res,
|
||||
CARRY_SUB(a, b),
|
||||
OVERFLOW_SUB(a, b, res));
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_ADD_IMM(ARM* cpu)
|
||||
|
@ -1180,6 +1230,7 @@ void T_ADD_IMM(ARM* cpu)
|
|||
!res,
|
||||
CARRY_ADD(a, b),
|
||||
OVERFLOW_ADD(a, b, res));
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_SUB_IMM(ARM* cpu)
|
||||
|
@ -1192,6 +1243,7 @@ void T_SUB_IMM(ARM* cpu)
|
|||
!res,
|
||||
CARRY_SUB(a, b),
|
||||
OVERFLOW_SUB(a, b, res));
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1203,6 +1255,7 @@ void T_AND_REG(ARM* cpu)
|
|||
cpu->R[cpu->CurInstr & 0x7] = res;
|
||||
cpu->SetNZ(res & 0x80000000,
|
||||
!res);
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_EOR_REG(ARM* cpu)
|
||||
|
@ -1213,6 +1266,7 @@ void T_EOR_REG(ARM* cpu)
|
|||
cpu->R[cpu->CurInstr & 0x7] = res;
|
||||
cpu->SetNZ(res & 0x80000000,
|
||||
!res);
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_LSL_REG(ARM* cpu)
|
||||
|
@ -1223,7 +1277,7 @@ void T_LSL_REG(ARM* cpu)
|
|||
cpu->R[cpu->CurInstr & 0x7] = a;
|
||||
cpu->SetNZ(a & 0x80000000,
|
||||
!a);
|
||||
cpu->Cycles += 1;
|
||||
cpu->AddCycles_CI(1);
|
||||
}
|
||||
|
||||
void T_LSR_REG(ARM* cpu)
|
||||
|
@ -1234,7 +1288,7 @@ void T_LSR_REG(ARM* cpu)
|
|||
cpu->R[cpu->CurInstr & 0x7] = a;
|
||||
cpu->SetNZ(a & 0x80000000,
|
||||
!a);
|
||||
cpu->Cycles += 1;
|
||||
cpu->AddCycles_CI(1);
|
||||
}
|
||||
|
||||
void T_ASR_REG(ARM* cpu)
|
||||
|
@ -1245,7 +1299,7 @@ void T_ASR_REG(ARM* cpu)
|
|||
cpu->R[cpu->CurInstr & 0x7] = a;
|
||||
cpu->SetNZ(a & 0x80000000,
|
||||
!a);
|
||||
cpu->Cycles += 1;
|
||||
cpu->AddCycles_CI(1);
|
||||
}
|
||||
|
||||
void T_ADC_REG(ARM* cpu)
|
||||
|
@ -1260,6 +1314,7 @@ void T_ADC_REG(ARM* cpu)
|
|||
!res,
|
||||
CARRY_ADD(a, b) | CARRY_ADD(res_tmp, carry),
|
||||
OVERFLOW_ADD(a, b, res_tmp) | OVERFLOW_ADD(res_tmp, carry, res));
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_SBC_REG(ARM* cpu)
|
||||
|
@ -1274,6 +1329,7 @@ void T_SBC_REG(ARM* cpu)
|
|||
!res,
|
||||
CARRY_SUB(a, b) & CARRY_SUB(res_tmp, carry),
|
||||
OVERFLOW_SUB(a, b, res_tmp) | OVERFLOW_SUB(res_tmp, carry, res));
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_ROR_REG(ARM* cpu)
|
||||
|
@ -1284,7 +1340,7 @@ void T_ROR_REG(ARM* cpu)
|
|||
cpu->R[cpu->CurInstr & 0x7] = a;
|
||||
cpu->SetNZ(a & 0x80000000,
|
||||
!a);
|
||||
cpu->Cycles += 1;
|
||||
cpu->AddCycles_CI(1);
|
||||
}
|
||||
|
||||
void T_TST_REG(ARM* cpu)
|
||||
|
@ -1294,6 +1350,7 @@ void T_TST_REG(ARM* cpu)
|
|||
u32 res = a & b;
|
||||
cpu->SetNZ(res & 0x80000000,
|
||||
!res);
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_NEG_REG(ARM* cpu)
|
||||
|
@ -1305,6 +1362,7 @@ void T_NEG_REG(ARM* cpu)
|
|||
!res,
|
||||
CARRY_SUB(0, b),
|
||||
OVERFLOW_SUB(0, b, res));
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_CMP_REG(ARM* cpu)
|
||||
|
@ -1316,6 +1374,7 @@ void T_CMP_REG(ARM* cpu)
|
|||
!res,
|
||||
CARRY_SUB(a, b),
|
||||
OVERFLOW_SUB(a, b, res));
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_CMN_REG(ARM* cpu)
|
||||
|
@ -1327,6 +1386,7 @@ void T_CMN_REG(ARM* cpu)
|
|||
!res,
|
||||
CARRY_ADD(a, b),
|
||||
OVERFLOW_ADD(a, b, res));
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_ORR_REG(ARM* cpu)
|
||||
|
@ -1337,6 +1397,7 @@ void T_ORR_REG(ARM* cpu)
|
|||
cpu->R[cpu->CurInstr & 0x7] = res;
|
||||
cpu->SetNZ(res & 0x80000000,
|
||||
!res);
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_MUL_REG(ARM* cpu)
|
||||
|
@ -1361,7 +1422,7 @@ void T_MUL_REG(ARM* cpu)
|
|||
else if (a & 0x0000FF00) cycles += 2;
|
||||
else cycles += 1;
|
||||
}
|
||||
cpu->Cycles += cycles;
|
||||
cpu->AddCycles_CI(cycles);
|
||||
}
|
||||
|
||||
void T_BIC_REG(ARM* cpu)
|
||||
|
@ -1372,6 +1433,7 @@ void T_BIC_REG(ARM* cpu)
|
|||
cpu->R[cpu->CurInstr & 0x7] = res;
|
||||
cpu->SetNZ(res & 0x80000000,
|
||||
!res);
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_MVN_REG(ARM* cpu)
|
||||
|
@ -1381,6 +1443,7 @@ void T_MVN_REG(ARM* cpu)
|
|||
cpu->R[cpu->CurInstr & 0x7] = res;
|
||||
cpu->SetNZ(res & 0x80000000,
|
||||
!res);
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1395,6 +1458,8 @@ void T_ADD_HIREG(ARM* cpu)
|
|||
u32 a = cpu->R[rd];
|
||||
u32 b = cpu->R[rs];
|
||||
|
||||
cpu->AddCycles_C();
|
||||
|
||||
if (rd == 15)
|
||||
{
|
||||
cpu->JumpTo((a + b) | 1);
|
||||
|
@ -1418,6 +1483,7 @@ void T_CMP_HIREG(ARM* cpu)
|
|||
!res,
|
||||
CARRY_SUB(a, b),
|
||||
OVERFLOW_SUB(a, b, res));
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_MOV_HIREG(ARM* cpu)
|
||||
|
@ -1425,6 +1491,8 @@ void T_MOV_HIREG(ARM* cpu)
|
|||
u32 rd = (cpu->CurInstr & 0x7) | ((cpu->CurInstr >> 4) & 0x8);
|
||||
u32 rs = (cpu->CurInstr >> 3) & 0xF;
|
||||
|
||||
cpu->AddCycles_C();
|
||||
|
||||
if (rd == 15)
|
||||
{
|
||||
cpu->JumpTo(cpu->R[rs] | 1);
|
||||
|
@ -1441,6 +1509,7 @@ void T_ADD_PCREL(ARM* cpu)
|
|||
u32 val = cpu->R[15] & ~2;
|
||||
val += ((cpu->CurInstr & 0xFF) << 2);
|
||||
cpu->R[(cpu->CurInstr >> 8) & 0x7] = val;
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_ADD_SPREL(ARM* cpu)
|
||||
|
@ -1448,6 +1517,7 @@ void T_ADD_SPREL(ARM* cpu)
|
|||
u32 val = cpu->R[13];
|
||||
val += ((cpu->CurInstr & 0xFF) << 2);
|
||||
cpu->R[(cpu->CurInstr >> 8) & 0x7] = val;
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_ADD_SP(ARM* cpu)
|
||||
|
@ -1458,6 +1528,7 @@ void T_ADD_SP(ARM* cpu)
|
|||
else
|
||||
val += ((cpu->CurInstr & 0x7F) << 2);
|
||||
cpu->R[13] = val;
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -66,6 +66,8 @@ void T_BCOND(ARM* cpu)
|
|||
s32 offset = (s32)(cpu->CurInstr << 24) >> 23;
|
||||
cpu->JumpTo(cpu->R[15] + offset + 1);
|
||||
}
|
||||
else
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_BX(ARM* cpu)
|
||||
|
@ -96,6 +98,7 @@ void T_BL_LONG_1(ARM* cpu)
|
|||
{
|
||||
s32 offset = (s32)((cpu->CurInstr & 0x7FF) << 21) >> 9;
|
||||
cpu->R[14] = cpu->R[15] + offset;
|
||||
cpu->AddCycles_C();
|
||||
}
|
||||
|
||||
void T_BL_LONG_2(ARM* cpu)
|
||||
|
|
|
@ -62,29 +62,35 @@ namespace ARMInterpreter
|
|||
|
||||
#define A_STR \
|
||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
cpu->DataWrite32(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset;
|
||||
if (!cpu->DataWrite32(offset, cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||
cpu->AddCycles_CD();
|
||||
|
||||
#define A_STR_POST \
|
||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
cpu->DataWrite32(addr, cpu->R[(cpu->CurInstr>>12) & 0xF], cpu->CurInstr & (1<<21)); \
|
||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset;
|
||||
if (!cpu->DataWrite32(addr, cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq | (cpu->CurInstr & (1<<21)))) return; \
|
||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||
cpu->AddCycles_CD();
|
||||
|
||||
#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;
|
||||
if (!cpu->DataWrite8(offset, cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||
cpu->AddCycles_CD();
|
||||
|
||||
#define A_STRB_POST \
|
||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
cpu->DataWrite8(addr, cpu->R[(cpu->CurInstr>>12) & 0xF], cpu->CurInstr & (1<<21)); \
|
||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset;
|
||||
if (!cpu->DataWrite8(addr, cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq | (cpu->CurInstr & (1<<21)))) return; \
|
||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||
cpu->AddCycles_CD();
|
||||
|
||||
#define A_LDR \
|
||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 val = cpu->DataRead32(offset); val = ROR(val, ((offset&0x3)<<3)); \
|
||||
u32 val; \
|
||||
if (!cpu->DataRead32(offset, &val, RWFlags_Nonseq)) return; \
|
||||
val = ROR(val, ((offset&0x3)<<3)); \
|
||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||
cpu->Cycles += 1; \
|
||||
cpu->AddCycles_CDI(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
if (cpu->Num==1) val &= ~0x1; \
|
||||
|
@ -97,9 +103,11 @@ namespace ARMInterpreter
|
|||
|
||||
#define A_LDR_POST \
|
||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 val = cpu->DataRead32(addr, cpu->CurInstr & (1<<21)); val = ROR(val, ((addr&0x3)<<3)); \
|
||||
u32 val; \
|
||||
if (!cpu->DataRead32(addr, &val, RWFlags_Nonseq | (cpu->CurInstr & (1<<21)))) return; \
|
||||
val = ROR(val, ((addr&0x3)<<3)); \
|
||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||
cpu->Cycles += 1; \
|
||||
cpu->AddCycles_CDI(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||
{ \
|
||||
if (cpu->Num==1) val &= ~0x1; \
|
||||
|
@ -112,17 +120,19 @@ namespace ARMInterpreter
|
|||
|
||||
#define A_LDRB \
|
||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 val = cpu->DataRead8(offset); \
|
||||
u32 val; \
|
||||
if (!cpu->DataRead8(offset, &val, RWFlags_Nonseq)) return; \
|
||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||
cpu->Cycles += 1; \
|
||||
cpu->AddCycles_CDI(); \
|
||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRB PC %08X\n", cpu->R[15]); \
|
||||
|
||||
#define A_LDRB_POST \
|
||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 val = cpu->DataRead8(addr, cpu->CurInstr & (1<<21)); \
|
||||
u32 val; \
|
||||
if (!cpu->DataRead8(addr, &val, RWFlags_Nonseq | (cpu->CurInstr & (1<<21)))) return; \
|
||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||
cpu->Cycles += 1; \
|
||||
cpu->AddCycles_CDI(); \
|
||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRB PC %08X\n", cpu->R[15]); \
|
||||
|
||||
|
@ -209,13 +219,15 @@ 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->DataWrite16(offset, cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||
cpu->AddCycles_CD();
|
||||
|
||||
#define A_STRH_POST \
|
||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
cpu->DataWrite16(addr, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
||||
if (!cpu->DataWrite16(addr, cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||
cpu->AddCycles_CD();
|
||||
|
||||
// TODO: CHECK LDRD/STRD TIMINGS!!
|
||||
|
||||
|
@ -223,69 +235,85 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||
if (cpu->Num != 0) return; \
|
||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||
cpu->Cycles += 1; \
|
||||
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
||||
cpu->R[r ] = cpu->DataRead32(offset ); \
|
||||
cpu->R[r+1] = cpu->DataRead32(offset+4); \
|
||||
if (r&1) printf("!! MISALIGNED LDRD %d\n", r); \
|
||||
if (!cpu->DataRead32(offset , &cpu->R[r ], RWFlags_Nonseq)) return; \
|
||||
if (!cpu->DataRead32(offset+4, &cpu->R[r+1], 0)) return; \
|
||||
cpu->AddCycles_CDI();
|
||||
|
||||
#define A_LDRD_POST \
|
||||
if (cpu->Num != 0) return; \
|
||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||
cpu->Cycles += 1; \
|
||||
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
||||
cpu->R[r ] = cpu->DataRead32(addr ); \
|
||||
cpu->R[r+1] = cpu->DataRead32(addr+4); \
|
||||
if (r&1) printf("!! MISALIGNED LDRD_POST %d\n", r); \
|
||||
if (!cpu->DataRead32(addr , &cpu->R[r ], RWFlags_Nonseq)) return; \
|
||||
if (!cpu->DataRead32(addr+4, &cpu->R[r+1], 0)) return; \
|
||||
cpu->AddCycles_CDI();
|
||||
|
||||
#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; \
|
||||
cpu->DataWrite32(offset , cpu->R[r ]); \
|
||||
cpu->DataWrite32(offset+4, cpu->R[r+1]); \
|
||||
if (r&1) printf("!! MISALIGNED STRD %d\n", r); \
|
||||
if (!cpu->DataWrite32(offset , cpu->R[r ], RWFlags_Nonseq)) return; \
|
||||
if (!cpu->DataWrite32(offset+4, cpu->R[r+1], 0)) return; \
|
||||
cpu->AddCycles_CD();
|
||||
|
||||
#define A_STRD_POST \
|
||||
if (cpu->Num != 0) return; \
|
||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
||||
cpu->DataWrite32(offset , cpu->R[r ]); \
|
||||
cpu->DataWrite32(offset+4, cpu->R[r+1]); \
|
||||
if (r&1) printf("!! MISALIGNED STRD_POST %d\n", r); \
|
||||
if (!cpu->DataWrite32(offset , cpu->R[r ], RWFlags_Nonseq)) return; \
|
||||
if (!cpu->DataWrite32(offset+4, cpu->R[r+1], 0)) return; \
|
||||
cpu->AddCycles_CD();
|
||||
|
||||
#define A_LDRH \
|
||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = cpu->DataRead16(offset); \
|
||||
if (!cpu->DataRead16(offset, &cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
||||
cpu->AddCycles_CDI(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRH PC %08X\n", cpu->R[15]); \
|
||||
|
||||
#define A_LDRH_POST \
|
||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = cpu->DataRead16(addr); \
|
||||
if (!cpu->DataRead16(addr, &cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
||||
cpu->AddCycles_CDI(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRH PC %08X\n", cpu->R[15]); \
|
||||
|
||||
#define A_LDRSB \
|
||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->DataRead8(offset); \
|
||||
if (!cpu->DataRead8(offset, &cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->R[(cpu->CurInstr>>12) & 0xF]; \
|
||||
cpu->AddCycles_CDI(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSB PC %08X\n", cpu->R[15]); \
|
||||
|
||||
#define A_LDRSB_POST \
|
||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->DataRead8(addr); \
|
||||
if (!cpu->DataRead8(addr, &cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->R[(cpu->CurInstr>>12) & 0xF]; \
|
||||
cpu->AddCycles_CDI(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSB PC %08X\n", cpu->R[15]); \
|
||||
|
||||
#define A_LDRSH \
|
||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->DataRead16(offset); \
|
||||
if (!cpu->DataRead16(offset, &cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->R[(cpu->CurInstr>>12) & 0xF]; \
|
||||
cpu->AddCycles_CDI(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSH PC %08X\n", cpu->R[15]); \
|
||||
|
||||
#define A_LDRSH_POST \
|
||||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
|
||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->DataRead16(addr); \
|
||||
if (!cpu->DataRead16(addr, &cpu->R[(cpu->CurInstr>>12) & 0xF], RWFlags_Nonseq)) return; \
|
||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->R[(cpu->CurInstr>>12) & 0xF]; \
|
||||
cpu->AddCycles_CDI(); \
|
||||
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSH PC %08X\n", cpu->R[15]); \
|
||||
|
||||
|
||||
|
@ -328,12 +356,15 @@ void A_SWP(ARM* cpu)
|
|||
u32 base = cpu->R[(cpu->CurInstr >> 16) & 0xF];
|
||||
u32 rm = cpu->R[cpu->CurInstr & 0xF];
|
||||
|
||||
u32 val = cpu->DataRead32(base);
|
||||
u32 val;
|
||||
if (!cpu->DataRead32(base, &val, RWFlags_Nonseq)) return;
|
||||
cpu->R[(cpu->CurInstr >> 12) & 0xF] = ROR(val, 8*(base&0x3));
|
||||
|
||||
cpu->DataWrite32(base, rm);
|
||||
u32 numD = cpu->DataCycles;
|
||||
if (!cpu->DataWrite32(base, rm, RWFlags_Nonseq)) return;
|
||||
cpu->DataCycles += numD;
|
||||
|
||||
cpu->Cycles += 1;
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
void A_SWPB(ARM* cpu)
|
||||
|
@ -341,11 +372,13 @@ void A_SWPB(ARM* cpu)
|
|||
u32 base = cpu->R[(cpu->CurInstr >> 16) & 0xF];
|
||||
u32 rm = cpu->R[cpu->CurInstr & 0xF] & 0xFF;
|
||||
|
||||
cpu->R[(cpu->CurInstr >> 12) & 0xF] = cpu->DataRead8(base);
|
||||
if (!cpu->DataRead8(base, &cpu->R[(cpu->CurInstr >> 12) & 0xF], RWFlags_Nonseq)) return;
|
||||
|
||||
cpu->DataWrite8(base, rm);
|
||||
u32 numD = cpu->DataCycles;
|
||||
if (!cpu->DataWrite8(base, rm, RWFlags_Nonseq)) return;
|
||||
cpu->DataCycles += numD;
|
||||
|
||||
cpu->Cycles += 1;
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
|
||||
|
@ -356,6 +389,7 @@ void A_LDM(ARM* cpu)
|
|||
u32 base = cpu->R[baseid];
|
||||
u32 wbbase;
|
||||
u32 preinc = (cpu->CurInstr & (1<<24));
|
||||
u32 flags = RWFlags_Nonseq;
|
||||
|
||||
if (!(cpu->CurInstr & (1<<23)))
|
||||
{
|
||||
|
@ -374,8 +408,6 @@ void A_LDM(ARM* cpu)
|
|||
preinc = !preinc;
|
||||
}
|
||||
|
||||
cpu->Cycles += 1;
|
||||
|
||||
if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15)))
|
||||
cpu->UpdateMode(cpu->CPSR, (cpu->CPSR&~0x1F)|0x10);
|
||||
|
||||
|
@ -384,15 +416,17 @@ void A_LDM(ARM* cpu)
|
|||
if (cpu->CurInstr & (1<<i))
|
||||
{
|
||||
if (preinc) base += 4;
|
||||
cpu->R[i] = cpu->DataRead32(base);
|
||||
if (!cpu->DataRead32(base, &cpu->R[i], flags)) return;
|
||||
flags &= ~RWFlags_Nonseq;
|
||||
if (!preinc) base += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu->CurInstr & (1<<15))
|
||||
{
|
||||
u32 pc;
|
||||
if (preinc) base += 4;
|
||||
u32 pc = cpu->DataRead32(base);
|
||||
if (!cpu->DataRead32(base, &pc, flags)) return;
|
||||
if (!preinc) base += 4;
|
||||
|
||||
if (cpu->Num == 1)
|
||||
|
@ -422,6 +456,8 @@ void A_LDM(ARM* cpu)
|
|||
else
|
||||
cpu->R[baseid] = wbbase;
|
||||
}
|
||||
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
void A_STM(ARM* cpu)
|
||||
|
@ -430,6 +466,7 @@ void A_STM(ARM* cpu)
|
|||
u32 base = cpu->R[baseid];
|
||||
u32 oldbase = base;
|
||||
u32 preinc = (cpu->CurInstr & (1<<24));
|
||||
u32 flags = RWFlags_Nonseq;
|
||||
|
||||
if (!(cpu->CurInstr & (1<<23)))
|
||||
{
|
||||
|
@ -463,15 +500,19 @@ void A_STM(ARM* cpu)
|
|||
{
|
||||
if (preinc) base += 4;
|
||||
|
||||
bool res;
|
||||
if (i == baseid && !isbanked)
|
||||
{
|
||||
if ((cpu->Num == 0) || (!(cpu->CurInstr & ((1<<i)-1))))
|
||||
cpu->DataWrite32(base, oldbase);
|
||||
res = cpu->DataWrite32(base, oldbase, flags);
|
||||
else
|
||||
cpu->DataWrite32(base, base); // checkme
|
||||
res = cpu->DataWrite32(base, base, flags); // checkme
|
||||
}
|
||||
else
|
||||
cpu->DataWrite32(base, cpu->R[i]);
|
||||
res = cpu->DataWrite32(base, cpu->R[i], flags);
|
||||
|
||||
if (!res) return;
|
||||
flags &= ~RWFlags_Nonseq;
|
||||
|
||||
if (!preinc) base += 4;
|
||||
}
|
||||
|
@ -482,6 +523,8 @@ void A_STM(ARM* cpu)
|
|||
|
||||
if ((cpu->CurInstr & (1<<23)) && (cpu->CurInstr & (1<<21)))
|
||||
cpu->R[baseid] = base;
|
||||
|
||||
cpu->AddCycles_CD();
|
||||
}
|
||||
|
||||
|
||||
|
@ -494,71 +537,80 @@ void A_STM(ARM* cpu)
|
|||
void T_LDR_PCREL(ARM* cpu)
|
||||
{
|
||||
u32 addr = (cpu->R[15] & ~0x2) + ((cpu->CurInstr & 0xFF) << 2);
|
||||
cpu->R[(cpu->CurInstr >> 8) & 0x7] = cpu->DataRead32(addr);
|
||||
if (!cpu->DataRead32(addr, &cpu->R[(cpu->CurInstr >> 8) & 0x7], RWFlags_Nonseq)) return;
|
||||
|
||||
cpu->Cycles += 1;
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
|
||||
void T_STR_REG(ARM* cpu)
|
||||
{
|
||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||
cpu->DataWrite32(addr, cpu->R[cpu->CurInstr & 0x7]);
|
||||
if (!cpu->DataWrite32(addr, cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
||||
|
||||
cpu->AddCycles_CD();
|
||||
}
|
||||
|
||||
void T_STRB_REG(ARM* cpu)
|
||||
{
|
||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||
cpu->DataWrite8(addr, cpu->R[cpu->CurInstr & 0x7]);
|
||||
if (!cpu->DataWrite8(addr, cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
||||
|
||||
cpu->AddCycles_CD();
|
||||
}
|
||||
|
||||
void T_LDR_REG(ARM* cpu)
|
||||
{
|
||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||
|
||||
u32 val = cpu->DataRead32(addr);
|
||||
u32 val;
|
||||
if (!cpu->DataRead32(addr, &val, RWFlags_Nonseq)) return;
|
||||
cpu->R[cpu->CurInstr & 0x7] = ROR(val, 8*(addr&0x3));
|
||||
|
||||
cpu->Cycles += 1;
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
void T_LDRB_REG(ARM* cpu)
|
||||
{
|
||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||
cpu->R[cpu->CurInstr & 0x7] = cpu->DataRead8(addr);
|
||||
if (!cpu->DataRead8(addr, &cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
||||
|
||||
cpu->Cycles += 1;
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
|
||||
void T_STRH_REG(ARM* cpu)
|
||||
{
|
||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||
cpu->DataWrite16(addr, cpu->R[cpu->CurInstr & 0x7]);
|
||||
if (!cpu->DataWrite16(addr, cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
||||
|
||||
cpu->AddCycles_CD();
|
||||
}
|
||||
|
||||
void T_LDRSB_REG(ARM* cpu)
|
||||
{
|
||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||
cpu->R[cpu->CurInstr & 0x7] = (s32)(s8)cpu->DataRead8(addr);
|
||||
if (!cpu->DataRead8(addr, &cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
||||
cpu->R[cpu->CurInstr & 0x7] = (s32)(s8)cpu->R[cpu->CurInstr & 0x7];
|
||||
|
||||
cpu->Cycles += 1;
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
void T_LDRH_REG(ARM* cpu)
|
||||
{
|
||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||
cpu->R[cpu->CurInstr & 0x7] = cpu->DataRead16(addr);
|
||||
if (!cpu->DataRead16(addr, &cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
||||
|
||||
cpu->Cycles += 1;
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
void T_LDRSH_REG(ARM* cpu)
|
||||
{
|
||||
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
|
||||
cpu->R[cpu->CurInstr & 0x7] = (s32)(s16)cpu->DataRead16(addr);
|
||||
if (!cpu->DataRead16(addr, &cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
||||
cpu->R[cpu->CurInstr & 0x7] = (s32)(s16)cpu->R[cpu->CurInstr & 0x7];
|
||||
|
||||
cpu->Cycles += 1;
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
|
||||
|
@ -567,7 +619,8 @@ void T_STR_IMM(ARM* cpu)
|
|||
u32 offset = (cpu->CurInstr >> 4) & 0x7C;
|
||||
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
||||
|
||||
cpu->DataWrite32(offset, cpu->R[cpu->CurInstr & 0x7]);
|
||||
if (!cpu->DataWrite32(offset, cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
||||
cpu->AddCycles_CD();
|
||||
}
|
||||
|
||||
void T_LDR_IMM(ARM* cpu)
|
||||
|
@ -575,9 +628,10 @@ void T_LDR_IMM(ARM* cpu)
|
|||
u32 offset = (cpu->CurInstr >> 4) & 0x7C;
|
||||
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
||||
|
||||
u32 val = cpu->DataRead32(offset);
|
||||
u32 val;
|
||||
if (!cpu->DataRead32(offset, &val, RWFlags_Nonseq)) return;
|
||||
cpu->R[cpu->CurInstr & 0x7] = ROR(val, 8*(offset&0x3));
|
||||
cpu->Cycles += 1;
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
void T_STRB_IMM(ARM* cpu)
|
||||
|
@ -585,7 +639,8 @@ void T_STRB_IMM(ARM* cpu)
|
|||
u32 offset = (cpu->CurInstr >> 6) & 0x1F;
|
||||
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
||||
|
||||
cpu->DataWrite8(offset, cpu->R[cpu->CurInstr & 0x7]);
|
||||
if (!cpu->DataWrite8(offset, cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
||||
cpu->AddCycles_CD();
|
||||
}
|
||||
|
||||
void T_LDRB_IMM(ARM* cpu)
|
||||
|
@ -593,8 +648,8 @@ void T_LDRB_IMM(ARM* cpu)
|
|||
u32 offset = (cpu->CurInstr >> 6) & 0x1F;
|
||||
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
||||
|
||||
cpu->R[cpu->CurInstr & 0x7] = cpu->DataRead8(offset);
|
||||
cpu->Cycles += 1;
|
||||
if (!cpu->DataRead8(offset, &cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
|
||||
|
@ -603,7 +658,8 @@ void T_STRH_IMM(ARM* cpu)
|
|||
u32 offset = (cpu->CurInstr >> 5) & 0x3E;
|
||||
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
||||
|
||||
cpu->DataWrite16(offset, cpu->R[cpu->CurInstr & 0x7]);
|
||||
if (!cpu->DataWrite16(offset, cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
||||
cpu->AddCycles_CD();
|
||||
}
|
||||
|
||||
void T_LDRH_IMM(ARM* cpu)
|
||||
|
@ -611,8 +667,8 @@ void T_LDRH_IMM(ARM* cpu)
|
|||
u32 offset = (cpu->CurInstr >> 5) & 0x3E;
|
||||
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
|
||||
|
||||
cpu->R[cpu->CurInstr & 0x7] = cpu->DataRead16(offset);
|
||||
cpu->Cycles += 1;
|
||||
if (!cpu->DataRead16(offset, &cpu->R[cpu->CurInstr & 0x7], RWFlags_Nonseq)) return;
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
|
||||
|
@ -621,7 +677,8 @@ void T_STR_SPREL(ARM* cpu)
|
|||
u32 offset = (cpu->CurInstr << 2) & 0x3FC;
|
||||
offset += cpu->R[13];
|
||||
|
||||
cpu->DataWrite32(offset, cpu->R[(cpu->CurInstr >> 8) & 0x7]);
|
||||
if (!cpu->DataWrite32(offset, cpu->R[(cpu->CurInstr >> 8) & 0x7], RWFlags_Nonseq)) return;
|
||||
cpu->AddCycles_CD();
|
||||
}
|
||||
|
||||
void T_LDR_SPREL(ARM* cpu)
|
||||
|
@ -629,14 +686,15 @@ void T_LDR_SPREL(ARM* cpu)
|
|||
u32 offset = (cpu->CurInstr << 2) & 0x3FC;
|
||||
offset += cpu->R[13];
|
||||
|
||||
cpu->R[(cpu->CurInstr >> 8) & 0x7] = cpu->DataRead32(offset);
|
||||
cpu->Cycles += 1;
|
||||
if (!cpu->DataRead32(offset, &cpu->R[(cpu->CurInstr >> 8) & 0x7], RWFlags_Nonseq)) return;
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
|
||||
void T_PUSH(ARM* cpu)
|
||||
{
|
||||
int nregs = 0;
|
||||
u32 flags = RWFlags_Nonseq;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
|
@ -655,77 +713,87 @@ void T_PUSH(ARM* cpu)
|
|||
{
|
||||
if (cpu->CurInstr & (1<<i))
|
||||
{
|
||||
cpu->DataWrite32(base, cpu->R[i]);
|
||||
if (!cpu->DataWrite32(base, cpu->R[i], flags)) return;
|
||||
flags &= ~RWFlags_Nonseq;
|
||||
base += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu->CurInstr & (1<<8))
|
||||
{
|
||||
cpu->DataWrite32(base, cpu->R[14]);
|
||||
if (!cpu->DataWrite32(base, cpu->R[14], flags)) return;
|
||||
}
|
||||
|
||||
cpu->AddCycles_CD();
|
||||
}
|
||||
|
||||
void T_POP(ARM* cpu)
|
||||
{
|
||||
u32 base = cpu->R[13];
|
||||
|
||||
cpu->Cycles += 1;
|
||||
u32 flags = RWFlags_Nonseq;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (cpu->CurInstr & (1<<i))
|
||||
{
|
||||
cpu->R[i] = cpu->DataRead32(base);
|
||||
if (!cpu->DataRead32(base, &cpu->R[i], flags)) return;
|
||||
flags &= ~RWFlags_Nonseq;
|
||||
base += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu->CurInstr & (1<<8))
|
||||
{
|
||||
u32 pc = cpu->DataRead32(base);
|
||||
u32 pc;
|
||||
if (!cpu->DataRead32(base, &pc, flags)) return;
|
||||
if (cpu->Num==1) pc |= 0x1;
|
||||
cpu->JumpTo(pc);
|
||||
base += 4;
|
||||
}
|
||||
|
||||
cpu->R[13] = base;
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
void T_STMIA(ARM* cpu)
|
||||
{
|
||||
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
|
||||
u32 flags = RWFlags_Nonseq;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (cpu->CurInstr & (1<<i))
|
||||
{
|
||||
cpu->DataWrite32(base, cpu->R[i]);
|
||||
if (!cpu->DataWrite32(base, cpu->R[i], flags)) return;
|
||||
flags &= ~RWFlags_Nonseq;
|
||||
base += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: check "Rb included in Rlist" case
|
||||
cpu->R[(cpu->CurInstr >> 8) & 0x7] = base;
|
||||
cpu->AddCycles_CD();
|
||||
}
|
||||
|
||||
void T_LDMIA(ARM* cpu)
|
||||
{
|
||||
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
|
||||
|
||||
cpu->Cycles += 1;
|
||||
u32 flags = RWFlags_Nonseq;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (cpu->CurInstr & (1<<i))
|
||||
{
|
||||
cpu->R[i] = cpu->DataRead32(base);
|
||||
if (!cpu->DataRead32(base, &cpu->R[i], flags)) return;
|
||||
flags &= ~RWFlags_Nonseq;
|
||||
base += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cpu->CurInstr & (1<<((cpu->CurInstr >> 8) & 0x7))))
|
||||
cpu->R[(cpu->CurInstr >> 8) & 0x7] = base;
|
||||
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
|
||||
|
|
178
src/CP15.cpp
178
src/CP15.cpp
|
@ -20,31 +20,12 @@
|
|||
#include <string.h>
|
||||
#include "NDS.h"
|
||||
#include "ARM.h"
|
||||
#include "CP15.h"
|
||||
|
||||
|
||||
// derp
|
||||
namespace NDS
|
||||
|
||||
void ARMv5::CP15Reset()
|
||||
{
|
||||
extern ARM* ARM9;
|
||||
}
|
||||
|
||||
namespace CP15
|
||||
{
|
||||
|
||||
u32 Control;
|
||||
|
||||
u32 DTCMSetting, ITCMSetting;
|
||||
|
||||
u8 ITCM[0x8000];
|
||||
u32 ITCMSize;
|
||||
u8 DTCM[0x4000];
|
||||
u32 DTCMBase, DTCMSize;
|
||||
|
||||
|
||||
void Reset()
|
||||
{
|
||||
Control = 0x78; // dunno
|
||||
CP15Control = 0x78; // dunno
|
||||
|
||||
DTCMSetting = 0;
|
||||
ITCMSetting = 0;
|
||||
|
@ -57,11 +38,11 @@ void Reset()
|
|||
DTCMSize = 0;
|
||||
}
|
||||
|
||||
void DoSavestate(Savestate* file)
|
||||
void ARMv5::CP15DoSavestate(Savestate* file)
|
||||
{
|
||||
file->Section("CP15");
|
||||
|
||||
file->Var32(&Control);
|
||||
file->Var32(&CP15Control);
|
||||
|
||||
file->Var32(&DTCMSetting);
|
||||
file->Var32(&ITCMSetting);
|
||||
|
@ -77,9 +58,9 @@ void DoSavestate(Savestate* file)
|
|||
}
|
||||
|
||||
|
||||
void UpdateDTCMSetting()
|
||||
void ARMv5::UpdateDTCMSetting()
|
||||
{
|
||||
if (Control & (1<<16))
|
||||
if (CP15Control & (1<<16))
|
||||
{
|
||||
DTCMBase = DTCMSetting & 0xFFFFF000;
|
||||
DTCMSize = 0x200 << ((DTCMSetting >> 1) & 0x1F);
|
||||
|
@ -93,9 +74,9 @@ void UpdateDTCMSetting()
|
|||
}
|
||||
}
|
||||
|
||||
void UpdateITCMSetting()
|
||||
void ARMv5::UpdateITCMSetting()
|
||||
{
|
||||
if (Control & (1<<18))
|
||||
if (CP15Control & (1<<18))
|
||||
{
|
||||
ITCMSize = 0x200 << ((ITCMSetting >> 1) & 0x1F);
|
||||
//printf("ITCM [%08X] enabled at %08X, size %X\n", ITCMSetting, 0, ITCMSize);
|
||||
|
@ -108,7 +89,7 @@ void UpdateITCMSetting()
|
|||
}
|
||||
|
||||
|
||||
void Write(u32 id, u32 val)
|
||||
void ARMv5::CP15Write(u32 id, u32 val)
|
||||
{
|
||||
//printf("CP15 write op %03X %08X %08X\n", id, val, NDS::ARM9->R[15]);
|
||||
|
||||
|
@ -116,8 +97,8 @@ void Write(u32 id, u32 val)
|
|||
{
|
||||
case 0x100:
|
||||
val &= 0x000FF085;
|
||||
Control &= ~0x000FF085;
|
||||
Control |= val;
|
||||
CP15Control &= ~0x000FF085;
|
||||
CP15Control |= val;
|
||||
UpdateDTCMSetting();
|
||||
UpdateITCMSetting();
|
||||
return;
|
||||
|
@ -125,7 +106,7 @@ void Write(u32 id, u32 val)
|
|||
|
||||
case 0x704:
|
||||
case 0x782:
|
||||
NDS::ARM9->Halt(1);
|
||||
Halt(1);
|
||||
return;
|
||||
|
||||
|
||||
|
@ -158,7 +139,7 @@ void Write(u32 id, u32 val)
|
|||
printf("unknown CP15 write op %03X %08X\n", id, val);
|
||||
}
|
||||
|
||||
u32 Read(u32 id)
|
||||
u32 ARMv5::CP15Read(u32 id)
|
||||
{
|
||||
//printf("CP15 read op %03X %08X\n", id, NDS::ARM9->R[15]);
|
||||
|
||||
|
@ -180,7 +161,7 @@ u32 Read(u32 id)
|
|||
|
||||
|
||||
case 0x100: // control reg
|
||||
return Control;
|
||||
return CP15Control;
|
||||
|
||||
|
||||
case 0x910:
|
||||
|
@ -197,135 +178,202 @@ u32 Read(u32 id)
|
|||
// TCM are handled here.
|
||||
// TODO: later on, handle PU, and maybe caches
|
||||
|
||||
bool HandleCodeRead16(u32 addr, u16* val)
|
||||
u32 ARMv5::CodeRead32(u32 addr)
|
||||
{
|
||||
// PU/cache check here
|
||||
|
||||
if (addr < ITCMSize)
|
||||
{
|
||||
*val = *(u16*)&ITCM[addr & 0x7FFF];
|
||||
return true;
|
||||
CodeRegion = NDS::Region9_ITCM;
|
||||
return *(u32*)&ITCM[addr & 0x7FFF];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HandleCodeRead32(u32 addr, u32* val)
|
||||
{
|
||||
if (addr < ITCMSize)
|
||||
{
|
||||
*val = *(u32*)&ITCM[addr & 0x7FFF];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
u32 ret;
|
||||
CodeRegion = NDS::ARM9Read32(addr, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool HandleDataRead8(u32 addr, u8* val, u32 forceuser)
|
||||
bool ARMv5::DataRead8(u32 addr, u32* val, u32 flags)
|
||||
{
|
||||
// PU/cache check here
|
||||
|
||||
if (addr < ITCMSize)
|
||||
{
|
||||
DataRegion = NDS::Region9_ITCM;
|
||||
DataCycles += 1;
|
||||
*val = *(u8*)&ITCM[addr & 0x7FFF];
|
||||
return true;
|
||||
}
|
||||
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
||||
{
|
||||
DataRegion = NDS::Region9_ITCM;
|
||||
DataCycles += 1;
|
||||
*val = *(u8*)&DTCM[(addr - DTCMBase) & 0x3FFF];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
DataRegion = NDS::ARM9Read8(addr, val);
|
||||
if (flags & RWFlags_Nonseq)
|
||||
DataCycles = NDS::ARM9MemTimings[DataRegion][0];
|
||||
else
|
||||
DataCycles += NDS::ARM9MemTimings[DataRegion][1];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HandleDataRead16(u32 addr, u16* val, u32 forceuser)
|
||||
bool ARMv5::DataRead16(u32 addr, u32* val, u32 flags)
|
||||
{
|
||||
addr &= ~1;
|
||||
|
||||
// PU/cache check here
|
||||
|
||||
if (addr < ITCMSize)
|
||||
{
|
||||
DataRegion = NDS::Region9_ITCM;
|
||||
DataCycles += 1;
|
||||
*val = *(u16*)&ITCM[addr & 0x7FFF];
|
||||
return true;
|
||||
}
|
||||
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
||||
{
|
||||
DataRegion = NDS::Region9_ITCM;
|
||||
DataCycles += 1;
|
||||
*val = *(u16*)&DTCM[(addr - DTCMBase) & 0x3FFF];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
DataRegion = NDS::ARM9Read16(addr, val);
|
||||
if (flags & RWFlags_Nonseq)
|
||||
DataCycles = NDS::ARM9MemTimings[DataRegion][0];
|
||||
else
|
||||
DataCycles += NDS::ARM9MemTimings[DataRegion][1];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HandleDataRead32(u32 addr, u32* val, u32 forceuser)
|
||||
bool ARMv5::DataRead32(u32 addr, u32* val, u32 flags)
|
||||
{
|
||||
addr &= ~3;
|
||||
|
||||
// PU/cache check here
|
||||
|
||||
if (addr < ITCMSize)
|
||||
{
|
||||
DataRegion = NDS::Region9_ITCM;
|
||||
DataCycles += 1;
|
||||
*val = *(u32*)&ITCM[addr & 0x7FFF];
|
||||
return true;
|
||||
}
|
||||
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
||||
{
|
||||
DataRegion = NDS::Region9_ITCM;
|
||||
DataCycles += 1;
|
||||
*val = *(u32*)&DTCM[(addr - DTCMBase) & 0x3FFF];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
DataRegion = NDS::ARM9Read32(addr, val);
|
||||
if (flags & RWFlags_Nonseq)
|
||||
DataCycles = NDS::ARM9MemTimings[DataRegion][2];
|
||||
else
|
||||
DataCycles += NDS::ARM9MemTimings[DataRegion][3];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HandleDataWrite8(u32 addr, u8 val, u32 forceuser)
|
||||
bool ARMv5::DataWrite8(u32 addr, u8 val, u32 flags)
|
||||
{
|
||||
// PU/cache check here
|
||||
|
||||
if (addr < ITCMSize)
|
||||
{
|
||||
DataRegion = NDS::Region9_ITCM;
|
||||
DataCycles += 1;
|
||||
*(u8*)&ITCM[addr & 0x7FFF] = val;
|
||||
return true;
|
||||
}
|
||||
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
||||
{
|
||||
DataRegion = NDS::Region9_ITCM;
|
||||
DataCycles += 1;
|
||||
*(u8*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
DataRegion = NDS::ARM9Write8(addr, val);
|
||||
if (flags & RWFlags_Nonseq)
|
||||
DataCycles = NDS::ARM9MemTimings[DataRegion][0];
|
||||
else
|
||||
DataCycles += NDS::ARM9MemTimings[DataRegion][1];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HandleDataWrite16(u32 addr, u16 val, u32 forceuser)
|
||||
bool ARMv5::DataWrite16(u32 addr, u16 val, u32 flags)
|
||||
{
|
||||
addr &= ~1;
|
||||
|
||||
// PU/cache check here
|
||||
|
||||
if (addr < ITCMSize)
|
||||
{
|
||||
DataRegion = NDS::Region9_ITCM;
|
||||
DataCycles += 1;
|
||||
*(u16*)&ITCM[addr & 0x7FFF] = val;
|
||||
return true;
|
||||
}
|
||||
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
||||
{
|
||||
DataRegion = NDS::Region9_ITCM;
|
||||
DataCycles += 1;
|
||||
*(u16*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
DataRegion = NDS::ARM9Write16(addr, val);
|
||||
if (flags & RWFlags_Nonseq)
|
||||
DataCycles = NDS::ARM9MemTimings[DataRegion][0];
|
||||
else
|
||||
DataCycles += NDS::ARM9MemTimings[DataRegion][1];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HandleDataWrite32(u32 addr, u32 val, u32 forceuser)
|
||||
bool ARMv5::DataWrite32(u32 addr, u32 val, u32 flags)
|
||||
{
|
||||
addr &= ~3;
|
||||
|
||||
// PU/cache check here
|
||||
|
||||
if (addr < ITCMSize)
|
||||
{
|
||||
DataRegion = NDS::Region9_ITCM;
|
||||
DataCycles += 1;
|
||||
*(u32*)&ITCM[addr & 0x7FFF] = val;
|
||||
return true;
|
||||
}
|
||||
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
|
||||
{
|
||||
DataRegion = NDS::Region9_ITCM;
|
||||
DataCycles += 1;
|
||||
*(u32*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
DataRegion = NDS::ARM9Write32(addr, val);
|
||||
if (flags & RWFlags_Nonseq)
|
||||
DataCycles = NDS::ARM9MemTimings[DataRegion][2];
|
||||
else
|
||||
DataCycles += NDS::ARM9MemTimings[DataRegion][3];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetCodeMemRegion(u32 addr, NDS::MemRegion* region)
|
||||
void ARMv5::GetCodeMemRegion(u32 addr, NDS::MemRegion* region)
|
||||
{
|
||||
if (addr < ITCMSize)
|
||||
{
|
||||
region->Region = NDS::Region9_ITCM;
|
||||
region->Mem = ITCM;
|
||||
region->Mask = 0x7FFF;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
return false;
|
||||
NDS::ARM9GetMemRegion(addr, false, &CodeMem);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,10 +32,9 @@ void UpdateITCMSetting();
|
|||
void Write(u32 id, u32 val);
|
||||
u32 Read(u32 id);
|
||||
|
||||
bool HandleCodeRead16(u32 addr, u16* val);
|
||||
bool HandleCodeRead32(u32 addr, u32* val);
|
||||
bool HandleDataRead8(u32 addr, u8* val, u32 forceuser=0);
|
||||
bool HandleDataRead16(u32 addr, u16* val, u32 forceuser=0);
|
||||
bool HandleDataRead8(u32 addr, u32* val, u32 forceuser=0);
|
||||
bool HandleDataRead16(u32 addr, u32* val, u32 forceuser=0);
|
||||
bool HandleDataRead32(u32 addr, u32* val, u32 forceuser=0);
|
||||
bool HandleDataWrite8(u32 addr, u8 val, u32 forceuser=0);
|
||||
bool HandleDataWrite16(u32 addr, u16 val, u32 forceuser=0);
|
||||
|
|
16
src/DMA.cpp
16
src/DMA.cpp
|
@ -246,12 +246,14 @@ s32 DMA::Run(s32 cycles)
|
|||
|
||||
if (!(Cnt & 0x04000000))
|
||||
{
|
||||
u16 (*readfn)(u32) = CPU ? NDS::ARM7Read16 : NDS::ARM9Read16;
|
||||
void (*writefn)(u32,u16) = CPU ? NDS::ARM7Write16 : NDS::ARM9Write16;
|
||||
int (*readfn)(u32,u32*) = CPU ? NDS::ARM7Read16 : NDS::ARM9Read16;
|
||||
int (*writefn)(u32,u16) = CPU ? NDS::ARM7Write16 : NDS::ARM9Write16;
|
||||
|
||||
while (IterCount > 0 && cycles > 0 && !Stall)
|
||||
{
|
||||
writefn(CurDstAddr, readfn(CurSrcAddr));
|
||||
u32 val;
|
||||
readfn(CurSrcAddr, &val);
|
||||
writefn(CurDstAddr, val);
|
||||
|
||||
s32 c = (Waitstates[0][(CurSrcAddr >> 24) & 0xF] + Waitstates[0][(CurDstAddr >> 24) & 0xF]);
|
||||
cycles -= c;
|
||||
|
@ -283,12 +285,14 @@ s32 DMA::Run(s32 cycles)
|
|||
}
|
||||
}*/
|
||||
|
||||
u32 (*readfn)(u32) = CPU ? NDS::ARM7Read32 : NDS::ARM9Read32;
|
||||
void (*writefn)(u32,u32) = CPU ? NDS::ARM7Write32 : NDS::ARM9Write32;
|
||||
int (*readfn)(u32,u32*) = CPU ? NDS::ARM7Read32 : NDS::ARM9Read32;
|
||||
int (*writefn)(u32,u32) = CPU ? NDS::ARM7Write32 : NDS::ARM9Write32;
|
||||
|
||||
while (IterCount > 0 && cycles > 0 && !Stall)
|
||||
{
|
||||
writefn(CurDstAddr, readfn(CurSrcAddr));
|
||||
u32 val;
|
||||
readfn(CurSrcAddr, &val);
|
||||
writefn(CurDstAddr, val);
|
||||
|
||||
s32 c = (Waitstates[1][(CurSrcAddr >> 24) & 0xF] + Waitstates[1][(CurDstAddr >> 24) & 0xF]);
|
||||
cycles -= c;
|
||||
|
|
|
@ -1984,12 +1984,10 @@ void ExecuteCommand()
|
|||
break;
|
||||
|
||||
case 0x21: // normal
|
||||
{
|
||||
Normal[0] = (s16)((ExecParams[0] & 0x000003FF) << 6) >> 6;
|
||||
Normal[1] = (s16)((ExecParams[0] & 0x000FFC00) >> 4) >> 6;
|
||||
Normal[2] = (s16)((ExecParams[0] & 0x3FF00000) >> 14) >> 6;
|
||||
CalculateLighting();
|
||||
}
|
||||
Normal[0] = (s16)((ExecParams[0] & 0x000003FF) << 6) >> 6;
|
||||
Normal[1] = (s16)((ExecParams[0] & 0x000FFC00) >> 4) >> 6;
|
||||
Normal[2] = (s16)((ExecParams[0] & 0x3FF00000) >> 14) >> 6;
|
||||
CalculateLighting();
|
||||
break;
|
||||
|
||||
case 0x22: // texcoord
|
||||
|
|
604
src/NDS.cpp
604
src/NDS.cpp
File diff suppressed because it is too large
Load Diff
89
src/NDS.h
89
src/NDS.h
|
@ -87,13 +87,78 @@ typedef struct
|
|||
|
||||
} Timer;
|
||||
|
||||
enum
|
||||
{
|
||||
Region9_Void = 0,
|
||||
|
||||
Region9_BIOS,
|
||||
|
||||
Region9_ICache,
|
||||
Region9_DCache,
|
||||
Region9_ITCM,
|
||||
Region9_DTCM,
|
||||
|
||||
Region9_MainRAM,
|
||||
Region9_SharedWRAM,
|
||||
|
||||
Region9_IO,
|
||||
|
||||
Region9_Palette,
|
||||
Region9_VRAM_ABG,
|
||||
Region9_VRAM_BBG,
|
||||
Region9_VRAM_AOBJ,
|
||||
Region9_VRAM_BOBJ,
|
||||
Region9_VRAM_LCDC,
|
||||
Region9_OAM,
|
||||
|
||||
Region9_GBAROM,
|
||||
Region9_GBARAM,
|
||||
|
||||
Region9_MAX
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
Region7_Void = 0,
|
||||
|
||||
Region7_BIOS,
|
||||
|
||||
Region7_MainRAM,
|
||||
Region7_SharedWRAM,
|
||||
Region7_ARM7WRAM,
|
||||
|
||||
Region7_IO,
|
||||
Region7_Wifi0,
|
||||
Region7_Wifi1,
|
||||
|
||||
Region7_VRAM,
|
||||
|
||||
Region7_GBAROM,
|
||||
Region7_GBARAM,
|
||||
|
||||
Region7_MAX
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 BusType; // 0=32bit 1=16bit 2=8bit/GBARAM 3=ARM9/internal
|
||||
u8 DelayS; // baseline sequential access delay
|
||||
u8 DelayN; // baseline nonsequential access delay
|
||||
u8 _pad;
|
||||
|
||||
} RegionTimings;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int Region;
|
||||
u8* Mem;
|
||||
u32 Mask;
|
||||
|
||||
} MemRegion;
|
||||
|
||||
extern u8 ARM9MemTimings[Region9_MAX+1][4];
|
||||
extern u8 ARM7MemTimings[Region7_MAX+1][4];
|
||||
|
||||
// hax
|
||||
extern u32 IME[2];
|
||||
extern u32 IE[2];
|
||||
|
@ -159,21 +224,21 @@ void StopDMAs(u32 cpu, u32 mode);
|
|||
|
||||
void RunTimingCriticalDevices(u32 cpu, s32 cycles);
|
||||
|
||||
u8 ARM9Read8(u32 addr);
|
||||
u16 ARM9Read16(u32 addr);
|
||||
u32 ARM9Read32(u32 addr);
|
||||
void ARM9Write8(u32 addr, u8 val);
|
||||
void ARM9Write16(u32 addr, u16 val);
|
||||
void ARM9Write32(u32 addr, u32 val);
|
||||
int ARM9Read8(u32 addr, u32* val);
|
||||
int ARM9Read16(u32 addr, u32* val);
|
||||
int ARM9Read32(u32 addr, u32* val);
|
||||
int ARM9Write8(u32 addr, u8 val);
|
||||
int ARM9Write16(u32 addr, u16 val);
|
||||
int ARM9Write32(u32 addr, u32 val);
|
||||
|
||||
bool ARM9GetMemRegion(u32 addr, bool write, MemRegion* region);
|
||||
|
||||
u8 ARM7Read8(u32 addr);
|
||||
u16 ARM7Read16(u32 addr);
|
||||
u32 ARM7Read32(u32 addr);
|
||||
void ARM7Write8(u32 addr, u8 val);
|
||||
void ARM7Write16(u32 addr, u16 val);
|
||||
void ARM7Write32(u32 addr, u32 val);
|
||||
int ARM7Read8(u32 addr, u32* val);
|
||||
int ARM7Read16(u32 addr, u32* val);
|
||||
int ARM7Read32(u32 addr, u32* val);
|
||||
int ARM7Write8(u32 addr, u8 val);
|
||||
int ARM7Write16(u32 addr, u16 val);
|
||||
int ARM7Write32(u32 addr, u32 val);
|
||||
|
||||
bool ARM7GetMemRegion(u32 addr, bool write, MemRegion* region);
|
||||
|
||||
|
|
|
@ -214,7 +214,7 @@ void Channel::FIFO_BufferData()
|
|||
|
||||
for (u32 i = 0; i < burstlen; i += 4)
|
||||
{
|
||||
FIFO[FIFOWritePos] = NDS::ARM7Read32(SrcAddr + FIFOReadOffset);
|
||||
NDS::ARM7Read32(SrcAddr + FIFOReadOffset, &FIFO[FIFOWritePos]);
|
||||
FIFOReadOffset += 4;
|
||||
FIFOWritePos++;
|
||||
FIFOWritePos &= 0x7;
|
||||
|
|
|
@ -518,8 +518,8 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
|
|||
if (evt->Scancode == Config::KeyMapping[i])
|
||||
KeyInputMask &= ~(1<<i);
|
||||
|
||||
//if (evt->Scancode == 0x57) // F11
|
||||
// NDS::debug(0);
|
||||
if (evt->Scancode == 0x57) // F11
|
||||
NDS::debug(0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
Loading…
Reference in New Issue