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:: 2009-08-20#$
14 $Rev: 10997 $
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 definition */
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 prohibited */
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 // Various 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 // (2) Correction of boot type (if illegal, consider it to be an unsupported firmware and go to ROM)
236 ldr r1, =HW_WM_BOOT_BUF
237 ldrh r2, [r1, #OSBootInfo.boot_type]
238 cmp r2, #OS_BOOTTYPE_ILLEGAL
239 moveq r2, #OS_BOOTTYPE_ROM
240 streqh r2, [r1, #OSBootInfo.boot_type]
241
242 /* Copy the micro-code for the handshake to ITCM */
243 ldr r1, =microcode_ShakeHand
244 ldr r2, =HW_ITCM
245 add r3, r2, #40
246 @001: ldr r0, [r1], #4
247 str r0, [r2], #4
248 cmp r2, r3
249 blt @001
250
251 /* Handshake with ARM7 with the code on ITCM */
252 ldr r0, =HW_BOOT_SYNC_PHASE
253 mov r1, #BOOT_SYNC_PHASE_1
254 strh r1, [r0]
255 ldr r0, =HW_BOOT_SHAKEHAND_9
256 ldr r1, =HW_BOOT_SHAKEHAND_7
257 ldr r2, =HW_ITCM
258 blx r2
259
260 #ifdef SDK_TWLLTD
261 /* For LTD on NTR, do not synchronize with the ARM7 (it will not respond) */
262 bl INITi_IsRunOnTwl
263 bne @020
264 #endif
265
266 /* Overwrite and copy the micro-code for synchronous wait with ARM7 to ITCM */
267 ldr r1, =microcode_WaitAgreement
268 ldr r2, =HW_ITCM
269 add r3, r2, #28
270 @002: ldr r0, [r1], #4
271 str r0, [r2], #4
272 cmp r2, r3
273 blt @002
274
275 @003:
276 /* Synchronize with ARM7 */
277 ldr r0, =HW_BOOT_SYNC_PHASE
278 mov r1, #BOOT_SYNC_PHASE_4
279 ldr r2, =HW_ITCM
280 blx r2
281
282 @010:
283 /* Investigate whether running on TWL hardware */
284 bl INITi_IsRunOnTwl
285 bne @020
286
287 /* Copy the micro-code for changing to double speed to ITCM */
288 ldr r1, =microcode_SwitchCpuClock
289 ldr r2, =HW_ITCM
290 add r2, r2, #28
291 mov r3, #52
292 @011: subs r3, r3, #4
293 ldr r0, [r1, r3]
294 str r0, [r2, r3]
295 bgt @011
296 /* Change to double-speed mode for the CPU clock */
297 mov r0, #REG_SCFG_CLK_CPUSPD_MASK
298 mov r1, #8
299 blx r2
300
301 /* [TODO] Run the default settings of the added I/O registers that can only be set on ARM9 */
302
303 @020:
304 /* Region default settings */
305 bl INITi_InitRegion
306
307 /* Stack pointer settings */
308 mov r0, #HW_PSR_SVC_MODE // SuperVisor mode
309 msr cpsr_c, r0
310 ldr r1, =SDK_AUTOLOAD_DTCM_START
311 add r1, r1, #HW_DTCM_SIZE
312 sub sp, r1, #HW_DTCM_SYSRV_SIZE
313 sub r1, sp, #HW_SVC_STACK_SIZE
314 mov r0, #HW_PSR_IRQ_MODE // IRQ mode
315 msr cpsr_c, r0
316 sub sp, r1, #4 // 4 bytes for stack check code
317 tst sp, #4
318 subeq sp, sp, #4 /* Adjust so that sp is 8-byte aligned at the time of the jump to the IRQ handler */
319 ldr r0, =SDK_IRQ_STACKSIZE
320 sub r1, r1, r0
321 mov r0, #HW_PSR_SYS_MODE // System mode
322 msr cpsr_csfx, r0
323 sub sp, r1, #4 // 4 bytes for stack check code
324 tst sp, #4
325 subne sp, sp, #4 /* Adjust so that sp is 8-byte aligned at the time of the jump to the Main function */
326
327 /* Clear the stack region */
328 mov r0, #0
329 ldr r1, =SDK_AUTOLOAD_DTCM_START
330 mov r2, #HW_DTCM_SIZE
331 bl INITi_CpuClear32
332
333 /* Zero-clear the VRAM */
334 mov r1, #0 // r1 = clear value for VRAM
335 ldr r0, =HW_PLTT // r0 = start address of VRAM for pallet
336 mov r2, #HW_PLTT_SIZE // r2 = size of VRAM for pallet
337 bl INITi_Fill32
338 ldr r0, =HW_OAM // r0 = start address of VRAM for OAM
339 mov r2, #HW_OAM_SIZE // r2 = size of VRAM for OAM
340 bl INITi_Fill32
341
342 /* Implement Autoload */
343 bl INITi_DoAutoload
344
345 /* Zero-clear the .bss section of the STATIC block */
346 mov r1, #0 // r1 = clear value for STATIC bss section
347 ldr r3, =_start_ModuleParams
348 ldr r0, [r3, #12] // r0 = start address of STATIC bss section
349 ldr r2, [r3, #16]
350 subs r2, r2, r0 // r2 = size of STATIC bss section
351 blgt INITi_Fill32
352
353 /* Configure interrupt vector */
354 ldr r1, =SDK_AUTOLOAD_DTCM_START
355 add r1, r1, #HW_DTCM_SIZE - HW_DTCM_SYSRV_SIZE
356 add r1, r1, #HW_DTCM_SYSRV_OFS_INTR_VECTOR
357 ldr r0, =OS_IrqHandler
358 str r0, [r1]
359
360 #ifdef SDK_TWLLTD
361 /* Display warning screen for LTD on NTR */
362 bl INITi_IsRunOnTwl
363 blne OS_ShowAttentionOfLimitedRom
364 // (The above functions do not return.)
365 #endif
366
367 #ifndef SDK_NOINIT
368 /* Initialize for C++ */
369 bl _fp_init
370 bl TwlStartUp
371 bl __call_static_initializers
372 bl INITi_CallStaticInitializers
373 #endif
374
375 /* V-Count adjustment */
376 ldr r1, =REG_VCOUNT_ADDR
377 @022: ldrh r0, [r1]
378 cmp r0, #0
379 bne @022
380
381 @030:
382 /* Jump to Main function */
383 ldr r1, =TwlMain
384 ldr lr, =HW_RESET_VECTOR
385 bx r1
386 }
387
388 /*---------------------------------------------------------------------------*
389 Name: INITi_CpuClear32
390 Description: Clears buffer in 32-bit units.
391 Arguments: r0: Value to clear
392 r1: Pointer to the clear destination
393 r2: Buffer length to continuously clear
394 Returns: None.
395 *---------------------------------------------------------------------------*/
396 static asm void
INITi_CpuClear32(register u32 data,register void * destp,register u32 size)397 INITi_CpuClear32(register u32 data, register void* destp, register u32 size)
398 {
399 add r12, r1, r2
400 @001: cmp r1, r12
401 strlt r0, [r1], #4
402 blt @001
403 bx lr
404 }
405
406 /*---------------------------------------------------------------------------*
407 Name: INITi_InitCoprocessor
408 Description: Initializes the system control co-processor.
409 At the same time, enable the use of I-TCM and D-TCM.
410 Arguments: None.
411 Returns: None.
412 *---------------------------------------------------------------------------*/
413 static asm void
INITi_InitCoprocessor(void)414 INITi_InitCoprocessor(void)
415 {
416 /* Get the co-processor state */
417 mrc p15, 0, r0, c1, c0, 0
418
419 tst r0, #HW_C1_PROTECT_UNIT_ENABLE
420 beq @010
421 tst r0, #HW_C1_DCACHE_ENABLE
422 beq @003
423
424 /* Write back the D-Cache content to memory */
425 mov r1, #0
426 @001: mov r2, #0
427 @002: orr r3, r1, r2
428 mcr p15, 0, r3, c7, c10, 2
429 add r2, r2, #HW_CACHE_LINE_SIZE
430 cmp r2, #HW_DCACHE_SIZE / 4
431 blt @002
432 adds r1, r1, #1 << HW_C7_CACHE_SET_NO_SHIFT
433 bne @001
434
435 @003: /* Wait until the write buffer is empty */
436 mov r1, #0
437 mcr p15, 0, r1, c7, c10, 4
438
439 @010: /* Initialize the co-processor state */
440 ldr r1, = HW_C1_ITCM_LOAD_MODE \
441 | HW_C1_DTCM_LOAD_MODE \
442 | HW_C1_ITCM_ENABLE \
443 | HW_C1_DTCM_ENABLE \
444 | HW_C1_LD_INTERWORK_DISABLE \
445 | HW_C1_ICACHE_ENABLE \
446 | HW_C1_DCACHE_ENABLE \
447 | HW_C1_PROTECT_UNIT_ENABLE
448 bic r0, r0, r1
449 ldr r1, = HW_C1_SB1_BITSET \
450 | HW_C1_EXCEPT_VEC_UPPER
451 orr r0, r0, r1
452 mcr p15, 0, r0, c1, c0, 0
453
454 /* Set the I-TCM size */
455 mov r1, #HW_C9_TCMR_32MB
456 mcr p15, 0, r1, c9, c1, 1
457 /* Set the D-TCM size and region base address */
458 ldr r1, =SDK_AUTOLOAD_DTCM_START
459 orr r1, r1, #HW_C9_TCMR_16KB
460 mcr p15, 0, r1, c9, c1, 0
461
462 /* Set to allow use of I-TCM and D-TCM */
463 mov r1, #HW_C1_ITCM_ENABLE | HW_C1_DTCM_ENABLE
464 orr r0, r0, r1
465 mcr p15, 0, r0, c1, c0, 0
466
467 bx lr
468 }
469
470 /*---------------------------------------------------------------------------*
471 Name: INITi_InitRegion
472 Description: Initializes the region settings.
473 Arguments: None.
474 Returns: None.
475 *---------------------------------------------------------------------------*/
476 /* When hardware is TWL
477 ; Region G: BACK_GROUND: Base = 0x0, Size = 4GB, I:NC NB / D:NC NB, I:NA / D:NA
478 ; Region 0: IO_VRAM: Base = 0x04000000, Size = 64MB, I:NC NB / D:NC NB, I:RW / D:RW
479 ; Region 1: MAINMEM_WRAM: Base = 0x02000000, Size = 32MB, I:Cach Buf / D:Cach Buf, I:RW / D:RW
480 ; Region 2: ARM7_RESERVE: Base = 0x02f80000, Size = 512KB, I:NC NB / D:NC NB, I:NA / D:NA
481 ; Region 3: EX_MAINMEM: Base = 0x0d000000, Size = 16MB, I:Cach Buf / D:Cach Buf, I:RW / D:RW
482 ; Region 4: DTCM: Base = 0x02fe0000, Size = 16KB, I:NC NB / D:NC NB, I:NA / D:RW
483 ; Region 5: ITCM: Base = 0x01000000, Size = 16MB, I:NC NB / D:NC NB, I:RW / D:RW
484 ; Region 6: BIOS: Base = 0xffff0000, Size = 32KB, I:Cach NB / D:Cach NB, I:RO / D:RO
485 ; Region 7: SHARED_WORK: Base = 0x02ffc000, Size = 16KB, I:NC NB / D:NC NB, I:NA / D:RW
486 */
487 /* When hardware is NITRO
488 ; Region G: BACK_GROUND: Base = 0x0, Size = 4GB, I:NC NB / D:NC NB, I:NA / D:NA
489 ; Region 0: IO_VRAM: Base = 0x04000000, Size = 64MB, I:NC NB / D:NC NB, I:RW / D:RW
490 ; Region 1: MAIN_MEM: Base = 0x02000000, Size = 8MB*, I:Cach Buf / D:Cach Buf, I:RW / D:RW
491 ; (* When hardware is not debugger, size will be reduced to 4MB in OS_InitArena() )
492 ;// Region 2: ARM7_RESERVE: Base = 0x027e0000, Size = 128KB, I:NC NB / D:NC NB, I:NA / D:NA
493 ;// (* When hardware is not debugger, base will be moved to 0x023e0000 in OS_InitArena() )
494 ; Region 2: SHARED_WORK: Base = 0x027ff000, Size = 4KB, I:NC NB / D:NC NB, I:NA / D:RW
495 ; Region 3: CARTRIDGE: Base = 0x08000000, Size = 128MB, I:NC NB / D:NC NB, I:NA / D:RW
496 ; Region 4: DTCM: Base = 0x02fe0000, Size = 16KB, I:NC NB / D:NC NB, I:NA / D:RW
497 ; Region 5: ITCM: Base = 0x01000000, Size = 16MB, I:NC NB / D:NC NB, I:RW / D:RW
498 ; Region 6: BIOS: Base = 0xffff0000, Size = 32KB, I:Cach NB / D:Cach NB, I:RO / D:RO
499 ; Region 7: SHARED_WORK: Base = 0x02fff000, Size = 4KB, I:NC NB / D:NC NB, I:NA / D:RW
500 */
501
502 static asm void
INITi_InitRegion(void)503 INITi_InitRegion(void)
504 {
505 mov r12, lr
506
507 //#define SET_PROTECTION_A(id, adr, siz) ldr r0, =(adr|HW_C6_PR_##siz|HW_C6_PR_ENABLE)
508 //#define SET_PROTECTION_B(id, adr, siz) mcr p15, 0, r0, c6, id, 0
509 #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))
510 #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))
511 #define NA 0
512 #define RW 1
513 #define RO 5
514
515 /* (0) I/O register and VRAM, etc. */
516 SET_PROTECTION_A(c0, HW_IOREG, 64MB)
517 SET_PROTECTION_B(c0, HW_IOREG, 64MB)
518
519 /* (4) D-TCM */
520 ldr r0, =SDK_AUTOLOAD_DTCM_START
521 orr r0, r0, #HW_C6_PR_16KB | HW_C6_PR_ENABLE
522 SET_PROTECTION_B(c4, SDK_AUTOLOAD_DTCM_START, 16KB)
523
524 /* (5) I-TCM */
525 SET_PROTECTION_A(c5, HW_ITCM_IMAGE, 16MB)
526 SET_PROTECTION_B(c5, HW_ITCM_IMAGE, 16MB)
527
528 /* (6) System call ROM */
529 SET_PROTECTION_A(c6, HW_BIOS, 32KB)
530 SET_PROTECTION_B(c6, HW_BIOS, 32KB)
531
532 /* Investigate whether running on TWL hardware */
533 bl INITi_IsRunOnTwl
534 bne @002
535
536 @001: /* When using TWL hardware */
537 /* (1) Main memory and WRAM */
538 SET_PROTECTION_A(c1, HW_TWL_MAIN_MEM_MAIN, 32MB)
539 SET_PROTECTION_B(c1, HW_TWL_MAIN_MEM_MAIN, 32MB)
540
541 /* (2) ARM7-dedicated main memory space */
542 SET_PROTECTION_A(c2, HW_TWL_MAIN_MEM_SUB, 512KB)
543 SET_PROTECTION_B(c2, HW_TWL_MAIN_MEM_SUB, 512KB)
544
545 /* (3) Extended main memory */
546 SET_PROTECTION_A(c3, HW_CTRDG_ROM, 128MB)
547 SET_PROTECTION_B(c3, HW_CTRDG_ROM, 128MB)
548 //SET_PROTECTION_A(c3, HW_TWL_MAIN_MEM_EX, 16MB)
549 //SET_PROTECTION_B(c3, HW_TWL_MAIN_MEM_EX, 16MB)
550
551 /* (7) ARM9/ARM7-shared main memory space */
552 SET_PROTECTION_A(c7, HW_TWL_MAIN_MEM_SHARED, 16KB)
553 SET_PROTECTION_B(c7, HW_TWL_MAIN_MEM_SHARED, 16KB)
554
555 /* Command cache permission */
556 mov r0, #REGION_BIT(0, 1, 0, 1, 0, 0, 1, 0)
557 mcr p15, 0, r0, c2, c0, 1
558
559 /* Data cache permission */
560 mov r0, #REGION_BIT(0, 1, 0, 1, 0, 0, 1, 0)
561 mcr p15, 0, r0, c2, c0, 0
562
563 /* Write buffer permission */
564 mov r0, #REGION_BIT(0, 1, 0, 1, 0, 0, 0, 0)
565 mcr p15, 0, r0, c3, c0, 0
566
567 /* Command access permission */
568 ldr r0, =REGION_ACC(RW, RW, NA, RW, NA, RW, RO, NA)
569 mcr p15, 0, r0, c5, c0, 3
570
571 /* Data access permission */
572 ldr r0, =REGION_ACC(RW, RW, NA, RW, RW, RW, RO, RW)
573 mcr p15, 0, r0, c5, c0, 2
574
575 b @003
576
577 @002: /* When using NITRO hardware */
578 /* (1) Main memory */
579 //SET_PROTECTION_A(c1, HW_MAIN_MEM_MAIN, 8MB)
580 //SET_PROTECTION_B(c1, HW_MAIN_MEM_MAIN, 8MB)
581 SET_PROTECTION_A(c1, HW_MAIN_MEM_MAIN, 32MB)
582 SET_PROTECTION_B(c1, HW_MAIN_MEM_MAIN, 32MB)
583 /* Size will be arranged in OS_InitArena() */
584
585 /* (2) ARM7-dedicated main memory space */
586 //SET_PROTECTION_A(c2, (HW_MAIN_MEM_EX_END - HW_MAIN_MEM_SHARED_SIZE - HW_MAIN_MEM_SUB_SIZE), 128KB)
587 //SET_PROTECTION_B(c2, (HW_MAIN_MEM_EX_END - HW_MAIN_MEM_SHARED_SIZE - HW_MAIN_MEM_SUB_SIZE), 128KB)
588 SET_PROTECTION_A(c2, (HW_MAIN_MEM_IM_SHARED_END - HW_MAIN_MEM_IM_SHARED_SIZE), 4KB)
589 SET_PROTECTION_B(c2, (HW_MAIN_MEM_IM_SHARED_END - HW_MAIN_MEM_IM_SHARED_SIZE), 4KB)
590 /* Base address will be moved in OS_InitArena() */
591
592 /* (3) Cartridge */
593 SET_PROTECTION_A(c3, HW_CTRDG_ROM, 128MB)
594 SET_PROTECTION_B(c3, HW_CTRDG_ROM, 128MB)
595 //SET_PROTECTION_A(c3, HW_CTRDG_ROM, 32MB)
596 //SET_PROTECTION_B(c3, HW_CTRDG_ROM, 32MB)
597
598 /* (7) ARM9/ARM7-shared main memory space */
599 SET_PROTECTION_A(c7, HW_MAIN_MEM_SHARED, 4KB)
600 SET_PROTECTION_B(c7, HW_MAIN_MEM_SHARED, 4KB)
601
602 /* Command cache permission */
603 mov r0, #REGION_BIT(0, 1, 0, 0, 0, 0, 1, 0)
604 mcr p15, 0, r0, c2, c0, 1
605
606 /* Data cache permission */
607 mov r0, #REGION_BIT(0, 1, 0, 0, 0, 0, 1, 0)
608 mcr p15, 0, r0, c2, c0, 0
609
610 /* Write buffer permission */
611 mov r0, #REGION_BIT(0, 1, 0, 0, 0, 0, 0, 0)
612 mcr p15, 0, r0, c3, c0, 0
613
614 /* Command access permission */
615 //ldr r0, =REGION_ACC(RW, RW, NA, NA, NA, RW, RO, NA)
616 ldr r0, =REGION_ACC(RW, RW, NA, RW, NA, RW, RO, NA)
617 mcr p15, 0, r0, c5, c0, 3
618
619 /* Data access permission */
620 ldr r0, =REGION_ACC(RW, RW, RW, RW, RW, RW, RO, RW)
621 mcr p15, 0, r0, c5, c0, 2
622
623 @003: /* Set to allow use of the protection unit and cache */
624 mrc p15, 0, r0, c1, c0, 0
625 ldr r1, = HW_C1_ICACHE_ENABLE \
626 | HW_C1_DCACHE_ENABLE \
627 | HW_C1_CACHE_ROUND_ROBIN \
628 | HW_C1_PROTECT_UNIT_ENABLE
629 orr r0, r0, r1
630 mcr p15, 0, r0, c1, c0, 0
631
632 /* Destroy the content of the cache */
633 mov r1, #0
634 mcr p15, 0, r1, c7, c6, 0
635 mcr p15, 0, r1, c7, c5, 0
636
637 bx r12
638 }
639
640 /*---------------------------------------------------------------------------*
641 Name: INITi_DoAutoload
642 Description: Zero-clears the expansion of the fixed data portion and variable portion of each autoload block, in conjunction with link information.
643 Expands the autoload block located in the PSRAM memory space that exceeds 4 MB only when using TWL hardware.
644
645 If a portion of the autoload source data and the autoload destination overlap, expand from the end
646
647 Arguments: None.
648 Returns: None.
649 *---------------------------------------------------------------------------*/
650 /*
651 * < Two-stage autoload >
652 * The static segment and first level load source binary (second half compressed if necessary) are located at 0x02000000.
653 * If compressed, initially expand while overwriting from the end at 0x02000000.
654 * Load binary data located on ITCM that can be shared with NITRO to 0x01ff8000.
655 * Load binary data located on DTCM that can be shared with NITRO to 0x02fe0000.
656 * The binary data of the second-level load source (all compressed if necessary) is located at 0x02400000.
657 * If compressed, initially expand while overwriting from the end at 0x02400000.
658 * Load binary data that should be located on WRAM that can only run on TWL to each specified address.
659 * Load binary data that should be located in main memory that can only run on TWL from the front by copying.
660 * 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.
661 *
662 * 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.
663 *
664 */
665 static asm void
INITi_DoAutoload(void)666 INITi_DoAutoload(void)
667 {
668 stmfd sp!, {lr}
669
670 @01_uncompress:
671 /* Decompress the NITRO-shared block */
672 ldr r1, =_start_ModuleParams
673 ldr r0, [r1, #20] // r0 = bottom of compressed data
674 bl MIi_UncompressBackward
675 @01_autoload:
676 /* Autoload the NITRO-shared block */
677 ldr r0, =_start_ModuleParams
678 ldr r12, [r0] // r12 = SDK_AUTOLOAD_LIST
679 ldr r3, [r0, #4] // r3 = SDK_AUTOLOAD_LIST_END
680 ldr r1, [r0, #8] // r1 = SDK_AUTOLOAD_START
681 @01_segments_loop:
682 cmp r12, r3
683 bge @02_start
684 stmfd sp!, {r3}
685 /* Fixed section */
686 ldr r0, [r12], #4 // r0 = start address of destination range of fixed section
687 ldr r2, [r12], #4 // r2 = size of fixed section
688 stmfd sp!, {r0}
689 bl INITi_Copy32
690 stmfd sp!, {r0, r1}
691 /* static initializer table */
692 ldr r0, [r12], #4 // r0 = start address of source range of static initializer table
693 #ifndef SDK_NOINIT
694 stmfd sp!, {r12}
695 bl INITi_ShelterStaticInitializer
696 ldmfd sp!, {r12}
697 #endif
698 /* bss section */
699 ldmfd sp!, {r0} // r0 = start address of destination range of bss section
700 mov r1, #0 // r1 = clear value for bss section
701 ldr r2, [r12], #4 // r2 = size of bss section
702 bl INITi_Fill32
703 ldmfd sp!, {r1, r2} // r1 = end address of source range of the autoload segment
704 // r2 = start address of destination range of fixed section
705 /* Determine the presence of a cache at the edit destination */
706 mov r3, #HW_ITCM_IMAGE
707 cmp r2, r3
708 movge r3, #HW_ITCM_END
709 cmpge r3, r2
710 bgt @01_next_segment // If I-TCM autoload block, skip cache store loop
711 ldr r3, =SDK_AUTOLOAD_DTCM_START
712 cmp r2, r3
713 addge r3, r3, #HW_DTCM_SIZE
714 cmpge r3, r2
715 bgt @01_next_segment // If D-TCM autoload block, skip cache store loop
716 /* Cache store at the edit destination */
717 bic r2, r2, #(HW_CACHE_LINE_SIZE - 1)
718 @01_cache_store_loop:
719 cmp r2, r0
720 bge @01_next_segment
721 mcr p15, 0, r2, c7, c14, 1 // Store and invalidate D-Cache
722 mcr p15, 0, r2, c7, c5, 1 // Invalidate I-Cache
723 add r2, r2, #HW_CACHE_LINE_SIZE
724 b @01_cache_store_loop
725 @01_next_segment:
726 ldmfd sp!, {r3}
727 b @01_segments_loop
728
729 @02_start:
730 /* Investigate whether running on TWL hardware */
731 bl INITi_IsRunOnTwl
732 bne @03_start
733
734 /* Verify existence of TWL-dedicated autoload block */
735 ldr r1, =HW_TWL_ROM_HEADER_BUF + 0x1cc // Expansion resident module ROM size for ARM9
736 ldr r0, [r1]
737 cmp r0, #0
738 beq @03_start
739
740 @02_uncompress:
741 /* Decompress the TWL-dedicated block */
742 ldr r1, =_start_LtdModuleParams
743 ldr r0, [r1, #12] // r0 = bottom of compressed data
744 bl MIi_UncompressBackward
745 @02_autoload:
746 /* Autoload the TWL-dedicated block */
747 ldr r0, =_start_LtdModuleParams
748 ldr r12, [r0] // r12 = SDK_LTDAUTOLOAD_LIST
749 ldr r3, [r0, #4] // r3 = SDK_LTDAUTOLOAD_LIST_END
750 ldr r1, [r0, #8] // r1 = SDK_LTDAUTOLOAD_START
751 @02_segments_loop:
752 cmp r12, r3
753 bge @03_start
754 stmfd sp!, {r3}
755 /* Fixed section */
756 ldr r0, [r12], #4 // r0 = start address of destination range of fixed section
757 ldr r2, [r12], #4 // r2 = size of fixed section
758 stmfd sp!, {r0}
759 bl INITi_Copy32
760 stmfd sp!, {r0, r1}
761 /* static initializer table */
762 ldr r0, [r12], #4 // r0 = start address of source range of static initializer table
763 #ifndef SDK_NOINIT
764 stmfd sp!, {r12}
765 bl INITi_ShelterStaticInitializer
766 ldmfd sp!, {r12}
767 #endif
768 /* bss section */
769 ldmfd sp!, {r0} // r0 = start address of destination range of bss section
770 mov r1, #0 // r1 = clear value for bss section
771 ldr r2, [r12], #4 // r2 = size of bss section
772 bl INITi_Fill32
773 ldmfd sp!, {r1, r2} // r1 = end address of source range of the ltdautoload segment
774 // r2 = start address of destination range of fixed section
775 /* Determine the presence of a cache at the edit destination */
776 mov r3, #HW_ITCM_IMAGE
777 cmp r2, r3
778 movge r3, #HW_ITCM_END
779 cmpge r3, r2
780 bgt @02_next_segment // If I-TCM autoload block, skip cache store loop
781 ldr r3, =SDK_AUTOLOAD_DTCM_START
782 cmp r2, r3
783 addge r3, r3, #HW_DTCM_SIZE
784 cmpge r3, r2
785 bgt @02_next_segment // If D-TCM autoload block, skip cache store loop
786 /* Cache store at the edit destination */
787 bic r2, r2, #(HW_CACHE_LINE_SIZE - 1)
788 @02_cache_store_loop:
789 cmp r2, r0
790 bge @02_next_segment
791 mcr p15, 0, r2, c7, c14, 1 // Store and invalidate D-Cache
792 mcr p15, 0, r2, c7, c5, 1 // Invalidate I-Cache
793 add r2, r2, #HW_CACHE_LINE_SIZE
794 b @02_cache_store_loop
795 @02_next_segment
796 ldmfd sp!, {r3}
797 b @02_segments_loop
798
799 @03_start:
800 /* Wait until the write buffer is empty */
801 mov r0, #0
802 mcr p15, 0, r0, c7, c10, 4
803
804 /* Call to the autoload complete callback function */
805 ldr r0, =_start_ModuleParams
806 ldr r1, =_start_LtdModuleParams
807 ldmfd sp!, {lr}
808 b _start_AutoloadDoneCallback
809 }
810
811 /*---------------------------------------------------------------------------*
812 Name: INITi_ShelterStaticInitializer
813 Description: Pointer to the static initializer in each autoload segment.
814 Move the table to the top (a position shifted four bytes from there) of the IRQ stack.
815
816 Arguments: ptr: Pointer to pointer table in the segment
817 It is necessary for the table to be at the end with NULL
818 Returns: None.
819 *---------------------------------------------------------------------------*/
820 #ifndef SDK_NOINIT
821 static asm void
INITi_ShelterStaticInitializer(u32 * ptr)822 INITi_ShelterStaticInitializer(u32* ptr)
823 {
824 /* Check argument */
825 cmp r0, #0
826 bxeq lr
827
828 /* Calculate the top address of the moved location */
829 ldr r1, =SDK_AUTOLOAD_DTCM_START
830 add r1, r1, #HW_DTCM_SIZE
831 sub r1, r1, #HW_DTCM_SYSRV_SIZE
832 sub r1, r1, #HW_SVC_STACK_SIZE
833 ldr r2, =SDK_IRQ_STACKSIZE
834 sub r1, r1, r2
835 add r1, r1, #4
836
837 /* Investigate the empty locations from the top of the moved location */
838 @001: ldr r2, [r1]
839 cmp r2, #0
840 addne r1, r1, #4
841 bne @001
842
843 /* Copy the table to an empty location */
844 @002: ldr r2, [r0], #4
845 str r2, [r1], #4
846 cmp r2, #0
847 bne @002
848
849 bx lr
850 }
851
852 /*---------------------------------------------------------------------------*
853 Name: INITi_CallStaticInitializers
854 Description: Call the static initializer in each autoload segment.
855 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.
856
857
858 Arguments: None.
859 Returns: None.
860 *---------------------------------------------------------------------------*/
861 static asm void
INITi_CallStaticInitializers(void)862 INITi_CallStaticInitializers(void)
863 {
864 stmdb sp!, {lr}
865
866 /* Calculate the top address of the table moved location */
867 ldr r1, =SDK_AUTOLOAD_DTCM_START
868 add r1, r1, #HW_DTCM_SIZE
869 sub r1, r1, #HW_DTCM_SYSRV_SIZE
870 sub r1, r1, #HW_SVC_STACK_SIZE
871 ldr r2, =SDK_IRQ_STACKSIZE
872 sub r1, r1, r2
873 add r1, r1, #4
874
875 /* Call pointers managed in tables one at a time */
876 @001: ldr r0, [r1]
877 cmp r0, #0
878 beq @002
879 stmdb sp!, {r1}
880 blx r0
881 ldmia sp!, {r1}
882 /* Zero-clear pointers that were called once (because of borrowing the IRQ stack) */
883 mov r0, #0
884 str r0, [r1], #4
885 b @001
886
887 @002:
888 ldmia sp!, {lr}
889 bx lr
890 }
891 #endif
892
893 /*---------------------------------------------------------------------------*
894 Name: MIi_UncompressBackward
895 Description: Uncompresses special archive for module compression.
896 Arguments: bottom: Bottom address of packed archive + 1
897 bottom[-8..-6]: Offset for top of compressed data
898 inp_top = bottom - bottom[-8..-6]
899 bottom[ -5]: Offset for bottom of compressed data
900 inp = bottom - bottom[-5]
901 bottom[-4..-1]: Offset for bottom of original data
902 outp = bottom + bottom[-4..-1]
903 typedef struct
904 {
905 u32 bufferTop:24;
906 u32 compressBottom:8;
907 u32 originalBottom;
908 } CompFooter;
909 Returns: None.
910 *---------------------------------------------------------------------------*/
911 asm void
MIi_UncompressBackward(register void * bottom)912 MIi_UncompressBackward(register void* bottom)
913 {
914 #define data r0
915 #define inp_top r1
916 #define outp r2
917 #define inp r3
918 #define outp_save r4
919 #define flag r5
920 #define count8 r6
921 #define index r7
922 #define dummy r8
923 #define len r12
924
925 cmp bottom, #0
926 beq @exit
927 stmfd sp!, {r4-r8}
928 ldmdb bottom, {r1-r2}
929 add outp, bottom, outp
930 sub inp, bottom, inp_top, LSR #24
931 bic inp_top, inp_top, #0xff000000
932 sub inp_top, bottom, inp_top
933 mov outp_save, outp
934 @loop:
935 cmp inp, inp_top // Exit if inp==inp_top
936 ble @end_loop
937 ldrb flag, [inp, #-1]! // r4 = compress_flag = *--inp
938 mov count8, #8
939 @loop8:
940 subs count8, count8, #1
941 blt @loop
942 tst flag, #0x80
943 bne @blockcopy
944 @bytecopy:
945 ldrb data, [inp, #-1]!
946 ldrb dummy, [outp, #-1] // Dummy read to use D-Cache efficiently
947 strb data, [outp, #-1]! // Copy 1 byte
948 b @joinhere
949 @blockcopy:
950 ldrb len, [inp, #-1]!
951 ldrb index, [inp, #-1]!
952 orr index, index, len, LSL #8
953 bic index, index, #0xf000
954 add index, index, #0x0002
955 add len, len, #0x0020
956 @patterncopy:
957 ldrb data, [outp, index]
958 ldrb dummy, [outp, #-1] // Dummy read to use D-Cache efficiently
959 strb data, [outp, #-1]!
960 subs len, len, #0x0010
961 bge @patterncopy
962
963 @joinhere:
964 cmp inp, inp_top
965 mov flag, flag, LSL #1
966 bgt @loop8
967 @end_loop:
968
969 // DC_FlushRange & IC_InvalidateRange
970 mov r0, #0
971 bic inp, inp_top, #HW_CACHE_LINE_SIZE - 1
972 @cacheflush:
973 mcr p15, 0, r0, c7, c10, 4 // Wait writebuffer empty
974 mcr p15, 0, inp, c7, c5, 1 // ICache
975 mcr p15, 0, inp, c7, c14, 1 // DCache
976 add inp, inp, #HW_CACHE_LINE_SIZE
977 cmp inp, outp_save
978 blt @cacheflush
979
980 ldmfd sp!, {r4-r8}
981 @exit bx lr
982 }
983
984 /*---------------------------------------------------------------------------*
985 Name: _start_AutoloadDoneCallback
986 Description: Autoload completion callback.
987 Arguments: argv: Array retaining the autoload parameters
988 argv[0] = SDK_AUTOLOAD_LIST
989 argv[1] = SDK_AUTOLOAD_LIST_END
990 argv[2] = SDK_AUTOLOAD_START
991 argv[3] = SDK_STATIC_BSS_START
992 argv[4] = SDK_STATIC_BSS_END
993 Returns: None.
994 *---------------------------------------------------------------------------*/
995 SDK_WEAK_SYMBOL asm void
_start_AutoloadDoneCallback(void * argv[])996 _start_AutoloadDoneCallback(void* argv[])
997 {
998 bx lr
999 }
1000
1001 /*---------------------------------------------------------------------------*
1002 Name: NitroStartUp
1003 Description: Hook for user start-up.
1004 Arguments: None.
1005 Returns: None.
1006 *---------------------------------------------------------------------------*/
1007 SDK_WEAK_SYMBOL void
NitroStartUp(void)1008 NitroStartUp(void)
1009 {
1010 }
1011
1012 /*---------------------------------------------------------------------------*
1013 Name: OSi_ReferSymbol
1014 Description: Used by SDK_REFER_SYMBOL macro to avoid deadstripping.
1015 Arguments: symbol: Unused
1016 Returns: None.
1017 *---------------------------------------------------------------------------*/
1018 void
OSi_ReferSymbol(void * symbol)1019 OSi_ReferSymbol(void* symbol)
1020 {
1021 #pragma unused(symbol)
1022 }
1023
1024 /*---------------------------------------------------------------------------*
1025 Name: INITi_IsRunOnTwl
1026
1027 Description: Checks running platform.
1028
1029 This function is used in only NITRO-TWL hybrid mode.
1030 (In NITRO mode and TWL limited mode, treated as constant)
1031
1032 Arguments: None.
1033
1034 Returns: TRUE: running on TWL
1035 FALSE: running on NITRO
1036 *---------------------------------------------------------------------------*/
INITi_IsRunOnTwl(void)1037 static asm BOOL INITi_IsRunOnTwl( void )
1038 {
1039 ldr r0, =REG_A9ROM_ADDR
1040 ldrb r0, [r0]
1041 and r0, r0, #REG_SCFG_A9ROM_SEC_MASK | REG_SCFG_A9ROM_RSEL_MASK
1042 cmp r0, #REG_SCFG_A9ROM_SEC_MASK
1043 moveq r0, #TRUE
1044 movne r0, #FALSE
1045
1046 bx lr
1047 }
1048
1049 /*---------------------------------------------------------------------------*
1050 Name: INITi_Copy32
1051 Description: Where possible, copy in 32-byte units; remnant portions can be copied in 4-byte units.
1052
1053 The stack is consumed in 36-bytes, but registers r3 - r12 are not destroyed.
1054 Arguments: r0: Pointer to copy destination (4-byte aligned)
1055 r1: Pointer to copy source (4-byte aligned)
1056 r2: Length to be copied in byte units (multiples of 4)
1057 Returns: r0: Pointer to the copy destination after copying (r0 + r2).
1058 r1: Pointer to the copy source after copying (r1 + r2).
1059 *---------------------------------------------------------------------------*/
1060 static asm void*
INITi_Copy32(void * dst,void * src,u32 size)1061 INITi_Copy32(void* dst, void* src, u32 size)
1062 {
1063 stmfd sp!, {r3-r11}
1064 bics r3, r2, #0x0000001f
1065 beq @next
1066 add r3, r0, r3
1067 @loop:
1068 ldmia r1!, {r4-r11}
1069 stmia r0!, {r4-r11}
1070 cmp r3, r0
1071 bgt @loop
1072 @next:
1073 tst r2, #0x00000010
1074 ldmneia r1!, {r4-r7}
1075 stmneia r0!, {r4-r7}
1076 tst r2, #0x00000008
1077 ldmneia r1!, {r4-r5}
1078 stmneia r0!, {r4-r5}
1079 tst r2, #0x00000004
1080 ldmneia r1!, {r4}
1081 stmneia r0!, {r4}
1082 ldmfd sp!, {r3-r11}
1083 bx lr
1084 }
1085
1086 /*---------------------------------------------------------------------------*
1087 Name: INITi_Fill32
1088 Description: Where possible, fill the buffer with specified data in 32-byte units; remnant portions can be filled in 4-byte units.
1089
1090 The stack is consumed in 36-bytes, but registers r3 - r12 are not destroyed.
1091 Arguments: r0: Pointer to the buffer (4-byte aligned)
1092 r1: Content to fill the buffer using 32-bit values
1093 r2: Length to fill the buffer in byte units (multiples of 4)
1094 Returns: r0: Pointer to the buffer after processing (r0 + r2).
1095 *---------------------------------------------------------------------------*/
1096 static asm void*
INITi_Fill32(void * dst,u32 value,u32 size)1097 INITi_Fill32(void* dst, u32 value, u32 size)
1098 {
1099 stmfd sp!, {r3-r11}
1100 mov r4, r1
1101 mov r5, r1
1102 mov r6, r1
1103 mov r7, r1
1104 mov r8, r1
1105 mov r9, r1
1106 mov r10, r1
1107 mov r11, r1
1108 bics r3, r2, #0x0000001f
1109 beq @next
1110 add r3, r0, r3
1111 @loop:
1112 stmia r0!, {r4-r11}
1113 cmp r3, r0
1114 bgt @loop
1115 @next:
1116 tst r2, #0x00000010
1117 stmneia r0!, {r4-r7}
1118 tst r2, #0x00000008
1119 stmneia r0!, {r4-r5}
1120 tst r2, #0x00000004
1121 stmneia r0!, {r4}
1122 ldmfd sp!, {r3-r11}
1123 bx lr
1124 }
1125
1126 #include <twl/codereset.h>
1127