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