1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - libraries - init - ARM9.TWL
3 File: crt0.FLX.c
4
5 Copyright 2007-2009 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:: 2010-02-04#$
14 $Rev: 11289 $
15 $Author: yada $
16 *---------------------------------------------------------------------------*/
17
18 #include <nitro/types.h>
19 #include <nitro/hw/common/armArch.h>
20 #include <nitro/mi/uncompress.h>
21 #include <nitro/os/common/systemWork.h>
22 #include <twl/init/crt0.h>
23 #include <twl/memorymap.h>
24 #include <twl/misc.h>
25 #include <twl/version.h>
26 #include "boot_sync.h"
27
28 /*---------------------------------------------------------------------------*/
29 void _start(void);
30 void _start_AutoloadDoneCallback(void* argv[]);
31
32 #define SDK_NITROCODE_LE 0x2106c0de
33 #define SDK_NITROCODE_BE 0xdec00621
34
35 #define SDK_TWLCODE_LE 0x6314c0de
36 #define SDK_TWLCODE_BE 0xdec01463
37
38 #define SDK_BUILDCODE_LE 0x3381c0de
39 #define SDK_BUILDCODE_BE 0xdec08133
40
41
42 /* For embedding build type */
43 #if defined(SDK_DEBUG)
44 #define SDK_BUILDCODE 2
45 #elif defined(SDK_RELEASE)
46 #define SDK_BUILDCODE 1
47 #elif defined(SDK_FINALROM)
48 #define SDK_BUILDCODE 0
49 #else
50 #define SDK_BUILDCODE 255 // Error
51 #endif
52
53 #if defined(SDK_ARM9)
54 #define SDK_TARGET 9
55 #elif defined(SDK_ARM7)
56 #define SDK_TARGET 7
57 #else
58 #define SDK_TARGET 255 // Error
59 #endif
60
61 /* External function reference definitions */
62 extern void OS_IrqHandler(void);
63 extern void _fp_init(void);
64 extern void __call_static_initializers(void);
65 extern void OS_ShowAttentionOfLimitedRom(void);
66
67 /* Internal Function Prototype Definitions */
68 static void INITi_CpuClear32(register u32 data, register void* destp, register u32 size);
69 static void INITi_InitCoprocessor(void);
70 static void INITi_InitRegion(void);
71 static BOOL INITi_IsRunOnTwl( void );
72 static void INITi_DoAutoload(void);
73 #ifndef SDK_NOINIT
74 static void INITi_ShelterStaticInitializer(u32* ptr);
75 static void INITi_CallStaticInitializers(void);
76 #endif
77 static void* INITi_Copy32(void* dst, void* src, u32 size);
78 static void* INITi_Fill32(void* dst, u32 value, u32 size);
79
80 /* Symbol reference defined by linker script */
81 extern void SDK_AUTOLOAD_LIST(void);
82 extern void SDK_AUTOLOAD_LIST_END(void);
83 extern void SDK_AUTOLOAD_START(void);
84 extern void SDK_STATIC_BSS_START(void);
85 extern void SDK_STATIC_BSS_END(void);
86
87
88 void* const _start_ModuleParams[] =
89 {
90 (void*)SDK_AUTOLOAD_LIST,
91 (void*)SDK_AUTOLOAD_LIST_END,
92 (void*)SDK_AUTOLOAD_START,
93 (void*)SDK_STATIC_BSS_START,
94 (void*)SDK_STATIC_BSS_END,
95 (void*)0, // CompressedStaticEnd. This fixed number will be updated by the compstatic tool
96 (void*)SDK_CURRENT_VERSION_NUMBER,
97 (void*)SDK_NITROCODE_BE,
98 (void*)SDK_NITROCODE_LE,
99 };
100
101 /* Allocate 32 bytes for storage of build information */
102 #pragma force_active on
103 void* const _start_BuildParams[] =
104 {
105 (void*)0, // Reserved
106 (void*)0, // Reserved
107 (void*)0, // Reserved
108 (void*)0, // Reserved
109 (void*)(SDK_BUILDCODE | (SDK_TARGET << 8)), // Build target and build type
110 (void*)1, // Version (1byte) Reserved (3byte)
111 (void*)SDK_BUILDCODE_BE,
112 (void*)SDK_BUILDCODE_LE,
113 };
114
115 extern void SDK_LTDAUTOLOAD_LIST(void);
116 extern void SDK_LTDAUTOLOAD_LIST_END(void);
117 extern void SDK_LTDAUTOLOAD_START(void);
118
119 void* const _start_LtdModuleParams[] =
120 {
121 (void*)SDK_LTDAUTOLOAD_LIST,
122 (void*)SDK_LTDAUTOLOAD_LIST_END,
123 (void*)SDK_LTDAUTOLOAD_START,
124 (void*)0, // CompressedLtdautoloadEnd. This fixed number will be updated by the compstatic tool
125 (void*)SDK_TWLCODE_BE,
126 (void*)SDK_TWLCODE_LE,
127 };
128
129
130
131 /*---------------------------------------------------------------------------*
132 Name: ShakeHand
133 Description: Synchronizes with the ARM7 ShakeHand function.
134 Must be run in memory space that is not the main memory.
135 Arguments: r0: Pointer to a variable used to synchronize with the ARM9
136 r1: Pointer to a variable used to synchronize with the ARM7
137 Returns: None.
138 *---------------------------------------------------------------------------*/
139 static const u32 microcode_ShakeHand[10] =
140 {
141 0xe1d120b0, /* ldrh r2, [r1] ; Read synchronous variable 7 from shared memory */
142 0xe1d030b0, /* ldrh r3, [r0] ; Read synchronous variable 9 from shared memory */
143 0xe2833001, /* @1: add r3, r3, #1 ; Synchronous variable 9++ */
144 0xe1c030b0, /* strh r3, [r0] ; Write synchronous variable 9 to shared memory */
145 0xe1d1c0b0, /* ldrh r12, [r1] ; Read the current state of synchronous variable 7 from shared memory */
146 0xe152000c, /* cmp r2, r12 ; Determine change of synchronous variable 7 */
147 0x0afffffa, /* beq @1 ; If not changed, loop */
148 0xe2833001, /* add r3, r3, #1 ; Synchronous variable 9++ */
149 0xe1c030b0, /* strh r3, [r0] ; Write synchronous variable 9 to shared memory */
150 0xe12fff1e /* bx lr ; Complete handshake */
151 };
152
153 /*---------------------------------------------------------------------------*
154 Name: WaitAgreement
155 Description: Waits until the ARM7 startup vector is in a specific state.
156 Must be run in memory space that is not the main memory.
157 Arguments: r0: Pointer to phase management variable for synchronization
158 r1: Idling phase number
159 Returns: None.
160 *---------------------------------------------------------------------------*/
161 static const u32 microcode_WaitAgreement[7] =
162 {
163 0xe1d020b0, /* @1: ldrh r2, [r0] ; Read the phase management variable from shared memory */
164 0xe1510002, /* cmp r1, r2 ; Compare with idling phase number */
165 0x012fff1e, /* bxeq lr ; If matched, complete idling */
166 0xe3a03010, /* mov r3, #16 ; Initialize empty loop count */
167 0xe2533001, /* @2: subs r3, r3, #1 ; Empty loop count -- */
168 0x1afffffd, /* bne @2 ; 16 loops */
169 0xeafffff8 /* b @1 ; Return to top */
170 };
171
172 /*---------------------------------------------------------------------------*
173 Name: SwitchCpuClock
174 Description: Changes ARM CPU core operating clock.
175 Must be run in I-TCM.
176 Arguments: r0: Speed mode to switch
177 ( 0: Constant speed/ other than 0: Double speed)
178 r1: Cycle count to idle after changing the clock.
179 Returns: r0: Returns the speed mode prior to the change.
180 ( 0: Constant speed/1: Double speed)
181 *---------------------------------------------------------------------------*/
182 static const u32 microcode_SwitchCpuClock[13] =
183 {
184 0xe3500000, /* cmp r0, #0 ; Evaluate first argument */
185 0xe59f3024, /* ldr r3, [pc, #36] ; Read the REG_CLK_ADDR constant */
186 0xe1d300b0, /* ldrh r0, [r3] ; Read the REG_CLK_ADDR content */
187 0x03c02001, /* biceq r2, r0, #1 ; Lower the REG_SCFG_CLK_CPUSPD_MASK flag when changing to constant speed */
188 0x13802001, /* orrne r2, r0, #1 ; Raise the REG_SCFG_CLK_CPUSPD_MASK flag when changing to double speed */
189 0xe1500002, /* cmp r0, r2 ; Evaluate the need to change the content of REG_CLK_ADDR */
190 0xe2000001, /* and r0, r0, #1 ; Edit the function return value */
191 0x012fff1e, /* bxeq lr ; Quit function if change is not necessary */
192 0xe1c320b0, /* strh r2, [r3] ; Write the changed contents to REG_CLK_ADDR */
193 0xe2511004, /* @1: subs r1, r1, #4 ; 1 cycle ; Empty loop count -- */
194 0xaafffffd, /* bge @1 ; 3 cycles or 1 cycle ; (Idle cycle count/4) numbers of loops; Complete clock change */
195 0xe12fff1e, /* bx lr ; Check instruction from branch destination at second cycle */
196 0x04004004 /* REG_CLK_ADDR ; REG_CLK_ADDR constant definition */
197 };
198
199 /*---------------------------------------------------------------------------*/
200 #include <twl/code32.h>
201
202 /*---------------------------------------------------------------------------*
203 Name: _start
204 Description: Startup vector.
205 Arguments: None.
206 Returns: None.
207 *---------------------------------------------------------------------------*/
208 #define SET_PROTECTION_A(id, adr, siz) ldr r0, =(adr|HW_C6_PR_##siz|HW_C6_PR_ENABLE)
209 #define SET_PROTECTION_B(id, adr, siz) mcr p15, 0, r0, c6, id, 0
210
211
212 SDK_WEAK_SYMBOL asm void
_start(void)213 _start(void)
214 {
215 @000:
216 /* Interrupts disabled */
217 mov r12, #HW_REG_BASE
218 str r12, [r12, #REG_IME_OFFSET] // Use that LSB of HW_REG_BASE is 0b0
219
220 /* Initialize system control coprocessor */
221 bl INITi_InitCoprocessor
222
223 // Processes to cover the initial state of IPL
224
225 // (1) Clear the shared region to zero (avoid because HW_CTRDG_LOCK_BUF is also using IS-NITRO-DEBUGGER)
226 mov r0, #0
227 ldr r1, =HW_PXI_SIGNAL_PARAM_ARM9
228 ldr r2, =(HW_CTRDG_LOCK_BUF-HW_PXI_SIGNAL_PARAM_ARM9)
229 bl INITi_CpuClear32
230 mov r0, #0
231 ldr r1, =HW_INIT_LOCK_BUF
232 ldr r2, =(HW_MAIN_MEM_SYSTEM_END-HW_INIT_LOCK_BUF)
233 bl INITi_CpuClear32
234
235 // (1.5) Clear reserved area in parameter region
236 mov r0, #0
237 ldr r1, =(HW_MAIN_MEM_PARAMETER_BUF_END-HW_PARAM_TWL_RESERVED_AREA_SIZE)
238 ldr r2, =HW_PARAM_TWL_RESERVED_AREA_SIZE
239 bl INITi_CpuClear32
240
241 // (2) Correction of boot type (if illegal, consider it to be an unsupported firmware and go to ROM)
242 ldr r1, =HW_WM_BOOT_BUF
243 ldrh r2, [r1, #OSBootInfo.boot_type]
244 cmp r2, #OS_BOOTTYPE_ILLEGAL
245 moveq r2, #OS_BOOTTYPE_ROM
246 streqh r2, [r1, #OSBootInfo.boot_type]
247
248 /* Copy the micro-code for the handshake to ITCM */
249 ldr r1, =microcode_ShakeHand
250 ldr r2, =HW_ITCM
251 add r3, r2, #40
252 @001: ldr r0, [r1], #4
253 str r0, [r2], #4
254 cmp r2, r3
255 blt @001
256
257 /* Handshake with ARM7 with the code on ITCM */
258 ldr r0, =HW_BOOT_SYNC_PHASE
259 mov r1, #BOOT_SYNC_PHASE_1
260 strh r1, [r0]
261 ldr r0, =HW_BOOT_SHAKEHAND_9
262 ldr r1, =HW_BOOT_SHAKEHAND_7
263 ldr r2, =HW_ITCM
264 blx r2
265
266 #ifdef SDK_TWLLTD
267 /* For LTD on NTR, do not synchronize with the ARM7 (it will not respond) */
268 bl INITi_IsRunOnTwl
269 bne @020
270 #endif
271
272 /* Overwrite and copy the micro-code for synchronization with ARM7 to ITCM */
273 ldr r1, =microcode_WaitAgreement
274 ldr r2, =HW_ITCM
275 add r3, r2, #28
276 @002: ldr r0, [r1], #4
277 str r0, [r2], #4
278 cmp r2, r3
279 blt @002
280
281 @003:
282 /* Synchronize with ARM7 */
283 ldr r0, =HW_BOOT_SYNC_PHASE
284 mov r1, #BOOT_SYNC_PHASE_4
285 ldr r2, =HW_ITCM
286 blx r2
287
288 @010:
289 /* Check whether running on TWL hardware */
290 bl INITi_IsRunOnTwl
291 bne @020
292
293 /* Copy the micro-code for changing to double speed to ITCM */
294 ldr r1, =microcode_SwitchCpuClock
295 ldr r2, =HW_ITCM
296 add r2, r2, #28
297 mov r3, #52
298 @011: subs r3, r3, #4
299 ldr r0, [r1, r3]
300 str r0, [r2, r3]
301 bgt @011
302 /* Change to double-speed mode for the CPU clock */
303 mov r0, #REG_SCFG_CLK_CPUSPD_MASK
304 mov r1, #8
305 blx r2
306
307 /* [TODO] Run the default settings of the added I/O registers that can only be set on ARM9 */
308
309 @020:
310 /* Region default settings */
311 bl INITi_InitRegion
312
313 /* Stack pointer settings */
314 mov r0, #HW_PSR_SVC_MODE // SuperVisor mode
315 msr cpsr_c, r0
316 ldr r1, =SDK_AUTOLOAD_DTCM_START
317 add r1, r1, #HW_DTCM_SIZE
318 sub sp, r1, #HW_DTCM_SYSRV_SIZE
319 sub r1, sp, #HW_SVC_STACK_SIZE
320 mov r0, #HW_PSR_IRQ_MODE // IRQ mode
321 msr cpsr_c, r0
322 sub sp, r1, #4 // 4 bytes for stack check code
323 tst sp, #4
324 subeq sp, sp, #4 /* Adjust so that sp is 8-byte aligned at the time of the jump to the IRQ handler */
325 ldr r0, =SDK_IRQ_STACKSIZE
326 sub r1, r1, r0
327 mov r0, #HW_PSR_SYS_MODE // System mode
328 msr cpsr_csfx, r0
329 sub sp, r1, #4 // 4 bytes for stack check code
330 tst sp, #4
331 subne sp, sp, #4 /* Adjust so that sp is 8-byte aligned at the time of the jump to the Main function */
332
333 /* Clear the stack region */
334 mov r0, #0
335 ldr r1, =SDK_AUTOLOAD_DTCM_START
336 mov r2, #HW_DTCM_SIZE
337 bl INITi_CpuClear32
338
339 /* Clear the VRAM to 0 */
340 mov r1, #0 // r1 = clear value for VRAM
341 ldr r0, =HW_PLTT // r0 = start address of VRAM for pallet
342 mov r2, #HW_PLTT_SIZE // r2 = size of VRAM for pallet
343 bl INITi_Fill32
344 ldr r0, =HW_OAM // r0 = start address of VRAM for OAM
345 mov r2, #HW_OAM_SIZE // r2 = size of VRAM for OAM
346 bl INITi_Fill32
347
348 /* Implement Autoload */
349 bl INITi_DoAutoload
350
351 /* Clear the .bss section of the STATIC block to 0 */
352 mov r1, #0 // r1 = clear value for STATIC bss section
353 ldr r3, =_start_ModuleParams
354 ldr r0, [r3, #12] // r0 = start address of STATIC bss section
355 ldr r2, [r3, #16]
356 subs r2, r2, r0 // r2 = size of STATIC bss section
357 blgt INITi_Fill32
358
359 /* Configure interrupt vector */
360 ldr r1, =SDK_AUTOLOAD_DTCM_START
361 add r1, r1, #HW_DTCM_SIZE - HW_DTCM_SYSRV_SIZE
362 add r1, r1, #HW_DTCM_SYSRV_OFS_INTR_VECTOR
363 ldr r0, =OS_IrqHandler
364 str r0, [r1]
365
366 #ifdef SDK_TWLLTD
367 /* Warning screen for LTD on NTR */
368 bl INITi_IsRunOnTwl
369 blne OS_ShowAttentionOfLimitedRom
370 // (Does not return from the function above.)
371 #endif
372
373 #ifndef SDK_NOINIT
374 /* Initialize for C++ */
375 bl _fp_init
376 bl TwlStartUp
377 bl __call_static_initializers
378 bl INITi_CallStaticInitializers
379 #endif
380
381 /* V-Count adjustment */
382 ldr r1, =REG_VCOUNT_ADDR
383 @022: ldrh r0, [r1]
384 cmp r0, #0
385 bne @022
386
387 @030:
388 /* Jump to Main function */
389 ldr r1, =TwlMain
390 ldr lr, =HW_RESET_VECTOR
391 bx r1
392 }
393
394 /*---------------------------------------------------------------------------*
395 Name: INITi_CpuClear32
396 Description: Clears buffer in 32-bit units.
397 Arguments: r0: Value to clear
398 r1: Pointer to the clear destination
399 r2: Buffer length to continuously clear
400 Returns: None.
401 *---------------------------------------------------------------------------*/
402 static asm void
INITi_CpuClear32(register u32 data,register void * destp,register u32 size)403 INITi_CpuClear32(register u32 data, register void* destp, register u32 size)
404 {
405 add r12, r1, r2
406 @001: cmp r1, r12
407 strlt r0, [r1], #4
408 blt @001
409 bx lr
410 }
411
412 /*---------------------------------------------------------------------------*
413 Name: INITi_InitCoprocessor
414 Description: Initializes the system control co-processor.
415 At the same time, enable the use of I-TCM and D-TCM.
416 Arguments: None.
417 Returns: None.
418 *---------------------------------------------------------------------------*/
419 static asm void
INITi_InitCoprocessor(void)420 INITi_InitCoprocessor(void)
421 {
422 /* Get the co-processor state */
423 mrc p15, 0, r0, c1, c0, 0
424
425 tst r0, #HW_C1_PROTECT_UNIT_ENABLE
426 beq @010
427 tst r0, #HW_C1_DCACHE_ENABLE
428 beq @003
429
430 /* Write back the D-Cache content to memory */
431 mov r1, #0
432 @001: mov r2, #0
433 @002: orr r3, r1, r2
434 mcr p15, 0, r3, c7, c10, 2
435 add r2, r2, #HW_CACHE_LINE_SIZE
436 cmp r2, #HW_DCACHE_SIZE / 4
437 blt @002
438 adds r1, r1, #1 << HW_C7_CACHE_SET_NO_SHIFT
439 bne @001
440
441 @003: /* Wait until the write buffer is empty */
442 mov r1, #0
443 mcr p15, 0, r1, c7, c10, 4
444
445 @010: /* Initialize the co-processor state */
446 ldr r1, = HW_C1_ITCM_LOAD_MODE \
447 | HW_C1_DTCM_LOAD_MODE \
448 | HW_C1_ITCM_ENABLE \
449 | HW_C1_DTCM_ENABLE \
450 | HW_C1_LD_INTERWORK_DISABLE \
451 | HW_C1_ICACHE_ENABLE \
452 | HW_C1_DCACHE_ENABLE \
453 | HW_C1_PROTECT_UNIT_ENABLE
454 bic r0, r0, r1
455 ldr r1, = HW_C1_SB1_BITSET \
456 | HW_C1_EXCEPT_VEC_UPPER
457 orr r0, r0, r1
458 mcr p15, 0, r0, c1, c0, 0
459
460 /* Set the I-TCM size */
461 mov r1, #HW_C9_TCMR_32MB
462 mcr p15, 0, r1, c9, c1, 1
463 /* Set the D-TCM size and region base address */
464 ldr r1, =SDK_AUTOLOAD_DTCM_START
465 orr r1, r1, #HW_C9_TCMR_16KB
466 mcr p15, 0, r1, c9, c1, 0
467
468 /* Set to allow use of I-TCM and D-TCM */
469 mov r1, #HW_C1_ITCM_ENABLE | HW_C1_DTCM_ENABLE
470 orr r0, r0, r1
471 mcr p15, 0, r0, c1, c0, 0
472
473 bx lr
474 }
475
476 /*---------------------------------------------------------------------------*
477 Name: INITi_InitRegion
478 Description: Initializes the region settings.
479 Arguments: None.
480 Returns: None.
481 *---------------------------------------------------------------------------*/
482 /* When hardware is TWL
483 ; Region G: BACK_GROUND: Base = 0x0, Size = 4GB, I:NC NB / D:NC NB, I:NA / D:NA
484 ; Region 0: IO_VRAM: Base = 0x04000000, Size = 64MB, I:NC NB / D:NC NB, I:RW / D:RW
485 ; Region 1: MAINMEM_WRAM: Base = 0x02000000, Size = 32MB, I:Cach Buf / D:Cach Buf, I:RW / D:RW
486 ; Region 2: ARM7_RESERVE: Base = 0x02f80000, Size = 512KB, I:NC NB / D:NC NB, I:NA / D:NA
487 ; Region 3: EX_MAINMEM: Base = 0x0d000000, Size = 16MB, I:Cach Buf / D:Cach Buf, I:RW / D:RW
488 ; Region 4: DTCM: Base = 0x02fe0000, Size = 16KB, I:NC NB / D:NC NB, I:NA / D:RW
489 ; Region 5: ITCM: Base = 0x01000000, Size = 16MB, I:NC NB / D:NC NB, I:RW / D:RW
490 ; Region 6: BIOS: Base = 0xffff0000, Size = 32KB, I:Cach NB / D:Cach NB, I:RO / D:RO
491 ; Region 7: SHARED_WORK: Base = 0x02ffc000, Size = 16KB, I:NC NB / D:NC NB, I:NA / D:RW
492 */
493 /* When hardware is NITRO
494 ; Region G: BACK_GROUND: Base = 0x0, Size = 4GB, I:NC NB / D:NC NB, I:NA / D:NA
495 ; Region 0: IO_VRAM: Base = 0x04000000, Size = 64MB, I:NC NB / D:NC NB, I:RW / D:RW
496 ; Region 1: MAIN_MEM: Base = 0x02000000, Size = 8MB*, I:Cach Buf / D:Cach Buf, I:RW / D:RW
497 ; (* When hardware is not debugger, size will be reduced to 4MB in OS_InitArena() )
498 ;// Region 2: ARM7_RESERVE: Base = 0x027e0000, Size = 128KB, I:NC NB / D:NC NB, I:NA / D:NA
499 ;// (* When hardware is not debugger, base will be moved to 0x023e0000 in OS_InitArena() )
500 ; Region 2: SHARED_WORK: Base = 0x027ff000, Size = 4KB, I:NC NB / D:NC NB, I:NA / D:RW
501 ; Region 3: CARTRIDGE: Base = 0x08000000, Size = 128MB, I:NC NB / D:NC NB, I:NA / D:RW
502 ; Region 4: DTCM: Base = 0x02fe0000, Size = 16KB, I:NC NB / D:NC NB, I:NA / D:RW
503 ; Region 5: ITCM: Base = 0x01000000, Size = 16MB, I:NC NB / D:NC NB, I:RW / D:RW
504 ; Region 6: BIOS: Base = 0xffff0000, Size = 32KB, I:Cach NB / D:Cach NB, I:RO / D:RO
505 ; Region 7: SHARED_WORK: Base = 0x02fff000, Size = 4KB, I:NC NB / D:NC NB, I:NA / D:RW
506 */
507
508 static asm void
INITi_InitRegion(void)509 INITi_InitRegion(void)
510 {
511 mov r12, lr
512
513 //#define SET_PROTECTION_A(id, adr, siz) ldr r0, =(adr|HW_C6_PR_##siz|HW_C6_PR_ENABLE)
514 //#define SET_PROTECTION_B(id, adr, siz) mcr p15, 0, r0, c6, id, 0
515 #define REGION_BIT(a, b, c, d, e, f, g, h) (((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | ((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7))
516 #define REGION_ACC(a, b, c, d, e, f, g, h) (((a) << 0) | ((b) << 4) | ((c) << 8) | ((d) << 12) | ((e) << 16) | ((f) << 20) | ((g) << 24) | ((h) << 28))
517 #define NA 0
518 #define RW 1
519 #define RO 5
520
521 /* (0) I/O register and VRAM, etc. */
522 SET_PROTECTION_A(c0, HW_IOREG, 64MB)
523 SET_PROTECTION_B(c0, HW_IOREG, 64MB)
524
525 /* (4) D-TCM */
526 ldr r0, =SDK_AUTOLOAD_DTCM_START
527 orr r0, r0, #HW_C6_PR_16KB | HW_C6_PR_ENABLE
528 SET_PROTECTION_B(c4, SDK_AUTOLOAD_DTCM_START, 16KB)
529
530 /* (5) I-TCM */
531 SET_PROTECTION_A(c5, HW_ITCM_IMAGE, 16MB)
532 SET_PROTECTION_B(c5, HW_ITCM_IMAGE, 16MB)
533
534 /* (6) System call ROM */
535 SET_PROTECTION_A(c6, HW_BIOS, 32KB)
536 SET_PROTECTION_B(c6, HW_BIOS, 32KB)
537
538 /* Check whether running on TWL hardware */
539 bl INITi_IsRunOnTwl
540 bne @002
541
542 @001: /* When using TWL hardware */
543 /* (1) Main memory and WRAM */
544 SET_PROTECTION_A(c1, HW_TWL_MAIN_MEM_MAIN, 32MB)
545 SET_PROTECTION_B(c1, HW_TWL_MAIN_MEM_MAIN, 32MB)
546
547 /* (2) ARM7-dedicated main memory space */
548 SET_PROTECTION_A(c2, HW_TWL_MAIN_MEM_SUB, 512KB)
549 SET_PROTECTION_B(c2, HW_TWL_MAIN_MEM_SUB, 512KB)
550
551 /* (3) Extended main memory */
552 SET_PROTECTION_A(c3, HW_CTRDG_ROM, 128MB)
553 SET_PROTECTION_B(c3, HW_CTRDG_ROM, 128MB)
554 //SET_PROTECTION_A(c3, HW_TWL_MAIN_MEM_EX, 16MB)
555 //SET_PROTECTION_B(c3, HW_TWL_MAIN_MEM_EX, 16MB)
556
557 /* (7) ARM9/ARM7-shared main memory space */
558 SET_PROTECTION_A(c7, HW_TWL_MAIN_MEM_SHARED, 16KB)
559 SET_PROTECTION_B(c7, HW_TWL_MAIN_MEM_SHARED, 16KB)
560
561 /* Command cache permission */
562 mov r0, #REGION_BIT(0, 1, 0, 1, 0, 0, 1, 0)
563 mcr p15, 0, r0, c2, c0, 1
564
565 /* Data cache permission */
566 mov r0, #REGION_BIT(0, 1, 0, 1, 0, 0, 1, 0)
567 mcr p15, 0, r0, c2, c0, 0
568
569 /* Write buffer permission */
570 mov r0, #REGION_BIT(0, 1, 0, 1, 0, 0, 0, 0)
571 mcr p15, 0, r0, c3, c0, 0
572
573 /* Command access permission */
574 ldr r0, =REGION_ACC(RW, RW, NA, RW, NA, RW, RO, NA)
575 mcr p15, 0, r0, c5, c0, 3
576
577 /* Data access permission */
578 ldr r0, =REGION_ACC(RW, RW, NA, RW, RW, RW, RO, RW)
579 mcr p15, 0, r0, c5, c0, 2
580
581 b @003
582
583 @002: /* When using NITRO hardware */
584 /* (1) Main memory */
585 //SET_PROTECTION_A(c1, HW_MAIN_MEM_MAIN, 8MB)
586 //SET_PROTECTION_B(c1, HW_MAIN_MEM_MAIN, 8MB)
587 SET_PROTECTION_A(c1, HW_MAIN_MEM_MAIN, 32MB)
588 SET_PROTECTION_B(c1, HW_MAIN_MEM_MAIN, 32MB)
589 /* Size will be arranged in OS_InitArena() */
590
591 /* (2) ARM7-dedicated main memory space */
592 //SET_PROTECTION_A(c2, (HW_MAIN_MEM_EX_END - HW_MAIN_MEM_SHARED_SIZE - HW_MAIN_MEM_SUB_SIZE), 128KB)
593 //SET_PROTECTION_B(c2, (HW_MAIN_MEM_EX_END - HW_MAIN_MEM_SHARED_SIZE - HW_MAIN_MEM_SUB_SIZE), 128KB)
594 SET_PROTECTION_A(c2, (HW_MAIN_MEM_IM_SHARED_END - HW_MAIN_MEM_IM_SHARED_SIZE), 4KB)
595 SET_PROTECTION_B(c2, (HW_MAIN_MEM_IM_SHARED_END - HW_MAIN_MEM_IM_SHARED_SIZE), 4KB)
596 /* Base address will be moved in OS_InitArena() */
597
598 /* (3) Cartridge */
599 SET_PROTECTION_A(c3, HW_CTRDG_ROM, 128MB)
600 SET_PROTECTION_B(c3, HW_CTRDG_ROM, 128MB)
601 //SET_PROTECTION_A(c3, HW_CTRDG_ROM, 32MB)
602 //SET_PROTECTION_B(c3, HW_CTRDG_ROM, 32MB)
603
604 /* (7) ARM9/ARM7-shared main memory space */
605 SET_PROTECTION_A(c7, HW_MAIN_MEM_SHARED, 4KB)
606 SET_PROTECTION_B(c7, HW_MAIN_MEM_SHARED, 4KB)
607
608 /* Command cache permission */
609 mov r0, #REGION_BIT(0, 1, 0, 0, 0, 0, 1, 0)
610 mcr p15, 0, r0, c2, c0, 1
611
612 /* Data cache permission */
613 mov r0, #REGION_BIT(0, 1, 0, 0, 0, 0, 1, 0)
614 mcr p15, 0, r0, c2, c0, 0
615
616 /* Write buffer permission */
617 mov r0, #REGION_BIT(0, 1, 0, 0, 0, 0, 0, 0)
618 mcr p15, 0, r0, c3, c0, 0
619
620 /* Command access permission */
621 //ldr r0, =REGION_ACC(RW, RW, NA, NA, NA, RW, RO, NA)
622 ldr r0, =REGION_ACC(RW, RW, NA, RW, NA, RW, RO, NA)
623 mcr p15, 0, r0, c5, c0, 3
624
625 /* Data access permission */
626 ldr r0, =REGION_ACC(RW, RW, RW, RW, RW, RW, RO, RW)
627 mcr p15, 0, r0, c5, c0, 2
628
629 @003: /* Set to allow use of the protection unit and cache */
630 mrc p15, 0, r0, c1, c0, 0
631 ldr r1, = HW_C1_ICACHE_ENABLE \
632 | HW_C1_DCACHE_ENABLE \
633 | HW_C1_CACHE_ROUND_ROBIN \
634 | HW_C1_PROTECT_UNIT_ENABLE
635 orr r0, r0, r1
636 mcr p15, 0, r0, c1, c0, 0
637
638 /* Destroy the content of the cache */
639 mov r1, #0
640 mcr p15, 0, r1, c7, c6, 0
641 mcr p15, 0, r1, c7, c5, 0
642
643 bx r12
644 }
645
646 /*---------------------------------------------------------------------------*
647 Name: INITi_DoAutoload
648 Description: Clears to 0 the expansion of the fixed data portion and variable portion of each autoload block based on link information.
649 Expands the autoload block located in the PSRAM memory space that exceeds 4 MB only when using TWL hardware.
650 If a portion of the autoload source data and the autoload destination overlap, expand from the end
651
652
653 Arguments: None.
654 Returns: None.
655 *---------------------------------------------------------------------------*/
656 /*
657 * < Two-stage autoload >
658 * The static segment and first level load source binary (second half compressed if necessary) are located at 0x02000000.
659 * If compressed, initially expand while overwriting from the end at 0x02000000.
660 * Load binary data located on ITCM that can be shared with NITRO to 0x01ff8000.
661 * Load binary data located on DTCM that can be shared with NITRO to 0x02fe0000.
662 * The binary data of the second-level load source (all compressed if necessary) is located at 0x02400000.
663 * If compressed, initially expand while overwriting from the end at 0x02400000.
664 * Load TWL-specific binary data for WRAM to its specified addresses.
665 * Load TWL-specific binary data for main memory by copying from the front.
666 * Because NITRO data for main memory is not expected to exceed 0x02400000, the storage address is expected to be smaller than 0x02400000.
667 * In some cases, the autoload information list itself is destroyed in the process of clearing the .bss section of the autoload block for main memory. But this occurs in the final stage of the autoload processes, and should not cause any problems.
668 *
669 *
670 */
671 static asm void
INITi_DoAutoload(void)672 INITi_DoAutoload(void)
673 {
674 stmfd sp!, {lr}
675
676 @01_uncompress:
677 /* Decompress the NITRO-shared block */
678 ldr r1, =_start_ModuleParams
679 ldr r0, [r1, #20] // r0 = bottom of compressed data
680 bl MIi_UncompressBackward
681 @01_autoload:
682 /* Autoload the NITRO-shared block */
683 ldr r0, =_start_ModuleParams
684 ldr r12, [r0] // r12 = SDK_AUTOLOAD_LIST
685 ldr r3, [r0, #4] // r3 = SDK_AUTOLOAD_LIST_END
686 ldr r1, [r0, #8] // r1 = SDK_AUTOLOAD_START
687 @01_segments_loop:
688 cmp r12, r3
689 bge @02_start
690 stmfd sp!, {r3}
691 /* Fixed section */
692 ldr r0, [r12], #4 // r0 = start address of destination range of fixed section
693 ldr r2, [r12], #4 // r2 = size of fixed section
694 stmfd sp!, {r0}
695 bl INITi_Copy32
696 stmfd sp!, {r0, r1}
697 /* static initializer table */
698 ldr r0, [r12], #4 // r0 = start address of source range of static initializer table
699 #ifndef SDK_NOINIT
700 stmfd sp!, {r12}
701 bl INITi_ShelterStaticInitializer
702 ldmfd sp!, {r12}
703 #endif
704 /* bss section */
705 ldmfd sp!, {r0} // r0 = start address of destination range of bss section
706 mov r1, #0 // r1 = clear value for bss section
707 ldr r2, [r12], #4 // r2 = size of bss section
708 bl INITi_Fill32
709 ldmfd sp!, {r1, r2} // r1 = end address of source range of the autoload segment
710 // r2 = start address of destination range of fixed section
711 /* Check whether there is a cache at the edit destination */
712 mov r3, #HW_ITCM_IMAGE
713 cmp r2, r3
714 movge r3, #HW_ITCM_END
715 cmpge r3, r2
716 bgt @01_next_segment // If I-TCM autoload block, skip cache store loop
717 ldr r3, =SDK_AUTOLOAD_DTCM_START
718 cmp r2, r3
719 addge r3, r3, #HW_DTCM_SIZE
720 cmpge r3, r2
721 bgt @01_next_segment // If D-TCM autoload block, skip cache store loop
722 /* Cache store at the edit destination */
723 bic r2, r2, #(HW_CACHE_LINE_SIZE - 1)
724 @01_cache_store_loop:
725 cmp r2, r0
726 bge @01_next_segment
727 mcr p15, 0, r2, c7, c14, 1 // Store and invalidate D-Cache
728 mcr p15, 0, r2, c7, c5, 1 // Invalidate I-Cache
729 add r2, r2, #HW_CACHE_LINE_SIZE
730 b @01_cache_store_loop
731 @01_next_segment:
732 ldmfd sp!, {r3}
733 b @01_segments_loop
734
735 @02_start:
736 /* Check whether running on TWL hardware */
737 bl INITi_IsRunOnTwl
738 bne @03_start
739
740 /* Verify existence of TWL-specific autoload block */
741 ldr r1, =HW_TWL_ROM_HEADER_BUF + 0x1cc // Extended static module ROM size for ARM9
742 ldr r0, [r1]
743 cmp r0, #0
744 beq @03_start
745
746 @02_uncompress:
747 /* Decompress the TWL-specific block */
748 ldr r1, =_start_LtdModuleParams
749 ldr r0, [r1, #12] // r0 = bottom of compressed data
750 bl MIi_UncompressBackward
751 @02_autoload:
752 /* Autoload the TWL-specific block */
753 ldr r0, =_start_LtdModuleParams
754 ldr r12, [r0] // r12 = SDK_LTDAUTOLOAD_LIST
755 ldr r3, [r0, #4] // r3 = SDK_LTDAUTOLOAD_LIST_END
756 ldr r1, [r0, #8] // r1 = SDK_LTDAUTOLOAD_START
757 @02_segments_loop:
758 cmp r12, r3
759 bge @03_start
760 stmfd sp!, {r3}
761 /* Fixed section */
762 ldr r0, [r12], #4 // r0 = start address of destination range of fixed section
763 ldr r2, [r12], #4 // r2 = size of fixed section
764 stmfd sp!, {r0}
765 bl INITi_Copy32
766 stmfd sp!, {r0, r1}
767 /* static initializer table */
768 ldr r0, [r12], #4 // r0 = start address of source range of static initializer table
769 #ifndef SDK_NOINIT
770 stmfd sp!, {r12}
771 bl INITi_ShelterStaticInitializer
772 ldmfd sp!, {r12}
773 #endif
774 /* bss section */
775 ldmfd sp!, {r0} // r0 = start address of destination range of bss section
776 mov r1, #0 // r1 = clear value for bss section
777 ldr r2, [r12], #4 // r2 = size of bss section
778 bl INITi_Fill32
779 ldmfd sp!, {r1, r2} // r1 = end address of source range of the ltdautoload segment
780 // r2 = start address of destination range of fixed section
781 /* Check whether there is a cache at the edit destination */
782 mov r3, #HW_ITCM_IMAGE
783 cmp r2, r3
784 movge r3, #HW_ITCM_END
785 cmpge r3, r2
786 bgt @02_next_segment // If I-TCM autoload block, skip cache store loop
787 ldr r3, =SDK_AUTOLOAD_DTCM_START
788 cmp r2, r3
789 addge r3, r3, #HW_DTCM_SIZE
790 cmpge r3, r2
791 bgt @02_next_segment // If D-TCM autoload block, skip cache store loop
792 /* Cache store at the edit destination */
793 bic r2, r2, #(HW_CACHE_LINE_SIZE - 1)
794 @02_cache_store_loop:
795 cmp r2, r0
796 bge @02_next_segment
797 mcr p15, 0, r2, c7, c14, 1 // Store and invalidate D-Cache
798 mcr p15, 0, r2, c7, c5, 1 // Invalidate I-Cache
799 add r2, r2, #HW_CACHE_LINE_SIZE
800 b @02_cache_store_loop
801 @02_next_segment
802 ldmfd sp!, {r3}
803 b @02_segments_loop
804
805 @03_start:
806 /* Wait until the write buffer is empty */
807 mov r0, #0
808 mcr p15, 0, r0, c7, c10, 4
809
810 /* Call to the autoload the completion callback function */
811 ldr r0, =_start_ModuleParams
812 ldr r1, =_start_LtdModuleParams
813 ldmfd sp!, {lr}
814 b _start_AutoloadDoneCallback
815 }
816
817 /*---------------------------------------------------------------------------*
818 Name: INITi_ShelterStaticInitializer
819 Description: Saves the pointer table for the static initializer in each autoload segment to the start (offset by 4 bytes) of the IRQ stack.
820
821
822 Arguments: ptr: Pointer to pointer table in the segment
823 The table must be NULL terminated.
824 Returns: None.
825 *---------------------------------------------------------------------------*/
826 #ifndef SDK_NOINIT
827 static asm void
INITi_ShelterStaticInitializer(u32 * ptr)828 INITi_ShelterStaticInitializer(u32* ptr)
829 {
830 /* Check argument */
831 cmp r0, #0
832 bxeq lr
833
834 /* Calculate the start address of the moved location */
835 ldr r1, =SDK_AUTOLOAD_DTCM_START
836 add r1, r1, #HW_DTCM_SIZE
837 sub r1, r1, #HW_DTCM_SYSRV_SIZE
838 sub r1, r1, #HW_SVC_STACK_SIZE
839 ldr r2, =SDK_IRQ_STACKSIZE
840 sub r1, r1, r2
841 add r1, r1, #4
842
843 /* Check the empty locations from the top of the moved location */
844 @001: ldr r2, [r1]
845 cmp r2, #0
846 addne r1, r1, #4
847 bne @001
848
849 /* Copy the table to an empty location */
850 @002: ldr r2, [r0], #4
851 str r2, [r1], #4
852 cmp r2, #0
853 bne @002
854
855 bx lr
856 }
857
858 /*---------------------------------------------------------------------------*
859 Name: INITi_CallStaticInitializers
860 Description: Call the static initializer in each autoload segment.
861 Call the function pointer tables moved to the top (offset by 4 bytes) of the IRQ stack by the autoload process.
862
863
864 Arguments: None.
865 Returns: None.
866 *---------------------------------------------------------------------------*/
867 static asm void
INITi_CallStaticInitializers(void)868 INITi_CallStaticInitializers(void)
869 {
870 stmdb sp!, {lr}
871
872 /* Calculate the start address of the new table location */
873 ldr r1, =SDK_AUTOLOAD_DTCM_START
874 add r1, r1, #HW_DTCM_SIZE
875 sub r1, r1, #HW_DTCM_SYSRV_SIZE
876 sub r1, r1, #HW_SVC_STACK_SIZE
877 ldr r2, =SDK_IRQ_STACKSIZE
878 sub r1, r1, r2
879 add r1, r1, #4
880
881 /* Call pointers managed in tables one at a time */
882 @001: ldr r0, [r1]
883 cmp r0, #0
884 beq @002
885 stmdb sp!, {r1}
886 blx r0
887 ldmia sp!, {r1}
888 /* Zero-clear pointers that were called once (because of borrowing the IRQ stack) */
889 mov r0, #0
890 str r0, [r1], #4
891 b @001
892
893 @002:
894 ldmia sp!, {lr}
895 bx lr
896 }
897 #endif
898
899 /*---------------------------------------------------------------------------*
900 Name: MIi_UncompressBackward
901 Description: Uncompresses special archive for module compression.
902 Arguments: bottom: Bottom address of packed archive + 1
903 bottom[-8..-6]: Offset for top of compressed data
904 inp_top = bottom - bottom[-8..-6]
905 bottom[ -5]: Offset for bottom of compressed data
906 inp = bottom - bottom[-5]
907 bottom[-4..-1] = offset for bottom of original data
908 outp = bottom + bottom[-4..-1]
909 typedef struct
910 {
911 u32 bufferTop:24;
912 u32 compressBottom:8;
913 u32 originalBottom;
914 } CompFooter;
915 Returns: None.
916 *---------------------------------------------------------------------------*/
917 asm void
MIi_UncompressBackward(register void * bottom)918 MIi_UncompressBackward(register void* bottom)
919 {
920 #define data r0
921 #define inp_top r1
922 #define outp r2
923 #define inp r3
924 #define outp_save r4
925 #define flag r5
926 #define count8 r6
927 #define index r7
928 #define dummy r8
929 #define len r12
930
931 cmp bottom, #0
932 beq @exit
933 stmfd sp!, {r4-r8}
934 ldmdb bottom, {r1-r2}
935 add outp, bottom, outp
936 sub inp, bottom, inp_top, LSR #24
937 bic inp_top, inp_top, #0xff000000
938 sub inp_top, bottom, inp_top
939 mov outp_save, outp
940 @loop:
941 cmp inp, inp_top // Exit if inp==inp_top
942 ble @end_loop
943 ldrb flag, [inp, #-1]! // r4 = compress_flag = *--inp
944 mov count8, #8
945 @loop8:
946 subs count8, count8, #1
947 blt @loop
948 tst flag, #0x80
949 bne @blockcopy
950 @bytecopy:
951 ldrb data, [inp, #-1]!
952 ldrb dummy, [outp, #-1] // Dummy read to use D-Cache efficiently
953 strb data, [outp, #-1]! // Copy 1 byte
954 b @joinhere
955 @blockcopy:
956 ldrb len, [inp, #-1]!
957 ldrb index, [inp, #-1]!
958 orr index, index, len, LSL #8
959 bic index, index, #0xf000
960 add index, index, #0x0002
961 add len, len, #0x0020
962 @patterncopy:
963 ldrb data, [outp, index]
964 ldrb dummy, [outp, #-1] // Dummy read to use D-Cache efficiently
965 strb data, [outp, #-1]!
966 subs len, len, #0x0010
967 bge @patterncopy
968
969 @joinhere:
970 cmp inp, inp_top
971 mov flag, flag, LSL #1
972 bgt @loop8
973 @end_loop:
974
975 // DC_FlushRange & IC_InvalidateRange
976 mov r0, #0
977 bic inp, inp_top, #HW_CACHE_LINE_SIZE - 1
978 @cacheflush:
979 mcr p15, 0, r0, c7, c10, 4 // Wait writebuffer empty
980 mcr p15, 0, inp, c7, c5, 1 // ICache
981 mcr p15, 0, inp, c7, c14, 1 // DCache
982 add inp, inp, #HW_CACHE_LINE_SIZE
983 cmp inp, outp_save
984 blt @cacheflush
985
986 ldmfd sp!, {r4-r8}
987 @exit bx lr
988 }
989
990 /*---------------------------------------------------------------------------*
991 Name: _start_AutoloadDoneCallback
992 Description: Autoload completion callback.
993 Arguments: argv: Array retaining the autoload parameters
994 argv[0] = SDK_AUTOLOAD_LIST
995 argv[1] = SDK_AUTOLOAD_LIST_END
996 argv[2] = SDK_AUTOLOAD_START
997 argv[3] = SDK_STATIC_BSS_START
998 argv[4] = SDK_STATIC_BSS_END
999 Returns: None.
1000 *---------------------------------------------------------------------------*/
1001 SDK_WEAK_SYMBOL asm void
_start_AutoloadDoneCallback(void * argv[])1002 _start_AutoloadDoneCallback(void* argv[])
1003 {
1004 bx lr
1005 }
1006
1007 /*---------------------------------------------------------------------------*
1008 Name: NitroStartUp
1009 Description: Hook for user start-up.
1010 Arguments: None.
1011 Returns: None.
1012 *---------------------------------------------------------------------------*/
1013 SDK_WEAK_SYMBOL void
NitroStartUp(void)1014 NitroStartUp(void)
1015 {
1016 }
1017
1018 /*---------------------------------------------------------------------------*
1019 Name: OSi_ReferSymbol
1020 Description: Used by SDK_REFER_SYMBOL macro to avoid deadstripping.
1021 Arguments: symbol: Unused
1022 Returns: None.
1023 *---------------------------------------------------------------------------*/
1024 void
OSi_ReferSymbol(void * symbol)1025 OSi_ReferSymbol(void* symbol)
1026 {
1027 #pragma unused(symbol)
1028 }
1029
1030 /*---------------------------------------------------------------------------*
1031 Name: INITi_IsRunOnTwl
1032
1033 Description: Checks running platform.
1034
1035 This function is used in only NITRO-TWL hybrid mode.
1036 (In NITRO mode and TWL limited mode, treated as constant)
1037
1038 Arguments: None.
1039
1040 Returns: TRUE: running on TWL
1041 FALSE: running on NITRO
1042 *---------------------------------------------------------------------------*/
INITi_IsRunOnTwl(void)1043 static asm BOOL INITi_IsRunOnTwl( void )
1044 {
1045 ldr r0, =REG_A9ROM_ADDR
1046 ldrb r0, [r0]
1047 and r0, r0, #REG_SCFG_A9ROM_SEC_MASK | REG_SCFG_A9ROM_RSEL_MASK
1048 cmp r0, #REG_SCFG_A9ROM_SEC_MASK
1049 moveq r0, #TRUE
1050 movne r0, #FALSE
1051
1052 bx lr
1053 }
1054
1055 /*---------------------------------------------------------------------------*
1056 Name: INITi_Copy32
1057 Description: Where possible, copy in 32-byte units; remainder can be copied in 4-byte units.
1058 The stack is consumed in 36-bytes, but registers r3 - r12 are not destroyed.
1059
1060 Arguments: r0: Pointer to copy destination (4-byte aligned)
1061 r1: Pointer to copy source (4-byte aligned)
1062 r2: Length to be copied in bytes (multiples of 4)
1063 Returns: r0: Pointer to the copy destination after copying (r0 + r2).
1064 r1: Pointer to the copy source after copying (r1 + r2).
1065 *---------------------------------------------------------------------------*/
1066 static asm void*
INITi_Copy32(void * dst,void * src,u32 size)1067 INITi_Copy32(void* dst, void* src, u32 size)
1068 {
1069 stmfd sp!, {r3-r11}
1070 bics r3, r2, #0x0000001f
1071 beq @next
1072 add r3, r0, r3
1073 @loop:
1074 ldmia r1!, {r4-r11}
1075 stmia r0!, {r4-r11}
1076 cmp r3, r0
1077 bgt @loop
1078 @next:
1079 tst r2, #0x00000010
1080 ldmneia r1!, {r4-r7}
1081 stmneia r0!, {r4-r7}
1082 tst r2, #0x00000008
1083 ldmneia r1!, {r4-r5}
1084 stmneia r0!, {r4-r5}
1085 tst r2, #0x00000004
1086 ldmneia r1!, {r4}
1087 stmneia r0!, {r4}
1088 ldmfd sp!, {r3-r11}
1089 bx lr
1090 }
1091
1092 /*---------------------------------------------------------------------------*
1093 Name: INITi_Fill32
1094 Description: Where possible, fill the buffer with specified data in 32-byte units; the remainder can be filled in 4-byte units.
1095 The stack is consumed in 36-bytes, but registers r3 - r12 are not destroyed.
1096
1097 Arguments: r0: Pointer to the buffer (4-byte aligned)
1098 r1: Content to fill the buffer using 32-bit values
1099 r2: Length to fill the buffer in byte units (multiples of 4)
1100 Returns: r0: Pointer to the buffer after processing (r0 + r2).
1101 *---------------------------------------------------------------------------*/
1102 static asm void*
INITi_Fill32(void * dst,u32 value,u32 size)1103 INITi_Fill32(void* dst, u32 value, u32 size)
1104 {
1105 stmfd sp!, {r3-r11}
1106 mov r4, r1
1107 mov r5, r1
1108 mov r6, r1
1109 mov r7, r1
1110 mov r8, r1
1111 mov r9, r1
1112 mov r10, r1
1113 mov r11, r1
1114 bics r3, r2, #0x0000001f
1115 beq @next
1116 add r3, r0, r3
1117 @loop:
1118 stmia r0!, {r4-r11}
1119 cmp r3, r0
1120 bgt @loop
1121 @next:
1122 tst r2, #0x00000010
1123 stmneia r0!, {r4-r7}
1124 tst r2, #0x00000008
1125 stmneia r0!, {r4-r5}
1126 tst r2, #0x00000004
1127 stmneia r0!, {r4}
1128 ldmfd sp!, {r3-r11}
1129 bx lr
1130 }
1131
1132 #include <twl/codereset.h>
1133