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