more realistic exception handling
This commit is contained in:
parent
4069c5a517
commit
a9b186acb3
|
@ -586,8 +586,11 @@ inline void SetupMMU(BOOL debugConsole) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FORCEINLINE void CheckMemoryDebugEvent(const EDEBUG_EVENT event, const MMU_ACCESS_TYPE type, const u32 procnum, const u32 addr, const u32 size, const u32 val)
|
FORCEINLINE void CheckMemoryDebugEvent(EDEBUG_EVENT event, const MMU_ACCESS_TYPE type, const u32 procnum, const u32 addr, const u32 size, const u32 val)
|
||||||
{
|
{
|
||||||
|
//TODO - ugh work out a better prefetch event system
|
||||||
|
if(type == MMU_AT_CODE && event == DEBUG_EVENT_READ)
|
||||||
|
event = DEBUG_EVENT_EXECUTE;
|
||||||
if(CheckDebugEvent(event))
|
if(CheckDebugEvent(event))
|
||||||
{
|
{
|
||||||
DebugEventData.memAccessType = type;
|
DebugEventData.memAccessType = type;
|
||||||
|
@ -596,11 +599,6 @@ FORCEINLINE void CheckMemoryDebugEvent(const EDEBUG_EVENT event, const MMU_ACCES
|
||||||
DebugEventData.size = size;
|
DebugEventData.size = size;
|
||||||
DebugEventData.val = val;
|
DebugEventData.val = val;
|
||||||
HandleDebugEvent(event);
|
HandleDebugEvent(event);
|
||||||
|
|
||||||
if(type == MMU_AT_CODE && event == DEBUG_EVENT_READ)
|
|
||||||
{
|
|
||||||
HandleDebugEvent(DEBUG_EVENT_EXECUTE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,6 +702,12 @@ FORCEINLINE u32 _MMU_read32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u
|
||||||
if(addr<0x02000000)
|
if(addr<0x02000000)
|
||||||
return T1ReadLong_guaranteedAligned(MMU.ARM9_ITCM, addr&0x7FFC);
|
return T1ReadLong_guaranteedAligned(MMU.ARM9_ITCM, addr&0x7FFC);
|
||||||
|
|
||||||
|
//what happens when we execute from DTCM? nocash makes it look like we get 0xFFFFFFFF but i can't seem to verify it
|
||||||
|
//historically, desmume would fall through to its old memory map struct
|
||||||
|
//which would return unused memory (0)
|
||||||
|
//it seems the hardware returns 0 or something benign because in actuality 0xFFFFFFFF is an undefined opcode
|
||||||
|
//and we know our handling for that is solid
|
||||||
|
|
||||||
goto dunno;
|
goto dunno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
|
|
||||||
//#define LOG_ARM9
|
//#define LOG_ARM9
|
||||||
//#define LOG_ARM7
|
//#define LOG_ARM7
|
||||||
bool dolog = true;
|
//bool dolog = true;
|
||||||
//#define LOG_TO_FILE
|
//#define LOG_TO_FILE
|
||||||
//#define LOG_TO_FILE_REGS
|
//#define LOG_TO_FILE_REGS
|
||||||
|
|
||||||
|
@ -2127,25 +2127,67 @@ void NDS_Reset()
|
||||||
{
|
{
|
||||||
NDS_ARM9.swi_tab = ARM9_swi_tab;
|
NDS_ARM9.swi_tab = ARM9_swi_tab;
|
||||||
|
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x0000, 0xEAFFFFFE); // loop for Reset !!!
|
//bios chains data abort to fast irq
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEAFFFFFE); // loop for Undef instr expection
|
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x0008, 0xEA00009C); // SWI
|
//exception vectors:
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x000C, 0xEAFFFFFE); // loop for Prefetch Abort
|
T1WriteLong(MMU.ARM9_BIOS, 0x0000, 0xEAFFFFFE); // (infinite loop for) Reset !!!
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x0010, 0xEAFFFFFE); // loop for Data Abort
|
//T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEAFFFFFE); // (infinite loop for) Undefined instruction
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEA000004); // Undefined instruction -> Fast IRQ (just guessing)
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x0008, 0xEA00009C); // SWI -> ?????
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x000C, 0xEAFFFFFE); // (infinite loop for) Prefetch Abort
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x0010, 0xEA000001); // Data Abort -> Fast IRQ
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x0014, 0x00000000); // Reserved
|
T1WriteLong(MMU.ARM9_BIOS, 0x0014, 0x00000000); // Reserved
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x0018, 0xEA000095); // Normal IRQ
|
T1WriteLong(MMU.ARM9_BIOS, 0x0018, 0xEA000095); // Normal IRQ -> 0x0274
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x001C, 0x00000000); // Fast IRQ
|
T1WriteLong(MMU.ARM9_BIOS, 0x001C, 0xEA00009D); // Fast IRQ -> 0x0298
|
||||||
for (int t = 0; t < 156; t++) // logo
|
|
||||||
|
// logo (do some games fail to boot without this? example?)
|
||||||
|
for (int t = 0; t < 0x9C; t++)
|
||||||
MMU.ARM9_BIOS[t + 0x20] = logo_data[t];
|
MMU.ARM9_BIOS[t + 0x20] = logo_data[t];
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x0274, 0xE92D500F);
|
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x0278, 0xEE190F11);
|
//...0xBC:
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x027C, 0xE1A00620);
|
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x0280, 0xE1A00600);
|
//(now what goes in this gap??)
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x0284, 0xE2800C40);
|
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x0288, 0xE28FE000);
|
//IRQ handler: get dtcm address and jump to a vector in it
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x028C, 0xE510F004);
|
T1WriteLong(MMU.ARM9_BIOS, 0x0274, 0xE92D500F); //STMDB SP!, {R0-R3,R12,LR}
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x0290, 0xE8BD500F);
|
T1WriteLong(MMU.ARM9_BIOS, 0x0278, 0xEE190F11); //MRC CP15, 0, R0, CR9, CR1, 0
|
||||||
T1WriteLong(MMU.ARM9_BIOS, 0x0294, 0xE25EF004);
|
T1WriteLong(MMU.ARM9_BIOS, 0x027C, 0xE1A00620); //MOV R0, R0, LSR #C
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x0280, 0xE1A00600); //MOV R0, R0, LSL #C
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x0284, 0xE2800C40); //ADD R0, R0, #4000
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x0288, 0xE28FE000); //ADD LR, PC, #0
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x028C, 0xE510F004); //LDR PC, [R0, -#4]
|
||||||
|
|
||||||
|
//????
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x0290, 0xE8BD500F); //LDMIA SP!, {R0-R3,R12,LR}
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x0294, 0xE25EF004); //SUBS PC, LR, #4
|
||||||
|
|
||||||
|
//-------
|
||||||
|
//FIQ and abort exception handler
|
||||||
|
//TODO - this code is copied from the bios. refactor it
|
||||||
|
//friendly reminder: to calculate an immediate offset: encoded = (desired_address-cur_address-8)
|
||||||
|
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x0298, 0xE10FD000); //MRS SP, CPSR
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x029C, 0xE38DD0C0); //ORR SP, SP, #C0
|
||||||
|
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x02A0, 0xE12FF00D); //MSR CPSR_fsxc, SP
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x02A4, 0xE59FD000 | (0x2D4-0x2A4-8)); //LDR SP, [FFFF02D4]
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x02A8, 0xE28DD001); //ADD SP, SP, #1
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x02AC, 0xE92D5000); //STMDB SP!, {R12,LR}
|
||||||
|
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x02B0, 0xE14FE000); //MRS LR, SPSR
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x02B4, 0xEE11CF10); //MRC CP15, 0, R12, CR1, CR0, 0
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x02B8, 0xE92D5000); //STMDB SP!, {R12,LR}
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x02BC, 0xE3CCC001); //BIC R12, R12, #1
|
||||||
|
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x02C0, 0xEE01CF10); //MCR CP15, 0, R12, CR1, CR0, 0
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x02C4, 0xE3CDC001); //BIC R12, SP, #1
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x02C8, 0xE59CC010); //LDR R12, [R12, #10]
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x02CC, 0xE35C0000); //CMP R12, #0
|
||||||
|
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x02D0, 0x112FFF3C); //BLXNE R12
|
||||||
|
T1WriteLong(MMU.ARM9_BIOS, 0x02D4, 0x027FFD9C); //0x027FFD9C
|
||||||
|
//---------
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LOG_ARM7
|
#ifdef LOG_ARM7
|
||||||
|
@ -2247,6 +2289,9 @@ void NDS_Reset()
|
||||||
NDS_ARM9.R13_svc = 0x00803FC0;
|
NDS_ARM9.R13_svc = 0x00803FC0;
|
||||||
NDS_ARM9.R13_irq = 0x00803FA0;
|
NDS_ARM9.R13_irq = 0x00803FA0;
|
||||||
NDS_ARM9.R13_usr = 0x00803EC0;
|
NDS_ARM9.R13_usr = 0x00803EC0;
|
||||||
|
NDS_ARM9.R13_abt = NDS_ARM9.R13_usr; //?????
|
||||||
|
//I think it is wrong to take gbatek's "SYS" and put it in USR--maybe USR doesnt matter.
|
||||||
|
//i think SYS is all the misc modes. please verify by setting nonsensical stack values for USR here
|
||||||
NDS_ARM9.R[13] = NDS_ARM9.R13_usr;
|
NDS_ARM9.R[13] = NDS_ARM9.R13_usr;
|
||||||
//n.b.: im not sure about all these, I dont know enough about arm9 svc/irq/etc modes
|
//n.b.: im not sure about all these, I dont know enough about arm9 svc/irq/etc modes
|
||||||
//and how theyre named in desmume to match them up correctly. i just guessed.
|
//and how theyre named in desmume to match them up correctly. i just guessed.
|
||||||
|
|
|
@ -261,28 +261,6 @@ TEMPLATE static u32 FASTCALL OP_UND(const u32 i)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TRAPUNDEF() \
|
|
||||||
LOG("Undefined instruction: %#08X PC = %#08X \n", cpu->instruction, cpu->instruct_adr); \
|
|
||||||
\
|
|
||||||
if (((cpu->intVector != 0) ^ (PROCNUM == ARMCPU_ARM9))) \
|
|
||||||
{ \
|
|
||||||
Status_Reg tmp = cpu->CPSR; \
|
|
||||||
armcpu_switchMode(cpu, UND); /* enter und mode */ \
|
|
||||||
cpu->R[14] = cpu->R[15] - 4; /* jump to und Vector */ \
|
|
||||||
cpu->SPSR = tmp; /* save old CPSR as new SPSR */ \
|
|
||||||
cpu->CPSR.bits.T = 0; /* handle as ARM32 code */ \
|
|
||||||
cpu->CPSR.bits.I = cpu->SPSR.bits.I; /* keep int disable flag */ \
|
|
||||||
cpu->changeCPSR(); \
|
|
||||||
cpu->R[15] = cpu->intVector + 0x04; \
|
|
||||||
cpu->next_instruction = cpu->R[15]; \
|
|
||||||
return 4; \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
emu_halt(); \
|
|
||||||
return 4; \
|
|
||||||
} \
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// AND / ANDS
|
// AND / ANDS
|
||||||
// Timing: OK
|
// Timing: OK
|
||||||
|
@ -3176,6 +3154,8 @@ TEMPLATE static u32 FASTCALL OP_BX(const u32 i)
|
||||||
u32 tmp = cpu->R[REG_POS(cpu->instruction, 0)];
|
u32 tmp = cpu->R[REG_POS(cpu->instruction, 0)];
|
||||||
|
|
||||||
cpu->CPSR.bits.T = BIT0(tmp);
|
cpu->CPSR.bits.T = BIT0(tmp);
|
||||||
|
//zeromus has a little concern about these. shouldnt they be 0xFFFFFFFC?
|
||||||
|
//can someone refute this or prove it?
|
||||||
cpu->R[15] = tmp & 0xFFFFFFFE;
|
cpu->R[15] = tmp & 0xFFFFFFFE;
|
||||||
cpu->next_instruction = cpu->R[15];
|
cpu->next_instruction = cpu->R[15];
|
||||||
return 3;
|
return 3;
|
||||||
|
@ -3187,6 +3167,8 @@ TEMPLATE static u32 FASTCALL OP_BLX_REG(const u32 i)
|
||||||
|
|
||||||
cpu->R[14] = cpu->next_instruction;
|
cpu->R[14] = cpu->next_instruction;
|
||||||
cpu->CPSR.bits.T = BIT0(tmp);
|
cpu->CPSR.bits.T = BIT0(tmp);
|
||||||
|
//zeromus has a little concern about these. shouldnt they be 0xFFFFFFFC?
|
||||||
|
//can someone refute this or prove it?
|
||||||
cpu->R[15] = tmp & 0xFFFFFFFE;
|
cpu->R[15] = tmp & 0xFFFFFFFE;
|
||||||
cpu->next_instruction = cpu->R[15];
|
cpu->next_instruction = cpu->R[15];
|
||||||
return 3;
|
return 3;
|
||||||
|
@ -6732,37 +6714,37 @@ TEMPLATE static u32 FASTCALL OP_LDRD_STRD_OFFSET_PRE_INDEX(const u32 i)
|
||||||
|
|
||||||
TEMPLATE static u32 FASTCALL OP_STC_P_IMM_OFF(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_STC_P_IMM_OFF(const u32 i)
|
||||||
{
|
{
|
||||||
TRAPUNDEF();
|
return TRAPUNDEF(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMPLATE static u32 FASTCALL OP_STC_M_IMM_OFF(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_STC_M_IMM_OFF(const u32 i)
|
||||||
{
|
{
|
||||||
TRAPUNDEF();
|
return TRAPUNDEF(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMPLATE static u32 FASTCALL OP_STC_P_PREIND(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_STC_P_PREIND(const u32 i)
|
||||||
{
|
{
|
||||||
TRAPUNDEF();
|
return TRAPUNDEF(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMPLATE static u32 FASTCALL OP_STC_M_PREIND(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_STC_M_PREIND(const u32 i)
|
||||||
{
|
{
|
||||||
TRAPUNDEF();
|
return TRAPUNDEF(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMPLATE static u32 FASTCALL OP_STC_P_POSTIND(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_STC_P_POSTIND(const u32 i)
|
||||||
{
|
{
|
||||||
TRAPUNDEF();
|
return TRAPUNDEF(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMPLATE static u32 FASTCALL OP_STC_M_POSTIND(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_STC_M_POSTIND(const u32 i)
|
||||||
{
|
{
|
||||||
TRAPUNDEF();
|
return TRAPUNDEF(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMPLATE static u32 FASTCALL OP_STC_OPTION(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_STC_OPTION(const u32 i)
|
||||||
{
|
{
|
||||||
TRAPUNDEF();
|
return TRAPUNDEF(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -6772,38 +6754,37 @@ TEMPLATE static u32 FASTCALL OP_STC_OPTION(const u32 i)
|
||||||
|
|
||||||
TEMPLATE static u32 FASTCALL OP_LDC_P_IMM_OFF(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_LDC_P_IMM_OFF(const u32 i)
|
||||||
{
|
{
|
||||||
TRAPUNDEF();
|
return TRAPUNDEF(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMPLATE static u32 FASTCALL OP_LDC_M_IMM_OFF(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_LDC_M_IMM_OFF(const u32 i)
|
||||||
{
|
{
|
||||||
TRAPUNDEF();
|
return TRAPUNDEF(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMPLATE static u32 FASTCALL OP_LDC_P_PREIND(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_LDC_P_PREIND(const u32 i)
|
||||||
{
|
{
|
||||||
TRAPUNDEF();
|
return TRAPUNDEF(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMPLATE static u32 FASTCALL OP_LDC_M_PREIND(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_LDC_M_PREIND(const u32 i)
|
||||||
{
|
{
|
||||||
TRAPUNDEF();
|
return TRAPUNDEF(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMPLATE static u32 FASTCALL OP_LDC_P_POSTIND(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_LDC_P_POSTIND(const u32 i)
|
||||||
{
|
{
|
||||||
TRAPUNDEF();
|
return TRAPUNDEF(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMPLATE static u32 FASTCALL OP_LDC_M_POSTIND(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_LDC_M_POSTIND(const u32 i)
|
||||||
{
|
{
|
||||||
TRAPUNDEF();
|
return TRAPUNDEF(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMPLATE static u32 FASTCALL OP_LDC_OPTION(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_LDC_OPTION(const u32 i)
|
||||||
{
|
{
|
||||||
TRAPUNDEF();
|
return TRAPUNDEF(cpu);
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -6911,7 +6892,7 @@ TEMPLATE static u32 FASTCALL OP_BKPT(const u32 i)
|
||||||
TEMPLATE static u32 FASTCALL OP_CDP(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_CDP(const u32 i)
|
||||||
{
|
{
|
||||||
LOG("Stopped (OP_CDP) \n");
|
LOG("Stopped (OP_CDP) \n");
|
||||||
TRAPUNDEF();
|
return TRAPUNDEF(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
|
@ -397,7 +397,7 @@ FORCEINLINE static u32 armcpu_prefetch()
|
||||||
armcpu->R[15] = armcpu->next_instruction + 4;
|
armcpu->R[15] = armcpu->next_instruction + 4;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
curInstruction &= 0x0FFFFFFC;
|
curInstruction &= 0xFFFFFFFC; //please don't change this to 0x0FFFFFFC -- the NDS will happily run on 0xF******* addresses all day long
|
||||||
armcpu->instruction = _MMU_read32<PROCNUM, MMU_AT_CODE>(curInstruction);
|
armcpu->instruction = _MMU_read32<PROCNUM, MMU_AT_CODE>(curInstruction);
|
||||||
armcpu->instruct_adr = curInstruction;
|
armcpu->instruct_adr = curInstruction;
|
||||||
armcpu->next_instruction = curInstruction + 4;
|
armcpu->next_instruction = curInstruction + 4;
|
||||||
|
@ -419,7 +419,7 @@ FORCEINLINE static u32 armcpu_prefetch()
|
||||||
armcpu->R[15] = armcpu->next_instruction + 2;
|
armcpu->R[15] = armcpu->next_instruction + 2;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
curInstruction &= 0x0FFFFFFE;
|
curInstruction &= 0xFFFFFFFE; //please don't change this to 0x0FFFFFFE -- the NDS will happily run on 0xF******* addresses all day long
|
||||||
armcpu->instruction = _MMU_read16<PROCNUM, MMU_AT_CODE>(curInstruction);
|
armcpu->instruction = _MMU_read16<PROCNUM, MMU_AT_CODE>(curInstruction);
|
||||||
armcpu->instruct_adr = curInstruction;
|
armcpu->instruct_adr = curInstruction;
|
||||||
armcpu->next_instruction = curInstruction + 2;
|
armcpu->next_instruction = curInstruction + 2;
|
||||||
|
@ -469,6 +469,37 @@ static BOOL (FASTCALL* test_conditions[])(Status_Reg CPSR)= {
|
||||||
(cond<15&&test_conditions[cond](CPSR))
|
(cond<15&&test_conditions[cond](CPSR))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//TODO - merge with armcpu_irqException?
|
||||||
|
//http://www.ethernut.de/en/documents/arm-exceptions.html
|
||||||
|
//http://docs.google.com/viewer?a=v&q=cache:V4ht1YkxprMJ:www.cs.nctu.edu.tw/~wjtsai/EmbeddedSystemDesign/Ch3-1.pdf+arm+exception+handling&hl=en&gl=us&pid=bl&srcid=ADGEEShx9VTHbUhWdDOrTVRzLkcCsVfJiijncNDkkgkrlJkLa7D0LCpO8fQ_hhU3DTcgZh9rcZWWQq4TYhhCovJ625h41M0ZUX3WGasyzWQFxYzDCB-VS6bsUmpoJnRxAc-bdkD0qmsu&sig=AHIEtbR9VHvDOCRmZFQDUVwy53iJDjoSPQ
|
||||||
|
void armcpu_exception(armcpu_t *cpu, u32 number)
|
||||||
|
{
|
||||||
|
Mode cpumode = USR;
|
||||||
|
switch(number)
|
||||||
|
{
|
||||||
|
case EXCEPTION_RESET: cpumode = SVC; break;
|
||||||
|
case EXCEPTION_UNDEFINED_INSTRUCTION: cpumode = UND; break;
|
||||||
|
case EXCEPTION_SWI: cpumode = SVC; break;
|
||||||
|
case EXCEPTION_PREFETCH_ABORT: cpumode = ABT; break;
|
||||||
|
case EXCEPTION_DATA_ABORT: cpumode = ABT; break;
|
||||||
|
case EXCEPTION_RESERVED_0x14: emu_halt(); break;
|
||||||
|
case EXCEPTION_IRQ: cpumode = IRQ; break;
|
||||||
|
case EXCEPTION_FAST_IRQ: cpumode = FIQ; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status_Reg tmp = cpu->CPSR;
|
||||||
|
armcpu_switchMode(cpu, cpumode); //enter new mode
|
||||||
|
cpu->R[14] = cpu->next_instruction;
|
||||||
|
cpu->SPSR = tmp; //save old CPSR as new SPSR
|
||||||
|
cpu->CPSR.bits.T = 0; //handle as ARM32 code
|
||||||
|
cpu->CPSR.bits.I = 1;
|
||||||
|
cpu->changeCPSR();
|
||||||
|
cpu->R[15] = cpu->intVector + number;
|
||||||
|
cpu->next_instruction = cpu->R[15];
|
||||||
|
printf("armcpu_exception!\n");
|
||||||
|
//extern bool dolog;
|
||||||
|
//dolog=true;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL armcpu_irqException(armcpu_t *armcpu)
|
BOOL armcpu_irqException(armcpu_t *armcpu)
|
||||||
{
|
{
|
||||||
|
@ -502,6 +533,21 @@ BOOL armcpu_irqException(armcpu_t *armcpu)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 TRAPUNDEF(armcpu_t* cpu)
|
||||||
|
{
|
||||||
|
LOG("Undefined instruction: %#08X PC = %#08X \n", cpu->instruction, cpu->instruct_adr);
|
||||||
|
if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9)))
|
||||||
|
{
|
||||||
|
armcpu_exception(&NDS_ARM9,0x04);
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emu_halt();
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//BOOL
|
//BOOL
|
||||||
//armcpu_flagIrq( armcpu_t *armcpu) {
|
//armcpu_flagIrq( armcpu_t *armcpu) {
|
||||||
// if(armcpu->CPSR.bits.I) return FALSE;
|
// if(armcpu->CPSR.bits.I) return FALSE;
|
||||||
|
@ -524,6 +570,11 @@ u32 armcpu_exec()
|
||||||
u32 cFetch = 0;
|
u32 cFetch = 0;
|
||||||
u32 cExecute = 0;
|
u32 cExecute = 0;
|
||||||
|
|
||||||
|
if(NDS_ARM9.instruct_adr == 0x0201125C)
|
||||||
|
{
|
||||||
|
int zzz=9;
|
||||||
|
}
|
||||||
|
|
||||||
//this assert is annoying. but sometimes it is handy.
|
//this assert is annoying. but sometimes it is handy.
|
||||||
//assert(ARMPROC.instruct_adr!=0x00000000);
|
//assert(ARMPROC.instruct_adr!=0x00000000);
|
||||||
#ifdef DEVELOPER
|
#ifdef DEVELOPER
|
||||||
|
@ -538,18 +589,18 @@ u32 armcpu_exec()
|
||||||
break;
|
break;
|
||||||
case 0x00000004:
|
case 0x00000004:
|
||||||
printf("BIOS%c: Undefined instruction\n", PROCNUM?'7':'9');
|
printf("BIOS%c: Undefined instruction\n", PROCNUM?'7':'9');
|
||||||
emu_halt();
|
//emu_halt();
|
||||||
break;
|
break;
|
||||||
case 0x00000008:
|
case 0x00000008:
|
||||||
//printf("BIOS%c: SWI\n", PROCNUM?'7':'9');
|
//printf("BIOS%c: SWI\n", PROCNUM?'7':'9');
|
||||||
break;
|
break;
|
||||||
case 0x0000000C:
|
case 0x0000000C:
|
||||||
printf("BIOS%c: Prefetch Abort!!!\n", PROCNUM?'7':'9');
|
printf("BIOS%c: Prefetch Abort!!!\n", PROCNUM?'7':'9');
|
||||||
emu_halt();
|
//emu_halt();
|
||||||
break;
|
break;
|
||||||
case 0x00000010:
|
case 0x00000010:
|
||||||
printf("BIOS%c: Data Abort!!!\n", PROCNUM?'7':'9');
|
//printf("BIOS%c: Data Abort!!!\n", PROCNUM?'7':'9');
|
||||||
emu_halt();
|
//emu_halt();
|
||||||
break;
|
break;
|
||||||
case 0x00000014:
|
case 0x00000014:
|
||||||
printf("BIOS%c: Reserved!!!\n", PROCNUM?'7':'9');
|
printf("BIOS%c: Reserved!!!\n", PROCNUM?'7':'9');
|
||||||
|
|
|
@ -29,6 +29,15 @@
|
||||||
#define OPCODE(i) (((i)>>21)&0xF)
|
#define OPCODE(i) (((i)>>21)&0xF)
|
||||||
#define SIGNEBIT(i) BIT_N(i,20)
|
#define SIGNEBIT(i) BIT_N(i,20)
|
||||||
|
|
||||||
|
#define EXCEPTION_RESET 0x00
|
||||||
|
#define EXCEPTION_UNDEFINED_INSTRUCTION 0x04
|
||||||
|
#define EXCEPTION_SWI 0x08
|
||||||
|
#define EXCEPTION_PREFETCH_ABORT 0x0C
|
||||||
|
#define EXCEPTION_DATA_ABORT 0x10
|
||||||
|
#define EXCEPTION_RESERVED_0x14 0x14
|
||||||
|
#define EXCEPTION_IRQ 0x18
|
||||||
|
#define EXCEPTION_FAST_IRQ 0x1C
|
||||||
|
|
||||||
#define INSTRUCTION_INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF))
|
#define INSTRUCTION_INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF))
|
||||||
|
|
||||||
inline u32 ROR(u32 i, u32 j) { return ((((u32)(i))>>(j)) | (((u32)(i))<<(32-(j)))); }
|
inline u32 ROR(u32 i, u32 j) { return ((((u32)(i))>>(j)) | (((u32)(i))<<(32-(j)))); }
|
||||||
|
@ -216,6 +225,8 @@ template<int PROCNUM> u32 armcpu_exec();
|
||||||
|
|
||||||
BOOL armcpu_irqException(armcpu_t *armcpu);
|
BOOL armcpu_irqException(armcpu_t *armcpu);
|
||||||
BOOL armcpu_flagIrq( armcpu_t *armcpu);
|
BOOL armcpu_flagIrq( armcpu_t *armcpu);
|
||||||
|
void armcpu_exception(armcpu_t *cpu, u32 number);
|
||||||
|
u32 TRAPUNDEF(armcpu_t* cpu);
|
||||||
|
|
||||||
extern armcpu_t NDS_ARM7;
|
extern armcpu_t NDS_ARM7;
|
||||||
extern armcpu_t NDS_ARM9;
|
extern armcpu_t NDS_ARM9;
|
||||||
|
|
|
@ -36,6 +36,8 @@
|
||||||
#include "lua-engine.h"
|
#include "lua-engine.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
armcpu_t* TDebugEventData::cpu() { return procnum==0?&NDS_ARM9:&NDS_ARM7; }
|
||||||
|
|
||||||
TDebugEventData DebugEventData;
|
TDebugEventData DebugEventData;
|
||||||
u32 debugFlag;
|
u32 debugFlag;
|
||||||
|
|
||||||
|
@ -43,25 +45,25 @@ u32 debugFlag;
|
||||||
const bool debug_acl = false;
|
const bool debug_acl = false;
|
||||||
|
|
||||||
static bool acl_check_access(u32 adr, u32 access) {
|
static bool acl_check_access(u32 adr, u32 access) {
|
||||||
//tweak the access value with the execution mode.
|
|
||||||
//user code is USR and every other mode is SYS.
|
//non-user modes get separate access handling, so check that here
|
||||||
//this is weird logic, but I didn't want to change..
|
if(NDS_ARM9.CPSR.bits.mode != USR)
|
||||||
access |= 1;
|
access |= 1;
|
||||||
if ((NDS_ARM9.CPSR.val & 0x1F) == 0x10) {
|
|
||||||
// is user mode access
|
|
||||||
access ^= 1;
|
|
||||||
}
|
|
||||||
if (armcp15_isAccessAllowed((armcp15_t *)NDS_ARM9.coproc[15],adr,access)==FALSE) {
|
if (armcp15_isAccessAllowed((armcp15_t *)NDS_ARM9.coproc[15],adr,access)==FALSE) {
|
||||||
HandleDebugEvent(DEBUG_EVENT_ACL_EXCEPTION);
|
HandleDebugEvent(DEBUG_EVENT_ACL_EXCEPTION);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void armcpu_exception(armcpu_t *cpu, u32 number);
|
||||||
void HandleDebugEvent_ACL_Exception()
|
void HandleDebugEvent_ACL_Exception()
|
||||||
{
|
{
|
||||||
printf("ACL EXCEPTION!\n");
|
printf("ACL EXCEPTION!\n");
|
||||||
emu_halt();
|
if(DebugEventData.memAccessType == MMU_AT_CODE)
|
||||||
|
armcpu_exception(DebugEventData.cpu(),EXCEPTION_PREFETCH_ABORT);
|
||||||
|
else if(DebugEventData.memAccessType == MMU_AT_DATA)
|
||||||
|
armcpu_exception(DebugEventData.cpu(),EXCEPTION_DATA_ABORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleDebugEvent_Read()
|
void HandleDebugEvent_Read()
|
||||||
|
|
|
@ -169,12 +169,14 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
extern DebugNotify DEBUG_Notify;
|
extern DebugNotify DEBUG_Notify;
|
||||||
|
struct armcpu_t;
|
||||||
|
|
||||||
//information about a debug event will be stuffed into here by the generator
|
//information about a debug event will be stuffed into here by the generator
|
||||||
struct TDebugEventData
|
struct TDebugEventData
|
||||||
{
|
{
|
||||||
MMU_ACCESS_TYPE memAccessType;
|
MMU_ACCESS_TYPE memAccessType;
|
||||||
u32 procnum, addr, size, val;
|
u32 procnum, addr, size, val;
|
||||||
|
armcpu_t* cpu();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern TDebugEventData DebugEventData;
|
extern TDebugEventData DebugEventData;
|
||||||
|
|
|
@ -69,8 +69,8 @@ static bool OverflowFromSUB(s32 alu_out, s32 left, s32 right)
|
||||||
|
|
||||||
TEMPLATE static u32 FASTCALL OP_UND_THUMB(const u32 i)
|
TEMPLATE static u32 FASTCALL OP_UND_THUMB(const u32 i)
|
||||||
{
|
{
|
||||||
INFO("THUMB%c: Undefined instruction: 0x%08X PC=0x%08X. Stopped!!!\n", cpu->proc_ID?'7':'9', cpu->instruction, cpu->instruct_adr);
|
INFO("THUMB%c: Undefined instruction: 0x%08X PC=0x%08X.\n", cpu->proc_ID?'7':'9', cpu->instruction, cpu->instruct_adr);
|
||||||
emu_halt();
|
TRAPUNDEF(cpu);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue