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; 
	} 
}