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