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

91
ARM.h
View File

@ -81,42 +81,86 @@ public:
void TriggerIRQ(); 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) if (!Num)
{ {
// TODO: PU shit // TODO: PU shit
return NDS::ARM9Read8(addr); val = NDS::ARM9Read16(addr);
} }
else 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; addr &= ~1;
if (!Num) if (!Num)
{ {
// TODO: PU shit // TODO: PU shit
return NDS::ARM9Read16(addr); val = NDS::ARM9Read16(addr);
} }
else 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; addr &= ~3;
if (!Num) if (!Num)
{ {
// TODO: PU shit // TODO: PU shit
return NDS::ARM9Read32(addr); val = NDS::ARM9Read32(addr);
} }
else 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) if (!Num)
{ {
@ -125,9 +169,11 @@ public:
} }
else else
NDS::ARM7Write8(addr, val); 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; addr &= ~1;
if (!Num) if (!Num)
@ -137,9 +183,11 @@ public:
} }
else else
NDS::ARM7Write16(addr, val); 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; addr &= ~3;
if (!Num) if (!Num)
@ -149,23 +197,18 @@ public:
} }
else else
NDS::ARM7Write32(addr, val); NDS::ARM7Write32(addr, val);
}
Cycles += Waitstates[3][(addr>>24)&0xF];
s32 MemWaitstate(u32 type, u32 addr)
{
// type:
// 0 = code16
// 1 = code32
// 2 = data16
// 3 = data32
return 1; // sorry
} }
u32 Num; u32 Num;
// waitstates:
// 0=code16 1=code32 2=data16 3=data32
// TODO eventually: nonsequential waitstates
s32 Waitstates[4][16];
s32 Cycles; s32 Cycles;
u32 Halted; u32 Halted;
@ -177,7 +220,7 @@ public:
u32 R_IRQ[3]; u32 R_IRQ[3];
u32 R_UND[3]; u32 R_UND[3];
u32 CurInstr; u32 CurInstr;
u32 NextInstr; u32 NextInstr[2];
u32 ExceptionBase; 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); 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]); for (int i = 0; i < 16; i++) printf("R%d: %08X\n", i, cpu->R[i]);
NDS::Halt(); 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); printf("undefined THUMB%d instruction %04X @ %08X\n", cpu->Num?7:9, cpu->CurInstr, cpu->R[15]-4);
NDS::Halt(); NDS::Halt();
return 0x7FFFFFFF;
} }
s32 A_MSR_IMM(ARM* cpu) void A_MSR_IMM(ARM* cpu)
{ {
u32* psr; u32* psr;
if (cpu->CurInstr & (1<<22)) if (cpu->CurInstr & (1<<22))
@ -58,7 +56,7 @@ s32 A_MSR_IMM(ARM* cpu)
case 0x13: psr = &cpu->R_SVC[2]; break; case 0x13: psr = &cpu->R_SVC[2]; break;
case 0x17: psr = &cpu->R_ABT[2]; break; case 0x17: psr = &cpu->R_ABT[2]; break;
case 0x1B: psr = &cpu->R_UND[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 else
@ -84,11 +82,9 @@ s32 A_MSR_IMM(ARM* cpu)
if (!(cpu->CurInstr & (1<<22))) if (!(cpu->CurInstr & (1<<22)))
cpu->UpdateMode(oldpsr, cpu->CPSR); cpu->UpdateMode(oldpsr, cpu->CPSR);
return C_S(1);
} }
s32 A_MSR_REG(ARM* cpu) void A_MSR_REG(ARM* cpu)
{ {
u32* psr; u32* psr;
if (cpu->CurInstr & (1<<22)) if (cpu->CurInstr & (1<<22))
@ -100,7 +96,7 @@ s32 A_MSR_REG(ARM* cpu)
case 0x13: psr = &cpu->R_SVC[2]; break; case 0x13: psr = &cpu->R_SVC[2]; break;
case 0x17: psr = &cpu->R_ABT[2]; break; case 0x17: psr = &cpu->R_ABT[2]; break;
case 0x1B: psr = &cpu->R_UND[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 else
@ -126,11 +122,9 @@ s32 A_MSR_REG(ARM* cpu)
if (!(cpu->CurInstr & (1<<22))) if (!(cpu->CurInstr & (1<<22)))
cpu->UpdateMode(oldpsr, cpu->CPSR); cpu->UpdateMode(oldpsr, cpu->CPSR);
return C_S(1);
} }
s32 A_MRS(ARM* cpu) void A_MRS(ARM* cpu)
{ {
u32 psr; u32 psr;
if (cpu->CurInstr & (1<<22)) if (cpu->CurInstr & (1<<22))
@ -142,19 +136,17 @@ s32 A_MRS(ARM* cpu)
case 0x13: psr = cpu->R_SVC[2]; break; case 0x13: psr = cpu->R_SVC[2]; break;
case 0x17: psr = cpu->R_ABT[2]; break; case 0x17: psr = cpu->R_ABT[2]; break;
case 0x1B: psr = cpu->R_UND[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 else
psr = cpu->CPSR; psr = cpu->CPSR;
cpu->R[(cpu->CurInstr>>12) & 0xF] = psr; 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 cp = (cpu->CurInstr >> 8) & 0xF;
//u32 op = (cpu->CurInstr >> 21) & 0x7; //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); 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 cp = (cpu->CurInstr >> 8) & 0xF;
//u32 op = (cpu->CurInstr >> 21) & 0x7; //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); 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; u32 oldcpsr = cpu->CPSR;
cpu->CPSR &= ~0xFF; cpu->CPSR &= ~0xFF;
@ -206,11 +198,9 @@ s32 A_SVC(ARM* cpu)
cpu->R_SVC[2] = oldcpsr; cpu->R_SVC[2] = oldcpsr;
cpu->R[14] = cpu->R[15] - 4; cpu->R[14] = cpu->R[15] - 4;
cpu->JumpTo(cpu->ExceptionBase + 0x08); 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; u32 oldcpsr = cpu->CPSR;
cpu->CPSR &= ~0xFF; cpu->CPSR &= ~0xFF;
@ -220,13 +210,11 @@ s32 T_SVC(ARM* cpu)
cpu->R_SVC[2] = oldcpsr; cpu->R_SVC[2] = oldcpsr;
cpu->R[14] = cpu->R[15] - 2; cpu->R[14] = cpu->R[15] - 2;
cpu->JumpTo(cpu->ExceptionBase + 0x08); 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" #include "ARM_InstrTable.h"
#undef INSTRFUNC_PROTO #undef INSTRFUNC_PROTO

View File

@ -25,10 +25,10 @@
namespace ARMInterpreter namespace ARMInterpreter
{ {
extern s32 (*ARMInstrTable[4096])(ARM* cpu); extern void (*ARMInstrTable[4096])(ARM* cpu);
extern s32 (*THUMBInstrTable[1024])(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) \ #define A_PROTO_ALU_OP(x) \
\ \
s32 A_##x##_IMM(ARM* cpu); \ void A_##x##_IMM(ARM* cpu); \
s32 A_##x##_REG_LSL_IMM(ARM* cpu); \ void A_##x##_REG_LSL_IMM(ARM* cpu); \
s32 A_##x##_REG_LSR_IMM(ARM* cpu); \ void A_##x##_REG_LSR_IMM(ARM* cpu); \
s32 A_##x##_REG_ASR_IMM(ARM* cpu); \ void A_##x##_REG_ASR_IMM(ARM* cpu); \
s32 A_##x##_REG_ROR_IMM(ARM* cpu); \ void A_##x##_REG_ROR_IMM(ARM* cpu); \
s32 A_##x##_REG_LSL_REG(ARM* cpu); \ void A_##x##_REG_LSL_REG(ARM* cpu); \
s32 A_##x##_REG_LSR_REG(ARM* cpu); \ void A_##x##_REG_LSR_REG(ARM* cpu); \
s32 A_##x##_REG_ASR_REG(ARM* cpu); \ void A_##x##_REG_ASR_REG(ARM* cpu); \
s32 A_##x##_REG_ROR_REG(ARM* cpu); \ void A_##x##_REG_ROR_REG(ARM* cpu); \
s32 A_##x##_IMM_S(ARM* cpu); \ void A_##x##_IMM_S(ARM* cpu); \
s32 A_##x##_REG_LSL_IMM_S(ARM* cpu); \ void A_##x##_REG_LSL_IMM_S(ARM* cpu); \
s32 A_##x##_REG_LSR_IMM_S(ARM* cpu); \ void A_##x##_REG_LSR_IMM_S(ARM* cpu); \
s32 A_##x##_REG_ASR_IMM_S(ARM* cpu); \ void A_##x##_REG_ASR_IMM_S(ARM* cpu); \
s32 A_##x##_REG_ROR_IMM_S(ARM* cpu); \ void A_##x##_REG_ROR_IMM_S(ARM* cpu); \
s32 A_##x##_REG_LSL_REG_S(ARM* cpu); \ void A_##x##_REG_LSL_REG_S(ARM* cpu); \
s32 A_##x##_REG_LSR_REG_S(ARM* cpu); \ void A_##x##_REG_LSR_REG_S(ARM* cpu); \
s32 A_##x##_REG_ASR_REG_S(ARM* cpu); \ void A_##x##_REG_ASR_REG_S(ARM* cpu); \
s32 A_##x##_REG_ROR_REG_S(ARM* cpu); void A_##x##_REG_ROR_REG_S(ARM* cpu);
#define A_PROTO_ALU_TEST(x) \ #define A_PROTO_ALU_TEST(x) \
\ \
s32 A_##x##_IMM(ARM* cpu); \ void A_##x##_IMM(ARM* cpu); \
s32 A_##x##_REG_LSL_IMM(ARM* cpu); \ void A_##x##_REG_LSL_IMM(ARM* cpu); \
s32 A_##x##_REG_LSR_IMM(ARM* cpu); \ void A_##x##_REG_LSR_IMM(ARM* cpu); \
s32 A_##x##_REG_ASR_IMM(ARM* cpu); \ void A_##x##_REG_ASR_IMM(ARM* cpu); \
s32 A_##x##_REG_ROR_IMM(ARM* cpu); \ void A_##x##_REG_ROR_IMM(ARM* cpu); \
s32 A_##x##_REG_LSL_REG(ARM* cpu); \ void A_##x##_REG_LSL_REG(ARM* cpu); \
s32 A_##x##_REG_LSR_REG(ARM* cpu); \ void A_##x##_REG_LSR_REG(ARM* cpu); \
s32 A_##x##_REG_ASR_REG(ARM* cpu); \ void A_##x##_REG_ASR_REG(ARM* cpu); \
s32 A_##x##_REG_ROR_REG(ARM* cpu); void A_##x##_REG_ROR_REG(ARM* cpu);
A_PROTO_ALU_OP(AND) A_PROTO_ALU_OP(AND)
A_PROTO_ALU_OP(EOR) A_PROTO_ALU_OP(EOR)
@ -72,54 +72,54 @@ A_PROTO_ALU_OP(MOV)
A_PROTO_ALU_OP(BIC) A_PROTO_ALU_OP(BIC)
A_PROTO_ALU_OP(MVN) A_PROTO_ALU_OP(MVN)
s32 A_MUL(ARM* cpu); void A_MUL(ARM* cpu);
s32 A_MLA(ARM* cpu); void A_MLA(ARM* cpu);
s32 A_UMULL(ARM* cpu); void A_UMULL(ARM* cpu);
s32 A_UMLAL(ARM* cpu); void A_UMLAL(ARM* cpu);
s32 A_SMULL(ARM* cpu); void A_SMULL(ARM* cpu);
s32 A_SMLAL(ARM* cpu); void A_SMLAL(ARM* cpu);
s32 A_CLZ(ARM* cpu); void A_CLZ(ARM* cpu);
s32 T_LSL_IMM(ARM* cpu); void T_LSL_IMM(ARM* cpu);
s32 T_LSR_IMM(ARM* cpu); void T_LSR_IMM(ARM* cpu);
s32 T_ASR_IMM(ARM* cpu); void T_ASR_IMM(ARM* cpu);
s32 T_ADD_REG_(ARM* cpu); void T_ADD_REG_(ARM* cpu);
s32 T_SUB_REG_(ARM* cpu); void T_SUB_REG_(ARM* cpu);
s32 T_ADD_IMM_(ARM* cpu); void T_ADD_IMM_(ARM* cpu);
s32 T_SUB_IMM_(ARM* cpu); void T_SUB_IMM_(ARM* cpu);
s32 T_MOV_IMM(ARM* cpu); void T_MOV_IMM(ARM* cpu);
s32 T_CMP_IMM(ARM* cpu); void T_CMP_IMM(ARM* cpu);
s32 T_ADD_IMM(ARM* cpu); void T_ADD_IMM(ARM* cpu);
s32 T_SUB_IMM(ARM* cpu); void T_SUB_IMM(ARM* cpu);
s32 T_AND_REG(ARM* cpu); void T_AND_REG(ARM* cpu);
s32 T_EOR_REG(ARM* cpu); void T_EOR_REG(ARM* cpu);
s32 T_LSL_REG(ARM* cpu); void T_LSL_REG(ARM* cpu);
s32 T_LSR_REG(ARM* cpu); void T_LSR_REG(ARM* cpu);
s32 T_ASR_REG(ARM* cpu); void T_ASR_REG(ARM* cpu);
s32 T_ADC_REG(ARM* cpu); void T_ADC_REG(ARM* cpu);
s32 T_SBC_REG(ARM* cpu); void T_SBC_REG(ARM* cpu);
s32 T_ROR_REG(ARM* cpu); void T_ROR_REG(ARM* cpu);
s32 T_TST_REG(ARM* cpu); void T_TST_REG(ARM* cpu);
s32 T_NEG_REG(ARM* cpu); void T_NEG_REG(ARM* cpu);
s32 T_CMP_REG(ARM* cpu); void T_CMP_REG(ARM* cpu);
s32 T_CMN_REG(ARM* cpu); void T_CMN_REG(ARM* cpu);
s32 T_ORR_REG(ARM* cpu); void T_ORR_REG(ARM* cpu);
s32 T_MUL_REG(ARM* cpu); void T_MUL_REG(ARM* cpu);
s32 T_BIC_REG(ARM* cpu); void T_BIC_REG(ARM* cpu);
s32 T_MVN_REG(ARM* cpu); void T_MVN_REG(ARM* cpu);
s32 T_ADD_HIREG(ARM* cpu); void T_ADD_HIREG(ARM* cpu);
s32 T_CMP_HIREG(ARM* cpu); void T_CMP_HIREG(ARM* cpu);
s32 T_MOV_HIREG(ARM* cpu); void T_MOV_HIREG(ARM* cpu);
s32 T_ADD_PCREL(ARM* cpu); void T_ADD_PCREL(ARM* cpu);
s32 T_ADD_SPREL(ARM* cpu); void T_ADD_SPREL(ARM* cpu);
s32 T_ADD_SP(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; s32 offset = (s32)(cpu->CurInstr << 8) >> 6;
cpu->JumpTo(cpu->R[15] + offset); 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; s32 offset = (s32)(cpu->CurInstr << 8) >> 6;
cpu->R[14] = cpu->R[15] - 4; cpu->R[14] = cpu->R[15] - 4;
cpu->JumpTo(cpu->R[15] + offset); 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; s32 offset = (s32)(cpu->CurInstr << 8) >> 6;
if (cpu->CurInstr & 0x01000000) offset += 2; if (cpu->CurInstr & 0x01000000) offset += 2;
cpu->R[14] = cpu->R[15] - 4; cpu->R[14] = cpu->R[15] - 4;
cpu->JumpTo(cpu->R[15] + offset + 1); 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]); 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; u32 lr = cpu->R[15] - 4;
cpu->JumpTo(cpu->R[cpu->CurInstr & 0xF]); cpu->JumpTo(cpu->R[cpu->CurInstr & 0xF]);
cpu->R[14] = lr; 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)) if (cpu->CheckCondition((cpu->CurInstr >> 8) & 0xF))
{ {
s32 offset = (s32)(cpu->CurInstr << 24) >> 23; s32 offset = (s32)(cpu->CurInstr << 24) >> 23;
cpu->JumpTo(cpu->R[15] + offset + 1); 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]); 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) if (cpu->Num==1)
{ {
printf("!! THUMB BLX_REG ON ARM7\n"); printf("!! THUMB BLX_REG ON ARM7\n");
return 1; return;
} }
u32 lr = cpu->R[15] - 1; u32 lr = cpu->R[15] - 1;
cpu->JumpTo(cpu->R[(cpu->CurInstr >> 3) & 0xF]); cpu->JumpTo(cpu->R[(cpu->CurInstr >> 3) & 0xF]);
cpu->R[14] = lr; 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; s32 offset = (s32)((cpu->CurInstr & 0x7FF) << 21) >> 20;
cpu->JumpTo(cpu->R[15] + offset + 1); 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; s32 offset = (s32)((cpu->CurInstr & 0x7FF) << 21) >> 9;
cpu->R[14] = cpu->R[15] + offset; 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; s32 offset = (cpu->CurInstr & 0x7FF) << 1;
u32 pc = cpu->R[14] + offset; u32 pc = cpu->R[14] + offset;
@ -129,7 +108,6 @@ s32 T_BL_LONG_2(ARM* cpu)
pc |= 1; pc |= 1;
cpu->JumpTo(pc); cpu->JumpTo(pc);
return C_S(2) + C_N(1);
} }

View File

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

View File

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

View File

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

View File

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

29
GPU.cpp
View File

@ -113,8 +113,33 @@ void Reset()
} }
// VRAM mapping shit. // VRAM mapping notes
// TODO eventually: work out priority orders in case of overlaps. there _are_ games that map overlapping banks. //
// 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) void MapVRAM_AB(u32 bank, u8 cnt)
{ {

View File

@ -1901,6 +1901,7 @@ void ARM7IOWrite8(u32 addr, u8 val)
return; return;
case 0x04000301: 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); if (val == 0x80) ARM7->Halt(1);
return; return;
} }

18
NDS.h
View File

@ -36,6 +36,22 @@ typedef struct _SchedEvent
} 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 enum
{ {
IRQ_VBlank = 0, IRQ_VBlank = 0,
@ -105,6 +121,8 @@ void RunEvents(s32 cycles);
// DO NOT CALL FROM ARM7!! // DO NOT CALL FROM ARM7!!
void CompensateARM7(); void CompensateARM7();
void debug(u32 p);
void Halt(); void Halt();
void MapSharedWRAM(u8 val); void MapSharedWRAM(u8 val);

View File

@ -88,6 +88,12 @@ void Reset()
fclose(f); 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 // verify shit
printf("FW: WIFI CRC16 = %s\n", VerifyCRC16(0x0000, 0x2C, *(u16*)&Firmware[0x2C], 0x2A)?"GOOD":"BAD"); 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"); 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_LEFT: NDS::PressKey(5); break;
case VK_RIGHT: NDS::PressKey(4); break; case VK_RIGHT: NDS::PressKey(4); break;
case 'P': NDS::PressKey(16+6); break; case 'P': NDS::PressKey(16+6); break;
case 'D': NDS::debug(0); break;
} }
return 0; return 0;

View File

@ -1,16 +1,16 @@
# depslib dependency file v1.0 # depslib dependency file v1.0
1484954918 source:c:\documents\sources\melonds\main.cpp 1485135566 source:c:\documents\sources\melonds\main.cpp
<stdio.h> <stdio.h>
<windows.h> <windows.h>
"NDS.h" "NDS.h"
"GPU.h" "GPU.h"
1485110344 c:\documents\sources\melonds\nds.h 1485792939 c:\documents\sources\melonds\nds.h
"types.h" "types.h"
1481161027 c:\documents\sources\melonds\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> <stdio.h>
<string.h> <string.h>
"NDS.h" "NDS.h"
@ -24,23 +24,23 @@
"RTC.h" "RTC.h"
"Wifi.h" "Wifi.h"
1485133372 source:c:\documents\sources\melonds\arm.cpp 1485797690 source:c:\documents\sources\melonds\arm.cpp
<stdio.h> <stdio.h>
"NDS.h" "NDS.h"
"ARM.h" "ARM.h"
"ARMInterpreter.h" "ARMInterpreter.h"
1481062839 c:\documents\sources\melonds\arm.h 1485797447 c:\documents\sources\melonds\arm.h
"types.h" "types.h"
"NDS.h" "NDS.h"
1484530962 c:\documents\sources\melonds\arm_instrtable.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" "types.h"
"ARM.h" "ARM.h"
1484752824 source:c:\documents\sources\melonds\arminterpreter.cpp 1485797066 source:c:\documents\sources\melonds\arminterpreter.cpp
<stdio.h> <stdio.h>
"NDS.h" "NDS.h"
"CP15.h" "CP15.h"
@ -50,27 +50,27 @@
"ARMInterpreter_LoadStore.h" "ARMInterpreter_LoadStore.h"
"ARM_InstrTable.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> <stdio.h>
"ARM.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> <stdio.h>
"ARM.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> <stdio.h>
"ARM.h" "ARM.h"
1481037554 c:\documents\sources\melonds\cp15.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> <stdio.h>
"NDS.h" "NDS.h"
"ARM.h" "ARM.h"
@ -78,7 +78,7 @@
1480957111 c:\documents\sources\melonds\spi.h 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> <stdio.h>
<string.h> <string.h>
"NDS.h" "NDS.h"
@ -115,7 +115,7 @@
1484698068 c:\documents\sources\melonds\dma.h 1484698068 c:\documents\sources\melonds\dma.h
"types.h" "types.h"
1484753188 source:c:\documents\sources\melonds\gpu.cpp 1485789352 source:c:\documents\sources\melonds\gpu.cpp
<stdio.h> <stdio.h>
<string.h> <string.h>
"NDS.h" "NDS.h"