/*---------------------------------------------------------------------------* Project: CtrBrom - libraries - OS File: os_context.c Copyright 2008 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: $ $Rev$ $Author$ *---------------------------------------------------------------------------*/ #include #define osPrintf(...) ((void)0) /*---------------------------------------------------------------------------* Name: osInitContext Description: Initialize context Arguments: context context to be initialized newpc program counter newsp stack pointer Returns: none *---------------------------------------------------------------------------*/ #include asm void osInitContext( OSContext* context, u32 newpc, u32 newsp ) { #define context r12 #define newpc r1 #define newsp r2 stmfd sp!, { r4-r7, lr } mov context, r0 // ---- 実行位置保存 (r12 = context) add newpc, newpc, #4 str newpc, [ context, #OS_CONTEXT_PC_PLUS4 ] // ---- スタック保存 #ifdef SDK_CONTEXT_HAS_SP_SVC str newsp, [ context, #OS_CONTEXT_SP_SVC ] sub newsp, newsp, #HW_BROM_SVC_STACK_SIZE #endif tst newsp, #4 subne newsp, newsp, #4 // for 8byte-alignment str newsp, [ context, #OS_CONTEXT_SP ] // ---- ステータス作成 ands r1, newpc, #1 movne r1, #HW_PSR_SYS_MODE|HW_PSR_THUMB_STATE moveq r1, #HW_PSR_SYS_MODE|HW_PSR_ARM_STATE str r1, [ context, #OS_CONTEXT_CPSR ] // ---- 他のレジスタをクリア mov r0, #0 mov r1, #0 mov r2, #0 mov r3, #0 stmfd sp!, { r0-r3 } ldmia sp, { r4-r7 } add lr, context, #__cpp(offsetof(OSContext,r[0])) stmia lr!, { r0-r7 } // r0-r7 stmia lr!, { r0-r4 } // r8-r12 str r1, [ context, #__cpp(offsetof(OSContext,lr)) ] // lr // ---- VFPレジスタをクリア(VFP例外で初期化) #ifdef SDK_CONTEXT_HAS_VFP add lr, context, #__cpp(offsetof(OSContext,fpexc)) stmia lr!, { r0-r1 } // fpexc, fpscr stmia lr!, { r0-r7 } // f0-f7 stmia lr!, { r0-r7 } // f8-f15 stmia lr!, { r0-r7 } // f16-f23 stmia lr!, { r0-r7 } // f24-f31 #endif ldmfd sp!, { r0-r7, lr } bx lr // start here and swicth arm/thumb mode #undef context #undef newpc #undef newsp } #if defined(SDK_TCM_APPLY) && defined(SDK_ARM9) #include #endif #ifdef SDK_CONTEXT_HAS_VFP /*---------------------------------------------------------------------------* Name: i_osSaveContextVFP Description: Save current context into specified memory Arguments: context pointer to the memory to be stored the current context Returns: None *---------------------------------------------------------------------------*/ asm BOOL i_osSaveContextVFP( OSContext* context ) { add r1, r0, #__cpp(offsetof(OSContext,fpexc)) fmrx r2, fpexc // VFPイネーブルレジスタ保存 stmia r1!, {r2} tst r2, #HW_FPEXC_VFP_ENABLE fmrxne r2, fpscr // VFPコントロールレジスタ保存(VFPイネーブル時) stmiane r1!, {r2} fstmiasne r1!, {f0-f31} // VFPレジスタの保存(VFPイネーブル時) bx lr } #endif // SDK_CONTEXT_HAS_VFP /*---------------------------------------------------------------------------* Name: osSaveContext Description: Save current context into specified memory Arguments: context pointer to the memory to be stored the current context Returns: 0 saving a context (normal) 1 if context are reloaded via osLoadContext *---------------------------------------------------------------------------*/ asm BOOL osSaveContext( OSContext* context ) { #ifdef SDK_CONTEXT_HAS_VFP stmfd sp!, { r0, lr } bl i_osSaveContextVFP ldmfd sp!, { r0, lr } #endif add r1, r0, #OS_CONTEXT_CPSR //---- Save CPSR mrs r2, cpsr str r2, [ r1 ], #OS_CONTEXT_R0-OS_CONTEXT_CPSR // r1 moved to context.r0 #ifdef SDK_CONTEXT_HAS_SP_SVC //---- Save SP_svc mov r0, #HW_PSR_SVC_MODE|HW_PSR_IRQ_DISABLE|HW_PSR_FIQ_DISABLE|HW_PSR_ARM_STATE msr cpsr_c, r0 str sp, [ r1, #OS_CONTEXT_SP_SVC - OS_CONTEXT_R0 ] msr cpsr_c, r2 #endif //---- Save others mov r0, #1 // return value via osLoadContext stmia r1, {r0-r14} // save R0-R14 add r0, pc, #8 // set PC_plus4 to do ("bx lr" + 4) str r0, [r1, #OS_CONTEXT_PC_PLUS4 - OS_CONTEXT_R0 ] mov r0, #0 // regular return value bx lr } #define OFFSETOF(x,y) (int)(&(((x*)0)->y)) #ifdef SDK_CONTEXT_HAS_VFP /*---------------------------------------------------------------------------* Name: i_osLoadContextVFP Description: Reload specified context as current context Arguments: context pointer to the memory to switch to the context Returns: None *---------------------------------------------------------------------------*/ asm void i_osLoadContextVFP( OSContext* context ) { mov r2, #HW_FPEXC_VFP_ENABLE fmxr fpexc, r2 // VFPを一時的に強制イネーブル ldr r2, [r0,#__cpp(offsetof(OSContext,fpscr))] // VFPコントロールレジスタ復帰 fmxr fpscr, r2 add r1, r0, #__cpp(offsetof(OSContext,fpexc)) // VFPイネーブルレジスタ復帰 ldmia r1!, {r2} fmxr fpexc, r2 tst r2, #HW_FPEXC_VFP_ENABLE fldmiasne r1!, {f0-f31} bx lr } #endif // SDK_CONTEXT_HAS_VFP /*---------------------------------------------------------------------------* Name: osLoadContext Description: Reload specified context as current context Arguments: context pointer to the memory to switch to the context Returns: None *---------------------------------------------------------------------------*/ asm void osLoadContext( OSContext* context ) { #ifdef SDK_CONTEXT_HAS_VFP stmfd sp!, { r0, lr } bl i_osLoadContextVFP ldmfd sp!, { r0, lr } #endif //---- モードを svc に mrs r1, cpsr bic r1, r1, #HW_PSR_CPU_MODE_MASK orr r1, r1, #HW_PSR_SVC_MODE|HW_PSR_IRQ_DISABLE|HW_PSR_FIQ_DISABLE msr cpsr_c, r1 //---- Load cpcr to spsr ldr r1, [ r0 ], #OS_CONTEXT_R0-OS_CONTEXT_CPSR msr spsr_fsxc, r1 #ifdef SDK_CONTEXT_HAS_SP_SVC //---- Load SP_svc ldr sp, [ r0, #OS_CONTEXT_SP_SVC - OS_CONTEXT_R0 ] #endif //---- Load r0-r14 ldr lr, [ r0, #OS_CONTEXT_PC_PLUS4 - OS_CONTEXT_R0 ] ldmia r0, { r0 - r14 }^ nop //---- Switch cpsr and Jump to (context->pc_plus4 - 4) subs pc, lr, #4 } #if defined(SDK_TCM_APPLY) && defined(SDK_ARM9) #include #endif #include /*---------------------------------------------------------------------------* Name: osDumpContext Description: Performs exception initialization. - installs the first level exception handlers - set up exception table and common exception handler Arguments: installDBIntegrator if TRUE, copy OSDBIntegrator into low memory. Returns: None. *---------------------------------------------------------------------------*/ void osDumpContext(OSContext *context) { #ifndef SDK_FINALROM s32 i; osPrintf("context=%08x\n", context); if (context) { osPrintf("CPSR %08x\n", context->cpsr); for (i = 0; i < 13; i++) { osPrintf("R%02d %08x\n", i, context->r[i]); } osPrintf("SP %08x\n", context->sp); osPrintf("LR %08x\n", context->lr); osPrintf("PC+4 %08x\n", context->pc_plus4); #ifdef SDK_CONTEXT_HAS_SP_SVC osPrintf("SPsvc %08x\n", context->sp_svc); #endif } #else (void)context; // avoiding to unused warning #endif }