start refactoring shit: more accurate timing and way of counting cycles.

This commit is contained in:
StapleButter 2017-01-30 18:36:11 +01:00
parent 296212ac49
commit 6f3b0498db
17 changed files with 636 additions and 595 deletions

145
ARM.cpp
View File

@ -47,6 +47,97 @@ ARM::ARM(u32 num)
{
// well uh
Num = num;
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()
@ -83,21 +174,23 @@ void ARM::JumpTo(u32 addr, bool restorecpsr)
if (addr == 0x02000800)
{
printf("!!!!!!!! %08X\n", R[15]);
printf("%08X %08X %08X %08X\n", Read32(0x02000000), Read32(0x0200000C), Read32(0x02000800), Read32(0x02000804));
//printf("%08X %08X %08X %08X\n", Read32(0x02000000), Read32(0x0200000C), Read32(0x02000800), Read32(0x02000804));
}
if (addr & 0x1)
{
addr &= ~0x1;
R[15] = addr+2;
NextInstr = Read16(addr);
NextInstr[0] = CodeRead16(addr);
NextInstr[1] = CodeRead16(addr+2);
CPSR |= 0x20;
}
else
{
addr &= ~0x3;
R[15] = addr+4;
NextInstr = Read32(addr);
NextInstr[0] = CodeRead32(addr);
NextInstr[1] = CodeRead32(addr+4);
CPSR &= ~0x20;
}
}
@ -227,67 +320,65 @@ void ARM::TriggerIRQ()
JumpTo(ExceptionBase + 0x18);
}
s32 ARM::Execute(s32 cycles)
s32 ARM::Execute(s32 cyclestorun)
{
if (Halted)
{
if (NDS::HaltInterrupted(Num))
Halted = 0;
else
return cycles;
{
Cycles = cyclestorun;
return Cycles;
}
}
s32 cyclesrun = 0;
Cycles = 0;
u32 addr = R[15] - (CPSR&0x20 ? 4:8);
u32 cpsr = CPSR;
while (cyclesrun < cycles)
while (Cycles < cyclestorun)
{
//if(Num==1)printf("%08X %08X\n", R[15] - (CPSR&0x20 ? 4:8), NextInstr);
if (CPSR & 0x20) // THUMB
{
// prefetch
CurInstr = NextInstr;
NextInstr = Read16(R[15]);
//cyclesrun += MemWaitstate(0, R[15]);
R[15] += 2;
Cycles = cyclesrun;
CurInstr = NextInstr[0];
NextInstr[0] = NextInstr[1];
NextInstr[1] = CodeRead16(R[15]);
// actually execute
u32 icode = (CurInstr >> 6);
cyclesrun += ARMInterpreter::THUMBInstrTable[icode](this);
ARMInterpreter::THUMBInstrTable[icode](this);
}
else
{
// prefetch
CurInstr = NextInstr;
NextInstr = Read32(R[15]);
//cyclesrun += MemWaitstate(1, R[15]);
R[15] += 4;
Cycles = cyclesrun;
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);
cyclesrun += ARMInterpreter::ARMInstrTable[icode](this);
ARMInterpreter::ARMInstrTable[icode](this);
}
else if ((CurInstr & 0xFE000000) == 0xFA000000)
{
cyclesrun += ARMInterpreter::A_BLX_IMM(this);
}
else
{
// not executing it. oh well
cyclesrun += 1; // 1S. todo: check
ARMInterpreter::A_BLX_IMM(this);
}
}
// TODO optimize this shit!!!
if (Halted) return cycles;
if (Halted)
{
Cycles = cyclestorun;
return Cycles;
}
if (NDS::HaltInterrupted(Num))
{
if (NDS::IME[Num]&1)
@ -299,5 +390,5 @@ s32 ARM::Execute(s32 cycles)
cpsr = CPSR;
}
return cyclesrun;
return Cycles;
}

91
ARM.h
View File

@ -81,42 +81,86 @@ public:
void TriggerIRQ();
u8 Read8(u32 addr, u32 forceuser=0)
u16 CodeRead16(u32 addr)
{
u16 val;
// TODO eventually: on ARM9, THUMB opcodes are prefetched with 32bit reads
if (!Num)
{
// TODO: PU shit
return NDS::ARM9Read8(addr);
val = NDS::ARM9Read16(addr);
}
else
return NDS::ARM7Read8(addr);
val = NDS::ARM7Read16(addr);
Cycles += Waitstates[0][(addr>>24)&0xF];
return val;
}
u16 Read16(u32 addr, u32 forceuser=0)
u32 CodeRead32(u32 addr)
{
u32 val;
if (!Num)
{
// TODO: PU shit
val = NDS::ARM9Read32(addr);
}
else
val = NDS::ARM7Read32(addr);
Cycles += Waitstates[1][(addr>>24)&0xF];
return val;
}
u8 DataRead8(u32 addr, u32 forceuser=0)
{
u8 val;
if (!Num)
{
// TODO: PU shit
val = NDS::ARM9Read8(addr);
}
else
val = NDS::ARM7Read8(addr);
Cycles += Waitstates[3][(addr>>24)&0xF];
return val;
}
u16 DataRead16(u32 addr, u32 forceuser=0)
{
u16 val;
addr &= ~1;
if (!Num)
{
// TODO: PU shit
return NDS::ARM9Read16(addr);
val = NDS::ARM9Read16(addr);
}
else
return NDS::ARM7Read16(addr);
val = NDS::ARM7Read16(addr);
Cycles += Waitstates[2][(addr>>24)&0xF];
return val;
}
u32 Read32(u32 addr, u32 forceuser=0)
u32 DataRead32(u32 addr, u32 forceuser=0)
{
u32 val;
addr &= ~3;
if (!Num)
{
// TODO: PU shit
return NDS::ARM9Read32(addr);
val = NDS::ARM9Read32(addr);
}
else
return NDS::ARM7Read32(addr);
val = NDS::ARM7Read32(addr);
Cycles += Waitstates[3][(addr>>24)&0xF];
return val;
}
void Write8(u32 addr, u8 val, u32 forceuser=0)
void DataWrite8(u32 addr, u8 val, u32 forceuser=0)
{
if (!Num)
{
@ -125,9 +169,11 @@ public:
}
else
NDS::ARM7Write8(addr, val);
Cycles += Waitstates[3][(addr>>24)&0xF];
}
void Write16(u32 addr, u16 val, u32 forceuser=0)
void DataWrite16(u32 addr, u16 val, u32 forceuser=0)
{
addr &= ~1;
if (!Num)
@ -137,9 +183,11 @@ public:
}
else
NDS::ARM7Write16(addr, val);
Cycles += Waitstates[2][(addr>>24)&0xF];
}
void Write32(u32 addr, u32 val, u32 forceuser=0)
void DataWrite32(u32 addr, u32 val, u32 forceuser=0)
{
addr &= ~3;
if (!Num)
@ -149,23 +197,18 @@ public:
}
else
NDS::ARM7Write32(addr, val);
}
s32 MemWaitstate(u32 type, u32 addr)
{
// type:
// 0 = code16
// 1 = code32
// 2 = data16
// 3 = data32
return 1; // sorry
Cycles += Waitstates[3][(addr>>24)&0xF];
}
u32 Num;
// waitstates:
// 0=code16 1=code32 2=data16 3=data32
// TODO eventually: nonsequential waitstates
s32 Waitstates[4][16];
s32 Cycles;
u32 Halted;
@ -177,7 +220,7 @@ public:
u32 R_IRQ[3];
u32 R_UND[3];
u32 CurInstr;
u32 NextInstr;
u32 NextInstr[2];
u32 ExceptionBase;

View File

@ -29,24 +29,22 @@ namespace ARMInterpreter
{
s32 A_UNK(ARM* cpu)
void A_UNK(ARM* cpu)
{
printf("undefined ARM%d instruction %08X @ %08X\n", cpu->Num?7:9, cpu->CurInstr, cpu->R[15]-8);
for (int i = 0; i < 16; i++) printf("R%d: %08X\n", i, cpu->R[i]);
NDS::Halt();
return 0x7FFFFFFF;
}
s32 T_UNK(ARM* cpu)
void T_UNK(ARM* cpu)
{
printf("undefined THUMB%d instruction %04X @ %08X\n", cpu->Num?7:9, cpu->CurInstr, cpu->R[15]-4);
NDS::Halt();
return 0x7FFFFFFF;
}
s32 A_MSR_IMM(ARM* cpu)
void A_MSR_IMM(ARM* cpu)
{
u32* psr;
if (cpu->CurInstr & (1<<22))
@ -58,7 +56,7 @@ s32 A_MSR_IMM(ARM* cpu)
case 0x13: psr = &cpu->R_SVC[2]; break;
case 0x17: psr = &cpu->R_ABT[2]; break;
case 0x1B: psr = &cpu->R_UND[2]; break;
default: printf("bad CPU mode %08X\n", cpu->CPSR); return 1;
default: printf("bad CPU mode %08X\n", cpu->CPSR); return;
}
}
else
@ -84,11 +82,9 @@ s32 A_MSR_IMM(ARM* cpu)
if (!(cpu->CurInstr & (1<<22)))
cpu->UpdateMode(oldpsr, cpu->CPSR);
return C_S(1);
}
s32 A_MSR_REG(ARM* cpu)
void A_MSR_REG(ARM* cpu)
{
u32* psr;
if (cpu->CurInstr & (1<<22))
@ -100,7 +96,7 @@ s32 A_MSR_REG(ARM* cpu)
case 0x13: psr = &cpu->R_SVC[2]; break;
case 0x17: psr = &cpu->R_ABT[2]; break;
case 0x1B: psr = &cpu->R_UND[2]; break;
default: printf("bad CPU mode %08X\n", cpu->CPSR); return 1;
default: printf("bad CPU mode %08X\n", cpu->CPSR); return;
}
}
else
@ -126,11 +122,9 @@ s32 A_MSR_REG(ARM* cpu)
if (!(cpu->CurInstr & (1<<22)))
cpu->UpdateMode(oldpsr, cpu->CPSR);
return C_S(1);
}
s32 A_MRS(ARM* cpu)
void A_MRS(ARM* cpu)
{
u32 psr;
if (cpu->CurInstr & (1<<22))
@ -142,19 +136,17 @@ s32 A_MRS(ARM* cpu)
case 0x13: psr = cpu->R_SVC[2]; break;
case 0x17: psr = cpu->R_ABT[2]; break;
case 0x1B: psr = cpu->R_UND[2]; break;
default: printf("bad CPU mode %08X\n", cpu->CPSR); return 1;
default: printf("bad CPU mode %08X\n", cpu->CPSR); return;
}
}
else
psr = cpu->CPSR;
cpu->R[(cpu->CurInstr>>12) & 0xF] = psr;
return C_S(1);
}
s32 A_MCR(ARM* cpu)
void A_MCR(ARM* cpu)
{
u32 cp = (cpu->CurInstr >> 8) & 0xF;
//u32 op = (cpu->CurInstr >> 21) & 0x7;
@ -171,10 +163,10 @@ s32 A_MCR(ARM* cpu)
printf("bad MCR opcode p%d,%d,%d,%d on ARM%d\n", cp, cn, cm, cpinfo, cpu->Num?7:9);
}
return C_S(1) + 1; // TODO: checkme
cpu->Cycles += 2; // TODO: checkme
}
s32 A_MRC(ARM* cpu)
void A_MRC(ARM* cpu)
{
u32 cp = (cpu->CurInstr >> 8) & 0xF;
//u32 op = (cpu->CurInstr >> 21) & 0x7;
@ -191,12 +183,12 @@ s32 A_MRC(ARM* cpu)
printf("bad MRC opcode p%d,%d,%d,%d on ARM%d\n", cp, cn, cm, cpinfo, cpu->Num?7:9);
}
return C_S(1) + 1 + C_I(1); // TODO: checkme
cpu->Cycles += 3; // TODO: checkme
}
s32 A_SVC(ARM* cpu)
void A_SVC(ARM* cpu)
{
u32 oldcpsr = cpu->CPSR;
cpu->CPSR &= ~0xFF;
@ -206,11 +198,9 @@ s32 A_SVC(ARM* cpu)
cpu->R_SVC[2] = oldcpsr;
cpu->R[14] = cpu->R[15] - 4;
cpu->JumpTo(cpu->ExceptionBase + 0x08);
return C_S(2) + C_N(1);
}
s32 T_SVC(ARM* cpu)
void T_SVC(ARM* cpu)
{
u32 oldcpsr = cpu->CPSR;
cpu->CPSR &= ~0xFF;
@ -220,13 +210,11 @@ s32 T_SVC(ARM* cpu)
cpu->R_SVC[2] = oldcpsr;
cpu->R[14] = cpu->R[15] - 2;
cpu->JumpTo(cpu->ExceptionBase + 0x08);
return C_S(2) + C_N(1);
}
#define INSTRFUNC_PROTO(x) s32 (*x)(ARM* cpu)
#define INSTRFUNC_PROTO(x) void (*x)(ARM* cpu)
#include "ARM_InstrTable.h"
#undef INSTRFUNC_PROTO

View File

@ -25,10 +25,10 @@
namespace ARMInterpreter
{
extern s32 (*ARMInstrTable[4096])(ARM* cpu);
extern s32 (*THUMBInstrTable[1024])(ARM* cpu);
extern void (*ARMInstrTable[4096])(ARM* cpu);
extern void (*THUMBInstrTable[1024])(ARM* cpu);
s32 A_BLX_IMM(ARM* cpu); // I'm a special one look at me
void A_BLX_IMM(ARM* cpu); // I'm a special one look at me
}

File diff suppressed because it is too large Load Diff

View File

@ -24,36 +24,36 @@ namespace ARMInterpreter
#define A_PROTO_ALU_OP(x) \
\
s32 A_##x##_IMM(ARM* cpu); \
s32 A_##x##_REG_LSL_IMM(ARM* cpu); \
s32 A_##x##_REG_LSR_IMM(ARM* cpu); \
s32 A_##x##_REG_ASR_IMM(ARM* cpu); \
s32 A_##x##_REG_ROR_IMM(ARM* cpu); \
s32 A_##x##_REG_LSL_REG(ARM* cpu); \
s32 A_##x##_REG_LSR_REG(ARM* cpu); \
s32 A_##x##_REG_ASR_REG(ARM* cpu); \
s32 A_##x##_REG_ROR_REG(ARM* cpu); \
s32 A_##x##_IMM_S(ARM* cpu); \
s32 A_##x##_REG_LSL_IMM_S(ARM* cpu); \
s32 A_##x##_REG_LSR_IMM_S(ARM* cpu); \
s32 A_##x##_REG_ASR_IMM_S(ARM* cpu); \
s32 A_##x##_REG_ROR_IMM_S(ARM* cpu); \
s32 A_##x##_REG_LSL_REG_S(ARM* cpu); \
s32 A_##x##_REG_LSR_REG_S(ARM* cpu); \
s32 A_##x##_REG_ASR_REG_S(ARM* cpu); \
s32 A_##x##_REG_ROR_REG_S(ARM* cpu);
void A_##x##_IMM(ARM* cpu); \
void A_##x##_REG_LSL_IMM(ARM* cpu); \
void A_##x##_REG_LSR_IMM(ARM* cpu); \
void A_##x##_REG_ASR_IMM(ARM* cpu); \
void A_##x##_REG_ROR_IMM(ARM* cpu); \
void A_##x##_REG_LSL_REG(ARM* cpu); \
void A_##x##_REG_LSR_REG(ARM* cpu); \
void A_##x##_REG_ASR_REG(ARM* cpu); \
void A_##x##_REG_ROR_REG(ARM* cpu); \
void A_##x##_IMM_S(ARM* cpu); \
void A_##x##_REG_LSL_IMM_S(ARM* cpu); \
void A_##x##_REG_LSR_IMM_S(ARM* cpu); \
void A_##x##_REG_ASR_IMM_S(ARM* cpu); \
void A_##x##_REG_ROR_IMM_S(ARM* cpu); \
void A_##x##_REG_LSL_REG_S(ARM* cpu); \
void A_##x##_REG_LSR_REG_S(ARM* cpu); \
void A_##x##_REG_ASR_REG_S(ARM* cpu); \
void A_##x##_REG_ROR_REG_S(ARM* cpu);
#define A_PROTO_ALU_TEST(x) \
\
s32 A_##x##_IMM(ARM* cpu); \
s32 A_##x##_REG_LSL_IMM(ARM* cpu); \
s32 A_##x##_REG_LSR_IMM(ARM* cpu); \
s32 A_##x##_REG_ASR_IMM(ARM* cpu); \
s32 A_##x##_REG_ROR_IMM(ARM* cpu); \
s32 A_##x##_REG_LSL_REG(ARM* cpu); \
s32 A_##x##_REG_LSR_REG(ARM* cpu); \
s32 A_##x##_REG_ASR_REG(ARM* cpu); \
s32 A_##x##_REG_ROR_REG(ARM* cpu);
void A_##x##_IMM(ARM* cpu); \
void A_##x##_REG_LSL_IMM(ARM* cpu); \
void A_##x##_REG_LSR_IMM(ARM* cpu); \
void A_##x##_REG_ASR_IMM(ARM* cpu); \
void A_##x##_REG_ROR_IMM(ARM* cpu); \
void A_##x##_REG_LSL_REG(ARM* cpu); \
void A_##x##_REG_LSR_REG(ARM* cpu); \
void A_##x##_REG_ASR_REG(ARM* cpu); \
void A_##x##_REG_ROR_REG(ARM* cpu);
A_PROTO_ALU_OP(AND)
A_PROTO_ALU_OP(EOR)
@ -72,54 +72,54 @@ A_PROTO_ALU_OP(MOV)
A_PROTO_ALU_OP(BIC)
A_PROTO_ALU_OP(MVN)
s32 A_MUL(ARM* cpu);
s32 A_MLA(ARM* cpu);
s32 A_UMULL(ARM* cpu);
s32 A_UMLAL(ARM* cpu);
s32 A_SMULL(ARM* cpu);
s32 A_SMLAL(ARM* cpu);
void A_MUL(ARM* cpu);
void A_MLA(ARM* cpu);
void A_UMULL(ARM* cpu);
void A_UMLAL(ARM* cpu);
void A_SMULL(ARM* cpu);
void A_SMLAL(ARM* cpu);
s32 A_CLZ(ARM* cpu);
void A_CLZ(ARM* cpu);
s32 T_LSL_IMM(ARM* cpu);
s32 T_LSR_IMM(ARM* cpu);
s32 T_ASR_IMM(ARM* cpu);
void T_LSL_IMM(ARM* cpu);
void T_LSR_IMM(ARM* cpu);
void T_ASR_IMM(ARM* cpu);
s32 T_ADD_REG_(ARM* cpu);
s32 T_SUB_REG_(ARM* cpu);
s32 T_ADD_IMM_(ARM* cpu);
s32 T_SUB_IMM_(ARM* cpu);
void T_ADD_REG_(ARM* cpu);
void T_SUB_REG_(ARM* cpu);
void T_ADD_IMM_(ARM* cpu);
void T_SUB_IMM_(ARM* cpu);
s32 T_MOV_IMM(ARM* cpu);
s32 T_CMP_IMM(ARM* cpu);
s32 T_ADD_IMM(ARM* cpu);
s32 T_SUB_IMM(ARM* cpu);
void T_MOV_IMM(ARM* cpu);
void T_CMP_IMM(ARM* cpu);
void T_ADD_IMM(ARM* cpu);
void T_SUB_IMM(ARM* cpu);
s32 T_AND_REG(ARM* cpu);
s32 T_EOR_REG(ARM* cpu);
s32 T_LSL_REG(ARM* cpu);
s32 T_LSR_REG(ARM* cpu);
s32 T_ASR_REG(ARM* cpu);
s32 T_ADC_REG(ARM* cpu);
s32 T_SBC_REG(ARM* cpu);
s32 T_ROR_REG(ARM* cpu);
s32 T_TST_REG(ARM* cpu);
s32 T_NEG_REG(ARM* cpu);
s32 T_CMP_REG(ARM* cpu);
s32 T_CMN_REG(ARM* cpu);
s32 T_ORR_REG(ARM* cpu);
s32 T_MUL_REG(ARM* cpu);
s32 T_BIC_REG(ARM* cpu);
s32 T_MVN_REG(ARM* cpu);
void T_AND_REG(ARM* cpu);
void T_EOR_REG(ARM* cpu);
void T_LSL_REG(ARM* cpu);
void T_LSR_REG(ARM* cpu);
void T_ASR_REG(ARM* cpu);
void T_ADC_REG(ARM* cpu);
void T_SBC_REG(ARM* cpu);
void T_ROR_REG(ARM* cpu);
void T_TST_REG(ARM* cpu);
void T_NEG_REG(ARM* cpu);
void T_CMP_REG(ARM* cpu);
void T_CMN_REG(ARM* cpu);
void T_ORR_REG(ARM* cpu);
void T_MUL_REG(ARM* cpu);
void T_BIC_REG(ARM* cpu);
void T_MVN_REG(ARM* cpu);
s32 T_ADD_HIREG(ARM* cpu);
s32 T_CMP_HIREG(ARM* cpu);
s32 T_MOV_HIREG(ARM* cpu);
void T_ADD_HIREG(ARM* cpu);
void T_CMP_HIREG(ARM* cpu);
void T_MOV_HIREG(ARM* cpu);
s32 T_ADD_PCREL(ARM* cpu);
s32 T_ADD_SPREL(ARM* cpu);
s32 T_ADD_SP(ARM* cpu);
void T_ADD_PCREL(ARM* cpu);
void T_ADD_SPREL(ARM* cpu);
void T_ADD_SP(ARM* cpu);
}

View File

@ -24,102 +24,81 @@ namespace ARMInterpreter
{
s32 A_B(ARM* cpu)
void A_B(ARM* cpu)
{
s32 offset = (s32)(cpu->CurInstr << 8) >> 6;
cpu->JumpTo(cpu->R[15] + offset);
return C_S(2) + C_N(1);
}
s32 A_BL(ARM* cpu)
void A_BL(ARM* cpu)
{
s32 offset = (s32)(cpu->CurInstr << 8) >> 6;
cpu->R[14] = cpu->R[15] - 4;
cpu->JumpTo(cpu->R[15] + offset);
return C_S(2) + C_N(1);
}
s32 A_BLX_IMM(ARM* cpu)
void A_BLX_IMM(ARM* cpu)
{
s32 offset = (s32)(cpu->CurInstr << 8) >> 6;
if (cpu->CurInstr & 0x01000000) offset += 2;
cpu->R[14] = cpu->R[15] - 4;
cpu->JumpTo(cpu->R[15] + offset + 1);
return C_S(2) + C_N(1);
}
s32 A_BX(ARM* cpu)
void A_BX(ARM* cpu)
{
cpu->JumpTo(cpu->R[cpu->CurInstr & 0xF]);
return C_S(2) + C_N(1);
}
s32 A_BLX_REG(ARM* cpu)
void A_BLX_REG(ARM* cpu)
{
u32 lr = cpu->R[15] - 4;
cpu->JumpTo(cpu->R[cpu->CurInstr & 0xF]);
cpu->R[14] = lr;
return C_S(2) + C_N(1);
}
s32 T_BCOND(ARM* cpu)
void T_BCOND(ARM* cpu)
{
if (cpu->CheckCondition((cpu->CurInstr >> 8) & 0xF))
{
s32 offset = (s32)(cpu->CurInstr << 24) >> 23;
cpu->JumpTo(cpu->R[15] + offset + 1);
return C_S(2) + C_N(1);
}
else
return C_S(1);
}
s32 T_BX(ARM* cpu)
void T_BX(ARM* cpu)
{
cpu->JumpTo(cpu->R[(cpu->CurInstr >> 3) & 0xF]);
return C_S(2) + C_N(1);
}
s32 T_BLX_REG(ARM* cpu)
void T_BLX_REG(ARM* cpu)
{
if (cpu->Num==1)
{
printf("!! THUMB BLX_REG ON ARM7\n");
return 1;
return;
}
u32 lr = cpu->R[15] - 1;
cpu->JumpTo(cpu->R[(cpu->CurInstr >> 3) & 0xF]);
cpu->R[14] = lr;
return C_S(2) + C_N(1);
}
s32 T_B(ARM* cpu)
void T_B(ARM* cpu)
{
s32 offset = (s32)((cpu->CurInstr & 0x7FF) << 21) >> 20;
cpu->JumpTo(cpu->R[15] + offset + 1);
return C_S(2) + C_N(1);
}
s32 T_BL_LONG_1(ARM* cpu)
void T_BL_LONG_1(ARM* cpu)
{
s32 offset = (s32)((cpu->CurInstr & 0x7FF) << 21) >> 9;
cpu->R[14] = cpu->R[15] + offset;
return C_S(1);
}
s32 T_BL_LONG_2(ARM* cpu)
void T_BL_LONG_2(ARM* cpu)
{
s32 offset = (cpu->CurInstr & 0x7FF) << 1;
u32 pc = cpu->R[14] + offset;
@ -129,7 +108,6 @@ s32 T_BL_LONG_2(ARM* cpu)
pc |= 1;
cpu->JumpTo(pc);
return C_S(2) + C_N(1);
}

View File

@ -22,17 +22,17 @@
namespace ARMInterpreter
{
s32 A_B(ARM* cpu);
s32 A_BL(ARM* cpu);
s32 A_BX(ARM* cpu);
s32 A_BLX_REG(ARM* cpu);
void A_B(ARM* cpu);
void A_BL(ARM* cpu);
void A_BX(ARM* cpu);
void A_BLX_REG(ARM* cpu);
s32 T_BCOND(ARM* cpu);
s32 T_BX(ARM* cpu);
s32 T_BLX_REG(ARM* cpu);
s32 T_B(ARM* cpu);
s32 T_BL_LONG_1(ARM* cpu);
s32 T_BL_LONG_2(ARM* cpu);
void T_BCOND(ARM* cpu);
void T_BX(ARM* cpu);
void T_BLX_REG(ARM* cpu);
void T_B(ARM* cpu);
void T_BL_LONG_1(ARM* cpu);
void T_BL_LONG_2(ARM* cpu);
}

View File

@ -62,135 +62,129 @@ namespace ARMInterpreter
#define A_STR \
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
cpu->Write32(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
return C_N(2) + cpu->MemWaitstate(3, offset);
cpu->DataWrite32(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset;
#define A_STR_POST \
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
cpu->Write32(addr, cpu->R[(cpu->CurInstr>>12) & 0xF], cpu->CurInstr & (1<<21)); \
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
return C_N(2) + cpu->MemWaitstate(3, addr);
cpu->DataWrite32(addr, cpu->R[(cpu->CurInstr>>12) & 0xF], cpu->CurInstr & (1<<21)); \
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset;
#define A_STRB \
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
cpu->Write8(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
return C_N(2) + cpu->MemWaitstate(3, offset);
cpu->DataWrite8(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset;
#define A_STRB_POST \
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
cpu->Write8(addr, cpu->R[(cpu->CurInstr>>12) & 0xF], cpu->CurInstr & (1<<21)); \
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
return C_N(2) + cpu->MemWaitstate(3, addr);
cpu->DataWrite8(addr, cpu->R[(cpu->CurInstr>>12) & 0xF], cpu->CurInstr & (1<<21)); \
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset;
#define A_LDR \
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 val = ROR(cpu->Read32(offset), ((offset&0x3)<<3)); \
u32 val = ROR(cpu->DataRead32(offset), ((offset&0x3)<<3)); \
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
cpu->Cycles += 1; \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
if (cpu->Num==1) val &= ~0x1; \
cpu->JumpTo(val); \
return C_S(2) + C_N(2) + C_I(1) + cpu->MemWaitstate(3, offset); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(3, offset); \
}
#define A_LDR_POST \
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 val = ROR(cpu->Read32(addr, cpu->CurInstr & (1<<21)), ((addr&0x3)<<3)); \
u32 val = ROR(cpu->DataRead32(addr, cpu->CurInstr & (1<<21)), ((addr&0x3)<<3)); \
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
cpu->Cycles += 1; \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
if (cpu->Num==1) val &= ~0x1; \
cpu->JumpTo(val); \
return C_S(2) + C_N(2) + C_I(1) + cpu->MemWaitstate(3, addr); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(3, addr); \
}
#define A_LDRB \
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 val = cpu->Read8(offset); \
u32 val = cpu->DataRead8(offset); \
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
cpu->Cycles += 1; \
cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRB PC %08X\n", cpu->R[15]); \
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(3, offset);
#define A_LDRB_POST \
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 val = cpu->Read8(addr, cpu->CurInstr & (1<<21)); \
u32 val = cpu->DataRead8(addr, cpu->CurInstr & (1<<21)); \
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
cpu->Cycles += 1; \
cpu->R[(cpu->CurInstr>>12) & 0xF] = val; \
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRB PC %08X\n", cpu->R[15]); \
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(3, addr);
#define A_IMPLEMENT_WB_LDRSTR(x) \
\
s32 A_##x##_IMM(ARM* cpu) \
void A_##x##_IMM(ARM* cpu) \
{ \
A_WB_CALC_OFFSET_IMM \
A_##x \
} \
\
s32 A_##x##_REG_LSL(ARM* cpu) \
void A_##x##_REG_LSL(ARM* cpu) \
{ \
A_WB_CALC_OFFSET_REG(LSL_IMM) \
A_##x \
} \
\
s32 A_##x##_REG_LSR(ARM* cpu) \
void A_##x##_REG_LSR(ARM* cpu) \
{ \
A_WB_CALC_OFFSET_REG(LSR_IMM) \
A_##x \
} \
\
s32 A_##x##_REG_ASR(ARM* cpu) \
void A_##x##_REG_ASR(ARM* cpu) \
{ \
A_WB_CALC_OFFSET_REG(ASR_IMM) \
A_##x \
} \
\
s32 A_##x##_REG_ROR(ARM* cpu) \
void A_##x##_REG_ROR(ARM* cpu) \
{ \
A_WB_CALC_OFFSET_REG(ROR_IMM) \
A_##x \
} \
\
s32 A_##x##_POST_IMM(ARM* cpu) \
void A_##x##_POST_IMM(ARM* cpu) \
{ \
A_WB_CALC_OFFSET_IMM \
A_##x##_POST \
} \
\
s32 A_##x##_POST_REG_LSL(ARM* cpu) \
void A_##x##_POST_REG_LSL(ARM* cpu) \
{ \
A_WB_CALC_OFFSET_REG(LSL_IMM) \
A_##x##_POST \
} \
\
s32 A_##x##_POST_REG_LSR(ARM* cpu) \
void A_##x##_POST_REG_LSR(ARM* cpu) \
{ \
A_WB_CALC_OFFSET_REG(LSR_IMM) \
A_##x##_POST \
} \
\
s32 A_##x##_POST_REG_ASR(ARM* cpu) \
void A_##x##_POST_REG_ASR(ARM* cpu) \
{ \
A_WB_CALC_OFFSET_REG(ASR_IMM) \
A_##x##_POST \
} \
\
s32 A_##x##_POST_REG_ROR(ARM* cpu) \
void A_##x##_POST_REG_ROR(ARM* cpu) \
{ \
A_WB_CALC_OFFSET_REG(ROR_IMM) \
A_##x##_POST \
@ -215,113 +209,102 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
#define A_STRH \
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
cpu->Write16(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
cpu->DataWrite16(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \
return C_N(2) + cpu->MemWaitstate(2, offset);
#define A_STRH_POST \
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
cpu->Write16(addr, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
cpu->DataWrite16(addr, cpu->R[(cpu->CurInstr>>12) & 0xF]); \
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
return C_N(2) + cpu->MemWaitstate(2, addr);
// TODO: CHECK LDRD/STRD TIMINGS!! also, ARM9-only
#define A_LDRD \
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->Read32(offset ); \
cpu->R[r+1] = cpu->Read32(offset+4); \
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(3, offset);
cpu->R[r ] = cpu->DataRead32(offset ); \
cpu->R[r+1] = cpu->DataRead32(offset+4); \
#define A_LDRD_POST \
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->Read32(addr ); \
cpu->R[r+1] = cpu->Read32(addr+4); \
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(3, addr);
cpu->R[r ] = cpu->DataRead32(addr ); \
cpu->R[r+1] = cpu->DataRead32(addr+4); \
#define A_STRD \
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->Write32(offset , cpu->R[r ]); \
cpu->Write32(offset+4, cpu->R[r+1]); \
return C_N(2) + cpu->MemWaitstate(3, offset);
cpu->DataWrite32(offset , cpu->R[r ]); \
cpu->DataWrite32(offset+4, cpu->R[r+1]); \
#define A_STRD_POST \
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \
u32 r = (cpu->CurInstr>>12) & 0xF; \
cpu->Write32(offset , cpu->R[r ]); \
cpu->Write32(offset+4, cpu->R[r+1]); \
return C_N(2) + cpu->MemWaitstate(3, addr);
cpu->DataWrite32(offset , cpu->R[r ]); \
cpu->DataWrite32(offset+4, cpu->R[r+1]); \
#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->Read16(offset); \
cpu->R[(cpu->CurInstr>>12) & 0xF] = cpu->DataRead16(offset); \
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRH PC %08X\n", cpu->R[15]); \
return C_N(2) + cpu->MemWaitstate(2, offset);
#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->Read16(addr); \
cpu->R[(cpu->CurInstr>>12) & 0xF] = cpu->DataRead16(addr); \
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRH PC %08X\n", cpu->R[15]); \
return C_N(2) + cpu->MemWaitstate(2, addr);
#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->Read8(offset); \
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->DataRead8(offset); \
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSB PC %08X\n", cpu->R[15]); \
return C_N(2) + cpu->MemWaitstate(3, offset);
#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->Read8(addr); \
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->DataRead8(addr); \
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSB PC %08X\n", cpu->R[15]); \
return C_N(2) + cpu->MemWaitstate(3, addr);
#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->Read16(offset); \
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->DataRead16(offset); \
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSH PC %08X\n", cpu->R[15]); \
return C_N(2) + cpu->MemWaitstate(2, offset);
#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->Read16(addr); \
cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->DataRead16(addr); \
if (((cpu->CurInstr>>12) & 0xF) == 15) printf("!! LDRSH PC %08X\n", cpu->R[15]); \
return C_N(2) + cpu->MemWaitstate(2, addr);
#define A_IMPLEMENT_HD_LDRSTR(x) \
\
s32 A_##x##_IMM(ARM* cpu) \
void A_##x##_IMM(ARM* cpu) \
{ \
A_HD_CALC_OFFSET_IMM \
A_##x \
} \
\
s32 A_##x##_REG(ARM* cpu) \
void A_##x##_REG(ARM* cpu) \
{ \
A_HD_CALC_OFFSET_REG \
A_##x \
} \
s32 A_##x##_POST_IMM(ARM* cpu) \
void A_##x##_POST_IMM(ARM* cpu) \
{ \
A_HD_CALC_OFFSET_IMM \
A_##x##_POST \
} \
\
s32 A_##x##_POST_REG(ARM* cpu) \
void A_##x##_POST_REG(ARM* cpu) \
{ \
A_HD_CALC_OFFSET_REG \
A_##x##_POST \
@ -336,36 +319,34 @@ A_IMPLEMENT_HD_LDRSTR(LDRSH)
s32 A_SWP(ARM* cpu)
void A_SWP(ARM* cpu)
{
u32 base = cpu->R[(cpu->CurInstr >> 16) & 0xF];
u32 rm = cpu->R[cpu->CurInstr & 0xF];
u32 val = cpu->Read32(base);
u32 val = cpu->DataRead32(base);
cpu->R[(cpu->CurInstr >> 12) & 0xF] = ROR(val, 8*(base&0x3));
cpu->Write32(base, rm);
cpu->DataWrite32(base, rm);
// the 1S is a code cycle. TODO
return C_S(1) + C_N(2) + C_I(1) + 2*cpu->MemWaitstate(3, base);
cpu->Cycles += 1;
}
s32 A_SWPB(ARM* cpu)
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->Read8(base);
cpu->R[(cpu->CurInstr >> 12) & 0xF] = cpu->DataRead8(base);
cpu->Write8(base, rm);
cpu->DataWrite8(base, rm);
// the 1S is a code cycle. TODO
return C_S(1) + C_N(2) + C_I(1) + 2*cpu->MemWaitstate(3, base);
cpu->Cycles += 1;
}
s32 A_LDM(ARM* cpu)
void A_LDM(ARM* cpu)
{
u32 baseid = (cpu->CurInstr >> 16) & 0xF;
u32 base = cpu->R[baseid];
@ -389,7 +370,7 @@ s32 A_LDM(ARM* cpu)
preinc = !preinc;
}
s32 cycles = C_N(1) + C_I(1);
cpu->Cycles += 1;
if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15)))
cpu->UpdateMode(cpu->CPSR, (cpu->CPSR&~0x1F)|0x10);
@ -399,8 +380,7 @@ s32 A_LDM(ARM* cpu)
if (cpu->CurInstr & (1<<i))
{
if (preinc) base += 4;
cpu->R[i] = cpu->Read32(base);
cycles += C_S(1) + cpu->MemWaitstate(3, base);
cpu->R[i] = cpu->DataRead32(base);
if (!preinc) base += 4;
}
}
@ -408,8 +388,7 @@ s32 A_LDM(ARM* cpu)
if (cpu->CurInstr & (1<<15))
{
if (preinc) base += 4;
u32 pc = cpu->Read32(base);
cycles += C_S(2) + C_N(1) + cpu->MemWaitstate(3, base);
u32 pc = cpu->DataRead32(base);
if (!preinc) base += 4;
if (cpu->Num == 1)
@ -439,11 +418,9 @@ s32 A_LDM(ARM* cpu)
else
cpu->R[baseid] = wbbase;
}
return cycles;
}
s32 A_STM(ARM* cpu)
void A_STM(ARM* cpu)
{
u32 baseid = (cpu->CurInstr >> 16) & 0xF;
u32 base = cpu->R[baseid];
@ -452,7 +429,7 @@ s32 A_STM(ARM* cpu)
if (!(cpu->CurInstr & (1<<23)))
{
for (int i = 0; i < 16; i++)
for (u32 i = 0; i < 16; i++)
{
if (cpu->CurInstr & (1<<i))
base -= 4;
@ -464,12 +441,10 @@ s32 A_STM(ARM* cpu)
preinc = !preinc;
}
s32 cycles = C_N(1) + C_I(1);
if (cpu->CurInstr & (1<<22))
cpu->UpdateMode(cpu->CPSR, (cpu->CPSR&~0x1F)|0x10);
for (int i = 0; i < 16; i++)
for (u32 i = 0; i < 16; i++)
{
if (cpu->CurInstr & (1<<i))
{
@ -478,14 +453,13 @@ s32 A_STM(ARM* cpu)
if (i == baseid)
{
if ((cpu->Num == 0) || (!(cpu->CurInstr & (i-1))))
cpu->Write32(base, oldbase);
cpu->DataWrite32(base, oldbase);
else
cpu->Write32(base, base); // checkme
cpu->DataWrite32(base, base); // checkme
}
else
cpu->Write32(base, cpu->R[i]);
cpu->DataWrite32(base, cpu->R[i]);
cycles += C_S(1) + cpu->MemWaitstate(3, base);
if (!preinc) base += 4;
}
}
@ -495,8 +469,6 @@ s32 A_STM(ARM* cpu)
if ((cpu->CurInstr & (1<<23)) && (cpu->CurInstr & (1<<21)))
cpu->R[baseid] = base;
return cycles;
}
@ -506,160 +478,150 @@ s32 A_STM(ARM* cpu)
s32 T_LDR_PCREL(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->Read32(addr);
cpu->R[(cpu->CurInstr >> 8) & 0x7] = cpu->DataRead32(addr);
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(3, addr);
cpu->Cycles += 1;
}
s32 T_STR_REG(ARM* cpu)
void T_STR_REG(ARM* cpu)
{
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
cpu->Write32(addr, cpu->R[cpu->CurInstr & 0x7]);
return C_N(2) + cpu->MemWaitstate(3, addr);
cpu->DataWrite32(addr, cpu->R[cpu->CurInstr & 0x7]);
}
s32 T_STRB_REG(ARM* cpu)
void T_STRB_REG(ARM* cpu)
{
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
cpu->Write8(addr, cpu->R[cpu->CurInstr & 0x7]);
return C_N(2) + cpu->MemWaitstate(3, addr);
cpu->DataWrite8(addr, cpu->R[cpu->CurInstr & 0x7]);
}
s32 T_LDR_REG(ARM* cpu)
void T_LDR_REG(ARM* cpu)
{
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
u32 val = cpu->Read32(addr);
u32 val = cpu->DataRead32(addr);
cpu->R[cpu->CurInstr & 0x7] = ROR(val, 8*(addr&0x3));
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(3, addr);
cpu->Cycles += 1;
}
s32 T_LDRB_REG(ARM* cpu)
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->Read8(addr);
cpu->R[cpu->CurInstr & 0x7] = cpu->DataRead8(addr);
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(3, addr);
cpu->Cycles += 1;
}
s32 T_STRH_REG(ARM* cpu)
void T_STRH_REG(ARM* cpu)
{
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
cpu->Write16(addr, cpu->R[cpu->CurInstr & 0x7]);
return C_N(2) + cpu->MemWaitstate(2, addr);
cpu->DataWrite16(addr, cpu->R[cpu->CurInstr & 0x7]);
}
s32 T_LDRSB_REG(ARM* cpu)
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->Read8(addr);
cpu->R[cpu->CurInstr & 0x7] = (s32)(s8)cpu->DataRead8(addr);
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(3, addr);
cpu->Cycles += 1;
}
s32 T_LDRH_REG(ARM* cpu)
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->Read16(addr);
cpu->R[cpu->CurInstr & 0x7] = cpu->DataRead16(addr);
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(2, addr);
cpu->Cycles += 1;
}
s32 T_LDRSH_REG(ARM* cpu)
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->Read16(addr);
cpu->R[cpu->CurInstr & 0x7] = (s32)(s16)cpu->DataRead16(addr);
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(2, addr);
cpu->Cycles += 1;
}
s32 T_STR_IMM(ARM* cpu)
void T_STR_IMM(ARM* cpu)
{
u32 offset = (cpu->CurInstr >> 4) & 0x7C;
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
cpu->Write32(offset, cpu->R[cpu->CurInstr & 0x7]);
return C_N(2) + cpu->MemWaitstate(3, offset);
cpu->DataWrite32(offset, cpu->R[cpu->CurInstr & 0x7]);
}
s32 T_LDR_IMM(ARM* cpu)
void T_LDR_IMM(ARM* cpu)
{
u32 offset = (cpu->CurInstr >> 4) & 0x7C;
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 val = cpu->Read32(offset);
u32 val = cpu->DataRead32(offset);
cpu->R[cpu->CurInstr & 0x7] = ROR(val, 8*(offset&0x3));
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(3, offset);
cpu->Cycles += 1;
}
s32 T_STRB_IMM(ARM* cpu)
void T_STRB_IMM(ARM* cpu)
{
u32 offset = (cpu->CurInstr >> 6) & 0x1F;
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
cpu->Write8(offset, cpu->R[cpu->CurInstr & 0x7]);
return C_N(2) + cpu->MemWaitstate(3, offset);
cpu->DataWrite8(offset, cpu->R[cpu->CurInstr & 0x7]);
}
s32 T_LDRB_IMM(ARM* cpu)
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->Read8(offset);
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(3, offset);
cpu->R[cpu->CurInstr & 0x7] = cpu->DataRead8(offset);
cpu->Cycles += 1;
}
s32 T_STRH_IMM(ARM* cpu)
void T_STRH_IMM(ARM* cpu)
{
u32 offset = (cpu->CurInstr >> 5) & 0x3E;
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
cpu->Write16(offset, cpu->R[cpu->CurInstr & 0x7]);
return C_N(2) + cpu->MemWaitstate(2, offset);
cpu->DataWrite16(offset, cpu->R[cpu->CurInstr & 0x7]);
}
s32 T_LDRH_IMM(ARM* cpu)
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->Read16(offset);
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(2, offset);
cpu->R[cpu->CurInstr & 0x7] = cpu->DataRead16(offset);
cpu->Cycles += 1;
}
s32 T_STR_SPREL(ARM* cpu)
void T_STR_SPREL(ARM* cpu)
{
u32 offset = (cpu->CurInstr << 2) & 0x3FC;
offset += cpu->R[13];
cpu->Write32(offset, cpu->R[(cpu->CurInstr >> 8) & 0x7]);
return C_N(2) + cpu->MemWaitstate(3, offset);
cpu->DataWrite32(offset, cpu->R[(cpu->CurInstr >> 8) & 0x7]);
}
s32 T_LDR_SPREL(ARM* cpu)
void T_LDR_SPREL(ARM* cpu)
{
u32 offset = (cpu->CurInstr << 2) & 0x3FC;
offset += cpu->R[13];
cpu->R[(cpu->CurInstr >> 8) & 0x7] = cpu->Read32(offset);
return C_S(1) + C_N(1) + C_I(1) + cpu->MemWaitstate(3, offset);
cpu->R[(cpu->CurInstr >> 8) & 0x7] = cpu->DataRead32(offset);
cpu->Cycles += 1;
}
s32 T_PUSH(ARM* cpu)
void T_PUSH(ARM* cpu)
{
int nregs = 0;
@ -676,99 +638,81 @@ s32 T_PUSH(ARM* cpu)
base -= (nregs<<2);
cpu->R[13] = base;
int cycles = C_N(2);
for (int i = 0; i < 8; i++)
{
if (cpu->CurInstr & (1<<i))
{
cpu->Write32(base, cpu->R[i]);
cycles += C_S(1) + cpu->MemWaitstate(3, base);
cpu->DataWrite32(base, cpu->R[i]);
base += 4;
}
}
if (cpu->CurInstr & (1<<8))
{
cpu->Write32(base, cpu->R[14]);
cycles += C_S(1) + cpu->MemWaitstate(3, base);
cpu->DataWrite32(base, cpu->R[14]);
}
return cycles - C_S(1);
}
s32 T_POP(ARM* cpu)
void T_POP(ARM* cpu)
{
u32 base = cpu->R[13];
int cycles = C_N(1) + C_I(1);
cpu->Cycles += 1;
for (int i = 0; i < 8; i++)
{
if (cpu->CurInstr & (1<<i))
{
cpu->R[i] = cpu->Read32(base);
cycles += C_S(1) + cpu->MemWaitstate(3, base);
cpu->R[i] = cpu->DataRead32(base);
base += 4;
}
}
if (cpu->CurInstr & (1<<8))
{
u32 pc = cpu->Read32(base);
u32 pc = cpu->DataRead32(base);
if (cpu->Num==1) pc |= 0x1;
cpu->JumpTo(pc);
cycles += C_S(2) + C_N(1) + cpu->MemWaitstate(3, base);
base += 4;
}
cpu->R[13] = base;
return cycles;
}
s32 T_STMIA(ARM* cpu)
void T_STMIA(ARM* cpu)
{
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
int cycles = C_N(2);
for (int i = 0; i < 8; i++)
{
if (cpu->CurInstr & (1<<i))
{
cpu->Write32(base, cpu->R[i]);
cycles += C_S(1) + cpu->MemWaitstate(3, base);
cpu->DataWrite32(base, cpu->R[i]);
base += 4;
}
}
// TODO: check "Rb included in Rlist" case
cpu->R[(cpu->CurInstr >> 8) & 0x7] = base;
return cycles - C_S(1);
}
s32 T_LDMIA(ARM* cpu)
void T_LDMIA(ARM* cpu)
{
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
int cycles = C_N(1) + C_I(1);
cpu->Cycles += 1;
for (int i = 0; i < 8; i++)
{
if (cpu->CurInstr & (1<<i))
{
cpu->R[i] = cpu->Read32(base);
cycles += C_S(1) + cpu->MemWaitstate(3, base);
cpu->R[i] = cpu->DataRead32(base);
base += 4;
}
}
if (!(cpu->CurInstr & (1<<((cpu->CurInstr >> 8) & 0x7))))
cpu->R[(cpu->CurInstr >> 8) & 0x7] = base;
return cycles;
}

View File

@ -24,16 +24,16 @@ namespace ARMInterpreter
#define A_PROTO_WB_LDRSTR(x) \
\
s32 A_##x##_IMM(ARM* cpu); \
s32 A_##x##_REG_LSL(ARM* cpu); \
s32 A_##x##_REG_LSR(ARM* cpu); \
s32 A_##x##_REG_ASR(ARM* cpu); \
s32 A_##x##_REG_ROR(ARM* cpu); \
s32 A_##x##_POST_IMM(ARM* cpu); \
s32 A_##x##_POST_REG_LSL(ARM* cpu); \
s32 A_##x##_POST_REG_LSR(ARM* cpu); \
s32 A_##x##_POST_REG_ASR(ARM* cpu); \
s32 A_##x##_POST_REG_ROR(ARM* cpu);
void A_##x##_IMM(ARM* cpu); \
void A_##x##_REG_LSL(ARM* cpu); \
void A_##x##_REG_LSR(ARM* cpu); \
void A_##x##_REG_ASR(ARM* cpu); \
void A_##x##_REG_ROR(ARM* cpu); \
void A_##x##_POST_IMM(ARM* cpu); \
void A_##x##_POST_REG_LSL(ARM* cpu); \
void A_##x##_POST_REG_LSR(ARM* cpu); \
void A_##x##_POST_REG_ASR(ARM* cpu); \
void A_##x##_POST_REG_ROR(ARM* cpu);
A_PROTO_WB_LDRSTR(STR)
A_PROTO_WB_LDRSTR(STRB)
@ -42,10 +42,10 @@ A_PROTO_WB_LDRSTR(LDRB)
#define A_PROTO_HD_LDRSTR(x) \
\
s32 A_##x##_IMM(ARM* cpu); \
s32 A_##x##_REG(ARM* cpu); \
s32 A_##x##_POST_IMM(ARM* cpu); \
s32 A_##x##_POST_REG(ARM* cpu);
void A_##x##_IMM(ARM* cpu); \
void A_##x##_REG(ARM* cpu); \
void A_##x##_POST_IMM(ARM* cpu); \
void A_##x##_POST_REG(ARM* cpu);
A_PROTO_HD_LDRSTR(STRH)
A_PROTO_HD_LDRSTR(LDRD)
@ -54,40 +54,40 @@ A_PROTO_HD_LDRSTR(LDRH)
A_PROTO_HD_LDRSTR(LDRSB)
A_PROTO_HD_LDRSTR(LDRSH)
s32 A_LDM(ARM* cpu);
s32 A_STM(ARM* cpu);
void A_LDM(ARM* cpu);
void A_STM(ARM* cpu);
s32 A_SWP(ARM* cpu);
s32 A_SWPB(ARM* cpu);
void A_SWP(ARM* cpu);
void A_SWPB(ARM* cpu);
s32 T_LDR_PCREL(ARM* cpu);
void T_LDR_PCREL(ARM* cpu);
s32 T_STR_REG(ARM* cpu);
s32 T_STRB_REG(ARM* cpu);
s32 T_LDR_REG(ARM* cpu);
s32 T_LDRB_REG(ARM* cpu);
void T_STR_REG(ARM* cpu);
void T_STRB_REG(ARM* cpu);
void T_LDR_REG(ARM* cpu);
void T_LDRB_REG(ARM* cpu);
s32 T_STRH_REG(ARM* cpu);
s32 T_LDRSB_REG(ARM* cpu);
s32 T_LDRH_REG(ARM* cpu);
s32 T_LDRSH_REG(ARM* cpu);
void T_STRH_REG(ARM* cpu);
void T_LDRSB_REG(ARM* cpu);
void T_LDRH_REG(ARM* cpu);
void T_LDRSH_REG(ARM* cpu);
s32 T_STR_IMM(ARM* cpu);
s32 T_LDR_IMM(ARM* cpu);
s32 T_STRB_IMM(ARM* cpu);
s32 T_LDRB_IMM(ARM* cpu);
void T_STR_IMM(ARM* cpu);
void T_LDR_IMM(ARM* cpu);
void T_STRB_IMM(ARM* cpu);
void T_LDRB_IMM(ARM* cpu);
s32 T_STRH_IMM(ARM* cpu);
s32 T_LDRH_IMM(ARM* cpu);
void T_STRH_IMM(ARM* cpu);
void T_LDRH_IMM(ARM* cpu);
s32 T_STR_SPREL(ARM* cpu);
s32 T_LDR_SPREL(ARM* cpu);
void T_STR_SPREL(ARM* cpu);
void T_LDR_SPREL(ARM* cpu);
s32 T_PUSH(ARM* cpu);
s32 T_POP(ARM* cpu);
s32 T_STMIA(ARM* cpu);
s32 T_LDMIA(ARM* cpu);
void T_PUSH(ARM* cpu);
void T_POP(ARM* cpu);
void T_STMIA(ARM* cpu);
void T_LDMIA(ARM* cpu);
}

View File

@ -78,6 +78,8 @@ void UpdateITCMSetting()
void Write(u32 id, u32 val)
{
//printf("CP15 write op %03X %08X %08X\n", id, val, NDS::ARM9->R[15]);
switch (id)
{
case 0x100:

29
GPU.cpp
View File

@ -113,8 +113,33 @@ void Reset()
}
// VRAM mapping shit.
// TODO eventually: work out priority orders in case of overlaps. there _are_ games that map overlapping banks.
// VRAM mapping notes
//
// mirroring:
// unmapped range reads zero
// LCD is mirrored every 0x100000 bytes, the gap between each mirror reads zero
// ABG:
// bank A,B,C,D,E mirror every 0x80000 bytes
// bank F,G mirror at base+0x8000, mirror every 0x80000 bytes
// AOBJ:
// bank A,B,E mirror every 0x40000 bytes
// bank F,G mirror at base+0x8000, mirror every 0x40000 bytes
// BBG:
// bank C mirrors every 0x20000 bytes
// bank H mirrors every 0x10000 bytes
// bank I mirrors at base+0x4000, mirrors every 0x10000 bytes
// BOBJ:
// bank D mirrors every 0x20000 bytes
// bank I mirrors every 0x4000 bytes
//
// untested:
// ARM7 (TODO)
// extended palette (mirroring doesn't apply)
// texture/texpal (does mirroring apply?)
//
// overlap:
// when reading: values are read from each bank and ORed together
// when writing: value is written to each bank
void MapVRAM_AB(u32 bank, u8 cnt)
{

View File

@ -1901,6 +1901,7 @@ void ARM7IOWrite8(u32 addr, u8 val)
return;
case 0x04000301:
//printf("ARM7 HALT %02X. IME=%08X IE=%08X IF=%08X\n", val, IME[1], IE[1], IF[1]);
if (val == 0x80) ARM7->Halt(1);
return;
}

18
NDS.h
View File

@ -36,6 +36,22 @@ typedef struct _SchedEvent
} SchedEvent;
enum
{
Event_ScanlineStart = 0,
Event_Timer9_0,
Event_Timer9_1,
Event_Timer9_2,
Event_Timer9_3,
Event_Timer7_0,
Event_Timer7_1,
Event_Timer7_2,
Event_Timer7_3,
Event_MAX
};
enum
{
IRQ_VBlank = 0,
@ -105,6 +121,8 @@ void RunEvents(s32 cycles);
// DO NOT CALL FROM ARM7!!
void CompensateARM7();
void debug(u32 p);
void Halt();
void MapSharedWRAM(u8 val);

View File

@ -88,6 +88,12 @@ void Reset()
fclose(f);
// temp: disable autoboot
/*Firmware[0x3FE64] &= 0xBF;
*(u16*)&Firmware[0x3FE72] = CRC16(&Firmware[0x3FE00], 0x70, 0xFFFF);
Firmware[0x3FF64] &= 0xBF;
*(u16*)&Firmware[0x3FF72] = CRC16(&Firmware[0x3FF00], 0x70, 0xFFFF);*/
// verify shit
printf("FW: WIFI CRC16 = %s\n", VerifyCRC16(0x0000, 0x2C, *(u16*)&Firmware[0x2C], 0x2A)?"GOOD":"BAD");
printf("FW: AP1 CRC16 = %s\n", VerifyCRC16(0x0000, 0x3FA00, 0xFE, 0x3FAFE)?"GOOD":"BAD");

View File

@ -57,6 +57,7 @@ LRESULT CALLBACK derpo(HWND window, UINT msg, WPARAM wparam, LPARAM lparam)
case VK_LEFT: NDS::PressKey(5); break;
case VK_RIGHT: NDS::PressKey(4); break;
case 'P': NDS::PressKey(16+6); break;
case 'D': NDS::debug(0); break;
}
return 0;

View File

@ -1,16 +1,16 @@
# depslib dependency file v1.0
1484954918 source:c:\documents\sources\melonds\main.cpp
1485135566 source:c:\documents\sources\melonds\main.cpp
<stdio.h>
<windows.h>
"NDS.h"
"GPU.h"
1485110344 c:\documents\sources\melonds\nds.h
1485792939 c:\documents\sources\melonds\nds.h
"types.h"
1481161027 c:\documents\sources\melonds\types.h
1485133568 source:c:\documents\sources\melonds\nds.cpp
1485374133 source:c:\documents\sources\melonds\nds.cpp
<stdio.h>
<string.h>
"NDS.h"
@ -24,23 +24,23 @@
"RTC.h"
"Wifi.h"
1485133372 source:c:\documents\sources\melonds\arm.cpp
1485797690 source:c:\documents\sources\melonds\arm.cpp
<stdio.h>
"NDS.h"
"ARM.h"
"ARMInterpreter.h"
1481062839 c:\documents\sources\melonds\arm.h
1485797447 c:\documents\sources\melonds\arm.h
"types.h"
"NDS.h"
1484530962 c:\documents\sources\melonds\arm_instrtable.h
1480965273 c:\documents\sources\melonds\arminterpreter.h
1485795549 c:\documents\sources\melonds\arminterpreter.h
"types.h"
"ARM.h"
1484752824 source:c:\documents\sources\melonds\arminterpreter.cpp
1485797066 source:c:\documents\sources\melonds\arminterpreter.cpp
<stdio.h>
"NDS.h"
"CP15.h"
@ -50,27 +50,27 @@
"ARMInterpreter_LoadStore.h"
"ARM_InstrTable.h"
1480957205 c:\documents\sources\melonds\arminterpreter_branch.h
1485795628 c:\documents\sources\melonds\arminterpreter_branch.h
1480957179 source:c:\documents\sources\melonds\arminterpreter_branch.cpp
1485797084 source:c:\documents\sources\melonds\arminterpreter_branch.cpp
<stdio.h>
"ARM.h"
1481160920 c:\documents\sources\melonds\arminterpreter_alu.h
1485795628 c:\documents\sources\melonds\arminterpreter_alu.h
1484917510 source:c:\documents\sources\melonds\arminterpreter_alu.cpp
1485797076 source:c:\documents\sources\melonds\arminterpreter_alu.cpp
<stdio.h>
"ARM.h"
1480957165 c:\documents\sources\melonds\arminterpreter_loadstore.h
1485795628 c:\documents\sources\melonds\arminterpreter_loadstore.h
1485133521 source:c:\documents\sources\melonds\arminterpreter_loadstore.cpp
1485797600 source:c:\documents\sources\melonds\arminterpreter_loadstore.cpp
<stdio.h>
"ARM.h"
1481037554 c:\documents\sources\melonds\cp15.h
1484754534 source:c:\documents\sources\melonds\cp15.cpp
1485136658 source:c:\documents\sources\melonds\cp15.cpp
<stdio.h>
"NDS.h"
"ARM.h"
@ -78,7 +78,7 @@
1480957111 c:\documents\sources\melonds\spi.h
1484762789 source:c:\documents\sources\melonds\spi.cpp
1485137440 source:c:\documents\sources\melonds\spi.cpp
<stdio.h>
<string.h>
"NDS.h"
@ -115,7 +115,7 @@
1484698068 c:\documents\sources\melonds\dma.h
"types.h"
1484753188 source:c:\documents\sources\melonds\gpu.cpp
1485789352 source:c:\documents\sources\melonds\gpu.cpp
<stdio.h>
<string.h>
"NDS.h"