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