mirror of
https://github.com/rvtr/ctr_firmware.git
synced 2025-10-31 07:51:08 -04:00
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_firmware@158 b871894f-2f95-9b40-918c-086798483c85
273 lines
8.6 KiB
C
273 lines
8.6 KiB
C
/*---------------------------------------------------------------------------*
|
||
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 <brom/os.h>
|
||
|
||
#define osPrintf(...) ((void)0)
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osInitContext
|
||
|
||
Description: Initialize context
|
||
|
||
Arguments: context context to be initialized
|
||
newpc program counter
|
||
newsp stack pointer
|
||
|
||
Returns: none
|
||
*---------------------------------------------------------------------------*/
|
||
#include <brom/code32.h>
|
||
asm void osInitContext(
|
||
register OSContext* context,
|
||
register u32 newpc,
|
||
register u32 newsp
|
||
)
|
||
{
|
||
#define context r0
|
||
#define newpc r1
|
||
#define newsp r2
|
||
|
||
// ---- 実行位置保存 (r0 = 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 r1, #0
|
||
str r1, [ context, #OS_CONTEXT_R0 ]
|
||
str r1, [ context, #OS_CONTEXT_R1 ]
|
||
str r1, [ context, #OS_CONTEXT_R2 ]
|
||
str r1, [ context, #OS_CONTEXT_R3 ]
|
||
str r1, [ context, #OS_CONTEXT_R4 ]
|
||
str r1, [ context, #OS_CONTEXT_R5 ]
|
||
str r1, [ context, #OS_CONTEXT_R6 ]
|
||
str r1, [ context, #OS_CONTEXT_R7 ]
|
||
str r1, [ context, #OS_CONTEXT_R8 ]
|
||
str r1, [ context, #OS_CONTEXT_R9 ]
|
||
str r1, [ context, #OS_CONTEXT_R10 ]
|
||
str r1, [ context, #OS_CONTEXT_R11 ]
|
||
str r1, [ context, #OS_CONTEXT_R12 ]
|
||
str r1, [ context, #OS_CONTEXT_LR ]
|
||
|
||
// ---- VFPレジスタを初期化
|
||
#ifdef SDK_CONTEXT_HAS_VFP
|
||
str r1, [ context, #__cpp(offsetof(OSContext,fpexc)) ]
|
||
#endif
|
||
|
||
bx lr // start here and swicth arm/thumb mode
|
||
|
||
#undef context
|
||
#undef newpc
|
||
#undef newsp
|
||
}
|
||
|
||
#if defined(SDK_TCM_APPLY) && defined(SDK_ARM9)
|
||
#include <brom/itcm_begin.h>
|
||
#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 <brom/itcm_end.h>
|
||
#endif
|
||
|
||
#include <brom/codereset.h>
|
||
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
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
|
||
}
|