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