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:
StapleButter 2018-12-04 17:54:10 +01:00
parent 808bda9171
commit 172fb4876a
14 changed files with 1428 additions and 666 deletions

View File

@ -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
View File

@ -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
{

View File

@ -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
}

View File

@ -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();
}

View File

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

View File

@ -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();
}

View File

@ -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);
}
}

View File

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

View File

@ -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;

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -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;

View File

@ -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;