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