mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-11-14 13:27:41 -07:00
* somewhat proper event scheduler
* support for timers * fixes, additions, shit
This commit is contained in:
parent
a14c01208a
commit
343797f47d
43
ARM.cpp
43
ARM.cpp
@ -38,6 +38,8 @@ ARM::~ARM()
|
|||||||
|
|
||||||
void ARM::Reset()
|
void ARM::Reset()
|
||||||
{
|
{
|
||||||
|
Cycles = 0;
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
R[i] = 0;
|
R[i] = 0;
|
||||||
|
|
||||||
@ -49,22 +51,25 @@ void ARM::Reset()
|
|||||||
JumpTo(ExceptionBase);
|
JumpTo(ExceptionBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARM::JumpTo(u32 addr)
|
void ARM::JumpTo(u32 addr, bool restorecpsr)
|
||||||
{
|
{
|
||||||
// pipeline shit
|
if (restorecpsr)
|
||||||
|
|
||||||
//printf("jump from %08X to %08X\n", R[15] - ((CPSR&0x20)?4:8), addr);
|
|
||||||
|
|
||||||
if (addr&1)
|
|
||||||
{
|
{
|
||||||
addr &= ~1;
|
RestoreCPSR();
|
||||||
|
if (CPSR & 0x20) addr |= 0x1;
|
||||||
|
else addr &= ~0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr & 0x1)
|
||||||
|
{
|
||||||
|
addr &= ~0x1;
|
||||||
NextInstr = Read16(addr);
|
NextInstr = Read16(addr);
|
||||||
R[15] = addr+2;
|
R[15] = addr+2;
|
||||||
CPSR |= 0x20;
|
CPSR |= 0x20;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
addr &= ~3;
|
addr &= ~0x3;
|
||||||
NextInstr = Read32(addr);
|
NextInstr = Read32(addr);
|
||||||
R[15] = addr+4;
|
R[15] = addr+4;
|
||||||
CPSR &= ~0x20;
|
CPSR &= ~0x20;
|
||||||
@ -191,49 +196,57 @@ void ARM::TriggerIRQ()
|
|||||||
UpdateMode(oldcpsr, CPSR);
|
UpdateMode(oldcpsr, CPSR);
|
||||||
|
|
||||||
R_IRQ[2] = oldcpsr;
|
R_IRQ[2] = oldcpsr;
|
||||||
R[14] = R[15];// - (oldcpsr & 0x20 ? 0 : 4);
|
R[14] = R[15] + (oldcpsr & 0x20 ? 2 : 0);
|
||||||
JumpTo(ExceptionBase + 0x18);
|
JumpTo(ExceptionBase + 0x18);
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 ARM::Execute(s32 cycles)
|
s32 ARM::Execute(s32 cycles)
|
||||||
{
|
{
|
||||||
while (cycles > 0)
|
s32 cyclesrun = 0;
|
||||||
|
|
||||||
|
while (cyclesrun < cycles)
|
||||||
{
|
{
|
||||||
if (CPSR & 0x20) // THUMB
|
if (CPSR & 0x20) // THUMB
|
||||||
{
|
{
|
||||||
// prefetch
|
// prefetch
|
||||||
CurInstr = NextInstr;
|
CurInstr = NextInstr;
|
||||||
NextInstr = Read16(R[15]);
|
NextInstr = Read16(R[15]);
|
||||||
|
//cyclesrun += MemWaitstate(0, R[15]);
|
||||||
R[15] += 2;
|
R[15] += 2;
|
||||||
|
|
||||||
|
Cycles = cyclesrun;
|
||||||
|
|
||||||
// actually execute
|
// actually execute
|
||||||
u32 icode = (CurInstr >> 6);
|
u32 icode = (CurInstr >> 6);
|
||||||
cycles -= ARMInterpreter::THUMBInstrTable[icode](this);
|
cyclesrun += ARMInterpreter::THUMBInstrTable[icode](this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// prefetch
|
// prefetch
|
||||||
CurInstr = NextInstr;
|
CurInstr = NextInstr;
|
||||||
NextInstr = Read32(R[15]);
|
NextInstr = Read32(R[15]);
|
||||||
|
//cyclesrun += MemWaitstate(1, R[15]);
|
||||||
R[15] += 4;
|
R[15] += 4;
|
||||||
|
|
||||||
|
Cycles = cyclesrun;
|
||||||
|
|
||||||
// actually execute
|
// actually execute
|
||||||
if (CheckCondition(CurInstr >> 28))
|
if (CheckCondition(CurInstr >> 28))
|
||||||
{
|
{
|
||||||
u32 icode = ((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0);
|
u32 icode = ((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0);
|
||||||
cycles -= ARMInterpreter::ARMInstrTable[icode](this);
|
cyclesrun += ARMInterpreter::ARMInstrTable[icode](this);
|
||||||
}
|
}
|
||||||
else if ((CurInstr & 0xFE000000) == 0xFA000000)
|
else if ((CurInstr & 0xFE000000) == 0xFA000000)
|
||||||
{
|
{
|
||||||
cycles -= ARMInterpreter::A_BLX_IMM(this);
|
cyclesrun += ARMInterpreter::A_BLX_IMM(this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// not executing it. oh well
|
// not executing it. oh well
|
||||||
cycles -= 1; // 1S. todo: check
|
cyclesrun += 1; // 1S. todo: check
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cycles;
|
return cyclesrun;
|
||||||
}
|
}
|
||||||
|
4
ARM.h
4
ARM.h
@ -21,7 +21,7 @@ public:
|
|||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
void JumpTo(u32 addr);
|
void JumpTo(u32 addr, bool restorecpsr = false);
|
||||||
void RestoreCPSR();
|
void RestoreCPSR();
|
||||||
|
|
||||||
s32 Execute(s32 cycles);
|
s32 Execute(s32 cycles);
|
||||||
@ -145,6 +145,8 @@ public:
|
|||||||
|
|
||||||
u32 Num;
|
u32 Num;
|
||||||
|
|
||||||
|
s32 Cycles;
|
||||||
|
|
||||||
u32 R[16]; // heh
|
u32 R[16]; // heh
|
||||||
u32 CPSR;
|
u32 CPSR;
|
||||||
u32 R_FIQ[8]; // holding SPSR too
|
u32 R_FIQ[8]; // holding SPSR too
|
||||||
|
@ -172,6 +172,24 @@ s32 A_MRC(ARM* cpu)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
s32 T_SVC(ARM* cpu)
|
||||||
|
{
|
||||||
|
u32 oldcpsr = cpu->CPSR;
|
||||||
|
cpu->CPSR &= ~0xFF;
|
||||||
|
cpu->CPSR |= 0xD3;
|
||||||
|
cpu->UpdateMode(oldcpsr, cpu->CPSR);
|
||||||
|
|
||||||
|
cpu->R_SVC[2] = oldcpsr;
|
||||||
|
cpu->R[14] = cpu->R[15] - 2;
|
||||||
|
cpu->JumpTo(cpu->ExceptionBase + 0x08);
|
||||||
|
|
||||||
|
printf("SWI %02X\n", (cpu->CurInstr & 0xFF));
|
||||||
|
|
||||||
|
return C_S(2) + C_N(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define INSTRFUNC_PROTO(x) s32 (*x)(ARM* cpu)
|
#define INSTRFUNC_PROTO(x) s32 (*x)(ARM* cpu)
|
||||||
#include "ARM_InstrTable.h"
|
#include "ARM_InstrTable.h"
|
||||||
#undef INSTRFUNC_PROTO
|
#undef INSTRFUNC_PROTO
|
||||||
|
@ -268,8 +268,7 @@ s32 A_##x##_REG_ROR_REG(ARM* cpu) \
|
|||||||
!res); \
|
!res); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||||
{ \
|
{ \
|
||||||
cpu->JumpTo(res); \
|
cpu->JumpTo(res, true); \
|
||||||
cpu->RestoreCPSR(); \
|
|
||||||
return C_S(2) + C_I(c) + C_N(1); \
|
return C_S(2) + C_I(c) + C_N(1); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
@ -302,8 +301,7 @@ A_IMPLEMENT_ALU_OP(AND)
|
|||||||
!res); \
|
!res); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||||
{ \
|
{ \
|
||||||
cpu->JumpTo(res); \
|
cpu->JumpTo(res, true); \
|
||||||
cpu->RestoreCPSR(); \
|
|
||||||
return C_S(2) + C_I(c) + C_N(1); \
|
return C_S(2) + C_I(c) + C_N(1); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
@ -338,8 +336,7 @@ A_IMPLEMENT_ALU_OP(EOR)
|
|||||||
OVERFLOW_SUB(a, b, res)); \
|
OVERFLOW_SUB(a, b, res)); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||||
{ \
|
{ \
|
||||||
cpu->JumpTo(res); \
|
cpu->JumpTo(res, true); \
|
||||||
cpu->RestoreCPSR(); \
|
|
||||||
return C_S(2) + C_I(c) + C_N(1); \
|
return C_S(2) + C_I(c) + C_N(1); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
@ -374,8 +371,7 @@ A_IMPLEMENT_ALU_OP(SUB)
|
|||||||
OVERFLOW_SUB(b, a, res)); \
|
OVERFLOW_SUB(b, a, res)); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||||
{ \
|
{ \
|
||||||
cpu->JumpTo(res); \
|
cpu->JumpTo(res, true); \
|
||||||
cpu->RestoreCPSR(); \
|
|
||||||
return C_S(2) + C_I(c) + C_N(1); \
|
return C_S(2) + C_I(c) + C_N(1); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
@ -410,8 +406,7 @@ A_IMPLEMENT_ALU_OP(RSB)
|
|||||||
OVERFLOW_ADD(a, b, res)); \
|
OVERFLOW_ADD(a, b, res)); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||||
{ \
|
{ \
|
||||||
cpu->JumpTo(res); \
|
cpu->JumpTo(res, true); \
|
||||||
cpu->RestoreCPSR(); \
|
|
||||||
return C_S(2) + C_I(c) + C_N(1); \
|
return C_S(2) + C_I(c) + C_N(1); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
@ -448,8 +443,7 @@ A_IMPLEMENT_ALU_OP(ADD)
|
|||||||
OVERFLOW_ADD(a, b, res_tmp) | OVERFLOW_ADD(res_tmp, carry, res)); \
|
OVERFLOW_ADD(a, b, res_tmp) | OVERFLOW_ADD(res_tmp, carry, res)); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||||
{ \
|
{ \
|
||||||
cpu->JumpTo(res); \
|
cpu->JumpTo(res, true); \
|
||||||
cpu->RestoreCPSR(); \
|
|
||||||
return C_S(2) + C_I(c) + C_N(1); \
|
return C_S(2) + C_I(c) + C_N(1); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
@ -486,8 +480,7 @@ A_IMPLEMENT_ALU_OP(ADC)
|
|||||||
OVERFLOW_SUB(a, b, res_tmp) | OVERFLOW_SUB(res_tmp, carry, res)); \
|
OVERFLOW_SUB(a, b, res_tmp) | OVERFLOW_SUB(res_tmp, carry, res)); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||||
{ \
|
{ \
|
||||||
cpu->JumpTo(res); \
|
cpu->JumpTo(res, true); \
|
||||||
cpu->RestoreCPSR(); \
|
|
||||||
return C_S(2) + C_I(c) + C_N(1); \
|
return C_S(2) + C_I(c) + C_N(1); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
@ -524,8 +517,7 @@ A_IMPLEMENT_ALU_OP(SBC)
|
|||||||
OVERFLOW_SUB(b, a, res_tmp) | OVERFLOW_SUB(res_tmp, carry, res)); \
|
OVERFLOW_SUB(b, a, res_tmp) | OVERFLOW_SUB(res_tmp, carry, res)); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||||
{ \
|
{ \
|
||||||
cpu->JumpTo(res); \
|
cpu->JumpTo(res, true); \
|
||||||
cpu->RestoreCPSR(); \
|
|
||||||
return C_S(2) + C_I(c) + C_N(1); \
|
return C_S(2) + C_I(c) + C_N(1); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
@ -602,8 +594,7 @@ A_IMPLEMENT_ALU_TEST(CMN)
|
|||||||
!res); \
|
!res); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||||
{ \
|
{ \
|
||||||
cpu->JumpTo(res); \
|
cpu->JumpTo(res, true); \
|
||||||
cpu->RestoreCPSR(); \
|
|
||||||
return C_S(2) + C_I(c) + C_N(1); \
|
return C_S(2) + C_I(c) + C_N(1); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
@ -632,8 +623,7 @@ A_IMPLEMENT_ALU_OP(ORR)
|
|||||||
!b); \
|
!b); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||||
{ \
|
{ \
|
||||||
cpu->JumpTo(b); \
|
cpu->JumpTo(b, true); \
|
||||||
cpu->RestoreCPSR(); \
|
|
||||||
return C_S(2) + C_I(c) + C_N(1); \
|
return C_S(2) + C_I(c) + C_N(1); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
@ -666,8 +656,7 @@ A_IMPLEMENT_ALU_OP(MOV)
|
|||||||
!res); \
|
!res); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||||
{ \
|
{ \
|
||||||
cpu->JumpTo(res); \
|
cpu->JumpTo(res, true); \
|
||||||
cpu->RestoreCPSR(); \
|
|
||||||
return C_S(2) + C_I(c) + C_N(1); \
|
return C_S(2) + C_I(c) + C_N(1); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
@ -698,8 +687,7 @@ A_IMPLEMENT_ALU_OP(BIC)
|
|||||||
!b); \
|
!b); \
|
||||||
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
if (((cpu->CurInstr>>12) & 0xF) == 15) \
|
||||||
{ \
|
{ \
|
||||||
cpu->JumpTo(b); \
|
cpu->JumpTo(b, true); \
|
||||||
cpu->RestoreCPSR(); \
|
|
||||||
return C_S(2) + C_I(c) + C_N(1); \
|
return C_S(2) + C_I(c) + C_N(1); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
@ -1057,7 +1045,7 @@ s32 T_ADD_HIREG(ARM* cpu)
|
|||||||
|
|
||||||
if (rd == 15)
|
if (rd == 15)
|
||||||
{
|
{
|
||||||
cpu->JumpTo(a + b);
|
cpu->JumpTo((a + b) | 1);
|
||||||
return C_S(2) + C_N(1);
|
return C_S(2) + C_N(1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1090,7 +1078,7 @@ s32 T_MOV_HIREG(ARM* cpu)
|
|||||||
|
|
||||||
if (rd == 15)
|
if (rd == 15)
|
||||||
{
|
{
|
||||||
cpu->JumpTo(cpu->R[rs]);
|
cpu->JumpTo(cpu->R[rs] | 1);
|
||||||
return C_S(2) + C_N(1);
|
return C_S(2) + C_N(1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1103,7 +1091,7 @@ s32 T_MOV_HIREG(ARM* cpu)
|
|||||||
|
|
||||||
s32 T_ADD_PCREL(ARM* cpu)
|
s32 T_ADD_PCREL(ARM* cpu)
|
||||||
{
|
{
|
||||||
u32 val = cpu->R[15] = ~2;
|
u32 val = cpu->R[15] & ~2;
|
||||||
val += ((cpu->CurInstr & 0xFF) << 2);
|
val += ((cpu->CurInstr & 0xFF) << 2);
|
||||||
cpu->R[(cpu->CurInstr >> 8) & 0x7] = val;
|
cpu->R[(cpu->CurInstr >> 8) & 0x7] = val;
|
||||||
return C_S(1);
|
return C_S(1);
|
||||||
|
@ -196,7 +196,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||||||
#define A_STRH \
|
#define A_STRH \
|
||||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
cpu->Write16(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
cpu->Write16(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
|
||||||
if (cpu->CurInstr & (1<<24)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||||
return C_N(2) + cpu->MemWaitstate(2, offset);
|
return C_N(2) + cpu->MemWaitstate(2, offset);
|
||||||
|
|
||||||
#define A_STRH_POST \
|
#define A_STRH_POST \
|
||||||
@ -225,7 +225,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||||||
|
|
||||||
#define A_STRD \
|
#define A_STRD \
|
||||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
if (cpu->CurInstr & (1<<24)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||||
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
||||||
cpu->Write32(offset , cpu->R[r ]); \
|
cpu->Write32(offset , cpu->R[r ]); \
|
||||||
cpu->Write32(offset+4, cpu->R[r+1]); \
|
cpu->Write32(offset+4, cpu->R[r+1]); \
|
||||||
@ -242,7 +242,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||||||
#define A_LDRH \
|
#define A_LDRH \
|
||||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = cpu->Read16(offset); \
|
cpu->R[(cpu->CurInstr>>12) & 0xF] = cpu->Read16(offset); \
|
||||||
if (cpu->CurInstr & (1<<24)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||||
return C_N(2) + cpu->MemWaitstate(2, offset);
|
return C_N(2) + cpu->MemWaitstate(2, offset);
|
||||||
|
|
||||||
#define A_LDRH_POST \
|
#define A_LDRH_POST \
|
||||||
@ -254,7 +254,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||||||
#define A_LDRSB \
|
#define A_LDRSB \
|
||||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->Read8(offset); \
|
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->Read8(offset); \
|
||||||
if (cpu->CurInstr & (1<<24)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||||
return C_N(2) + cpu->MemWaitstate(3, offset);
|
return C_N(2) + cpu->MemWaitstate(3, offset);
|
||||||
|
|
||||||
#define A_LDRSB_POST \
|
#define A_LDRSB_POST \
|
||||||
@ -266,7 +266,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||||||
#define A_LDRSH \
|
#define A_LDRSH \
|
||||||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||||
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->Read16(offset); \
|
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->Read16(offset); \
|
||||||
if (cpu->CurInstr & (1<<24)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
|
||||||
return C_N(2) + cpu->MemWaitstate(2, offset);
|
return C_N(2) + cpu->MemWaitstate(2, offset);
|
||||||
|
|
||||||
#define A_LDRSH_POST \
|
#define A_LDRSH_POST \
|
||||||
@ -310,6 +310,33 @@ A_IMPLEMENT_HD_LDRSTR(LDRSH)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
s32 A_SWP(ARM* cpu)
|
||||||
|
{
|
||||||
|
u32 base = cpu->R[(cpu->CurInstr >> 16) & 0xF];
|
||||||
|
|
||||||
|
u32 val = cpu->Read32(base);
|
||||||
|
cpu->R[(cpu->CurInstr >> 12) & 0xF] = ROR(val, 8*(base&0x3));
|
||||||
|
|
||||||
|
cpu->Write32(base, cpu->R[cpu->CurInstr & 0xF]);
|
||||||
|
|
||||||
|
// the 1S is a code cycle. TODO
|
||||||
|
return C_S(1) + C_N(2) + C_I(1) + 2*cpu->MemWaitstate(3, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 A_SWPB(ARM* cpu)
|
||||||
|
{
|
||||||
|
u32 base = cpu->R[(cpu->CurInstr >> 16) & 0xF];
|
||||||
|
|
||||||
|
cpu->R[(cpu->CurInstr >> 12) & 0xF] = cpu->Read8(base);
|
||||||
|
|
||||||
|
cpu->Write8(base, cpu->R[cpu->CurInstr & 0xF]);
|
||||||
|
|
||||||
|
// the 1S is a code cycle. TODO
|
||||||
|
return C_S(1) + C_N(2) + C_I(1) + 2*cpu->MemWaitstate(3, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
s32 A_LDM(ARM* cpu)
|
s32 A_LDM(ARM* cpu)
|
||||||
{
|
{
|
||||||
u32 base = cpu->R[(cpu->CurInstr >> 16) & 0xF];
|
u32 base = cpu->R[(cpu->CurInstr >> 16) & 0xF];
|
||||||
@ -359,8 +386,7 @@ s32 A_LDM(ARM* cpu)
|
|||||||
if (cpu->Num == 1)
|
if (cpu->Num == 1)
|
||||||
pc &= ~0x1;
|
pc &= ~0x1;
|
||||||
|
|
||||||
cpu->JumpTo(pc);
|
cpu->JumpTo(pc, cpu->CurInstr & (1<<22));
|
||||||
if (cpu->CurInstr & (1<<22)) cpu->RestoreCPSR();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15)))
|
if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15)))
|
||||||
|
@ -40,6 +40,9 @@ A_PROTO_HD_LDRSTR(LDRSH)
|
|||||||
s32 A_LDM(ARM* cpu);
|
s32 A_LDM(ARM* cpu);
|
||||||
s32 A_STM(ARM* cpu);
|
s32 A_STM(ARM* cpu);
|
||||||
|
|
||||||
|
s32 A_SWP(ARM* cpu);
|
||||||
|
s32 A_SWPB(ARM* cpu);
|
||||||
|
|
||||||
|
|
||||||
s32 T_LDR_PCREL(ARM* cpu);
|
s32 T_LDR_PCREL(ARM* cpu);
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ INSTRFUNC_PROTO(ARMInstrTable[4096]) =
|
|||||||
// 0001 0000 0000
|
// 0001 0000 0000
|
||||||
A_MRS, A_UNK, A_UNK, A_UNK,
|
A_MRS, A_UNK, A_UNK, A_UNK,
|
||||||
A_UNK, A_UNK, A_UNK, A_UNK,
|
A_UNK, A_UNK, A_UNK, A_UNK,
|
||||||
A_UNK, A_UNK, A_UNK, A_STRH_REG,
|
A_UNK, A_SWP, A_UNK, A_STRH_REG,
|
||||||
A_UNK, A_LDRD_REG, A_UNK, A_STRD_REG,
|
A_UNK, A_LDRD_REG, A_UNK, A_STRD_REG,
|
||||||
|
|
||||||
// 0001 0001 0000
|
// 0001 0001 0000
|
||||||
@ -126,7 +126,7 @@ INSTRFUNC_PROTO(ARMInstrTable[4096]) =
|
|||||||
// 0001 0100 0000
|
// 0001 0100 0000
|
||||||
A_MRS, A_UNK, A_UNK, A_UNK,
|
A_MRS, A_UNK, A_UNK, A_UNK,
|
||||||
A_UNK, A_UNK, A_UNK, A_UNK,
|
A_UNK, A_UNK, A_UNK, A_UNK,
|
||||||
A_UNK, A_UNK, A_UNK, A_STRH_IMM,
|
A_UNK, A_SWPB, A_UNK, A_STRH_IMM,
|
||||||
A_UNK, A_LDRD_IMM, A_UNK, A_STRD_IMM,
|
A_UNK, A_LDRD_IMM, A_UNK, A_STRD_IMM,
|
||||||
|
|
||||||
// 0001 0101 0000
|
// 0001 0101 0000
|
||||||
@ -1910,7 +1910,7 @@ INSTRFUNC_PROTO(THUMBInstrTable[1024]) =
|
|||||||
T_BCOND, T_BCOND, T_BCOND, T_BCOND,
|
T_BCOND, T_BCOND, T_BCOND, T_BCOND,
|
||||||
T_BCOND, T_BCOND, T_BCOND, T_BCOND,
|
T_BCOND, T_BCOND, T_BCOND, T_BCOND,
|
||||||
T_UNK, T_UNK, T_UNK, T_UNK,
|
T_UNK, T_UNK, T_UNK, T_UNK,
|
||||||
T_UNK, T_UNK, T_UNK, T_UNK,
|
T_SVC, T_SVC, T_SVC, T_SVC,
|
||||||
|
|
||||||
// 1110 0000 00
|
// 1110 0000 00
|
||||||
T_B, T_B, T_B, T_B,
|
T_B, T_B, T_B, T_B,
|
||||||
|
6
CP15.cpp
6
CP15.cpp
@ -23,7 +23,7 @@ void UpdateDTCMSetting()
|
|||||||
if (Control & (1<<16))
|
if (Control & (1<<16))
|
||||||
{
|
{
|
||||||
NDS::ARM9DTCMBase = DTCMSetting & 0xFFFFF000;
|
NDS::ARM9DTCMBase = DTCMSetting & 0xFFFFF000;
|
||||||
NDS::ARM9DTCMSize = 256 << (DTCMSetting & 0x3E);
|
NDS::ARM9DTCMSize = 0x200 << ((DTCMSetting >> 1) & 0x1F);
|
||||||
printf("DTCM enabled at %08X, size %X\n", NDS::ARM9DTCMBase, NDS::ARM9DTCMSize);
|
printf("DTCM enabled at %08X, size %X\n", NDS::ARM9DTCMBase, NDS::ARM9DTCMSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -38,8 +38,8 @@ void UpdateITCMSetting()
|
|||||||
{
|
{
|
||||||
if (Control & (1<<18))
|
if (Control & (1<<18))
|
||||||
{
|
{
|
||||||
NDS::ARM9ITCMSize = 256 << (DTCMSetting & 0x3E);
|
NDS::ARM9ITCMSize = 0x200 << ((ITCMSetting >> 1) & 0x1F);
|
||||||
printf("ITCM enabled at %08X, size %X\n", 0, NDS::ARM9DTCMSize);
|
printf("ITCM enabled at %08X, size %X\n", 0, NDS::ARM9ITCMSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
342
NDS.cpp
342
NDS.cpp
@ -9,10 +9,17 @@
|
|||||||
namespace NDS
|
namespace NDS
|
||||||
{
|
{
|
||||||
|
|
||||||
|
SchedEvent SchedBuffer[SCHED_BUF_LEN];
|
||||||
|
SchedEvent* SchedQueue;
|
||||||
|
|
||||||
|
bool NeedReschedule;
|
||||||
|
|
||||||
ARM* ARM9;
|
ARM* ARM9;
|
||||||
ARM* ARM7;
|
ARM* ARM7;
|
||||||
|
|
||||||
s32 ARM9Cycles, ARM7Cycles;
|
s32 ARM9Cycles, ARM7Cycles;
|
||||||
|
s32 CompensatedCycles;
|
||||||
|
s32 SchedCycles;
|
||||||
|
|
||||||
u8 ARM9BIOS[0x1000];
|
u8 ARM9BIOS[0x1000];
|
||||||
u8 ARM7BIOS[0x4000];
|
u8 ARM7BIOS[0x4000];
|
||||||
@ -37,8 +44,12 @@ u32 ARM9DTCMBase, ARM9DTCMSize;
|
|||||||
u32 IME[2];
|
u32 IME[2];
|
||||||
u32 IE[2], IF[2];
|
u32 IE[2], IF[2];
|
||||||
|
|
||||||
|
Timer Timers[8];
|
||||||
|
|
||||||
u16 IPCSync9, IPCSync7;
|
u16 IPCSync9, IPCSync7;
|
||||||
|
|
||||||
|
u16 _soundbias; // temp
|
||||||
|
|
||||||
bool Running;
|
bool Running;
|
||||||
|
|
||||||
|
|
||||||
@ -103,10 +114,18 @@ void Reset()
|
|||||||
ARM7->Reset();
|
ARM7->Reset();
|
||||||
CP15::Reset();
|
CP15::Reset();
|
||||||
|
|
||||||
|
memset(Timers, 0, 8*sizeof(Timer));
|
||||||
|
|
||||||
SPI::Reset();
|
SPI::Reset();
|
||||||
|
|
||||||
|
memset(SchedBuffer, 0, sizeof(SchedEvent)*SCHED_BUF_LEN);
|
||||||
|
SchedQueue = NULL;
|
||||||
|
|
||||||
ARM9Cycles = 0;
|
ARM9Cycles = 0;
|
||||||
ARM7Cycles = 0;
|
ARM7Cycles = 0;
|
||||||
|
SchedCycles = 0;
|
||||||
|
|
||||||
|
_soundbias = 0;
|
||||||
|
|
||||||
Running = true; // hax
|
Running = true; // hax
|
||||||
}
|
}
|
||||||
@ -116,17 +135,144 @@ void RunFrame()
|
|||||||
{
|
{
|
||||||
s32 framecycles = 560190<<1;
|
s32 framecycles = 560190<<1;
|
||||||
|
|
||||||
// very gross and temp. loop
|
const s32 maxcycles = 16;
|
||||||
|
|
||||||
while (Running && framecycles>0)
|
while (Running && framecycles>0)
|
||||||
{
|
{
|
||||||
ARM9Cycles = ARM9->Execute(32 + ARM9Cycles);
|
//ARM9Cycles = ARM9->Execute(32 + ARM9Cycles);
|
||||||
ARM7Cycles = ARM7->Execute(16 + ARM7Cycles);
|
//ARM7Cycles = ARM7->Execute(16 + ARM7Cycles);
|
||||||
|
|
||||||
framecycles -= 32;
|
//framecycles -= 32;
|
||||||
|
s32 cyclestorun = maxcycles;
|
||||||
|
// TODO: scheduler integration here
|
||||||
|
|
||||||
|
CompensatedCycles = ARM9Cycles;
|
||||||
|
s32 c9 = ARM9->Execute(cyclestorun - ARM9Cycles);
|
||||||
|
ARM9Cycles = c9 - cyclestorun;
|
||||||
|
c9 -= CompensatedCycles;
|
||||||
|
|
||||||
|
s32 c7 = ARM7->Execute((c9 - ARM7Cycles) >> 1) << 1;
|
||||||
|
ARM7Cycles = c7 - c9;
|
||||||
|
|
||||||
|
RunEvents(c9);
|
||||||
|
framecycles -= cyclestorun;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SchedEvent* ScheduleEvent(s32 Delay, void (*Func)(u32), u32 Param)
|
||||||
|
{
|
||||||
|
// find a free entry
|
||||||
|
u32 entry = -1;
|
||||||
|
for (int i = 0; i < SCHED_BUF_LEN; i++)
|
||||||
|
{
|
||||||
|
if (SchedBuffer[i].Func == NULL)
|
||||||
|
{
|
||||||
|
entry = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry == -1)
|
||||||
|
{
|
||||||
|
printf("!! SCHEDULER BUFFER FULL\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SchedEvent* evt = &SchedBuffer[entry];
|
||||||
|
evt->Func = Func;
|
||||||
|
evt->Param = Param;
|
||||||
|
|
||||||
|
SchedEvent* cur = SchedQueue;
|
||||||
|
SchedEvent* prev = NULL;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (cur == NULL) break;
|
||||||
|
if (cur->Delay > Delay) break;
|
||||||
|
|
||||||
|
Delay -= cur->Delay;
|
||||||
|
prev = cur;
|
||||||
|
cur = cur->NextEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// so, we found it. we insert our event before 'cur'.
|
||||||
|
evt->Delay = Delay;
|
||||||
|
|
||||||
|
if (cur == NULL)
|
||||||
|
{
|
||||||
|
if (prev == NULL)
|
||||||
|
{
|
||||||
|
// list empty
|
||||||
|
SchedQueue = evt;
|
||||||
|
evt->PrevEvent = NULL;
|
||||||
|
evt->NextEvent = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// inserting at the end of the list
|
||||||
|
evt->PrevEvent = prev;
|
||||||
|
evt->NextEvent = NULL;
|
||||||
|
prev->NextEvent = evt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
evt->NextEvent = cur;
|
||||||
|
evt->PrevEvent = cur->PrevEvent;
|
||||||
|
|
||||||
|
if (evt->PrevEvent)
|
||||||
|
evt->PrevEvent->NextEvent = evt;
|
||||||
|
|
||||||
|
cur->PrevEvent = evt;
|
||||||
|
cur->Delay -= evt->Delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CancelEvent(SchedEvent* event)
|
||||||
|
{
|
||||||
|
event->Func = NULL;
|
||||||
|
|
||||||
|
// unlink
|
||||||
|
|
||||||
|
if (event->PrevEvent)
|
||||||
|
event->PrevEvent->NextEvent = event->NextEvent;
|
||||||
|
else
|
||||||
|
SchedQueue = event->NextEvent;
|
||||||
|
|
||||||
|
if (event->NextEvent)
|
||||||
|
event->NextEvent->PrevEvent = event->PrevEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunEvents(s32 cycles)
|
||||||
|
{
|
||||||
|
SchedCycles += cycles;
|
||||||
|
|
||||||
|
SchedEvent* evt = SchedQueue;
|
||||||
|
while (evt && evt->Delay <= SchedCycles)
|
||||||
|
{
|
||||||
|
evt->Func(evt->Param);
|
||||||
|
evt->Func = NULL;
|
||||||
|
SchedCycles -= evt->Delay;
|
||||||
|
|
||||||
|
evt = evt->NextEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
SchedQueue = evt;
|
||||||
|
if (evt) evt->PrevEvent = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompensateARM7()
|
||||||
|
{
|
||||||
|
s32 c9 = ARM9->Cycles - CompensatedCycles;
|
||||||
|
CompensatedCycles = ARM9->Cycles;
|
||||||
|
|
||||||
|
s32 c7 = ARM7->Execute((c9 - ARM7Cycles) >> 1) << 1;
|
||||||
|
ARM7Cycles = c7 - c9;
|
||||||
|
|
||||||
|
RunEvents(c9);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Halt()
|
void Halt()
|
||||||
{
|
{
|
||||||
@ -182,6 +328,73 @@ void TriggerIRQ(u32 cpu, u32 irq)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const s32 TimerPrescaler[4] = {2, 128, 512, 2048};
|
||||||
|
|
||||||
|
void TimerIncrement(u32 param)
|
||||||
|
{
|
||||||
|
Timer* timer = &Timers[param];
|
||||||
|
|
||||||
|
u32 tid = param & 0x3;
|
||||||
|
u32 cpu = param >> 2;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
timer->Counter++;
|
||||||
|
if (param==7)printf("timer%d increment %04X %04X %04X\n", param, timer->Control, timer->Counter, timer->Reload);
|
||||||
|
if (tid == (param&0x3))
|
||||||
|
timer->Event = ScheduleEvent(TimerPrescaler[timer->Control&0x3], TimerIncrement, param);
|
||||||
|
|
||||||
|
if (timer->Counter == 0)
|
||||||
|
{
|
||||||
|
timer->Counter = timer->Reload;
|
||||||
|
|
||||||
|
if (timer->Control & (1<<6))
|
||||||
|
TriggerIRQ(cpu, IRQ_Timer0 + tid);
|
||||||
|
|
||||||
|
// cascade
|
||||||
|
if (tid == 3)
|
||||||
|
break;
|
||||||
|
timer++;
|
||||||
|
if ((timer->Control & 0x84) != 0x84)
|
||||||
|
break;
|
||||||
|
tid++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimerStart(u32 id, u16 cnt)
|
||||||
|
{
|
||||||
|
Timer* timer = &Timers[id];
|
||||||
|
u16 curstart = timer->Control & (1<<7);
|
||||||
|
u16 newstart = cnt & (1<<7);
|
||||||
|
|
||||||
|
printf("timer%d start: %04X %04X\n", id, timer->Control, cnt);
|
||||||
|
|
||||||
|
timer->Control = cnt;
|
||||||
|
|
||||||
|
if ((!curstart) && newstart)
|
||||||
|
{
|
||||||
|
// start the timer, if it's not a cascading timer
|
||||||
|
if (!(cnt & (1<<2)))
|
||||||
|
{
|
||||||
|
timer->Counter = timer->Reload;
|
||||||
|
timer->Event = ScheduleEvent(TimerPrescaler[cnt&0x3], TimerIncrement, id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
timer->Event = NULL;
|
||||||
|
}
|
||||||
|
else if (curstart && !newstart)
|
||||||
|
{
|
||||||
|
if (timer->Event)
|
||||||
|
CancelEvent(timer->Event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
u8 ARM9Read8(u32 addr)
|
u8 ARM9Read8(u32 addr)
|
||||||
{
|
{
|
||||||
if ((addr & 0xFFFFF000) == 0xFFFF0000)
|
if ((addr & 0xFFFFF000) == 0xFFFF0000)
|
||||||
@ -245,6 +458,15 @@ u16 ARM9Read16(u32 addr)
|
|||||||
case 0x04000000:
|
case 0x04000000:
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
|
case 0x04000100: return Timers[0].Counter;
|
||||||
|
case 0x04000102: return Timers[0].Control;
|
||||||
|
case 0x04000104: return Timers[1].Counter;
|
||||||
|
case 0x04000106: return Timers[1].Control;
|
||||||
|
case 0x04000108: return Timers[2].Counter;
|
||||||
|
case 0x0400010A: return Timers[2].Control;
|
||||||
|
case 0x0400010C: return Timers[3].Counter;
|
||||||
|
case 0x0400010E: return Timers[3].Control;
|
||||||
|
|
||||||
case 0x04000180: return IPCSync9;
|
case 0x04000180: return IPCSync9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,6 +490,20 @@ u32 ARM9Read32(u32 addr)
|
|||||||
return *(u32*)&ARM9DTCM[(addr - ARM9DTCMBase) & 0x3FFF];
|
return *(u32*)&ARM9DTCM[(addr - ARM9DTCMBase) & 0x3FFF];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (addr >= 0xFFFF1000)
|
||||||
|
{
|
||||||
|
Halt();
|
||||||
|
/*FILE* f = fopen("ram.bin", "wb");
|
||||||
|
fwrite(MainRAM, 0x400000, 1, f);
|
||||||
|
fclose(f);
|
||||||
|
fopen("wram.bin", "wb");
|
||||||
|
fwrite(ARM7WRAM, 0x10000, 1, f);
|
||||||
|
fclose(f);
|
||||||
|
fopen("swram.bin", "wb");
|
||||||
|
fwrite(ARM7WRAM, 0x8000, 1, f);
|
||||||
|
fclose(f);*/
|
||||||
|
}
|
||||||
|
|
||||||
switch (addr & 0xFF000000)
|
switch (addr & 0xFF000000)
|
||||||
{
|
{
|
||||||
case 0x02000000:
|
case 0x02000000:
|
||||||
@ -280,13 +516,18 @@ u32 ARM9Read32(u32 addr)
|
|||||||
case 0x04000000:
|
case 0x04000000:
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
|
case 0x04000100: return Timers[0].Counter | (Timers[0].Control << 16);
|
||||||
|
case 0x04000104: return Timers[1].Counter | (Timers[1].Control << 16);
|
||||||
|
case 0x04000108: return Timers[2].Counter | (Timers[2].Control << 16);
|
||||||
|
case 0x0400010C: return Timers[3].Counter | (Timers[3].Control << 16);
|
||||||
|
|
||||||
case 0x04000208: return IME[0];
|
case 0x04000208: return IME[0];
|
||||||
case 0x04000210: return IE[0];
|
case 0x04000210: return IE[0];
|
||||||
case 0x04000214: return IF[0];
|
case 0x04000214: return IF[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("unknown arm9 read32 %08X | %08X\n", addr, ARM9->R[15]);
|
printf("unknown arm9 read32 %08X | %08X %08X %08X\n", addr, ARM9->R[15], ARM9->R[12], ARM9Read32(0x027FF820));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,6 +593,15 @@ void ARM9Write16(u32 addr, u16 val)
|
|||||||
case 0x04000000:
|
case 0x04000000:
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
|
case 0x04000100: Timers[0].Reload = val; return;
|
||||||
|
case 0x04000102: TimerStart(0, val); return;
|
||||||
|
case 0x04000104: Timers[1].Reload = val; return;
|
||||||
|
case 0x04000106: TimerStart(1, val); return;
|
||||||
|
case 0x04000108: Timers[2].Reload = val; return;
|
||||||
|
case 0x0400010A: TimerStart(2, val); return;
|
||||||
|
case 0x0400010C: Timers[3].Reload = val; return;
|
||||||
|
case 0x0400010E: TimerStart(3, val); return;
|
||||||
|
|
||||||
case 0x04000180:
|
case 0x04000180:
|
||||||
IPCSync7 &= 0xFFF0;
|
IPCSync7 &= 0xFFF0;
|
||||||
IPCSync7 |= ((val & 0x0F00) >> 8);
|
IPCSync7 |= ((val & 0x0F00) >> 8);
|
||||||
@ -361,6 +611,7 @@ void ARM9Write16(u32 addr, u16 val)
|
|||||||
{
|
{
|
||||||
TriggerIRQ(1, IRQ_IPCSync);
|
TriggerIRQ(1, IRQ_IPCSync);
|
||||||
}
|
}
|
||||||
|
CompensateARM7();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -394,6 +645,23 @@ void ARM9Write32(u32 addr, u32 val)
|
|||||||
case 0x04000000:
|
case 0x04000000:
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
|
case 0x04000100:
|
||||||
|
Timers[0].Reload = val & 0xFFFF;
|
||||||
|
TimerStart(0, val>>16);
|
||||||
|
return;
|
||||||
|
case 0x04000104:
|
||||||
|
Timers[1].Reload = val & 0xFFFF;
|
||||||
|
TimerStart(1, val>>16);
|
||||||
|
return;
|
||||||
|
case 0x04000108:
|
||||||
|
Timers[2].Reload = val & 0xFFFF;
|
||||||
|
TimerStart(2, val>>16);
|
||||||
|
return;
|
||||||
|
case 0x0400010C:
|
||||||
|
Timers[3].Reload = val & 0xFFFF;
|
||||||
|
TimerStart(3, val>>16);
|
||||||
|
return;
|
||||||
|
|
||||||
case 0x04000208: IME[0] = val; return;
|
case 0x04000208: IME[0] = val; return;
|
||||||
case 0x04000210: IE[0] = val; return;
|
case 0x04000210: IE[0] = val; return;
|
||||||
case 0x04000214: IF[0] &= ~val; return;
|
case 0x04000214: IF[0] &= ~val; return;
|
||||||
@ -462,14 +730,25 @@ u16 ARM7Read16(u32 addr)
|
|||||||
case 0x04000000:
|
case 0x04000000:
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
|
case 0x04000100: return Timers[4].Counter;
|
||||||
|
case 0x04000102: return Timers[4].Control;
|
||||||
|
case 0x04000104: return Timers[5].Counter;
|
||||||
|
case 0x04000106: return Timers[5].Control;
|
||||||
|
case 0x04000108: return Timers[6].Counter;
|
||||||
|
case 0x0400010A: return Timers[6].Control;
|
||||||
|
case 0x0400010C: return Timers[7].Counter;
|
||||||
|
case 0x0400010E: return Timers[7].Control;
|
||||||
|
|
||||||
case 0x04000180: return IPCSync7;
|
case 0x04000180: return IPCSync7;
|
||||||
|
|
||||||
case 0x040001C0: return SPI::ReadCnt();
|
case 0x040001C0: return SPI::ReadCnt();
|
||||||
case 0x040001C2: return SPI::ReadData();
|
case 0x040001C2: return SPI::ReadData();
|
||||||
|
|
||||||
|
case 0x04000504: return _soundbias;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("unknown arm7 read16 %08X\n", addr);
|
printf("unknown arm7 read16 %08X %08X\n", addr, ARM7->R[15]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,6 +774,11 @@ u32 ARM7Read32(u32 addr)
|
|||||||
case 0x04000000:
|
case 0x04000000:
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
|
case 0x04000100: return Timers[4].Counter | (Timers[4].Control << 16);
|
||||||
|
case 0x04000104: return Timers[5].Counter | (Timers[5].Control << 16);
|
||||||
|
case 0x04000108: return Timers[6].Counter | (Timers[6].Control << 16);
|
||||||
|
case 0x0400010C: return Timers[7].Counter | (Timers[7].Control << 16);
|
||||||
|
|
||||||
case 0x040001A4:
|
case 0x040001A4:
|
||||||
return 0x00800000; // hax
|
return 0x00800000; // hax
|
||||||
|
|
||||||
@ -507,6 +791,7 @@ u32 ARM7Read32(u32 addr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((addr&0xFF000000) == 0xEA000000) Halt();
|
if ((addr&0xFF000000) == 0xEA000000) Halt();
|
||||||
|
|
||||||
printf("unknown arm7 read32 %08X | %08X\n", addr, ARM7->R[15]);
|
printf("unknown arm7 read32 %08X | %08X\n", addr, ARM7->R[15]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -545,6 +830,19 @@ void ARM7Write8(u32 addr, u8 val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (addr==0xA20)
|
||||||
|
{
|
||||||
|
/*FILE* f = fopen("ram.bin", "wb");
|
||||||
|
fwrite(MainRAM, 0x400000, 1, f);
|
||||||
|
fclose(f);
|
||||||
|
fopen("wram.bin", "wb");
|
||||||
|
fwrite(ARM7WRAM, 0x10000, 1, f);
|
||||||
|
fclose(f);
|
||||||
|
fopen("swram.bin", "wb");
|
||||||
|
fwrite(ARM7WRAM, 0x8000, 1, f);
|
||||||
|
fclose(f);*/
|
||||||
|
}
|
||||||
|
|
||||||
printf("unknown arm7 write8 %08X %02X | %08X | %08X %08X %08X %08X\n", addr, val, ARM7->R[15], IME[1], IE[1], ARM7->R[0], ARM7->R[1]);
|
printf("unknown arm7 write8 %08X %02X | %08X | %08X %08X %08X %08X\n", addr, val, ARM7->R[15], IME[1], IE[1], ARM7->R[0], ARM7->R[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,6 +866,15 @@ void ARM7Write16(u32 addr, u16 val)
|
|||||||
case 0x04000000:
|
case 0x04000000:
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
|
case 0x04000100: Timers[4].Reload = val; return;
|
||||||
|
case 0x04000102: TimerStart(4, val); return;
|
||||||
|
case 0x04000104: Timers[5].Reload = val; return;
|
||||||
|
case 0x04000106: TimerStart(5, val); return;
|
||||||
|
case 0x04000108: Timers[6].Reload = val; return;
|
||||||
|
case 0x0400010A: TimerStart(6, val); return;
|
||||||
|
case 0x0400010C: Timers[7].Reload = val; return;
|
||||||
|
case 0x0400010E: TimerStart(7, val); return;
|
||||||
|
|
||||||
case 0x04000180:
|
case 0x04000180:
|
||||||
IPCSync9 &= 0xFFF0;
|
IPCSync9 &= 0xFFF0;
|
||||||
IPCSync9 |= ((val & 0x0F00) >> 8);
|
IPCSync9 |= ((val & 0x0F00) >> 8);
|
||||||
@ -586,6 +893,10 @@ void ARM7Write16(u32 addr, u16 val)
|
|||||||
case 0x040001C2:
|
case 0x040001C2:
|
||||||
SPI::WriteData(val & 0xFF);
|
SPI::WriteData(val & 0xFF);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case 0x04000504:
|
||||||
|
_soundbias = val & 0x3FF;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -612,13 +923,30 @@ void ARM7Write32(u32 addr, u32 val)
|
|||||||
case 0x04000000:
|
case 0x04000000:
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
|
case 0x04000100:
|
||||||
|
Timers[4].Reload = val & 0xFFFF;
|
||||||
|
TimerStart(4, val>>16);
|
||||||
|
return;
|
||||||
|
case 0x04000104:
|
||||||
|
Timers[5].Reload = val & 0xFFFF;
|
||||||
|
TimerStart(5, val>>16);
|
||||||
|
return;
|
||||||
|
case 0x04000108:
|
||||||
|
Timers[6].Reload = val & 0xFFFF;
|
||||||
|
TimerStart(6, val>>16);
|
||||||
|
return;
|
||||||
|
case 0x0400010C:
|
||||||
|
Timers[7].Reload = val & 0xFFFF;
|
||||||
|
TimerStart(7, val>>16);
|
||||||
|
return;
|
||||||
|
|
||||||
case 0x04000208: IME[1] = val; return;
|
case 0x04000208: IME[1] = val; return;
|
||||||
case 0x04000210: IE[1] = val; return;
|
case 0x04000210: IE[1] = val; return;
|
||||||
case 0x04000214: IF[1] &= ~val; printf("IRQ ack %08X\n", val);return;
|
case 0x04000214: IF[1] &= ~val; printf("IRQ ack %08X\n", val);return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("unknown arm7 write32 %08X %08X | %08X\n", addr, val, ARM7->R[15]);
|
printf("unknown arm7 write32 %08X %08X | %08X %08X\n", addr, val, ARM7->R[15], ARM7->CurInstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
28
NDS.h
28
NDS.h
@ -7,6 +7,18 @@
|
|||||||
namespace NDS
|
namespace NDS
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#define SCHED_BUF_LEN 64
|
||||||
|
|
||||||
|
typedef struct _SchedEvent
|
||||||
|
{
|
||||||
|
u32 Delay;
|
||||||
|
void (*Func)(u32);
|
||||||
|
u32 Param;
|
||||||
|
struct _SchedEvent* PrevEvent;
|
||||||
|
struct _SchedEvent* NextEvent;
|
||||||
|
|
||||||
|
} SchedEvent;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
IRQ_VBlank = 0,
|
IRQ_VBlank = 0,
|
||||||
@ -36,6 +48,15 @@ enum
|
|||||||
IRQ_Wifi
|
IRQ_Wifi
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u16 Reload;
|
||||||
|
u16 Control;
|
||||||
|
u16 Counter;
|
||||||
|
SchedEvent* Event;
|
||||||
|
|
||||||
|
} Timer;
|
||||||
|
|
||||||
extern u32 ARM9ITCMSize;
|
extern u32 ARM9ITCMSize;
|
||||||
extern u32 ARM9DTCMBase, ARM9DTCMSize;
|
extern u32 ARM9DTCMBase, ARM9DTCMSize;
|
||||||
|
|
||||||
@ -44,6 +65,13 @@ void Reset();
|
|||||||
|
|
||||||
void RunFrame();
|
void RunFrame();
|
||||||
|
|
||||||
|
SchedEvent* ScheduleEvent(s32 Delay, void (*Func)(u32), u32 Param);
|
||||||
|
void CancelEvent(SchedEvent* event);
|
||||||
|
void RunEvents(s32 cycles);
|
||||||
|
|
||||||
|
// DO NOT CALL FROM ARM7!!
|
||||||
|
void CompensateARM7();
|
||||||
|
|
||||||
void Halt();
|
void Halt();
|
||||||
|
|
||||||
void MapSharedWRAM();
|
void MapSharedWRAM();
|
||||||
|
@ -14,3 +14,10 @@ NO ASKING ROMZ!! ILLEGAL
|
|||||||
|
|
||||||
|
|
||||||
license will eventually be GPL or some crap. don't steal the code and make money off of it or claim it as your own or be an asshole.
|
license will eventually be GPL or some crap. don't steal the code and make money off of it or claim it as your own or be an asshole.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TODO LIST
|
||||||
|
|
||||||
|
* take code fetch waitstates into account when fetching instructions, and during branches (pipeline shit) (tricky, some code fetches are nonsequential)
|
||||||
|
*
|
@ -3,12 +3,12 @@
|
|||||||
<stdio.h>
|
<stdio.h>
|
||||||
"NDS.h"
|
"NDS.h"
|
||||||
|
|
||||||
1480786846 c:\documents\sources\melonds\nds.h
|
1480942921 c:\documents\sources\melonds\nds.h
|
||||||
"types.h"
|
"types.h"
|
||||||
|
|
||||||
1463409689 c:\documents\sources\melonds\types.h
|
1463409689 c:\documents\sources\melonds\types.h
|
||||||
|
|
||||||
1480816263 source:c:\documents\sources\melonds\nds.cpp
|
1480953322 source:c:\documents\sources\melonds\nds.cpp
|
||||||
<stdio.h>
|
<stdio.h>
|
||||||
<string.h>
|
<string.h>
|
||||||
"NDS.h"
|
"NDS.h"
|
||||||
@ -16,23 +16,23 @@
|
|||||||
"CP15.h"
|
"CP15.h"
|
||||||
"SPI.h"
|
"SPI.h"
|
||||||
|
|
||||||
1480789789 source:c:\documents\sources\melonds\arm.cpp
|
1480953451 source:c:\documents\sources\melonds\arm.cpp
|
||||||
<stdio.h>
|
<stdio.h>
|
||||||
"NDS.h"
|
"NDS.h"
|
||||||
"ARM.h"
|
"ARM.h"
|
||||||
"ARMInterpreter.h"
|
"ARMInterpreter.h"
|
||||||
|
|
||||||
1480786942 c:\documents\sources\melonds\arm.h
|
1480951045 c:\documents\sources\melonds\arm.h
|
||||||
"types.h"
|
"types.h"
|
||||||
"NDS.h"
|
"NDS.h"
|
||||||
|
|
||||||
1480785229 c:\documents\sources\melonds\arm_instrtable.h
|
1480954012 c:\documents\sources\melonds\arm_instrtable.h
|
||||||
|
|
||||||
1480725698 c:\documents\sources\melonds\arminterpreter.h
|
1480725698 c:\documents\sources\melonds\arminterpreter.h
|
||||||
"types.h"
|
"types.h"
|
||||||
"ARM.h"
|
"ARM.h"
|
||||||
|
|
||||||
1480776855 source:c:\documents\sources\melonds\arminterpreter.cpp
|
1480952246 source:c:\documents\sources\melonds\arminterpreter.cpp
|
||||||
<stdio.h>
|
<stdio.h>
|
||||||
"NDS.h"
|
"NDS.h"
|
||||||
"CP15.h"
|
"CP15.h"
|
||||||
@ -50,24 +50,24 @@
|
|||||||
|
|
||||||
1480784137 c:\documents\sources\melonds\arminterpreter_alu.h
|
1480784137 c:\documents\sources\melonds\arminterpreter_alu.h
|
||||||
|
|
||||||
1480784110 source:c:\documents\sources\melonds\arminterpreter_alu.cpp
|
1480952092 source:c:\documents\sources\melonds\arminterpreter_alu.cpp
|
||||||
"ARM.h"
|
"ARM.h"
|
||||||
|
|
||||||
1480785175 c:\documents\sources\melonds\arminterpreter_loadstore.h
|
1480953933 c:\documents\sources\melonds\arminterpreter_loadstore.h
|
||||||
|
|
||||||
1480785158 source:c:\documents\sources\melonds\arminterpreter_loadstore.cpp
|
1480951014 source:c:\documents\sources\melonds\arminterpreter_loadstore.cpp
|
||||||
<stdio.h>
|
<stdio.h>
|
||||||
"ARM.h"
|
"ARM.h"
|
||||||
|
|
||||||
1480776964 c:\documents\sources\melonds\cp15.h
|
1480776964 c:\documents\sources\melonds\cp15.h
|
||||||
|
|
||||||
1480777799 source:c:\documents\sources\melonds\cp15.cpp
|
1480950166 source:c:\documents\sources\melonds\cp15.cpp
|
||||||
<stdio.h>
|
<stdio.h>
|
||||||
"NDS.h"
|
"NDS.h"
|
||||||
|
|
||||||
1480814622 c:\documents\sources\melonds\spi.h
|
1480814622 c:\documents\sources\melonds\spi.h
|
||||||
|
|
||||||
1480816142 source:c:\documents\sources\melonds\spi.cpp
|
1480816963 source:c:\documents\sources\melonds\spi.cpp
|
||||||
<stdio.h>
|
<stdio.h>
|
||||||
"NDS.h"
|
"NDS.h"
|
||||||
"SPI.h"
|
"SPI.h"
|
||||||
|
Loading…
Reference in New Issue
Block a user