www.pudn.com > potemkin_sourceforPSP.rar > ARM.cpp
#include "stdafx.h"
#include "ARM.h"
#include "ARMTables.h"
ARMState arm7(ARMTYPE_ARM7TDMI);
ARMState arm9(ARMTYPE_ARM9);
void ARM_Init()
{
FillARMTables();
arm7.type = 7;
arm9.type = 9;
FillThumbTables();
}
void ARM_Shutdown()
{
}
void ARMState::Reset()
{
for (int i=0; i<16; i++)
r[i]=0;
c=n=z=v=0;
cpsr=0xd3;
spsr=0;
spsr_abt=0;
spsr_irq=0;
spsr_fiq=0;
spsr_und=0;
spsr_svc=0;
thumb=false;
r[15] = highVectors?0xFFFF0000:0x00000000; // 0xffff0000? seems likely if gba bios is on 0x00000000
r13_irq=0;
r14_irq=0;
r13_abt=0;
r14_abt=0;
r13_und=0;
r14_und=0;
r13_irq=0;
r14_irq=0;
for (int i=0; i<6; i++)
r8_14_fiq[i]=0;
if (fakeBios)
{
cpsr = ARMMODE_SYSTEM | ARM_F_MASK;
r[13] = 0x03007F00;
r[15] = 0x08000000;
r13_irq = 0x03007FA0;
r13_svc = 0x03007FE0;
r13_usr = 0x03007F00;
}
else
{
cpsr = ARMMODE_SUPER | ARM_I_MASK | ARM_F_MASK; //?
//r[15] = (highVectors) ? 0xffff0000 : 0x00000000;
//r[15] = (highVectors) ? 0x02004800 : 0x00000000;
r[15] = (highVectors) ? 0xFFFF0000 : 0x00000000;
}
}
void ARMState::ModeSwitch(ARMMode mode, bool saveState)
{
ARMMode curMode = (ARMMode)(cpsr & 0x1F);
//if (curMode!=mode)
{
switch (curMode) {
case ARMMODE_IRQ:
r13_irq = r[13];
r14_irq = r[14];
spsr_irq = spsr;
break;
case ARMMODE_FIQ:
spsr_fiq = spsr;
break;
case ARMMODE_SUPER:
r13_svc = r[13];
r14_svc = r[14];
spsr_svc = spsr;
break;
case ARMMODE_ABORT:
break;
case ARMMODE_USER:
case ARMMODE_SYSTEM:
r13_usr = r[13];
r14_usr = r[14];
spsr = GetCPSR();
break;
}
}
switch (mode) {
case ARMMODE_IRQ:
r[13] = r13_irq;
r[14] = r14_irq;
if (saveState)
spsr = GetCPSR();
else
spsr = spsr_irq;
break;
case ARMMODE_FIQ:
spsr = spsr_fiq;
if (saveState)
spsr = GetCPSR();
else
spsr = spsr_fiq;
break;
case ARMMODE_SUPER:
r[13] = r13_svc;
r[14] = r14_svc;
if (saveState)
spsr = GetCPSR();
else
spsr = spsr_svc;
break;
case ARMMODE_ABORT:
break;
case ARMMODE_USER:
case ARMMODE_SYSTEM:
r[13] = r13_usr;
r[14] = r14_usr;
cpsr = spsr;
break;
}
cpsr = (cpsr & ~0x1f) | mode;
}
TCHAR *ARMState::GetName()
{
return type==7 ? _T("ARM7") : _T("ARM9");
}
u32 ARMState::GetCPSR()
{
return cpsr | (n<<31) | (z<<30) | (c<<29) | (v<<28) | ((int)thumb << 5);
}
void ARMState::SetCPSR(u32 ncpsr)
{
cpsr = ncpsr & 0x0FFFFFFF;
n = (ncpsr>>31)&1;
z = (ncpsr>>30)&1;
c = (ncpsr>>29)&1;
v = (ncpsr>>28)&1;
bool oldThumb = thumb;
thumb = (ncpsr>>5)&1;
//if (thumb != oldThumb)
// _dbg_assert_msg_(CPU,0,"THUMB flag changed in SetCPSR!");
}
void ARMState::Irq()
{
if (IRQEnabled())
{
spsr_irq = GetCPSR();
r14_irq = r[ARM_REG_PC] - (thumb ? 2 : 4);
ModeSwitch(ARMMODE_IRQ,true);
cpsr = (cpsr & 0xFFFFFF80 | ARM_F_MASK) | ARMMODE_IRQ | ARM_I_MASK;
thumb = 0;
r[ARM_REG_PC] = highVectors?0xFFFF0018:0x00000018;
}
}
void ARMState::FIrq()
{
if (FIRQEnabled())
{
spsr_fiq = GetCPSR();
r8_14_fiq[14-8] = r[ARM_REG_PC] + (thumb ? 2 : 4); // ?
cpsr = (cpsr & 0xFFFFFF80) | ARMMODE_FIQ | ARM_I_MASK | ARM_F_MASK;
thumb = 0;
ModeSwitch(ARMMODE_FIQ,true);
r[ARM_REG_PC] = highVectors?0xFFFF001C:0x0000001C;
}
else
{
//LOG(CPU,"firq even if disabled");
}
}
void ARMState::SWI()
{
bool savedThumb = thumb;
r14_svc = r[ARM_REG_PC] /* + (thumb ? 2 : 4)*/; //should be instruction after current one
spsr_svc = GetCPSR();
ModeSwitch(ARMMODE_SUPER,true);
cpsr = (cpsr & 0xFFFFFF80) | ARMMODE_SUPER | ARM_I_MASK | ARM_F_MASK;
thumb=0;
r[ARM_REG_PC] = highVectors ? 0xFFFF0008:0x00000008;
}
void ARMState::UndefInstr()
{
}
ARMMode ARMState::GetMode()
{
return (ARMMode)(cpsr & 0x1F);
}
bool ARMState::EvaluateCondition(int cc)
{
switch(cc)
{
case COND_EQ: return z;
case COND_NE: return !z;
case COND_CS: return c;
case COND_CC: return !c;
case COND_MI: return n;
case COND_PL: return !n;
case COND_VS: return v;
case COND_VC: return !v;
case COND_HI: return c && !z;
case COND_LS: return !c || z;
case COND_GE: return n == v;
case COND_LT: return n != v;
case COND_GT: return (z==0) && (n==v);
case COND_LE: return (z==1) || (n!=v);
case COND_AL: return true;
case COND_ERR: _dbg_assert_msg_(CPU,0,"Trying to evaluate an 0xF condition"); return false;
default: _dbg_assert_msg_(CPU,0,"Trying to evaluate an invalid condition"); return false;
}
}