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