1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - OS
3   File:     os_context.c
4 
5   Copyright 2003-2008 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2009-02-24#$
14   $Rev: 10073 $
15   $Author: yada $
16  *---------------------------------------------------------------------------*/
17 #include <nitro/os.h>
18 #include <nitro/memorymap.h>
19 
20 #ifdef SDK_ARM9
21 #include <nitro/cp/context.h>
22 #endif
23 
24 /*---------------------------------------------------------------------------*
25   Name:         OS_InitContext
26 
27   Description:  Initializes context.
28 
29   Arguments:    context:     Context to be initialized
30                 newpc:       Program counter
31                 newsp:       Stack pointer
32 
33   Returns:      None.
34  *---------------------------------------------------------------------------*/
35 #include    <nitro/code32.h>
OS_InitContext(register OSContext * context,register u32 newpc,register u32 newsp)36 asm void OS_InitContext(
37     register OSContext* context,
38     register u32         newpc,
39     register u32         newsp
40     )
41 {
42     // ---- Save the execution position (r0 = context)
43     add   newpc, newpc, #4
44     str   newpc, [ context, #OS_CONTEXT_PC_PLUS4 ]
45 
46     // ---- Save the stack
47 #ifdef  SDK_CONTEXT_HAS_SP_SVC
48     str   newsp, [ context, #OS_CONTEXT_SP_SVC ]
49     sub   newsp, newsp,     #HW_SVC_STACK_SIZE
50 #endif
51     tst   newsp, #4
52     subne newsp, newsp, #4 // For 8-byte alignment
53     str   newsp, [ context, #OS_CONTEXT_SP ]
54 
55     // ---- Make status
56     ands  r1, newpc, #1
57     movne r1, #HW_PSR_SYS_MODE|HW_PSR_THUMB_STATE
58     moveq r1, #HW_PSR_SYS_MODE|HW_PSR_ARM_STATE
59     str   r1, [ context, #OS_CONTEXT_CPSR ]
60 
61     // ---- Clear other registers
62     mov   r1, #0
63     str   r1, [ context, #OS_CONTEXT_R0 ]
64     str   r1, [ context, #OS_CONTEXT_R1 ]
65     str   r1, [ context, #OS_CONTEXT_R2 ]
66     str   r1, [ context, #OS_CONTEXT_R3 ]
67     str   r1, [ context, #OS_CONTEXT_R4 ]
68     str   r1, [ context, #OS_CONTEXT_R5 ]
69     str   r1, [ context, #OS_CONTEXT_R6 ]
70     str   r1, [ context, #OS_CONTEXT_R7 ]
71     str   r1, [ context, #OS_CONTEXT_R8 ]
72     str   r1, [ context, #OS_CONTEXT_R9 ]
73     str   r1, [ context, #OS_CONTEXT_R10 ]
74     str   r1, [ context, #OS_CONTEXT_R11 ]
75     str   r1, [ context, #OS_CONTEXT_R12 ]
76     str   r1, [ context, #OS_CONTEXT_LR  ]
77 
78     bx    lr    // Start here and switch arm/thumb mode
79 }
80 
81 #if defined(SDK_TCM_APPLY) && defined(SDK_ARM9)
82 #include    <nitro/itcm_begin.h>
83 #endif
84 /*---------------------------------------------------------------------------*
85   Name:         OS_SaveContext
86 
87   Description:  Saves current context into specified memory.
88 
89   Arguments:    context:   Pointer to the memory to be stored the current context
90 
91   Returns:      0:    Saving a context (normal)
92                 1:    If context are reloaded via OS_LoadContext
93  *---------------------------------------------------------------------------*/
OS_SaveContext(register OSContext * context)94 asm BOOL OS_SaveContext( register OSContext* context )
95 {
96 #if defined(SDK_ARM9)
97     stmfd   sp!, { lr, r0 }
98     add     r0, r0, #OS_CONTEXT_CP_CONTEXT
99     ldr     r1, =CP_SaveContext
100     blx     r1
101     ldmfd   sp!, { lr, r0 }
102 #endif
103 
104     add     r1, r0, #OS_CONTEXT_CPSR
105 
106     //---- Save CPSR
107     mrs     r2, cpsr
108     str     r2, [ r1 ], #OS_CONTEXT_R0-OS_CONTEXT_CPSR  // r1 moved to context.r0
109 
110 #ifdef  SDK_CONTEXT_HAS_SP_SVC
111     //---- Save SP_svc
112     mov     r0, #HW_PSR_SVC_MODE|HW_PSR_IRQ_DISABLE|HW_PSR_FIQ_DISABLE|HW_PSR_ARM_STATE
113     msr     cpsr_c, r0
114     str     sp, [ r1, #OS_CONTEXT_SP_SVC - OS_CONTEXT_R0 ]
115     msr     cpsr_c, r2
116 #endif
117 
118     //---- Save others
119     mov     r0, #1              // Return value via OS_LoadContext
120     stmia   r1, {r0-r14}        // Save R0-R14
121     add     r0, pc, #8          // Set  PC_plus4 to do ("bx lr" + 4)
122     str     r0, [r1, #OS_CONTEXT_PC_PLUS4 - OS_CONTEXT_R0 ]
123 
124     mov     r0, #0              // Regular return value
125     bx      lr
126 }
127 
128 
129 #define OFFSETOF(x,y) (int)(&(((x*)0)->y))
130 
131 /*---------------------------------------------------------------------------*
132   Name:         OS_LoadContext
133 
134   Description:  Reloads specified context as current context.
135 
136   Arguments:    context:   Pointer to the memory to switch to the context
137 
138   Returns:      None.
139  *---------------------------------------------------------------------------*/
OS_LoadContext(register OSContext * context)140 asm void OS_LoadContext( register OSContext* context )
141 {
142 #if OS_CONTEXT_CPSR != 0
143 #pragma message(has changed!!!)
144     add   r0, r0, #OS_CONTEXT_CPSR
145 #endif
146 
147 #if defined(SDK_ARM9)
148     // Call CPi_RestoreContext
149     stmfd     sp!, { lr, r0 }
150     add       r0, r0, #OS_CONTEXT_CP_CONTEXT
151 
152     ldr       r1, =CPi_RestoreContext
153     blx       r1
154     ldmfd     sp!, { lr, r0 }
155 #endif
156 
157     //---- Mode -> svc
158     mrs       r1, cpsr
159     bic       r1, r1, #HW_PSR_CPU_MODE_MASK
160     orr       r1, r1, #HW_PSR_SVC_MODE|HW_PSR_IRQ_DISABLE|HW_PSR_FIQ_DISABLE
161     msr       cpsr_c, r1
162 
163     //---- Load cpcr to spsr
164     ldr       r1, [ r0 ], #OS_CONTEXT_R0-OS_CONTEXT_CPSR
165     msr       spsr_fsxc, r1
166 
167 #ifdef  SDK_CONTEXT_HAS_SP_SVC
168     //---- Load SP_svc
169     ldr       sp, [ r0, #OS_CONTEXT_SP_SVC   - OS_CONTEXT_R0 ]
170 #endif
171 
172     //---- Load r0-r14
173     ldr       lr, [ r0, #OS_CONTEXT_PC_PLUS4 - OS_CONTEXT_R0 ]
174     ldmia     r0, { r0 - r14 }^
175     nop
176 
177     //---- CP_WaitDiv
178     // On NITRO mode, no need to wait divider, because still spend more than 34 cycle.
179 #if defined(SDK_ARM9) && defined(SDK_TWL)
180 #ifndef SDK_TWLLTD
181     stmfd     sp!, {r0-r3,r12,r14}
182 #else
183     stmfd     sp!, {r0-r1}
184 #endif
185 
186 #ifndef SDK_TWLLTD
187     bl        OS_IsRunOnTwl
188     beq       @01
189 #endif
190 
191     ldr       r0, =REG_DIVCNT_ADDR
192 @00:
193     ldr       r1, [r0]
194     ands      r1, r1, #REG_CP_DIVCNT_BUSY_MASK
195     bne       @00
196 
197 #ifndef SDK_TWLLTD
198 @01:
199     ldmfd  sp!, {r0-r3,r12,r14}
200 #else
201     ldmfd  sp!, {r0-r1}
202 #endif
203 #endif //if defined(SDK_ARM9) && defined(SDK_TWL)
204 
205     //---- Switch cpsr and Jump to (context->pc_plus4 - 4)
206     subs      pc, lr, #4
207 }
208 #if defined(SDK_TCM_APPLY) && defined(SDK_ARM9)
209 #include    <nitro/itcm_end.h>
210 #endif
211 
212 #include    <nitro/codereset.h>
213 
214 
215 /*---------------------------------------------------------------------------*
216   Name:         OS_DumpContext
217 
218   Description:  Performs exception initialization.
219                 - Installs the first level exception handlers
220                 - Sets up exception table and common exception handler
221 
222   Arguments:    installDBIntegrator if TRUE, copy OSDBIntegrator into
223                                     low memory.
224 
225   Returns:      None.
226  *---------------------------------------------------------------------------*/
OS_DumpContext(OSContext * context)227 void OS_DumpContext(OSContext *context)
228 {
229 #ifndef SDK_FINALROM
230     s32     i;
231 
232     OS_Printf("context=%08x\n", context);
233     if (context)
234     {
235         OS_Printf("CPSR  %08x\n", context->cpsr);
236         for (i = 0; i < 13; i++)
237         {
238             OS_Printf("R%02d   %08x\n", i, context->r[i]);
239         }
240         OS_Printf("SP    %08x\n", context->sp);
241         OS_Printf("LR    %08x\n", context->lr);
242         OS_Printf("PC+4  %08x\n", context->pc_plus4);
243 #ifdef  SDK_CONTEXT_HAS_SP_SVC
244         OS_Printf("SPsvc %08x\n", context->sp_svc);
245 #endif
246     }
247 #else
248     (void)context;                     // Avoiding to unused warning
249 #endif
250 }
251