start refactoring shit: more accurate timing and way of counting cycles.
This commit is contained in:
parent
296212ac49
commit
6f3b0498db
145
ARM.cpp
145
ARM.cpp
|
@ -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
91
ARM.h
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
2
CP15.cpp
2
CP15.cpp
|
@ -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
29
GPU.cpp
|
@ -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)
|
||||
{
|
||||
|
|
1
NDS.cpp
1
NDS.cpp
|
@ -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
18
NDS.h
|
@ -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);
|
||||
|
|
6
SPI.cpp
6
SPI.cpp
|
@ -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");
|
||||
|
|
1
main.cpp
1
main.cpp
|
@ -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;
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue